[dna-commits] DNA SVN: r707 - in trunk: dna-common/src/main/java/org/jboss/dna/common/statistic and 108 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Thu Jan 15 13:33:00 EST 2009


Author: rhauch
Date: 2009-01-15 13:32:57 -0500 (Thu, 15 Jan 2009)
New Revision: 707

Added:
   trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/
   trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/DetailedStatistics.java
   trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Histogram.java
   trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/SimpleStatistics.java
   trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Stopwatch.java
   trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/
   trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/DetailedStatisticsTest.java
   trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/HistogramTest.java
   trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/SimpleStatisticsTest.java
   trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/StopwatchTest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnection.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionPool.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryContext.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceCapabilities.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceListener.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Binary.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/BinaryFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/DateTime.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/DateTimeFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/InvalidPathException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/InvalidPathExpressionException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/IoException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Name.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NameFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceRegistry.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathExpression.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathNotFoundException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Property.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyType.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Reference.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ReferentialIntegrityException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/UuidFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueComparators.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactories.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFormatException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinaryValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactories.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicEmptyProperty.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicMultiValueProperty.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespace.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistry.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPath.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPathSegment.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicProperty.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPropertyFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicSingleValueProperty.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BooleanValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ChildPath.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DecimalValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DelegatingValueFactories.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DoubleValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTime.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistry.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LongValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ObjectValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/PathValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StandardValueFactories.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StringValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UriValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReference.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReferenceValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CacheableRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CompositeRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DeleteBranchRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/InvalidRequestException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/MoveBranchRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllChildrenRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllPropertiesRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBranchRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNextBlockOfChildrenRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNodeRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadPropertyRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertiesRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RenameNodeRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/Request.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/UpdatePropertiesRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerContext.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerOutput.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/StreamSequencer.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/package-info.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryConnectionPoolTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperation.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperations.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositorySourceLoadHarness.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepository.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepositorySource.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/TimeDelayingRepositorySource.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/package-info.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/AbstractValueComparatorsTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BinaryValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BooleanValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DateValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DecimalValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DoubleValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/LongValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/NameValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/PathExpressionTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/StringValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractPathTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathOldTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathSegmentTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BinaryContains.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BooleanValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/ChildPathTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DecimalValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DoubleValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/IsPathContaining.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LongValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/PathValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/RootPathTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/UuidValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/AbstractRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CompositeRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CopyBranchRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/DeleteBranchRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/MoveBranchRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllChildrenRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllPropertiesRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBranchRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadNodeRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadPropertyRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RenameNodeRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerContext.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerOutput.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitBasicFunctionTest.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitDerbyStressTest.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitInMemoryTest.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitTestUtil.java
   trunk/dna-jcr/src/test/resources/log4j.properties
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/InvalidSequencerPathExpression.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/Sequencer.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerConfig.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerException.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerLibrary.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerOutputMap.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerPathExpression.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencingService.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AbstractServiceAdministrator.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AdministeredService.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/ServiceAdministrator.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerA.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerB.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerConfigTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerPathExpressionTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencingServiceTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ConsoleInput.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ContentInfo.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/JavaInfo.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/MediaInfo.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/UserInterface.java
   trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/
   trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/MockUserInterface.java
   trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModel.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildId.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueId.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/NodeId.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/PropertiesEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceId.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphNodeEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQuery.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/ChangeLogEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/NamespaceEntity.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModelTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntityTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryTest.java
   trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/aperture/
   trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/aperture/ApertureMimeTypeDetector.java
   trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/aperture/
   trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/aperture/MimeTypeTest.java
   trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/
   trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadata.java
   trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadataSequencer.java
   trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageSequencerI18n.java
   trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/
   trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/ImageSequencerI18n.properties
   trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/images.cnd
   trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/
   trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataSequencerTest.java
   trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataTest.java
   trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageSequencerI18nTest.java
Removed:
   trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/DetailedStatistics.java
   trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Histogram.java
   trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/SimpleStatistics.java
   trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Stopwatch.java
   trunk/dna-common/src/main/java/org/jboss/dna/common/stats/
   trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/DetailedStatisticsTest.java
   trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/HistogramTest.java
   trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/SimpleStatisticsTest.java
   trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/StopwatchTest.java
   trunk/dna-common/src/test/java/org/jboss/dna/common/stats/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnection.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionPool.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryContext.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceCapabilities.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceListener.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Binary.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/BinaryFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTime.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTimeFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathExpressionException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/IoException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Name.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NameFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceRegistry.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Path.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathExpression.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathNotFoundException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Property.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyType.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Reference.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ReferentialIntegrityException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/UuidFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueComparators.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactories.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFormatException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinaryValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactories.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicEmptyProperty.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicMultiValueProperty.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespace.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistry.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPath.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPathSegment.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicProperty.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPropertyFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicSingleValueProperty.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BooleanValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ChildPath.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DecimalValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DelegatingValueFactories.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DoubleValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTime.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistry.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LongValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ObjectValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/PathValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StandardValueFactories.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StringValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UriValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReference.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReferenceValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidValueFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CacheableRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CompositeRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CopyBranchRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/DeleteBranchRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/InvalidRequestException.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/MoveBranchRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllChildrenRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBranchRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNodeRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadPropertyRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RemovePropertiesRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RenameNodeRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Request.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/UpdatePropertiesRequest.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerContext.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerOutput.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/StreamSequencer.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/package-info.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryConnectionPoolTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperation.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperations.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositorySourceLoadHarness.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepository.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepositorySource.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/TimeDelayingRepositorySource.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/AbstractValueComparatorsTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BinaryValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BooleanValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DateValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DecimalValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DoubleValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/LongValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/NameValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/PathExpressionTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/StringValueComparatorTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractPathTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathOldTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathSegmentTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BinaryContains.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BooleanValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/ChildPathTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DecimalValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DoubleValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/IsPathContaining.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LongValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/PathValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/RootPathTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/UuidValueFactoryTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/AbstractRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CompositeRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CopyBranchRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/DeleteBranchRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/MoveBranchRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllChildrenRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllPropertiesRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBranchRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadNodeRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadPropertyRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RenameNodeRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerContext.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerOutput.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/
   trunk/dna-integration-tests/src/main/java/
   trunk/dna-integration-tests/src/main/resources/
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitBasicFunctionTest.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitDerbyStressTest.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitInMemoryTest.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitTestUtil.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit/
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/InvalidSequencerPathExpression.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/Sequencer.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerConfig.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerException.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerLibrary.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerNodeContext.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerOutputMap.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerPathExpression.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencingService.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AbstractServiceAdministrator.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AdministeredService.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/ServiceAdministrator.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerA.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerB.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerConfigTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerNodeContextTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerPathExpressionTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencingServiceTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ConsoleInput.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ContentInfo.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/JavaInfo.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/MediaInfo.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/UserInterface.java
   trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/
   trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/MockUserInterface.java
   trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java
   trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModel.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildId.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueId.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/NodeId.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/PropertiesEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceId.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphNodeEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQuery.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/ChangeLogEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/NamespaceEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModelTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntityTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/
   trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/ApertureMimeTypeDetector.java
   trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/MimeTypeTest.java
   trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadata.java
   trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadataSequencer.java
   trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageSequencerI18n.java
   trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/images/
   trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/ImageSequencerI18n.properties
   trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/images.cnd
   trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/images/
   trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataSequencerTest.java
   trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataTest.java
   trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageSequencerI18nTest.java
   trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/images/
Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaLexicon.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrLexicon.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrMixLexicon.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrNtLexicon.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/Node.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/Subgraph.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/cache/Cacheable.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/cache/package-info.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithChildren.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithProperty.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java
   trunk/dna-integration-tests/.classpath
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeIterator.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrProperty.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeIteratorTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrValueTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestUtil.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryLibrary.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleService.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrNamespaceRegistry.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java
   trunk/dna-repository/src/test/resources/master.xml
   trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
   trunk/docs/examples/gettingstarted/repositories/src/test/resources/log4j.properties
   trunk/docs/examples/gettingstarted/sequencers/src/main/config/run.sh
   trunk/docs/examples/gettingstarted/sequencers/src/test/resources/log4j.properties
   trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_for_sequencing.xml
   trunk/docs/reference/src/main/docbook/en-US/custom.dtd
   trunk/extensions/dna-common-jdbc/src/main/java/org/jboss/dna/graph/sequencers/JdbcSequencer.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConfig.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiChildContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NonEmptyContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OneChildContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OnePropertyContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PlaceholderContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoChildContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContribution.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FederatedNode.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceIntegrationTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/EmptyContributionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiChildContributionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContributionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/NodeContributionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OneChildContributionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OnePropertyContributionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContributionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoChildContributionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContributionTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutorTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/FederatedNodeTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/MergePlanTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java
   trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemConnection.java
   trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java
   trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java
   trunk/extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorReadingTest.java
   trunk/extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemSourceTest.java
   trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
   trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java
   trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositorySource.java
   trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/Node.java
   trunk/extensions/dna-connector-inmemory/src/test/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryTest.java
   trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java
   trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheLexicon.java
   trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java
   trunk/extensions/dna-connector-jbosscache/src/main/resources/org/jboss/dna/connector/jbosscache/JBossCacheConnectorI18n.properties
   trunk/extensions/dna-connector-jbosscache/src/test/java/org/jboss/dna/connector/jbosscache/JBossCacheConnectionTest.java
   trunk/extensions/dna-connector-jbosscache/src/test/java/org/jboss/dna/connector/jbosscache/JBossCacheSourceTest.java
   trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcConnection.java
   trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositoryLexicon.java
   trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositorySource.java
   trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRequestProcesor.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnection.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/Model.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Namespaces.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/RequestProcessorCache.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorReadingTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/ModelTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/RequestProcessorCacheTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/SerializerTest.java
   trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryConnection.java
   trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryLexicon.java
   trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java
   trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java
   trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositoryConnectionTest.java
   trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositorySourceTest.java
   trunk/extensions/dna-sequencer-images/src/test/resources/log4j.properties
   trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/ArrayTypeFieldMetadataSequencer.java
   trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java
   trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/MethodMetadataSequencer.java
   trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/ParameterizedTypeFieldMetadataSequencer.java
   trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/SimpleTypeMetadataSequencer.java
   trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/VariableSequencer.java
   trunk/extensions/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataSequencerTest.java
   trunk/extensions/dna-sequencer-java/src/test/resources/log4j.properties
   trunk/extensions/dna-sequencer-mp3/src/main/java/org/jboss/dna/sequencer/mp3/Mp3MetadataSequencer.java
   trunk/extensions/dna-sequencer-mp3/src/test/resources/log4j.properties
   trunk/extensions/dna-sequencer-msoffice/src/main/java/org/jboss/dna/sequencer/msoffice/MSOfficeMetadataSequencer.java
   trunk/extensions/dna-sequencer-msoffice/src/test/resources/log4j.properties
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaDtdLexicon.java
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaXmlLexicon.java
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java
   trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerHandler.java
   trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencerTest.java
   trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerHandlerTest.java
   trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java
   trunk/extensions/dna-sequencer-xml/src/test/resources/log4j.properties
   trunk/extensions/dna-sequencer-xml/src/test/resources/master.xml
   trunk/extensions/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java
   trunk/extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/SequencingOutputTestClass.java
   trunk/extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java
   trunk/extensions/dna-sequencer-zip/src/test/resources/log4j.properties
Log:
Changed all of the plural package names to be singular, and changed a few from an abbreviation to regular words.  All tests pass.

Copied: trunk/dna-common/src/main/java/org/jboss/dna/common/statistic (from rev 705, trunk/dna-common/src/main/java/org/jboss/dna/common/stats)

Deleted: trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/DetailedStatistics.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/stats/DetailedStatistics.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/DetailedStatistics.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,247 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.common.stats;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.locks.Lock;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.math.MathOperations;
-import org.jboss.dna.common.text.Inflector;
-import org.jboss.dna.common.util.StringUtil;
-
-/**
- * Encapsulation of the statistics for a series of values to which new values are frequently added. The statistics include the
- * {@link #getMinimum() minimum}, {@link #getMaximum() maximum}, {@link #getTotal() total (aggregate sum)},
- * {@link #getMean() mean (average)}, {@link #getMedian() median}, {@link #getStandardDeviation() standard deviation} and the
- * {@link #getHistogram() histogram} of the values.
- * <p>
- * This class uses an efficient running calculation of the mean and standard deviation that is not as susceptible to roundoff
- * errors as other traditional algorithms. The recursive algorithm is as follows, where M is the median value, sigma is the
- * standard deviation, and S is a variable used in the calculation of sigma:
- * 
- * <pre>
- *   M(1) = x(1)
- *   S(1) = 0
- *   M(k) = M(k-1) + ( x(k) - M(k-1) ) / k
- *   S(k) = S(k-1) + ( x(k) - M(k-1) ) * (x(k) - M(k))
- * </pre>
- * 
- * Then, the standard deviation for n values in x is
- * 
- * <pre>
- * sigma = sqrt(S(n) / n)
- * </pre>
- * 
- * </p>
- * Unlike the other quantities, the median value (the value at which half of the values are greater and half the values are lower)
- * cannot be calculated incrementally. Therefore, this class does record the values so that the median can be properly calculated.
- * This fact should be kept in mind when performing statistics on large numbers of values.
- * </p>
- * <p>
- * This class is threadsafe.
- * </p>
- * @param <T> the number type for these statistics
- */
- at ThreadSafe
-public class DetailedStatistics<T extends Number> extends SimpleStatistics<T> {
-
-    private T median;
-    private Double medianValue;
-    private double s = 0.0d; // used in the calculation of standard deviation (sigma)
-    private double sigma = 0.0d;
-    private final List<T> values = new LinkedList<T>();
-    private final List<T> unmodifiableValues = Collections.unmodifiableList(this.values);
-    private Histogram<T> histogram;
-
-    public DetailedStatistics( MathOperations<T> operations ) {
-        super(operations);
-        this.medianValue = 0.0d;
-        this.median = this.math.createZeroValue();
-    }
-
-    /**
-     * Get the values that have been recorded in these statistics. The contents of this list may change if new values are
-     * {@link #add(Number) added} in another thread.
-     * @return the unmodifiable collection of values, in insertion order
-     */
-    public List<T> getValues() {
-        return this.unmodifiableValues;
-    }
-
-    @Override
-    protected void doAddValue( T value ) {
-        if (value == null) {
-            return;
-        }
-        double previousMean = this.getMeanValue();
-        super.doAddValue(value);
-        this.values.add(value);
-        this.medianValue = null;
-
-        // Calculate the mean and standard deviation ...
-        int count = getCount();
-        if (count == 1) {
-            this.s = 0.0d;
-            this.sigma = 0.0d;
-        } else {
-            double dValue = value.doubleValue();
-            double dCount = count;
-            // M(k) = M(k-1) + ( x(k) - M(k-1) ) / k
-            double meanValue = previousMean + ((dValue - previousMean) / dCount);
-            // S(k) = S(k-1) + ( x(k) - M(k-1) ) * ( x(k) - M(k) )
-            this.s = this.s + (dValue - previousMean) * (dValue - meanValue);
-            // sigma = sqrt( S(n) / (n-1) )
-            this.sigma = Math.sqrt(this.s / dCount);
-        }
-    }
-
-    /**
-     * Return the approximate mean (average) value represented as an instance of the operand type. Note that this may truncate if
-     * the operand type is not able to have the required precision. For the accurate mean, see {@link #getMedianValue() }.
-     * @return the mean (average), or 0.0 if the {@link #getCount() count} is 0
-     */
-    public T getMedian() {
-        getMedianValue();
-        return this.median;
-    }
-
-    /**
-     * Return the median value.
-     * @return the median value, or 0.0 if the {@link #getCount() count} is 0
-     * @see #getMedian()
-     */
-    public double getMedianValue() {
-        Lock lock = this.getLock().writeLock();
-        try {
-            lock.lock();
-            int count = this.values.size();
-            if (count == 0) {
-                return 0.0d;
-            }
-            if (this.medianValue == null) {
-                // Sort the values in numerical order..
-                Comparator<T> comparator = this.math.getComparator();
-                Collections.sort(this.values, comparator);
-                this.medianValue = 0.0d;
-                // If there is only one value, then the median is that value ...
-                if (count == 1) {
-                    this.medianValue = this.values.get(0).doubleValue();
-                }
-                // If there is an odd number of values, find value that is in the middle ..
-                else if (count % 2 != 0) {
-                    this.medianValue = this.values.get(((count + 1) / 2) - 1).doubleValue();
-                }
-                // Otherwise, there is an even number of values, so find the average of the middle two values ...
-                else {
-                    int upperMiddleValueIndex = count / 2;
-                    int lowerMiddleValueIndex = upperMiddleValueIndex - 1;
-                    double lowerValue = this.values.get(lowerMiddleValueIndex).doubleValue();
-                    double upperValue = this.values.get(upperMiddleValueIndex).doubleValue();
-                    this.medianValue = (lowerValue + upperValue) / 2.0d;
-                }
-                this.median = this.math.create(this.medianValue);
-                this.histogram = null;
-            }
-        } finally {
-            lock.unlock();
-        }
-        return this.medianValue;
-    }
-
-    /**
-     * Return the standard deviation. The standard deviation is a measure of the variation in a series of values. Values with a
-     * lower standard deviation has less variance in the values than a series of values with a higher standard deviation.
-     * @return the standard deviation, or 0.0 if the {@link #getCount() count} is 0 or if all of the values are the same.
-     */
-    public double getStandardDeviation() {
-        Lock lock = this.getLock().readLock();
-        lock.lock();
-        try {
-            return this.sigma;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Return the histogram of the {@link #getValues() values}. This method returns a histogram where all of the buckets are
-     * distributed normally and all have the same width. In this case, the 'numSigmas' should be set to 0. For other variations,
-     * see {@link #getHistogram(int)}.
-     * @return the histogram
-     * @see #getHistogram(int)
-     */
-    public Histogram<T> getHistogram() {
-        return getHistogram(0);
-    }
-
-    /**
-     * Return the histogram of the {@link #getValues() values}. This method is capable of creating two kinds of histograms. The
-     * first kind is a histogram where all of the buckets are distributed normally and all have the same width. In this case, the
-     * 'numSigmas' should be set to 0. See {@link #getHistogram()}.
-     * <p>
-     * The second kind of histogram is more useful when most of the data that is clustered near one value. This histogram is
-     * focused around the values that are up to 'numSigmas' above and below the {@link #getMedian() median}, and all values
-     * outside of this range are placed in the first and last bucket.
-     * </p>
-     * @param numSigmas the number of standard deviations from the {@link #getMedian() median}, or 0 if the buckets of the
-     * histogram should be evenly distributed
-     * @return the histogram
-     * @see #getHistogram()
-     */
-    public Histogram<T> getHistogram( int numSigmas ) {
-        Lock lock = this.getLock().writeLock();
-        lock.lock();
-        try {
-            Histogram<T> hist = new Histogram<T>(this.math, this.values);
-            if (numSigmas > 0) {
-                // The 'getMediaValue()' method will reset the current histogram, so don't set it...
-                hist.setStrategy(this.getMedianValue(), this.getStandardDeviation(), numSigmas);
-            }
-            this.histogram = hist;
-            return this.histogram;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    @Override
-    protected void doReset() {
-        super.doReset();
-        this.medianValue = 0.0d;
-        this.median = this.math.createZeroValue();
-        this.s = 0.0d;
-        this.sigma = 0.0d;
-        this.values.clear();
-    }
-
-    @Override
-    public String toString() {
-        int count = this.getCount();
-        String samples = Inflector.getInstance().pluralize("sample", count);
-        return StringUtil.createString("{0} {1}: min={2}; avg={3}; median={4}; stddev={5}; max={6}", count, samples, this.getMinimum(), this.getMean(), this.getMedian(), this.getStandardDeviation(),
-                                       this.getMaximum());
-    }
-
-}

Copied: trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/DetailedStatistics.java (from rev 706, trunk/dna-common/src/main/java/org/jboss/dna/common/stats/DetailedStatistics.java)
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/DetailedStatistics.java	                        (rev 0)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/DetailedStatistics.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,247 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.statistic;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.locks.Lock;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.math.MathOperations;
+import org.jboss.dna.common.text.Inflector;
+import org.jboss.dna.common.util.StringUtil;
+
+/**
+ * Encapsulation of the statistics for a series of values to which new values are frequently added. The statistics include the
+ * {@link #getMinimum() minimum}, {@link #getMaximum() maximum}, {@link #getTotal() total (aggregate sum)},
+ * {@link #getMean() mean (average)}, {@link #getMedian() median}, {@link #getStandardDeviation() standard deviation} and the
+ * {@link #getHistogram() histogram} of the values.
+ * <p>
+ * This class uses an efficient running calculation of the mean and standard deviation that is not as susceptible to roundoff
+ * errors as other traditional algorithms. The recursive algorithm is as follows, where M is the median value, sigma is the
+ * standard deviation, and S is a variable used in the calculation of sigma:
+ * 
+ * <pre>
+ *   M(1) = x(1)
+ *   S(1) = 0
+ *   M(k) = M(k-1) + ( x(k) - M(k-1) ) / k
+ *   S(k) = S(k-1) + ( x(k) - M(k-1) ) * (x(k) - M(k))
+ * </pre>
+ * 
+ * Then, the standard deviation for n values in x is
+ * 
+ * <pre>
+ * sigma = sqrt(S(n) / n)
+ * </pre>
+ * 
+ * </p>
+ * Unlike the other quantities, the median value (the value at which half of the values are greater and half the values are lower)
+ * cannot be calculated incrementally. Therefore, this class does record the values so that the median can be properly calculated.
+ * This fact should be kept in mind when performing statistics on large numbers of values.
+ * </p>
+ * <p>
+ * This class is threadsafe.
+ * </p>
+ * @param <T> the number type for these statistics
+ */
+ at ThreadSafe
+public class DetailedStatistics<T extends Number> extends SimpleStatistics<T> {
+
+    private T median;
+    private Double medianValue;
+    private double s = 0.0d; // used in the calculation of standard deviation (sigma)
+    private double sigma = 0.0d;
+    private final List<T> values = new LinkedList<T>();
+    private final List<T> unmodifiableValues = Collections.unmodifiableList(this.values);
+    private Histogram<T> histogram;
+
+    public DetailedStatistics( MathOperations<T> operations ) {
+        super(operations);
+        this.medianValue = 0.0d;
+        this.median = this.math.createZeroValue();
+    }
+
+    /**
+     * Get the values that have been recorded in these statistics. The contents of this list may change if new values are
+     * {@link #add(Number) added} in another thread.
+     * @return the unmodifiable collection of values, in insertion order
+     */
+    public List<T> getValues() {
+        return this.unmodifiableValues;
+    }
+
+    @Override
+    protected void doAddValue( T value ) {
+        if (value == null) {
+            return;
+        }
+        double previousMean = this.getMeanValue();
+        super.doAddValue(value);
+        this.values.add(value);
+        this.medianValue = null;
+
+        // Calculate the mean and standard deviation ...
+        int count = getCount();
+        if (count == 1) {
+            this.s = 0.0d;
+            this.sigma = 0.0d;
+        } else {
+            double dValue = value.doubleValue();
+            double dCount = count;
+            // M(k) = M(k-1) + ( x(k) - M(k-1) ) / k
+            double meanValue = previousMean + ((dValue - previousMean) / dCount);
+            // S(k) = S(k-1) + ( x(k) - M(k-1) ) * ( x(k) - M(k) )
+            this.s = this.s + (dValue - previousMean) * (dValue - meanValue);
+            // sigma = sqrt( S(n) / (n-1) )
+            this.sigma = Math.sqrt(this.s / dCount);
+        }
+    }
+
+    /**
+     * Return the approximate mean (average) value represented as an instance of the operand type. Note that this may truncate if
+     * the operand type is not able to have the required precision. For the accurate mean, see {@link #getMedianValue() }.
+     * @return the mean (average), or 0.0 if the {@link #getCount() count} is 0
+     */
+    public T getMedian() {
+        getMedianValue();
+        return this.median;
+    }
+
+    /**
+     * Return the median value.
+     * @return the median value, or 0.0 if the {@link #getCount() count} is 0
+     * @see #getMedian()
+     */
+    public double getMedianValue() {
+        Lock lock = this.getLock().writeLock();
+        try {
+            lock.lock();
+            int count = this.values.size();
+            if (count == 0) {
+                return 0.0d;
+            }
+            if (this.medianValue == null) {
+                // Sort the values in numerical order..
+                Comparator<T> comparator = this.math.getComparator();
+                Collections.sort(this.values, comparator);
+                this.medianValue = 0.0d;
+                // If there is only one value, then the median is that value ...
+                if (count == 1) {
+                    this.medianValue = this.values.get(0).doubleValue();
+                }
+                // If there is an odd number of values, find value that is in the middle ..
+                else if (count % 2 != 0) {
+                    this.medianValue = this.values.get(((count + 1) / 2) - 1).doubleValue();
+                }
+                // Otherwise, there is an even number of values, so find the average of the middle two values ...
+                else {
+                    int upperMiddleValueIndex = count / 2;
+                    int lowerMiddleValueIndex = upperMiddleValueIndex - 1;
+                    double lowerValue = this.values.get(lowerMiddleValueIndex).doubleValue();
+                    double upperValue = this.values.get(upperMiddleValueIndex).doubleValue();
+                    this.medianValue = (lowerValue + upperValue) / 2.0d;
+                }
+                this.median = this.math.create(this.medianValue);
+                this.histogram = null;
+            }
+        } finally {
+            lock.unlock();
+        }
+        return this.medianValue;
+    }
+
+    /**
+     * Return the standard deviation. The standard deviation is a measure of the variation in a series of values. Values with a
+     * lower standard deviation has less variance in the values than a series of values with a higher standard deviation.
+     * @return the standard deviation, or 0.0 if the {@link #getCount() count} is 0 or if all of the values are the same.
+     */
+    public double getStandardDeviation() {
+        Lock lock = this.getLock().readLock();
+        lock.lock();
+        try {
+            return this.sigma;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Return the histogram of the {@link #getValues() values}. This method returns a histogram where all of the buckets are
+     * distributed normally and all have the same width. In this case, the 'numSigmas' should be set to 0. For other variations,
+     * see {@link #getHistogram(int)}.
+     * @return the histogram
+     * @see #getHistogram(int)
+     */
+    public Histogram<T> getHistogram() {
+        return getHistogram(0);
+    }
+
+    /**
+     * Return the histogram of the {@link #getValues() values}. This method is capable of creating two kinds of histograms. The
+     * first kind is a histogram where all of the buckets are distributed normally and all have the same width. In this case, the
+     * 'numSigmas' should be set to 0. See {@link #getHistogram()}.
+     * <p>
+     * The second kind of histogram is more useful when most of the data that is clustered near one value. This histogram is
+     * focused around the values that are up to 'numSigmas' above and below the {@link #getMedian() median}, and all values
+     * outside of this range are placed in the first and last bucket.
+     * </p>
+     * @param numSigmas the number of standard deviations from the {@link #getMedian() median}, or 0 if the buckets of the
+     * histogram should be evenly distributed
+     * @return the histogram
+     * @see #getHistogram()
+     */
+    public Histogram<T> getHistogram( int numSigmas ) {
+        Lock lock = this.getLock().writeLock();
+        lock.lock();
+        try {
+            Histogram<T> hist = new Histogram<T>(this.math, this.values);
+            if (numSigmas > 0) {
+                // The 'getMediaValue()' method will reset the current histogram, so don't set it...
+                hist.setStrategy(this.getMedianValue(), this.getStandardDeviation(), numSigmas);
+            }
+            this.histogram = hist;
+            return this.histogram;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    protected void doReset() {
+        super.doReset();
+        this.medianValue = 0.0d;
+        this.median = this.math.createZeroValue();
+        this.s = 0.0d;
+        this.sigma = 0.0d;
+        this.values.clear();
+    }
+
+    @Override
+    public String toString() {
+        int count = this.getCount();
+        String samples = Inflector.getInstance().pluralize("sample", count);
+        return StringUtil.createString("{0} {1}: min={2}; avg={3}; median={4}; stddev={5}; max={6}", count, samples, this.getMinimum(), this.getMean(), this.getMedian(), this.getStandardDeviation(),
+                                       this.getMaximum());
+    }
+
+}

Deleted: trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Histogram.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/stats/Histogram.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Histogram.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,498 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.common.stats;
-
-import java.math.BigDecimal;
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import org.jboss.dna.common.math.MathOperations;
-import org.jboss.dna.common.util.StringUtil;
-
-public class Histogram<T extends Number> {
-
-    public static final int DEFAULT_BUCKET_COUNT = 10;
-    public static final int DEFAULT_SIGNIFICANT_FIGURES = 4;
-
-    protected final MathOperations<T> math;
-    protected final List<T> values;
-    private int bucketCount = DEFAULT_BUCKET_COUNT;
-    private int significantFigures = DEFAULT_SIGNIFICANT_FIGURES;
-    private BigDecimal bucketWidth;
-    private LinkedList<Bucket> buckets;
-    private BucketingStrategy actualValueStrategy = new DefaultBucketingStrategy();
-    private BucketingStrategy bucketingStrategy = actualValueStrategy;
-
-    public Histogram( MathOperations<T> operations, List<T> values ) {
-        this.math = operations;
-        this.values = new LinkedList<T>(values);
-        this.buckets = new LinkedList<Bucket>();
-        this.bucketWidth = null;
-        // Sort the data using natural order ...
-        Collections.sort(this.values, this.math.getComparator());
-    }
-
-    public Histogram( MathOperations<T> operations, T... values ) {
-        this(operations, Arrays.asList(values));
-    }
-
-    public BucketingStrategy getStrategy() {
-        return this.bucketingStrategy;
-    }
-
-    /**
-     * @return math
-     */
-    public MathOperations<T> getMathOperations() {
-        return this.math;
-    }
-
-    /**
-     * Set the histogram to use the standard deviation to determine the bucket sizes.
-     * @param median
-     * @param standardDeviation
-     * @param sigma
-     */
-    public void setStrategy( double median, double standardDeviation, int sigma ) {
-        this.bucketingStrategy = new StandardDeviationBucketingStrategy(median, standardDeviation, sigma);
-        this.bucketWidth = null;
-    }
-
-    /**
-     * Set the histogram to use the supplied minimum and maximum values to determine the bucket size.
-     * @param minimum
-     * @param maximum
-     */
-    public void setStrategy( T minimum, T maximum ) {
-        this.bucketingStrategy = new ExplicitBucketingStrategy(minimum, maximum);
-        this.bucketWidth = null;
-    }
-
-    /**
-     * Set the histogram to use the actual minimum and maximum values to determine the bucket sizes.
-     */
-    public void setStrategyToDefault() {
-        this.bucketingStrategy = this.actualValueStrategy;
-        this.bucketWidth = null;
-    }
-
-    public int getSignificantFigures() {
-        return significantFigures;
-    }
-
-    /**
-     * Set the number of significant figures used in the calculation of the bucket widths.
-     * @param significantFigures the number of significant figures for the bucket widths
-     * @return this histogram, useful for method-chaining
-     * @see #DEFAULT_SIGNIFICANT_FIGURES
-     */
-    public Histogram<T> setSignificantFigures( int significantFigures ) {
-        if (significantFigures != this.significantFigures) {
-            this.significantFigures = significantFigures;
-            this.bucketWidth = null;
-            this.buckets.clear();
-        }
-        return this;
-    }
-
-    /**
-     * Return the number of buckets in this histogram.
-     * @return the number of buckets.
-     */
-    public int getBucketCount() {
-        return bucketCount;
-    }
-
-    /**
-     * Set the number of buckets that this histogram will use.
-     * @param count the number of buckets
-     * @return this histogram, useful for method-chaining
-     * @see #DEFAULT_BUCKET_COUNT
-     */
-    public Histogram<T> setBucketCount( int count ) {
-        if (count != this.bucketCount) {
-            this.bucketCount = count;
-            this.bucketWidth = null;
-            this.buckets.clear();
-        }
-        return this;
-    }
-
-    /**
-     * Get the buckets in this histogram. If the histogram has not yet been computed, this method will cause it to be generated.
-     * The resulting list should not be modified.
-     * @return the histogram buckets.
-     */
-    public List<Bucket> getBuckets() {
-        compute();
-        return this.buckets;
-    }
-
-    protected void compute() {
-        // Only compute if there is not already a histogram ...
-        if (this.bucketWidth != null) return;
-
-        // Find the lower and upper bounds of the histogram using the strategy ...
-        T lowerBound = this.bucketingStrategy.getLowerBound();
-        T upperBound = this.bucketingStrategy.getUpperBound();
-
-        // Find the actual minimum and maximum values ...
-        T actualMinimum = this.actualValueStrategy.getLowerBound();
-        T actualMaximum = this.actualValueStrategy.getUpperBound();
-
-        // Create the buckets ...
-        List<T> boundaries = getBucketBoundaries(this.math, lowerBound, upperBound, actualMinimum, actualMaximum, this.bucketCount, this.significantFigures);
-        this.buckets.clear();
-        int numBuckets = boundaries.isEmpty() ? 0 : boundaries.size() - 1;
-        for (int i = 0; i != numBuckets; ++i) {
-            this.buckets.add(new Bucket(boundaries.get(i), boundaries.get(i + 1)));
-        }
-
-        // Create the histogram by adding values to each range ...
-        Iterator<Bucket> intervalIterator = this.buckets.iterator();
-        Bucket currentInterval = null;
-        for (T value : this.values) {
-            while (currentInterval == null || currentInterval.checkValue(value, !intervalIterator.hasNext()) > 0) {
-                if (!intervalIterator.hasNext()) break;
-                currentInterval = intervalIterator.next();
-            }
-            if (currentInterval != null) currentInterval.addValue(value);
-        }
-    }
-
-    /**
-     * Return the total number of values that have gone into this histogram.
-     * @return the total number of values
-     * @see Bucket#getPercentageOfValues()
-     */
-    public long getTotalNumberOfValues() {
-        return this.values.size();
-    }
-
-    protected float getMaximumPercentage() {
-        float maxPercentage = 0.0f;
-        for (Bucket bucket : this.buckets) {
-            maxPercentage = Math.max(maxPercentage, bucket.getPercentageOfValues());
-        }
-        return maxPercentage;
-    }
-
-    protected long getMaximumCount() {
-        long maxCount = 0l;
-        for (Bucket bucket : this.buckets) {
-            maxCount = Math.max(maxCount, bucket.getNumberOfValues());
-        }
-        return maxCount;
-    }
-
-    /**
-     * Generate a textual (horizontal) bar graph of this histogram.
-     * @param maxBarLength the maximum bar length, or 0 if the bar length is to represent actual counts
-     * @return the strings that make up the histogram
-     */
-    public List<String> getTextGraph( int maxBarLength ) {
-        compute();
-        if (maxBarLength < 1) maxBarLength = (int)this.getMaximumCount();
-        final float barLengthForHundredPercent = this.buckets.isEmpty() ? maxBarLength : 100.0f * maxBarLength / getMaximumPercentage();
-        final String fullLengthBar = StringUtil.createString('*', (int)barLengthForHundredPercent);
-        List<String> result = new LinkedList<String>();
-        // First calculate the labels and the max length ...
-        int maxLowerBoundLength = 0;
-        int maxUpperBoundLength = 0;
-        for (Bucket bucket : this.buckets) {
-            maxLowerBoundLength = Math.max(bucket.getLowerBound().toString().length(), maxLowerBoundLength);
-            maxUpperBoundLength = Math.max(bucket.getUpperBound().toString().length(), maxUpperBoundLength);
-        }
-
-        // Create the header ...
-        int rangeWidth = 1 + maxLowerBoundLength + 3 + maxUpperBoundLength + 1;
-        int barWidth = maxBarLength + 20;
-        result.add(StringUtil.justifyLeft("Ranges", rangeWidth, ' ') + " Distribution");
-        result.add(StringUtil.createString('-', rangeWidth) + ' ' + StringUtil.createString('-', barWidth));
-        for (Bucket bucket : this.buckets) {
-            float percent = bucket.getPercentageOfValues();
-            long number = bucket.getNumberOfValues();
-            StringBuilder sb = new StringBuilder();
-            sb.append("[");
-            sb.append(StringUtil.justifyLeft(bucket.getLowerBound().toString(), maxLowerBoundLength, ' '));
-            sb.append(" - ");
-            sb.append(StringUtil.justifyLeft(bucket.getUpperBound().toString(), maxUpperBoundLength, ' '));
-            sb.append("] ");
-            int barLength = Math.max((int)(barLengthForHundredPercent * percent / 100.0f), 0);
-            if (barLength == 0 && number != 0) barLength = 1; // make sure there is a bar for all non-zero buckets
-            sb.append(fullLengthBar.substring(0, barLength));
-            if (number != 0) {
-                sb.append(" ");
-                sb.append(number);
-                sb.append(" (");
-                sb.append(new DecimalFormat("###.#").format(percent));
-                sb.append("%)");
-            }
-            result.add(sb.toString());
-        }
-        return result;
-    }
-
-    protected static <T> List<T> getBucketBoundaries( MathOperations<T> math, T lowerBound, T upperBound, T actualMinimum, T actualMaximum, int bucketCount, int bucketWidthSigFigs ) {
-        lowerBound = math.compare(lowerBound, actualMinimum) < 0 ? actualMinimum : lowerBound;
-        upperBound = math.compare(actualMaximum, upperBound) < 0 ? actualMaximum : upperBound;
-        if (math.compare(lowerBound, upperBound) == 0) {
-            List<T> boundaries = new ArrayList<T>();
-            boundaries.add(lowerBound);
-            boundaries.add(upperBound);
-            return boundaries;
-        }
-        final boolean extraLowerBucketNeeded = math.compare(lowerBound, actualMinimum) > 0;
-        final boolean extraUpperBucketNeeded = math.compare(actualMaximum, upperBound) > 0;
-        if (extraLowerBucketNeeded) --bucketCount;
-        if (extraUpperBucketNeeded) --bucketCount;
-
-        // Compute the delta between the lower and upper bound ...
-        T totalWidth = math.subtract(upperBound, lowerBound);
-        int totalWidthScale = math.getExponentInScientificNotation(totalWidth);
-
-        // Modify the lower bound by rounding down to the next lower meaningful value,
-        // using the scale of the totalWidth to determine how to round down.
-        T roundedLowerBound = math.roundDown(lowerBound, -totalWidthScale);
-        T roundedUpperBound = math.roundUp(upperBound, -totalWidthScale);
-
-        // Create the ranges ...
-        double finalLowerBound = math.doubleValue(roundedLowerBound);
-        double finalUpperBound = math.doubleValue(roundedUpperBound);
-        double finalBucketCount = bucketCount;
-        double bucketWidth = (finalUpperBound - finalLowerBound) / finalBucketCount;
-
-        // DoubleOperations doubleOps = new DoubleOperations();
-        // bucketWidth = doubleOps.keepSignificantFigures(bucketWidth,bucketWidthSigFigs);
-
-        List<T> boundaries = new ArrayList<T>();
-        if (bucketWidth > 0.0d) {
-            if (extraLowerBucketNeeded) boundaries.add(actualMinimum);
-            double nextBoundary = finalLowerBound;
-            for (int i = 0; i != bucketCount; ++i) {
-                boundaries.add(math.create(nextBoundary));
-                nextBoundary = nextBoundary + bucketWidth;
-                // nextBoundary = doubleOps.roundUp(nextBoundary + bucketWidth, bucketWidthSigFigs );
-            }
-            boundaries.add(roundedUpperBound);
-            if (extraUpperBucketNeeded) boundaries.add(actualMaximum);
-        }
-        return boundaries;
-    }
-
-    /**
-     * Represents a bucket in a histogram.
-     */
-    public class Bucket implements Comparable<Bucket> {
-
-        private final T lowerBound;
-        private final T upperBound;
-        private final T width;
-        private long numValues;
-
-        protected Bucket( T lowerBound, T upperBound ) {
-            this.lowerBound = lowerBound;
-            this.upperBound = upperBound;
-            this.width = Histogram.this.math.subtract(upperBound, lowerBound);
-        }
-
-        /**
-         * Get the lower bound of this bucket.
-         * @return the lower bound
-         */
-        public T getLowerBound() {
-            return lowerBound;
-        }
-
-        /**
-         * Get the upper bound of this bucket.
-         * @return the upper bound
-         */
-        public T getUpperBound() {
-            return upperBound;
-        }
-
-        /**
-         * Get the width of this bucket.
-         * @return the width
-         */
-        public T getWidth() {
-            return this.width;
-        }
-
-        /**
-         * Return the percentage of values in the histogram that appear in this bucket.
-         * @return the percentage of all values in the histogram that appear in this bucket.
-         */
-        public float getPercentageOfValues() {
-            float total = Histogram.this.getTotalNumberOfValues();
-            if (total == 0.0f) return 0.0f;
-            float numValuesFloat = this.numValues;
-            return 100.0f * numValuesFloat / total;
-        }
-
-        /**
-         * Add a value to this bucket
-         * @param value
-         */
-        protected void addValue( T value ) {
-            ++this.numValues;
-        }
-
-        /**
-         * Get the number of values in this bucket.
-         * @return the number of values
-         */
-        public long getNumberOfValues() {
-            return this.numValues;
-        }
-
-        /**
-         * Check whether the value fits in this bucket.
-         * @param value the value to check
-         * @param isLast
-         * @return 0 if the value fits in this bucket, -1 if the value fits in a prior bucket, or 1 if the value fits in a later
-         * bucket
-         */
-        public int checkValue( T value, boolean isLast ) {
-            if (Histogram.this.math.compare(this.lowerBound, value) > 0) return -1;
-            if (isLast) {
-                if (Histogram.this.math.compare(value, this.upperBound) > 0) return 1;
-            } else {
-                if (Histogram.this.math.compare(value, this.upperBound) >= 0) return 1;
-            }
-            return 0;
-        }
-
-        public int compareTo( Bucket that ) {
-            // This is lower if 'that' has a lowerBound that is greater than 'this' lower bound ...
-            if (Histogram.this.math.compare(this.lowerBound, that.lowerBound) < 0) return -1;
-            if (Histogram.this.math.compare(this.lowerBound, that.lowerBound) > 0) return 1;
-            // The lower bounds are the same, so 'this' is lower if 'that' has an upperBound that is greater than 'this' lower
-            // bound ...
-            if (Histogram.this.math.compare(this.upperBound, that.upperBound) < 0) return -1;
-            if (Histogram.this.math.compare(this.upperBound, that.upperBound) > 0) return 1;
-            return 0;
-        }
-
-        protected Class<T> getNumberClass() {
-            return Histogram.this.math.getOperandClass();
-        }
-
-        @Override
-        public boolean equals( Object obj ) {
-            if (obj != null && obj.getClass() == this.getClass()) {
-                Bucket that = (Bucket)obj;
-                if (this.getNumberClass().isAssignableFrom(that.getNumberClass())) {
-                    if (Histogram.this.math.compare(this.lowerBound, that.lowerBound) != 0) return false;
-                    if (Histogram.this.math.compare(this.upperBound, that.upperBound) != 0) return false;
-                    if (Histogram.this.math.compare(this.width, that.width) != 0) return false;
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public String toString() {
-            return "[" + this.lowerBound + "," + this.upperBound + ")";
-        }
-
-    }
-
-    public abstract class BucketingStrategy {
-
-        public List<T> getValues() {
-            return Histogram.this.values;
-        }
-
-        public abstract T getLowerBound();
-
-        public abstract T getUpperBound();
-    }
-
-    public class DefaultBucketingStrategy extends BucketingStrategy {
-
-        @Override
-        public T getLowerBound() {
-            if (getValues().isEmpty()) return Histogram.this.math.createZeroValue();
-            return getValues().get(0);
-        }
-
-        @Override
-        public T getUpperBound() {
-            if (getValues().isEmpty()) return Histogram.this.math.createZeroValue();
-            return getValues().get(getValues().size() - 1);
-        }
-    }
-
-    public class ExplicitBucketingStrategy extends BucketingStrategy {
-
-        private final T lowerBound;
-        private final T upperBound;
-
-        protected ExplicitBucketingStrategy( T lowerBound, T upperBound ) {
-            this.lowerBound = lowerBound;
-            this.upperBound = upperBound;
-        }
-
-        @Override
-        public T getLowerBound() {
-            return this.lowerBound;
-        }
-
-        @Override
-        public T getUpperBound() {
-            return this.upperBound;
-        }
-    }
-
-    public class StandardDeviationBucketingStrategy extends BucketingStrategy {
-
-        private final double median;
-        private final double standardDeviation;
-        private final int numberOfDeviationsAboveAndBelow;
-
-        protected StandardDeviationBucketingStrategy( double median, double standardDeviation, int numDeviationsAboveAndBelow ) {
-            this.median = median;
-            this.standardDeviation = Math.abs(standardDeviation);
-            this.numberOfDeviationsAboveAndBelow = Math.abs(numDeviationsAboveAndBelow);
-        }
-
-        @Override
-        public T getLowerBound() {
-            double lower = this.median - (standardDeviation * numberOfDeviationsAboveAndBelow);
-            return Histogram.this.math.create(lower);
-        }
-
-        @Override
-        public T getUpperBound() {
-            double upper = this.median + (standardDeviation * numberOfDeviationsAboveAndBelow);
-            return Histogram.this.math.create(upper);
-        }
-    }
-
-}

Copied: trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Histogram.java (from rev 706, trunk/dna-common/src/main/java/org/jboss/dna/common/stats/Histogram.java)
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Histogram.java	                        (rev 0)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Histogram.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,498 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.statistic;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.jboss.dna.common.math.MathOperations;
+import org.jboss.dna.common.util.StringUtil;
+
+public class Histogram<T extends Number> {
+
+    public static final int DEFAULT_BUCKET_COUNT = 10;
+    public static final int DEFAULT_SIGNIFICANT_FIGURES = 4;
+
+    protected final MathOperations<T> math;
+    protected final List<T> values;
+    private int bucketCount = DEFAULT_BUCKET_COUNT;
+    private int significantFigures = DEFAULT_SIGNIFICANT_FIGURES;
+    private BigDecimal bucketWidth;
+    private LinkedList<Bucket> buckets;
+    private BucketingStrategy actualValueStrategy = new DefaultBucketingStrategy();
+    private BucketingStrategy bucketingStrategy = actualValueStrategy;
+
+    public Histogram( MathOperations<T> operations, List<T> values ) {
+        this.math = operations;
+        this.values = new LinkedList<T>(values);
+        this.buckets = new LinkedList<Bucket>();
+        this.bucketWidth = null;
+        // Sort the data using natural order ...
+        Collections.sort(this.values, this.math.getComparator());
+    }
+
+    public Histogram( MathOperations<T> operations, T... values ) {
+        this(operations, Arrays.asList(values));
+    }
+
+    public BucketingStrategy getStrategy() {
+        return this.bucketingStrategy;
+    }
+
+    /**
+     * @return math
+     */
+    public MathOperations<T> getMathOperations() {
+        return this.math;
+    }
+
+    /**
+     * Set the histogram to use the standard deviation to determine the bucket sizes.
+     * @param median
+     * @param standardDeviation
+     * @param sigma
+     */
+    public void setStrategy( double median, double standardDeviation, int sigma ) {
+        this.bucketingStrategy = new StandardDeviationBucketingStrategy(median, standardDeviation, sigma);
+        this.bucketWidth = null;
+    }
+
+    /**
+     * Set the histogram to use the supplied minimum and maximum values to determine the bucket size.
+     * @param minimum
+     * @param maximum
+     */
+    public void setStrategy( T minimum, T maximum ) {
+        this.bucketingStrategy = new ExplicitBucketingStrategy(minimum, maximum);
+        this.bucketWidth = null;
+    }
+
+    /**
+     * Set the histogram to use the actual minimum and maximum values to determine the bucket sizes.
+     */
+    public void setStrategyToDefault() {
+        this.bucketingStrategy = this.actualValueStrategy;
+        this.bucketWidth = null;
+    }
+
+    public int getSignificantFigures() {
+        return significantFigures;
+    }
+
+    /**
+     * Set the number of significant figures used in the calculation of the bucket widths.
+     * @param significantFigures the number of significant figures for the bucket widths
+     * @return this histogram, useful for method-chaining
+     * @see #DEFAULT_SIGNIFICANT_FIGURES
+     */
+    public Histogram<T> setSignificantFigures( int significantFigures ) {
+        if (significantFigures != this.significantFigures) {
+            this.significantFigures = significantFigures;
+            this.bucketWidth = null;
+            this.buckets.clear();
+        }
+        return this;
+    }
+
+    /**
+     * Return the number of buckets in this histogram.
+     * @return the number of buckets.
+     */
+    public int getBucketCount() {
+        return bucketCount;
+    }
+
+    /**
+     * Set the number of buckets that this histogram will use.
+     * @param count the number of buckets
+     * @return this histogram, useful for method-chaining
+     * @see #DEFAULT_BUCKET_COUNT
+     */
+    public Histogram<T> setBucketCount( int count ) {
+        if (count != this.bucketCount) {
+            this.bucketCount = count;
+            this.bucketWidth = null;
+            this.buckets.clear();
+        }
+        return this;
+    }
+
+    /**
+     * Get the buckets in this histogram. If the histogram has not yet been computed, this method will cause it to be generated.
+     * The resulting list should not be modified.
+     * @return the histogram buckets.
+     */
+    public List<Bucket> getBuckets() {
+        compute();
+        return this.buckets;
+    }
+
+    protected void compute() {
+        // Only compute if there is not already a histogram ...
+        if (this.bucketWidth != null) return;
+
+        // Find the lower and upper bounds of the histogram using the strategy ...
+        T lowerBound = this.bucketingStrategy.getLowerBound();
+        T upperBound = this.bucketingStrategy.getUpperBound();
+
+        // Find the actual minimum and maximum values ...
+        T actualMinimum = this.actualValueStrategy.getLowerBound();
+        T actualMaximum = this.actualValueStrategy.getUpperBound();
+
+        // Create the buckets ...
+        List<T> boundaries = getBucketBoundaries(this.math, lowerBound, upperBound, actualMinimum, actualMaximum, this.bucketCount, this.significantFigures);
+        this.buckets.clear();
+        int numBuckets = boundaries.isEmpty() ? 0 : boundaries.size() - 1;
+        for (int i = 0; i != numBuckets; ++i) {
+            this.buckets.add(new Bucket(boundaries.get(i), boundaries.get(i + 1)));
+        }
+
+        // Create the histogram by adding values to each range ...
+        Iterator<Bucket> intervalIterator = this.buckets.iterator();
+        Bucket currentInterval = null;
+        for (T value : this.values) {
+            while (currentInterval == null || currentInterval.checkValue(value, !intervalIterator.hasNext()) > 0) {
+                if (!intervalIterator.hasNext()) break;
+                currentInterval = intervalIterator.next();
+            }
+            if (currentInterval != null) currentInterval.addValue(value);
+        }
+    }
+
+    /**
+     * Return the total number of values that have gone into this histogram.
+     * @return the total number of values
+     * @see Bucket#getPercentageOfValues()
+     */
+    public long getTotalNumberOfValues() {
+        return this.values.size();
+    }
+
+    protected float getMaximumPercentage() {
+        float maxPercentage = 0.0f;
+        for (Bucket bucket : this.buckets) {
+            maxPercentage = Math.max(maxPercentage, bucket.getPercentageOfValues());
+        }
+        return maxPercentage;
+    }
+
+    protected long getMaximumCount() {
+        long maxCount = 0l;
+        for (Bucket bucket : this.buckets) {
+            maxCount = Math.max(maxCount, bucket.getNumberOfValues());
+        }
+        return maxCount;
+    }
+
+    /**
+     * Generate a textual (horizontal) bar graph of this histogram.
+     * @param maxBarLength the maximum bar length, or 0 if the bar length is to represent actual counts
+     * @return the strings that make up the histogram
+     */
+    public List<String> getTextGraph( int maxBarLength ) {
+        compute();
+        if (maxBarLength < 1) maxBarLength = (int)this.getMaximumCount();
+        final float barLengthForHundredPercent = this.buckets.isEmpty() ? maxBarLength : 100.0f * maxBarLength / getMaximumPercentage();
+        final String fullLengthBar = StringUtil.createString('*', (int)barLengthForHundredPercent);
+        List<String> result = new LinkedList<String>();
+        // First calculate the labels and the max length ...
+        int maxLowerBoundLength = 0;
+        int maxUpperBoundLength = 0;
+        for (Bucket bucket : this.buckets) {
+            maxLowerBoundLength = Math.max(bucket.getLowerBound().toString().length(), maxLowerBoundLength);
+            maxUpperBoundLength = Math.max(bucket.getUpperBound().toString().length(), maxUpperBoundLength);
+        }
+
+        // Create the header ...
+        int rangeWidth = 1 + maxLowerBoundLength + 3 + maxUpperBoundLength + 1;
+        int barWidth = maxBarLength + 20;
+        result.add(StringUtil.justifyLeft("Ranges", rangeWidth, ' ') + " Distribution");
+        result.add(StringUtil.createString('-', rangeWidth) + ' ' + StringUtil.createString('-', barWidth));
+        for (Bucket bucket : this.buckets) {
+            float percent = bucket.getPercentageOfValues();
+            long number = bucket.getNumberOfValues();
+            StringBuilder sb = new StringBuilder();
+            sb.append("[");
+            sb.append(StringUtil.justifyLeft(bucket.getLowerBound().toString(), maxLowerBoundLength, ' '));
+            sb.append(" - ");
+            sb.append(StringUtil.justifyLeft(bucket.getUpperBound().toString(), maxUpperBoundLength, ' '));
+            sb.append("] ");
+            int barLength = Math.max((int)(barLengthForHundredPercent * percent / 100.0f), 0);
+            if (barLength == 0 && number != 0) barLength = 1; // make sure there is a bar for all non-zero buckets
+            sb.append(fullLengthBar.substring(0, barLength));
+            if (number != 0) {
+                sb.append(" ");
+                sb.append(number);
+                sb.append(" (");
+                sb.append(new DecimalFormat("###.#").format(percent));
+                sb.append("%)");
+            }
+            result.add(sb.toString());
+        }
+        return result;
+    }
+
+    protected static <T> List<T> getBucketBoundaries( MathOperations<T> math, T lowerBound, T upperBound, T actualMinimum, T actualMaximum, int bucketCount, int bucketWidthSigFigs ) {
+        lowerBound = math.compare(lowerBound, actualMinimum) < 0 ? actualMinimum : lowerBound;
+        upperBound = math.compare(actualMaximum, upperBound) < 0 ? actualMaximum : upperBound;
+        if (math.compare(lowerBound, upperBound) == 0) {
+            List<T> boundaries = new ArrayList<T>();
+            boundaries.add(lowerBound);
+            boundaries.add(upperBound);
+            return boundaries;
+        }
+        final boolean extraLowerBucketNeeded = math.compare(lowerBound, actualMinimum) > 0;
+        final boolean extraUpperBucketNeeded = math.compare(actualMaximum, upperBound) > 0;
+        if (extraLowerBucketNeeded) --bucketCount;
+        if (extraUpperBucketNeeded) --bucketCount;
+
+        // Compute the delta between the lower and upper bound ...
+        T totalWidth = math.subtract(upperBound, lowerBound);
+        int totalWidthScale = math.getExponentInScientificNotation(totalWidth);
+
+        // Modify the lower bound by rounding down to the next lower meaningful value,
+        // using the scale of the totalWidth to determine how to round down.
+        T roundedLowerBound = math.roundDown(lowerBound, -totalWidthScale);
+        T roundedUpperBound = math.roundUp(upperBound, -totalWidthScale);
+
+        // Create the ranges ...
+        double finalLowerBound = math.doubleValue(roundedLowerBound);
+        double finalUpperBound = math.doubleValue(roundedUpperBound);
+        double finalBucketCount = bucketCount;
+        double bucketWidth = (finalUpperBound - finalLowerBound) / finalBucketCount;
+
+        // DoubleOperations doubleOps = new DoubleOperations();
+        // bucketWidth = doubleOps.keepSignificantFigures(bucketWidth,bucketWidthSigFigs);
+
+        List<T> boundaries = new ArrayList<T>();
+        if (bucketWidth > 0.0d) {
+            if (extraLowerBucketNeeded) boundaries.add(actualMinimum);
+            double nextBoundary = finalLowerBound;
+            for (int i = 0; i != bucketCount; ++i) {
+                boundaries.add(math.create(nextBoundary));
+                nextBoundary = nextBoundary + bucketWidth;
+                // nextBoundary = doubleOps.roundUp(nextBoundary + bucketWidth, bucketWidthSigFigs );
+            }
+            boundaries.add(roundedUpperBound);
+            if (extraUpperBucketNeeded) boundaries.add(actualMaximum);
+        }
+        return boundaries;
+    }
+
+    /**
+     * Represents a bucket in a histogram.
+     */
+    public class Bucket implements Comparable<Bucket> {
+
+        private final T lowerBound;
+        private final T upperBound;
+        private final T width;
+        private long numValues;
+
+        protected Bucket( T lowerBound, T upperBound ) {
+            this.lowerBound = lowerBound;
+            this.upperBound = upperBound;
+            this.width = Histogram.this.math.subtract(upperBound, lowerBound);
+        }
+
+        /**
+         * Get the lower bound of this bucket.
+         * @return the lower bound
+         */
+        public T getLowerBound() {
+            return lowerBound;
+        }
+
+        /**
+         * Get the upper bound of this bucket.
+         * @return the upper bound
+         */
+        public T getUpperBound() {
+            return upperBound;
+        }
+
+        /**
+         * Get the width of this bucket.
+         * @return the width
+         */
+        public T getWidth() {
+            return this.width;
+        }
+
+        /**
+         * Return the percentage of values in the histogram that appear in this bucket.
+         * @return the percentage of all values in the histogram that appear in this bucket.
+         */
+        public float getPercentageOfValues() {
+            float total = Histogram.this.getTotalNumberOfValues();
+            if (total == 0.0f) return 0.0f;
+            float numValuesFloat = this.numValues;
+            return 100.0f * numValuesFloat / total;
+        }
+
+        /**
+         * Add a value to this bucket
+         * @param value
+         */
+        protected void addValue( T value ) {
+            ++this.numValues;
+        }
+
+        /**
+         * Get the number of values in this bucket.
+         * @return the number of values
+         */
+        public long getNumberOfValues() {
+            return this.numValues;
+        }
+
+        /**
+         * Check whether the value fits in this bucket.
+         * @param value the value to check
+         * @param isLast
+         * @return 0 if the value fits in this bucket, -1 if the value fits in a prior bucket, or 1 if the value fits in a later
+         * bucket
+         */
+        public int checkValue( T value, boolean isLast ) {
+            if (Histogram.this.math.compare(this.lowerBound, value) > 0) return -1;
+            if (isLast) {
+                if (Histogram.this.math.compare(value, this.upperBound) > 0) return 1;
+            } else {
+                if (Histogram.this.math.compare(value, this.upperBound) >= 0) return 1;
+            }
+            return 0;
+        }
+
+        public int compareTo( Bucket that ) {
+            // This is lower if 'that' has a lowerBound that is greater than 'this' lower bound ...
+            if (Histogram.this.math.compare(this.lowerBound, that.lowerBound) < 0) return -1;
+            if (Histogram.this.math.compare(this.lowerBound, that.lowerBound) > 0) return 1;
+            // The lower bounds are the same, so 'this' is lower if 'that' has an upperBound that is greater than 'this' lower
+            // bound ...
+            if (Histogram.this.math.compare(this.upperBound, that.upperBound) < 0) return -1;
+            if (Histogram.this.math.compare(this.upperBound, that.upperBound) > 0) return 1;
+            return 0;
+        }
+
+        protected Class<T> getNumberClass() {
+            return Histogram.this.math.getOperandClass();
+        }
+
+        @Override
+        public boolean equals( Object obj ) {
+            if (obj != null && obj.getClass() == this.getClass()) {
+                Bucket that = (Bucket)obj;
+                if (this.getNumberClass().isAssignableFrom(that.getNumberClass())) {
+                    if (Histogram.this.math.compare(this.lowerBound, that.lowerBound) != 0) return false;
+                    if (Histogram.this.math.compare(this.upperBound, that.upperBound) != 0) return false;
+                    if (Histogram.this.math.compare(this.width, that.width) != 0) return false;
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "[" + this.lowerBound + "," + this.upperBound + ")";
+        }
+
+    }
+
+    public abstract class BucketingStrategy {
+
+        public List<T> getValues() {
+            return Histogram.this.values;
+        }
+
+        public abstract T getLowerBound();
+
+        public abstract T getUpperBound();
+    }
+
+    public class DefaultBucketingStrategy extends BucketingStrategy {
+
+        @Override
+        public T getLowerBound() {
+            if (getValues().isEmpty()) return Histogram.this.math.createZeroValue();
+            return getValues().get(0);
+        }
+
+        @Override
+        public T getUpperBound() {
+            if (getValues().isEmpty()) return Histogram.this.math.createZeroValue();
+            return getValues().get(getValues().size() - 1);
+        }
+    }
+
+    public class ExplicitBucketingStrategy extends BucketingStrategy {
+
+        private final T lowerBound;
+        private final T upperBound;
+
+        protected ExplicitBucketingStrategy( T lowerBound, T upperBound ) {
+            this.lowerBound = lowerBound;
+            this.upperBound = upperBound;
+        }
+
+        @Override
+        public T getLowerBound() {
+            return this.lowerBound;
+        }
+
+        @Override
+        public T getUpperBound() {
+            return this.upperBound;
+        }
+    }
+
+    public class StandardDeviationBucketingStrategy extends BucketingStrategy {
+
+        private final double median;
+        private final double standardDeviation;
+        private final int numberOfDeviationsAboveAndBelow;
+
+        protected StandardDeviationBucketingStrategy( double median, double standardDeviation, int numDeviationsAboveAndBelow ) {
+            this.median = median;
+            this.standardDeviation = Math.abs(standardDeviation);
+            this.numberOfDeviationsAboveAndBelow = Math.abs(numDeviationsAboveAndBelow);
+        }
+
+        @Override
+        public T getLowerBound() {
+            double lower = this.median - (standardDeviation * numberOfDeviationsAboveAndBelow);
+            return Histogram.this.math.create(lower);
+        }
+
+        @Override
+        public T getUpperBound() {
+            double upper = this.median + (standardDeviation * numberOfDeviationsAboveAndBelow);
+            return Histogram.this.math.create(upper);
+        }
+    }
+
+}

Deleted: trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/SimpleStatistics.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/stats/SimpleStatistics.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/SimpleStatistics.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,233 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.common.stats;
-
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.math.MathOperations;
-import org.jboss.dna.common.text.Inflector;
-import org.jboss.dna.common.util.StringUtil;
-
-/**
- * Encapsulation of the statistics for a series of values to which new values are frequently added. The statistics include the
- * {@link #getMinimum() minimum}, {@link #getMaximum() maximum}, {@link #getTotal() total (aggregate sum)}, and
- * {@link #getMean() mean (average)}. See {@link DetailedStatistics} for a subclass that also calculates the
- * {@link DetailedStatistics#getMedian() median}, {@link DetailedStatistics#getStandardDeviation() standard deviation} and the
- * {@link DetailedStatistics#getHistogram() histogram} of the values.
- * <p>
- * This class is threadsafe.
- * </p>
- * @param <T> the number type used in these statistics
- * @author Randall Hauch
- */
- at ThreadSafe
-public class SimpleStatistics<T extends Number> {
-
-    protected final MathOperations<T> math;
-    private int count = 0;
-    private T total;
-    private T maximum;
-    private T minimum;
-    private T mean;
-    private Double meanValue;
-    private final ReadWriteLock lock = new ReentrantReadWriteLock();
-
-    public SimpleStatistics( MathOperations<T> operations ) {
-        this.math = operations;
-        this.total = this.math.createZeroValue();
-        this.maximum = this.math.createZeroValue();
-        this.minimum = null;
-        this.mean = this.math.createZeroValue();
-        this.meanValue = 0.0d;
-    }
-
-    /**
-     * Add a new value to these statistics.
-     * @param value the new value
-     */
-    public void add( T value ) {
-        Lock lock = this.lock.writeLock();
-        try {
-            lock.lock();
-            doAddValue(value);
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * A method that can be overridden by subclasses when {@link #add(Number) add} is called. This method is called within the
-     * write lock, and does real work. Therefore, subclasses should call this method when they overwrite it.
-     * @param value the value already added
-     */
-    protected void doAddValue( T value ) {
-        if (value == null) return;
-        // Modify the basic statistics ...
-        ++this.count;
-        this.total = math.add(this.total, value);
-        this.maximum = this.math.maximum(this.maximum, value);
-        this.minimum = this.math.minimum(this.minimum, value);
-        // Calculate the mean and standard deviation ...
-        int count = getCount();
-        if (count == 1) {
-            // M(1) = x(1)
-            this.meanValue = value.doubleValue();
-            this.mean = value;
-        } else {
-            double dValue = value.doubleValue();
-            double dCount = count;
-            // M(k) = M(k-1) + ( x(k) - M(k-1) ) / k
-            this.meanValue = this.meanValue + ((dValue - this.meanValue) / dCount);
-            this.mean = this.math.create(this.meanValue);
-        }
-    }
-
-    /**
-     * Get the aggregate sum of the values in the series.
-     * @return the total of the values, or 0.0 if the {@link #getCount() count} is 0
-     */
-    public T getTotal() {
-        Lock lock = this.lock.readLock();
-        lock.lock();
-        try {
-            return this.total;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Get the maximum value in the series.
-     * @return the maximum value, or 0.0 if the {@link #getCount() count} is 0
-     */
-    public T getMaximum() {
-        Lock lock = this.lock.readLock();
-        lock.lock();
-        try {
-            return this.maximum;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Get the minimum value in the series.
-     * @return the minimum value, or 0.0 if the {@link #getCount() count} is 0
-     */
-    public T getMinimum() {
-        Lock lock = this.lock.readLock();
-        lock.lock();
-        try {
-            return this.minimum != null ? this.minimum : (T)this.math.createZeroValue();
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Get the number of values that have been measured.
-     * @return the count
-     */
-    public int getCount() {
-        Lock lock = this.lock.readLock();
-        lock.lock();
-        try {
-            return this.count;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Return the approximate mean (average) value represented as an instance of the operand type. Note that this may truncate if
-     * the operand type is not able to have the required precision. For the accurate mean, see {@link #getMeanValue() }.
-     * @return the mean (average), or 0.0 if the {@link #getCount() count} is 0
-     */
-    public T getMean() {
-        Lock lock = this.lock.readLock();
-        lock.lock();
-        try {
-            return this.mean;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Return the mean (average) value.
-     * @return the mean (average), or 0.0 if the {@link #getCount() count} is 0
-     * @see #getMean()
-     */
-    public double getMeanValue() {
-        Lock lock = this.lock.readLock();
-        lock.lock();
-        try {
-            return this.meanValue;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Reset the statistics in this object, and clear out any stored information.
-     */
-    public void reset() {
-        Lock lock = this.lock.writeLock();
-        lock.lock();
-        try {
-            doReset();
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    public MathOperations<T> getMathOperations() {
-        return math;
-    }
-
-    protected ReadWriteLock getLock() {
-        return this.lock;
-    }
-
-    /**
-     * Method that can be overridden by subclasses when {@link #reset()} is called. This method is called while the object is
-     * locked for write and does work; therefore, the subclass should call this method.
-     */
-    protected void doReset() {
-        this.total = this.math.createZeroValue();
-        this.maximum = this.math.createZeroValue();
-        this.minimum = null;
-        this.mean = this.math.createZeroValue();
-        this.meanValue = 0.0d;
-        this.count = 0;
-    }
-
-    @Override
-    public String toString() {
-        int count = this.getCount();
-        String samples = Inflector.getInstance().pluralize("sample", count);
-        return StringUtil.createString("{0} {1}: min={2}; avg={3}; max={4}", count, samples, this.minimum, this.mean, this.maximum);
-    }
-
-}

Copied: trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/SimpleStatistics.java (from rev 706, trunk/dna-common/src/main/java/org/jboss/dna/common/stats/SimpleStatistics.java)
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/SimpleStatistics.java	                        (rev 0)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/SimpleStatistics.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,233 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.statistic;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.math.MathOperations;
+import org.jboss.dna.common.text.Inflector;
+import org.jboss.dna.common.util.StringUtil;
+
+/**
+ * Encapsulation of the statistics for a series of values to which new values are frequently added. The statistics include the
+ * {@link #getMinimum() minimum}, {@link #getMaximum() maximum}, {@link #getTotal() total (aggregate sum)}, and
+ * {@link #getMean() mean (average)}. See {@link DetailedStatistics} for a subclass that also calculates the
+ * {@link DetailedStatistics#getMedian() median}, {@link DetailedStatistics#getStandardDeviation() standard deviation} and the
+ * {@link DetailedStatistics#getHistogram() histogram} of the values.
+ * <p>
+ * This class is threadsafe.
+ * </p>
+ * @param <T> the number type used in these statistics
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public class SimpleStatistics<T extends Number> {
+
+    protected final MathOperations<T> math;
+    private int count = 0;
+    private T total;
+    private T maximum;
+    private T minimum;
+    private T mean;
+    private Double meanValue;
+    private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+    public SimpleStatistics( MathOperations<T> operations ) {
+        this.math = operations;
+        this.total = this.math.createZeroValue();
+        this.maximum = this.math.createZeroValue();
+        this.minimum = null;
+        this.mean = this.math.createZeroValue();
+        this.meanValue = 0.0d;
+    }
+
+    /**
+     * Add a new value to these statistics.
+     * @param value the new value
+     */
+    public void add( T value ) {
+        Lock lock = this.lock.writeLock();
+        try {
+            lock.lock();
+            doAddValue(value);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * A method that can be overridden by subclasses when {@link #add(Number) add} is called. This method is called within the
+     * write lock, and does real work. Therefore, subclasses should call this method when they overwrite it.
+     * @param value the value already added
+     */
+    protected void doAddValue( T value ) {
+        if (value == null) return;
+        // Modify the basic statistics ...
+        ++this.count;
+        this.total = math.add(this.total, value);
+        this.maximum = this.math.maximum(this.maximum, value);
+        this.minimum = this.math.minimum(this.minimum, value);
+        // Calculate the mean and standard deviation ...
+        int count = getCount();
+        if (count == 1) {
+            // M(1) = x(1)
+            this.meanValue = value.doubleValue();
+            this.mean = value;
+        } else {
+            double dValue = value.doubleValue();
+            double dCount = count;
+            // M(k) = M(k-1) + ( x(k) - M(k-1) ) / k
+            this.meanValue = this.meanValue + ((dValue - this.meanValue) / dCount);
+            this.mean = this.math.create(this.meanValue);
+        }
+    }
+
+    /**
+     * Get the aggregate sum of the values in the series.
+     * @return the total of the values, or 0.0 if the {@link #getCount() count} is 0
+     */
+    public T getTotal() {
+        Lock lock = this.lock.readLock();
+        lock.lock();
+        try {
+            return this.total;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Get the maximum value in the series.
+     * @return the maximum value, or 0.0 if the {@link #getCount() count} is 0
+     */
+    public T getMaximum() {
+        Lock lock = this.lock.readLock();
+        lock.lock();
+        try {
+            return this.maximum;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Get the minimum value in the series.
+     * @return the minimum value, or 0.0 if the {@link #getCount() count} is 0
+     */
+    public T getMinimum() {
+        Lock lock = this.lock.readLock();
+        lock.lock();
+        try {
+            return this.minimum != null ? this.minimum : (T)this.math.createZeroValue();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Get the number of values that have been measured.
+     * @return the count
+     */
+    public int getCount() {
+        Lock lock = this.lock.readLock();
+        lock.lock();
+        try {
+            return this.count;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Return the approximate mean (average) value represented as an instance of the operand type. Note that this may truncate if
+     * the operand type is not able to have the required precision. For the accurate mean, see {@link #getMeanValue() }.
+     * @return the mean (average), or 0.0 if the {@link #getCount() count} is 0
+     */
+    public T getMean() {
+        Lock lock = this.lock.readLock();
+        lock.lock();
+        try {
+            return this.mean;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Return the mean (average) value.
+     * @return the mean (average), or 0.0 if the {@link #getCount() count} is 0
+     * @see #getMean()
+     */
+    public double getMeanValue() {
+        Lock lock = this.lock.readLock();
+        lock.lock();
+        try {
+            return this.meanValue;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Reset the statistics in this object, and clear out any stored information.
+     */
+    public void reset() {
+        Lock lock = this.lock.writeLock();
+        lock.lock();
+        try {
+            doReset();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public MathOperations<T> getMathOperations() {
+        return math;
+    }
+
+    protected ReadWriteLock getLock() {
+        return this.lock;
+    }
+
+    /**
+     * Method that can be overridden by subclasses when {@link #reset()} is called. This method is called while the object is
+     * locked for write and does work; therefore, the subclass should call this method.
+     */
+    protected void doReset() {
+        this.total = this.math.createZeroValue();
+        this.maximum = this.math.createZeroValue();
+        this.minimum = null;
+        this.mean = this.math.createZeroValue();
+        this.meanValue = 0.0d;
+        this.count = 0;
+    }
+
+    @Override
+    public String toString() {
+        int count = this.getCount();
+        String samples = Inflector.getInstance().pluralize("sample", count);
+        return StringUtil.createString("{0} {1}: min={2}; avg={3}; max={4}", count, samples, this.minimum, this.mean, this.maximum);
+    }
+
+}

Deleted: trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Stopwatch.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/stats/Stopwatch.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Stopwatch.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,222 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.common.stats;
-
-import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.common.math.Duration;
-import org.jboss.dna.common.math.DurationOperations;
-
-/**
- * Provides a mechanism to measure time in the same was as a physical stopwatch.
- * @author Randall Hauch
- */
- at NotThreadSafe
-public class Stopwatch implements Comparable<Stopwatch> {
-
-    private long lastStarted;
-    private final SimpleStatistics<Duration> stats;
-    private final DetailedStatistics<Duration> detailedStats;
-    private String description;
-
-    public Stopwatch() {
-        this(true);
-    }
-
-    public Stopwatch( boolean detailedStats ) {
-        this(detailedStats, null);
-    }
-
-    public Stopwatch( boolean detailedStats, String description ) {
-        this.description = description != null ? description : "";
-        this.detailedStats = detailedStats ? new DetailedStatistics<Duration>(new DurationOperations()) : null;
-        this.stats = detailedStats ? this.detailedStats : new SimpleStatistics<Duration>(new DurationOperations());
-        reset();
-    }
-
-    public String getDescription() {
-        return this.description;
-    }
-
-    /**
-     * Start the stopwatch and begin recording the statistics a new run. This method does nothing if the stopwatch is already
-     * {@link #isRunning() running}
-     * @see #isRunning()
-     */
-    public void start() {
-        if (!this.isRunning()) {
-            this.lastStarted = System.nanoTime();
-        }
-    }
-
-    /**
-     * Stop the stopwatch and record the statistics for the latest run. This method does nothing if the stopwatch is not currently
-     * {@link #isRunning() running}
-     * @see #isRunning()
-     */
-    public void stop() {
-        if (this.isRunning()) {
-            long duration = System.nanoTime() - this.lastStarted;
-            this.lastStarted = 0l;
-            this.stats.add(new Duration(duration));
-        }
-    }
-
-    /**
-     * Return the number of runs (complete starts and stops) this stopwatch has undergone.
-     * @return the number of runs.
-     * @see #isRunning()
-     */
-    public int getCount() {
-        return this.stats.getCount();
-    }
-
-    /**
-     * Return whether this stopwatch is currently running.
-     * @return true if running, or false if not
-     */
-    public boolean isRunning() {
-        return this.lastStarted != 0;
-    }
-
-    /**
-     * Get the total duration that this stopwatch has recorded.
-     * @return the total duration, or an empty duration if this stopwatch has not been used since creation or being
-     * {@link #reset() reset}
-     */
-    public Duration getTotalDuration() {
-        return this.stats.getTotal();
-    }
-
-    /**
-     * Get the average duration that this stopwatch has recorded.
-     * @return the average duration, or an empty duration if this stopwatch has not been used since creation or being
-     * {@link #reset() reset}
-     */
-    public Duration getAverageDuration() {
-        return this.stats.getMean();
-    }
-
-    /**
-     * Get the median duration that this stopwatch has recorded.
-     * @return the median duration, or an empty duration if this stopwatch has not been used since creation or being
-     * {@link #reset() reset}
-     */
-    public Duration getMedianDuration() {
-        return this.detailedStats != null ? this.detailedStats.getMedian() : new Duration(0l);
-    }
-
-    /**
-     * Get the minimum duration that this stopwatch has recorded.
-     * @return the total minimum, or an empty duration if this stopwatch has not been used since creation or being
-     * {@link #reset() reset}
-     */
-    public Duration getMinimumDuration() {
-        return this.stats.getMinimum();
-    }
-
-    /**
-     * Get the maximum duration that this stopwatch has recorded.
-     * @return the maximum duration, or an empty duration if this stopwatch has not been used since creation or being
-     * {@link #reset() reset}
-     */
-    public Duration getMaximumDuration() {
-        return this.stats.getMaximum();
-    }
-
-    /**
-     * Return this stopwatch's simple statistics.
-     * @return the statistics
-     * @see #getDetailedStatistics()
-     */
-    public SimpleStatistics<Duration> getSimpleStatistics() {
-        return this.stats;
-    }
-
-    /**
-     * Return this stopwatch's detailed statistics, if they are being kept.
-     * @return the statistics
-     * @see #getSimpleStatistics()
-     */
-    public DetailedStatistics<Duration> getDetailedStatistics() {
-        return this.detailedStats;
-    }
-
-    /**
-     * Return true if detailed statistics are being kept.
-     * @return true if {@link #getDetailedStatistics() detailed statistics} are being kept, or false if only
-     * {@link #getSimpleStatistics() simple statistics} are being kept.
-     */
-    public boolean isDetailedStatistics() {
-        return this.detailedStats != null;
-    }
-
-    /**
-     * Return the histogram of this stopwatch's individual runs. Two different kinds of histograms can be created. The first kind
-     * is a histogram where all of the buckets are distributed normally and all have the same width. In this case, the 'numSigmas'
-     * should be set to 0.
-     * <p>
-     * <i>Note: if only {@link #getSimpleStatistics() simple statistics} are being kept, the resulting histogram is always empty.
-     * <p>
-     * The second kind of histogram is more useful when most of the data that is clustered near one value. This histogram is
-     * focused around the values that are up to 'numSigmas' above and below the {@link #getMedianDuration() median}, and all
-     * values outside of this range are placed in the first and last bucket.
-     * </p>
-     * @param numSigmas the number of standard deviations from the {@link #getMedianDuration() median}, or 0 if the buckets of
-     * the histogram should be evenly distributed
-     * @return the histogram
-     */
-    public Histogram<Duration> getHistogram( int numSigmas ) {
-        return this.detailedStats != null ? this.detailedStats.getHistogram(numSigmas) : new Histogram<Duration>(this.stats.getMathOperations());
-    }
-
-    /**
-     * Reset this stopwatch and clear all statistics.
-     */
-    public void reset() {
-        this.lastStarted = 0l;
-        this.stats.reset();
-    }
-
-    public int compareTo( Stopwatch that ) {
-        return this.getTotalDuration().compareTo(that.getTotalDuration());
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(this.getTotalDuration());
-        if (this.stats.getCount() > 1) {
-            sb.append(" (");
-            sb.append(this.stats.getCount()).append(" samples, avg=");
-            sb.append(this.getAverageDuration());
-            sb.append("; median=");
-            sb.append(this.getMedianDuration());
-            sb.append("; min=");
-            sb.append(this.getMinimumDuration());
-            sb.append("; max=");
-            sb.append(this.getMaximumDuration());
-            sb.append(")");
-        }
-        return sb.toString();
-    }
-
-}

Copied: trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Stopwatch.java (from rev 706, trunk/dna-common/src/main/java/org/jboss/dna/common/stats/Stopwatch.java)
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Stopwatch.java	                        (rev 0)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/statistic/Stopwatch.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,222 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.statistic;
+
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.math.Duration;
+import org.jboss.dna.common.math.DurationOperations;
+
+/**
+ * Provides a mechanism to measure time in the same was as a physical stopwatch.
+ * @author Randall Hauch
+ */
+ at NotThreadSafe
+public class Stopwatch implements Comparable<Stopwatch> {
+
+    private long lastStarted;
+    private final SimpleStatistics<Duration> stats;
+    private final DetailedStatistics<Duration> detailedStats;
+    private String description;
+
+    public Stopwatch() {
+        this(true);
+    }
+
+    public Stopwatch( boolean detailedStats ) {
+        this(detailedStats, null);
+    }
+
+    public Stopwatch( boolean detailedStats, String description ) {
+        this.description = description != null ? description : "";
+        this.detailedStats = detailedStats ? new DetailedStatistics<Duration>(new DurationOperations()) : null;
+        this.stats = detailedStats ? this.detailedStats : new SimpleStatistics<Duration>(new DurationOperations());
+        reset();
+    }
+
+    public String getDescription() {
+        return this.description;
+    }
+
+    /**
+     * Start the stopwatch and begin recording the statistics a new run. This method does nothing if the stopwatch is already
+     * {@link #isRunning() running}
+     * @see #isRunning()
+     */
+    public void start() {
+        if (!this.isRunning()) {
+            this.lastStarted = System.nanoTime();
+        }
+    }
+
+    /**
+     * Stop the stopwatch and record the statistics for the latest run. This method does nothing if the stopwatch is not currently
+     * {@link #isRunning() running}
+     * @see #isRunning()
+     */
+    public void stop() {
+        if (this.isRunning()) {
+            long duration = System.nanoTime() - this.lastStarted;
+            this.lastStarted = 0l;
+            this.stats.add(new Duration(duration));
+        }
+    }
+
+    /**
+     * Return the number of runs (complete starts and stops) this stopwatch has undergone.
+     * @return the number of runs.
+     * @see #isRunning()
+     */
+    public int getCount() {
+        return this.stats.getCount();
+    }
+
+    /**
+     * Return whether this stopwatch is currently running.
+     * @return true if running, or false if not
+     */
+    public boolean isRunning() {
+        return this.lastStarted != 0;
+    }
+
+    /**
+     * Get the total duration that this stopwatch has recorded.
+     * @return the total duration, or an empty duration if this stopwatch has not been used since creation or being
+     * {@link #reset() reset}
+     */
+    public Duration getTotalDuration() {
+        return this.stats.getTotal();
+    }
+
+    /**
+     * Get the average duration that this stopwatch has recorded.
+     * @return the average duration, or an empty duration if this stopwatch has not been used since creation or being
+     * {@link #reset() reset}
+     */
+    public Duration getAverageDuration() {
+        return this.stats.getMean();
+    }
+
+    /**
+     * Get the median duration that this stopwatch has recorded.
+     * @return the median duration, or an empty duration if this stopwatch has not been used since creation or being
+     * {@link #reset() reset}
+     */
+    public Duration getMedianDuration() {
+        return this.detailedStats != null ? this.detailedStats.getMedian() : new Duration(0l);
+    }
+
+    /**
+     * Get the minimum duration that this stopwatch has recorded.
+     * @return the total minimum, or an empty duration if this stopwatch has not been used since creation or being
+     * {@link #reset() reset}
+     */
+    public Duration getMinimumDuration() {
+        return this.stats.getMinimum();
+    }
+
+    /**
+     * Get the maximum duration that this stopwatch has recorded.
+     * @return the maximum duration, or an empty duration if this stopwatch has not been used since creation or being
+     * {@link #reset() reset}
+     */
+    public Duration getMaximumDuration() {
+        return this.stats.getMaximum();
+    }
+
+    /**
+     * Return this stopwatch's simple statistics.
+     * @return the statistics
+     * @see #getDetailedStatistics()
+     */
+    public SimpleStatistics<Duration> getSimpleStatistics() {
+        return this.stats;
+    }
+
+    /**
+     * Return this stopwatch's detailed statistics, if they are being kept.
+     * @return the statistics
+     * @see #getSimpleStatistics()
+     */
+    public DetailedStatistics<Duration> getDetailedStatistics() {
+        return this.detailedStats;
+    }
+
+    /**
+     * Return true if detailed statistics are being kept.
+     * @return true if {@link #getDetailedStatistics() detailed statistics} are being kept, or false if only
+     * {@link #getSimpleStatistics() simple statistics} are being kept.
+     */
+    public boolean isDetailedStatistics() {
+        return this.detailedStats != null;
+    }
+
+    /**
+     * Return the histogram of this stopwatch's individual runs. Two different kinds of histograms can be created. The first kind
+     * is a histogram where all of the buckets are distributed normally and all have the same width. In this case, the 'numSigmas'
+     * should be set to 0.
+     * <p>
+     * <i>Note: if only {@link #getSimpleStatistics() simple statistics} are being kept, the resulting histogram is always empty.
+     * <p>
+     * The second kind of histogram is more useful when most of the data that is clustered near one value. This histogram is
+     * focused around the values that are up to 'numSigmas' above and below the {@link #getMedianDuration() median}, and all
+     * values outside of this range are placed in the first and last bucket.
+     * </p>
+     * @param numSigmas the number of standard deviations from the {@link #getMedianDuration() median}, or 0 if the buckets of
+     * the histogram should be evenly distributed
+     * @return the histogram
+     */
+    public Histogram<Duration> getHistogram( int numSigmas ) {
+        return this.detailedStats != null ? this.detailedStats.getHistogram(numSigmas) : new Histogram<Duration>(this.stats.getMathOperations());
+    }
+
+    /**
+     * Reset this stopwatch and clear all statistics.
+     */
+    public void reset() {
+        this.lastStarted = 0l;
+        this.stats.reset();
+    }
+
+    public int compareTo( Stopwatch that ) {
+        return this.getTotalDuration().compareTo(that.getTotalDuration());
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(this.getTotalDuration());
+        if (this.stats.getCount() > 1) {
+            sb.append(" (");
+            sb.append(this.stats.getCount()).append(" samples, avg=");
+            sb.append(this.getAverageDuration());
+            sb.append("; median=");
+            sb.append(this.getMedianDuration());
+            sb.append("; min=");
+            sb.append(this.getMinimumDuration());
+            sb.append("; max=");
+            sb.append(this.getMaximumDuration());
+            sb.append(")");
+        }
+        return sb.toString();
+    }
+
+}

Copied: trunk/dna-common/src/test/java/org/jboss/dna/common/statistic (from rev 705, trunk/dna-common/src/test/java/org/jboss/dna/common/stats)

Deleted: trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/DetailedStatisticsTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/stats/DetailedStatisticsTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/DetailedStatisticsTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,204 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.common.stats;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import org.jboss.dna.common.math.FloatOperations;
-import org.jboss.dna.common.math.IntegerOperations;
-import org.jboss.dna.common.util.Logger;
-import org.junit.Test;
-
-public class DetailedStatisticsTest {
-
-    private DetailedStatistics<Integer> intStats = new DetailedStatistics<Integer>(new IntegerOperations());
-    private DetailedStatistics<Float> floatStats = new DetailedStatistics<Float>(new FloatOperations());
-    private Logger logger = Logger.getLogger(DetailedStatisticsTest.class);
-
-    @Test
-    public void shouldHaveValidValuesWhenUnused() {
-        assertThat(this.intStats.getCount(), is(0));
-        assertThat(this.intStats.getMinimum(), is(0));
-        assertThat(this.intStats.getMaximum(), is(0));
-        assertThat(this.intStats.getMean(), is(0));
-        assertThat(this.intStats.getMedian(), is(0));
-        assertThat(this.intStats.getStandardDeviation(), is(0.0d));
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesWhenUnusedOnce() {
-        this.intStats.add(10);
-        assertThat(this.intStats.getCount(), is(1));
-        assertThat(this.intStats.getMinimum(), is(10));
-        assertThat(this.intStats.getMaximum(), is(10));
-        assertThat(this.intStats.getMean(), is(10));
-        assertThat(this.intStats.getMedian(), is(10));
-        assertThat(this.intStats.getStandardDeviation(), is(0.0d));
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesWhenUsedAnOddNumberOfTimesButMoreThanOnce() {
-        this.intStats.add(1);
-        this.intStats.add(2);
-        this.intStats.add(3);
-        assertThat(this.intStats.getCount(), is(3));
-        assertThat(this.intStats.getMinimum(), is(1));
-        assertThat(this.intStats.getMaximum(), is(3));
-        assertThat(this.intStats.getMean(), is(2));
-        assertThat(this.intStats.getMeanValue(), is(2.0d));
-        assertThat(this.intStats.getMedian(), is(2));
-        assertThat(this.intStats.getMedianValue(), is(2.0d));
-        assertEquals(0.816496d, this.intStats.getStandardDeviation(), 0.001d);
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesWhenUsedAnEvenNumberOfTimes() {
-        this.intStats.add(2);
-        this.intStats.add(4);
-        this.intStats.add(1);
-        this.intStats.add(3);
-        assertThat(this.intStats.getCount(), is(4));
-        assertThat(this.intStats.getMinimum(), is(1));
-        assertThat(this.intStats.getMaximum(), is(4));
-        assertThat(this.intStats.getMeanValue(), is(2.5d));
-        assertThat(this.intStats.getMedianValue(), is(2.5d));
-        assertEquals(1.0d, this.intStats.getStandardDeviation(), 0.2d);
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesWhenAllValuesAreTheSame() {
-        this.intStats.add(2);
-        this.intStats.add(2);
-        this.intStats.add(2);
-        this.intStats.add(2);
-        assertThat(this.intStats.getCount(), is(4));
-        assertThat(this.intStats.getMinimum(), is(2));
-        assertThat(this.intStats.getMaximum(), is(2));
-        assertThat(this.intStats.getMean(), is(2));
-        assertThat(this.intStats.getMeanValue(), is(2.0d));
-        assertThat(this.intStats.getMedian(), is(2));
-        assertThat(this.intStats.getMedianValue(), is(2.0d));
-        assertThat(this.intStats.getStandardDeviation(), is(0.0d));
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesForComplexIntegerData() {
-        this.intStats.add(19);
-        this.intStats.add(10);
-        this.intStats.add(20);
-        this.intStats.add(7);
-        this.intStats.add(73);
-        this.intStats.add(72);
-        this.intStats.add(42);
-        this.intStats.add(9);
-        this.intStats.add(47);
-        this.intStats.add(24);
-        System.out.println(this.intStats);
-        assertThat(this.intStats.getCount(), is(10));
-        assertThat(this.intStats.getMinimum(), is(7));
-        assertThat(this.intStats.getMaximum(), is(73));
-        assertThat(this.intStats.getMeanValue(), is(32.3d));
-        assertEquals(32.3d, this.intStats.getMeanValue(), 0.0001d);
-        assertEquals(22.0d, this.intStats.getMedianValue(), 0.0001d);
-        assertEquals(23.70675d, this.intStats.getStandardDeviation(), 0.0001d);
-
-        HistogramTest.writeHistogramToLog(this.logger, this.intStats.getHistogram(), 20, "Histogram of 10 integer values: ");
-        HistogramTest.writeHistogramToLog(this.logger,
-                                          this.intStats.getHistogram().setBucketCount(7),
-                                          20,
-                                          "Histogram of 10 integer values: ");
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesForComplexFloatData() {
-        this.floatStats.add(1.9f);
-        this.floatStats.add(1.0f);
-        this.floatStats.add(2.0f);
-        this.floatStats.add(0.7f);
-        this.floatStats.add(7.3f);
-        this.floatStats.add(7.2f);
-        this.floatStats.add(4.2f);
-        this.floatStats.add(0.9f);
-        this.floatStats.add(4.7f);
-        this.floatStats.add(2.4f);
-        System.out.println(this.floatStats);
-        assertThat(this.floatStats.getCount(), is(10));
-        assertThat(this.floatStats.getMinimum(), is(0.7f));
-        assertThat(this.floatStats.getMaximum(), is(7.3f));
-        assertEquals(3.23f, this.floatStats.getMeanValue(), 0.0001f);
-        assertEquals(2.20f, this.floatStats.getMedianValue(), 0.0001f);
-        assertEquals(2.370675f, this.floatStats.getStandardDeviation(), 0.0001f);
-
-        HistogramTest.writeHistogramToLog(this.logger, this.floatStats.getHistogram(), 20, "Histogram of 10 float values: ");
-        HistogramTest.writeHistogramToLog(this.logger,
-                                          this.floatStats.getHistogram().setBucketCount(7),
-                                          20,
-                                          "Histogram of 10 float values: ");
-    }
-
-    @Test
-    public void shouldHaveNoStatisticValuesAfterUnusedAndReset() {
-        this.intStats.add(19);
-        this.intStats.add(10);
-        this.intStats.add(20);
-        assertEquals(3, this.intStats.getCount());
-        this.intStats.reset();
-        assertThat(this.intStats.getCount(), is(0));
-        assertThat(this.intStats.getMinimum(), is(0));
-        assertThat(this.intStats.getMaximum(), is(0));
-        assertThat(this.intStats.getMean(), is(0));
-        assertThat(this.intStats.getMedian(), is(0));
-        assertThat(this.intStats.getStandardDeviation(), is(0.0d));
-    }
-
-    @Test
-    public void shouldHaveStringRepresentationWithoutStatisticsForSingleSample() {
-        this.intStats.add(19);
-        String str = this.intStats.toString();
-        System.out.println(str);
-        assertTrue(str.matches("1 sample.*"));
-        assertTrue(str.matches(".*min=\\d{1,5}.*"));
-        assertTrue(str.matches(".*max=\\d{1,5}.*"));
-        assertTrue(str.matches(".*avg=\\d{1,5}.*"));
-        assertTrue(str.matches(".*stddev=\\d{1,5}.*"));
-        assertTrue(str.matches(".*median=\\d{1,5}.*"));
-    }
-
-    @Test
-    public void shouldHaveStringRepresentationWithStatisticsForMultipleSample() {
-        this.intStats.add(19);
-        this.intStats.add(10);
-        this.intStats.add(20);
-        String str = this.intStats.toString();
-        System.out.println(str);
-        assertTrue(str.matches("^\\d{1,5}.*"));
-        assertTrue(str.matches(".*3 samples.*"));
-        assertTrue(str.matches(".*min=\\d{1,5}.*"));
-        assertTrue(str.matches(".*max=\\d{1,5}.*"));
-        assertTrue(str.matches(".*avg=\\d{1,5}.*"));
-        assertTrue(str.matches(".*stddev=\\d{1,5}.*"));
-        assertTrue(str.matches(".*median=\\d{1,5}.*"));
-    }
-
-}

Copied: trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/DetailedStatisticsTest.java (from rev 706, trunk/dna-common/src/test/java/org/jboss/dna/common/stats/DetailedStatisticsTest.java)
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/DetailedStatisticsTest.java	                        (rev 0)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/DetailedStatisticsTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,205 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.statistic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import org.jboss.dna.common.math.FloatOperations;
+import org.jboss.dna.common.math.IntegerOperations;
+import org.jboss.dna.common.statistic.DetailedStatistics;
+import org.jboss.dna.common.util.Logger;
+import org.junit.Test;
+
+public class DetailedStatisticsTest {
+
+    private DetailedStatistics<Integer> intStats = new DetailedStatistics<Integer>(new IntegerOperations());
+    private DetailedStatistics<Float> floatStats = new DetailedStatistics<Float>(new FloatOperations());
+    private Logger logger = Logger.getLogger(DetailedStatisticsTest.class);
+
+    @Test
+    public void shouldHaveValidValuesWhenUnused() {
+        assertThat(this.intStats.getCount(), is(0));
+        assertThat(this.intStats.getMinimum(), is(0));
+        assertThat(this.intStats.getMaximum(), is(0));
+        assertThat(this.intStats.getMean(), is(0));
+        assertThat(this.intStats.getMedian(), is(0));
+        assertThat(this.intStats.getStandardDeviation(), is(0.0d));
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesWhenUnusedOnce() {
+        this.intStats.add(10);
+        assertThat(this.intStats.getCount(), is(1));
+        assertThat(this.intStats.getMinimum(), is(10));
+        assertThat(this.intStats.getMaximum(), is(10));
+        assertThat(this.intStats.getMean(), is(10));
+        assertThat(this.intStats.getMedian(), is(10));
+        assertThat(this.intStats.getStandardDeviation(), is(0.0d));
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesWhenUsedAnOddNumberOfTimesButMoreThanOnce() {
+        this.intStats.add(1);
+        this.intStats.add(2);
+        this.intStats.add(3);
+        assertThat(this.intStats.getCount(), is(3));
+        assertThat(this.intStats.getMinimum(), is(1));
+        assertThat(this.intStats.getMaximum(), is(3));
+        assertThat(this.intStats.getMean(), is(2));
+        assertThat(this.intStats.getMeanValue(), is(2.0d));
+        assertThat(this.intStats.getMedian(), is(2));
+        assertThat(this.intStats.getMedianValue(), is(2.0d));
+        assertEquals(0.816496d, this.intStats.getStandardDeviation(), 0.001d);
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesWhenUsedAnEvenNumberOfTimes() {
+        this.intStats.add(2);
+        this.intStats.add(4);
+        this.intStats.add(1);
+        this.intStats.add(3);
+        assertThat(this.intStats.getCount(), is(4));
+        assertThat(this.intStats.getMinimum(), is(1));
+        assertThat(this.intStats.getMaximum(), is(4));
+        assertThat(this.intStats.getMeanValue(), is(2.5d));
+        assertThat(this.intStats.getMedianValue(), is(2.5d));
+        assertEquals(1.0d, this.intStats.getStandardDeviation(), 0.2d);
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesWhenAllValuesAreTheSame() {
+        this.intStats.add(2);
+        this.intStats.add(2);
+        this.intStats.add(2);
+        this.intStats.add(2);
+        assertThat(this.intStats.getCount(), is(4));
+        assertThat(this.intStats.getMinimum(), is(2));
+        assertThat(this.intStats.getMaximum(), is(2));
+        assertThat(this.intStats.getMean(), is(2));
+        assertThat(this.intStats.getMeanValue(), is(2.0d));
+        assertThat(this.intStats.getMedian(), is(2));
+        assertThat(this.intStats.getMedianValue(), is(2.0d));
+        assertThat(this.intStats.getStandardDeviation(), is(0.0d));
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesForComplexIntegerData() {
+        this.intStats.add(19);
+        this.intStats.add(10);
+        this.intStats.add(20);
+        this.intStats.add(7);
+        this.intStats.add(73);
+        this.intStats.add(72);
+        this.intStats.add(42);
+        this.intStats.add(9);
+        this.intStats.add(47);
+        this.intStats.add(24);
+        System.out.println(this.intStats);
+        assertThat(this.intStats.getCount(), is(10));
+        assertThat(this.intStats.getMinimum(), is(7));
+        assertThat(this.intStats.getMaximum(), is(73));
+        assertThat(this.intStats.getMeanValue(), is(32.3d));
+        assertEquals(32.3d, this.intStats.getMeanValue(), 0.0001d);
+        assertEquals(22.0d, this.intStats.getMedianValue(), 0.0001d);
+        assertEquals(23.70675d, this.intStats.getStandardDeviation(), 0.0001d);
+
+        HistogramTest.writeHistogramToLog(this.logger, this.intStats.getHistogram(), 20, "Histogram of 10 integer values: ");
+        HistogramTest.writeHistogramToLog(this.logger,
+                                          this.intStats.getHistogram().setBucketCount(7),
+                                          20,
+                                          "Histogram of 10 integer values: ");
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesForComplexFloatData() {
+        this.floatStats.add(1.9f);
+        this.floatStats.add(1.0f);
+        this.floatStats.add(2.0f);
+        this.floatStats.add(0.7f);
+        this.floatStats.add(7.3f);
+        this.floatStats.add(7.2f);
+        this.floatStats.add(4.2f);
+        this.floatStats.add(0.9f);
+        this.floatStats.add(4.7f);
+        this.floatStats.add(2.4f);
+        System.out.println(this.floatStats);
+        assertThat(this.floatStats.getCount(), is(10));
+        assertThat(this.floatStats.getMinimum(), is(0.7f));
+        assertThat(this.floatStats.getMaximum(), is(7.3f));
+        assertEquals(3.23f, this.floatStats.getMeanValue(), 0.0001f);
+        assertEquals(2.20f, this.floatStats.getMedianValue(), 0.0001f);
+        assertEquals(2.370675f, this.floatStats.getStandardDeviation(), 0.0001f);
+
+        HistogramTest.writeHistogramToLog(this.logger, this.floatStats.getHistogram(), 20, "Histogram of 10 float values: ");
+        HistogramTest.writeHistogramToLog(this.logger,
+                                          this.floatStats.getHistogram().setBucketCount(7),
+                                          20,
+                                          "Histogram of 10 float values: ");
+    }
+
+    @Test
+    public void shouldHaveNoStatisticValuesAfterUnusedAndReset() {
+        this.intStats.add(19);
+        this.intStats.add(10);
+        this.intStats.add(20);
+        assertEquals(3, this.intStats.getCount());
+        this.intStats.reset();
+        assertThat(this.intStats.getCount(), is(0));
+        assertThat(this.intStats.getMinimum(), is(0));
+        assertThat(this.intStats.getMaximum(), is(0));
+        assertThat(this.intStats.getMean(), is(0));
+        assertThat(this.intStats.getMedian(), is(0));
+        assertThat(this.intStats.getStandardDeviation(), is(0.0d));
+    }
+
+    @Test
+    public void shouldHaveStringRepresentationWithoutStatisticsForSingleSample() {
+        this.intStats.add(19);
+        String str = this.intStats.toString();
+        System.out.println(str);
+        assertTrue(str.matches("1 sample.*"));
+        assertTrue(str.matches(".*min=\\d{1,5}.*"));
+        assertTrue(str.matches(".*max=\\d{1,5}.*"));
+        assertTrue(str.matches(".*avg=\\d{1,5}.*"));
+        assertTrue(str.matches(".*stddev=\\d{1,5}.*"));
+        assertTrue(str.matches(".*median=\\d{1,5}.*"));
+    }
+
+    @Test
+    public void shouldHaveStringRepresentationWithStatisticsForMultipleSample() {
+        this.intStats.add(19);
+        this.intStats.add(10);
+        this.intStats.add(20);
+        String str = this.intStats.toString();
+        System.out.println(str);
+        assertTrue(str.matches("^\\d{1,5}.*"));
+        assertTrue(str.matches(".*3 samples.*"));
+        assertTrue(str.matches(".*min=\\d{1,5}.*"));
+        assertTrue(str.matches(".*max=\\d{1,5}.*"));
+        assertTrue(str.matches(".*avg=\\d{1,5}.*"));
+        assertTrue(str.matches(".*stddev=\\d{1,5}.*"));
+        assertTrue(str.matches(".*median=\\d{1,5}.*"));
+    }
+
+}

Deleted: trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/HistogramTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/stats/HistogramTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/HistogramTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,206 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.common.stats;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-import org.jboss.dna.common.i18n.MockI18n;
-import org.jboss.dna.common.math.FloatOperations;
-import org.jboss.dna.common.math.MathOperations;
-import org.jboss.dna.common.text.Inflector;
-import org.jboss.dna.common.util.Logger;
-import org.junit.Test;
-
-public class HistogramTest {
-
-    private Logger logger = Logger.getLogger(HistogramTest.class);
-    private Inflector inflector = Inflector.getInstance();
-
-    public static <T extends Number> Histogram<T> createRandomHistogram( T minimum,
-                                                                         T maximum,
-                                                                         int numberOfValues,
-                                                                         MathOperations<T> ops ) {
-        List<T> values = new ArrayList<T>();
-        Random rng = new Random();
-        for (int i = 0; i != numberOfValues; ++i) {
-            T newValue = ops.random(minimum, maximum, rng);
-            values.add(newValue);
-        }
-        return new Histogram<T>(ops, values);
-    }
-
-    public static <T extends Number> void writeHistogramToLog( Logger logger,
-                                                               Histogram<T> histogram,
-                                                               int barLength,
-                                                               String description ) {
-        logger.info(MockI18n.passthrough, description != null ? description : "Histogram:");
-        List<String> barGraph = histogram.getTextGraph(barLength);
-        for (String line : barGraph) {
-            logger.debug("  " + line);
-        }
-    }
-
-    public <T extends Number> void assertBucketValueCount( Histogram<T> histogram,
-                                                           long... values ) {
-        List<Histogram<T>.Bucket> buckets = histogram.getBuckets();
-        // Check the number of buckets ...
-        assertEquals("The number of buckets didn't match expected number", values.length, buckets.size());
-        // Check the number of values ...
-        for (int i = 0; i != buckets.size(); ++i) {
-            assertEquals("The " + inflector.ordinalize(i + 1) + " bucket didn't have the expected number of values",
-                         values[i],
-                         buckets.get(i).getNumberOfValues());
-        }
-    }
-
-    @Test
-    public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSameOddNumberOfBuckets() {
-        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f};
-        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
-        gram.setBucketCount(3);
-        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
-        // "shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSameOddNumberOfBuckets");
-        assertBucketValueCount(gram, 1, 1, 2);
-    }
-
-    @Test
-    public void shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSameEvenNumberOfBuckets() {
-        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f};
-        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
-        gram.setBucketCount(4);
-        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
-        // "shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSameEvenNumberOfBuckets");
-        assertBucketValueCount(gram, 1, 1, 1, 1);
-
-    }
-
-    @Test
-    public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBuckets() {
-        Float[] values = {3.0f, 1.0f, 2.0f};
-        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
-        gram.setBucketCount(2);
-        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
-        // "shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSameEvenNumberOfBuckets");
-        assertBucketValueCount(gram, 1, 2);
-    }
-
-    @Test
-    public void shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSmallerNumberOfBuckets() {
-        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f};
-        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
-        gram.setBucketCount(2);
-        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
-        // "shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSmallerNumberOfBuckets");
-        assertBucketValueCount(gram, 2, 2);
-    }
-
-    @Test
-    public void shouldReturnListOfBuckets() {
-        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f};
-        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
-        assertTrue(gram.getBuckets() instanceof LinkedList<?>);
-    }
-
-    @Test
-    public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumAndMaximumRanges() {
-        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f};
-        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
-        gram.setBucketCount(5);
-        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
-        // "shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumAndMaximumRanges");
-        assertBucketValueCount(gram, 2, 2, 2, 2, 2);
-    }
-
-    @Test
-    public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumRanges() {
-        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 9.999f};
-        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
-        gram.setBucketCount(5);
-        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
-        // "shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumRanges");
-        assertBucketValueCount(gram, 2, 2, 2, 2, 2);
-    }
-
-    @Test
-    public void shouldCorrectlyConstructHistogramWithStandardDeviation() {
-        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 9.999f, 3.1f, 3.2f, 3.3f, 3.21f, 3.22f, 3.33f};
-        // RunningStatistics<Float> stats = new RunningStatistics<Float>(new FloatOperations());
-        // for (Float value : values) stats.add(value);
-        // System.out.println(stats);
-        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
-        gram.setBucketCount(6);
-        gram.setStrategy(3.315f, 2.52367f, 1);
-
-        HistogramTest.writeHistogramToLog(this.logger, gram, 0, "shouldCorrectlyConstructHistogramWithStandardDeviation");
-        assertBucketValueCount(gram, 1, 1, 7, 1, 1, 5);
-    }
-
-    @Test
-    public void shouldCorrectlyPlace1000RandomFloatValues() {
-        Histogram<Float> gram = createRandomHistogram(10.0f, 100.0f, 1000, new FloatOperations());
-        // gram.setDesiredRange(0.0f,100.0f);
-        HistogramTest.writeHistogramToLog(this.logger, gram, 0, "Histogram of 1000 random float values in "
-                                                                + gram.getBucketCount() + " buckets: ");
-    }
-
-    @Test
-    public void shouldCorrectlyConstructBoundariesWithWindowSmallerThanActualFloats() {
-        List<Float> boundaries = Histogram.getBucketBoundaries(new FloatOperations(), 10.0f, 20.0f, 5.0f, 25.0f, 12, 3);
-        assertNotNull(boundaries);
-        assertEquals(13, boundaries.size());
-        Float[] expectedBoundaries = {5.0f, 10.0f, 11f, 12f, 13f, 14f, 15f, 16f, 17f, 18f, 19f, 20f, 25f};
-        assertArrayEquals(expectedBoundaries, boundaries.toArray(new Float[boundaries.size()]));
-    }
-
-    @Test
-    public void shouldCorrectlyConstructBoundariesWithWindowSmallerThanActualNarrowlyVaryingFloats() {
-        List<Float> boundaries = Histogram.getBucketBoundaries(new FloatOperations(),
-                                                               10.00020f,
-                                                               10.00030f,
-                                                               10.00011f,
-                                                               10.00050f,
-                                                               12,
-                                                               3);
-        assertNotNull(boundaries);
-        assertEquals(13, boundaries.size());
-        assertEquals(10.00011f, boundaries.get(0), 0.00001f);
-        assertEquals(10.00020f, boundaries.get(1), 0.00001f);
-        assertEquals(10.00021f, boundaries.get(2), 0.00001f);
-        assertEquals(10.00022f, boundaries.get(3), 0.00001f);
-        assertEquals(10.00023f, boundaries.get(4), 0.00001f);
-        assertEquals(10.00024f, boundaries.get(5), 0.00001f);
-        assertEquals(10.00025f, boundaries.get(6), 0.00001f);
-        assertEquals(10.00026f, boundaries.get(7), 0.00001f);
-        assertEquals(10.00027f, boundaries.get(8), 0.00001f);
-        assertEquals(10.00028f, boundaries.get(9), 0.00001f);
-        assertEquals(10.00029f, boundaries.get(10), 0.00001f);
-        assertEquals(10.00030f, boundaries.get(11), 0.00001f);
-        assertEquals(10.00050f, boundaries.get(12), 0.00001f);
-    }
-
-}

Copied: trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/HistogramTest.java (from rev 706, trunk/dna-common/src/test/java/org/jboss/dna/common/stats/HistogramTest.java)
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/HistogramTest.java	                        (rev 0)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/HistogramTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,207 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.statistic;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import org.jboss.dna.common.i18n.MockI18n;
+import org.jboss.dna.common.math.FloatOperations;
+import org.jboss.dna.common.math.MathOperations;
+import org.jboss.dna.common.statistic.Histogram;
+import org.jboss.dna.common.text.Inflector;
+import org.jboss.dna.common.util.Logger;
+import org.junit.Test;
+
+public class HistogramTest {
+
+    private Logger logger = Logger.getLogger(HistogramTest.class);
+    private Inflector inflector = Inflector.getInstance();
+
+    public static <T extends Number> Histogram<T> createRandomHistogram( T minimum,
+                                                                         T maximum,
+                                                                         int numberOfValues,
+                                                                         MathOperations<T> ops ) {
+        List<T> values = new ArrayList<T>();
+        Random rng = new Random();
+        for (int i = 0; i != numberOfValues; ++i) {
+            T newValue = ops.random(minimum, maximum, rng);
+            values.add(newValue);
+        }
+        return new Histogram<T>(ops, values);
+    }
+
+    public static <T extends Number> void writeHistogramToLog( Logger logger,
+                                                               Histogram<T> histogram,
+                                                               int barLength,
+                                                               String description ) {
+        logger.info(MockI18n.passthrough, description != null ? description : "Histogram:");
+        List<String> barGraph = histogram.getTextGraph(barLength);
+        for (String line : barGraph) {
+            logger.debug("  " + line);
+        }
+    }
+
+    public <T extends Number> void assertBucketValueCount( Histogram<T> histogram,
+                                                           long... values ) {
+        List<Histogram<T>.Bucket> buckets = histogram.getBuckets();
+        // Check the number of buckets ...
+        assertEquals("The number of buckets didn't match expected number", values.length, buckets.size());
+        // Check the number of values ...
+        for (int i = 0; i != buckets.size(); ++i) {
+            assertEquals("The " + inflector.ordinalize(i + 1) + " bucket didn't have the expected number of values",
+                         values[i],
+                         buckets.get(i).getNumberOfValues());
+        }
+    }
+
+    @Test
+    public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSameOddNumberOfBuckets() {
+        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f};
+        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
+        gram.setBucketCount(3);
+        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
+        // "shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSameOddNumberOfBuckets");
+        assertBucketValueCount(gram, 1, 1, 2);
+    }
+
+    @Test
+    public void shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSameEvenNumberOfBuckets() {
+        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f};
+        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
+        gram.setBucketCount(4);
+        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
+        // "shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSameEvenNumberOfBuckets");
+        assertBucketValueCount(gram, 1, 1, 1, 1);
+
+    }
+
+    @Test
+    public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBuckets() {
+        Float[] values = {3.0f, 1.0f, 2.0f};
+        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
+        gram.setBucketCount(2);
+        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
+        // "shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSameEvenNumberOfBuckets");
+        assertBucketValueCount(gram, 1, 2);
+    }
+
+    @Test
+    public void shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSmallerNumberOfBuckets() {
+        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f};
+        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
+        gram.setBucketCount(2);
+        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
+        // "shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSmallerNumberOfBuckets");
+        assertBucketValueCount(gram, 2, 2);
+    }
+
+    @Test
+    public void shouldReturnListOfBuckets() {
+        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f};
+        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
+        assertTrue(gram.getBuckets() instanceof LinkedList<?>);
+    }
+
+    @Test
+    public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumAndMaximumRanges() {
+        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f};
+        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
+        gram.setBucketCount(5);
+        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
+        // "shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumAndMaximumRanges");
+        assertBucketValueCount(gram, 2, 2, 2, 2, 2);
+    }
+
+    @Test
+    public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumRanges() {
+        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 9.999f};
+        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
+        gram.setBucketCount(5);
+        // HistogramTest.writeHistogramToLog(this.logger, gram, 0,
+        // "shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumRanges");
+        assertBucketValueCount(gram, 2, 2, 2, 2, 2);
+    }
+
+    @Test
+    public void shouldCorrectlyConstructHistogramWithStandardDeviation() {
+        Float[] values = {3.0f, 1.0f, 2.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 9.999f, 3.1f, 3.2f, 3.3f, 3.21f, 3.22f, 3.33f};
+        // RunningStatistics<Float> stats = new RunningStatistics<Float>(new FloatOperations());
+        // for (Float value : values) stats.add(value);
+        // System.out.println(stats);
+        Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values);
+        gram.setBucketCount(6);
+        gram.setStrategy(3.315f, 2.52367f, 1);
+
+        HistogramTest.writeHistogramToLog(this.logger, gram, 0, "shouldCorrectlyConstructHistogramWithStandardDeviation");
+        assertBucketValueCount(gram, 1, 1, 7, 1, 1, 5);
+    }
+
+    @Test
+    public void shouldCorrectlyPlace1000RandomFloatValues() {
+        Histogram<Float> gram = createRandomHistogram(10.0f, 100.0f, 1000, new FloatOperations());
+        // gram.setDesiredRange(0.0f,100.0f);
+        HistogramTest.writeHistogramToLog(this.logger, gram, 0, "Histogram of 1000 random float values in "
+                                                                + gram.getBucketCount() + " buckets: ");
+    }
+
+    @Test
+    public void shouldCorrectlyConstructBoundariesWithWindowSmallerThanActualFloats() {
+        List<Float> boundaries = Histogram.getBucketBoundaries(new FloatOperations(), 10.0f, 20.0f, 5.0f, 25.0f, 12, 3);
+        assertNotNull(boundaries);
+        assertEquals(13, boundaries.size());
+        Float[] expectedBoundaries = {5.0f, 10.0f, 11f, 12f, 13f, 14f, 15f, 16f, 17f, 18f, 19f, 20f, 25f};
+        assertArrayEquals(expectedBoundaries, boundaries.toArray(new Float[boundaries.size()]));
+    }
+
+    @Test
+    public void shouldCorrectlyConstructBoundariesWithWindowSmallerThanActualNarrowlyVaryingFloats() {
+        List<Float> boundaries = Histogram.getBucketBoundaries(new FloatOperations(),
+                                                               10.00020f,
+                                                               10.00030f,
+                                                               10.00011f,
+                                                               10.00050f,
+                                                               12,
+                                                               3);
+        assertNotNull(boundaries);
+        assertEquals(13, boundaries.size());
+        assertEquals(10.00011f, boundaries.get(0), 0.00001f);
+        assertEquals(10.00020f, boundaries.get(1), 0.00001f);
+        assertEquals(10.00021f, boundaries.get(2), 0.00001f);
+        assertEquals(10.00022f, boundaries.get(3), 0.00001f);
+        assertEquals(10.00023f, boundaries.get(4), 0.00001f);
+        assertEquals(10.00024f, boundaries.get(5), 0.00001f);
+        assertEquals(10.00025f, boundaries.get(6), 0.00001f);
+        assertEquals(10.00026f, boundaries.get(7), 0.00001f);
+        assertEquals(10.00027f, boundaries.get(8), 0.00001f);
+        assertEquals(10.00028f, boundaries.get(9), 0.00001f);
+        assertEquals(10.00029f, boundaries.get(10), 0.00001f);
+        assertEquals(10.00030f, boundaries.get(11), 0.00001f);
+        assertEquals(10.00050f, boundaries.get(12), 0.00001f);
+    }
+
+}

Deleted: trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/SimpleStatisticsTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/stats/SimpleStatisticsTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/SimpleStatisticsTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,167 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.common.stats;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import org.jboss.dna.common.math.FloatOperations;
-import org.jboss.dna.common.math.IntegerOperations;
-import org.junit.Test;
-
-public class SimpleStatisticsTest {
-
-    private SimpleStatistics<Integer> intStats = new SimpleStatistics<Integer>(new IntegerOperations());
-    private SimpleStatistics<Float> floatStats = new SimpleStatistics<Float>(new FloatOperations());
-
-    // private Logger logger = Logger.getLogger(SimpleStatisticsTest.class);
-
-    @Test
-    public void shouldHaveValidValuesWhenUnused() {
-        assertThat(this.intStats.getCount(), is(0));
-        assertThat(this.intStats.getMinimum(), is(0));
-        assertThat(this.intStats.getMaximum(), is(0));
-        assertThat(this.intStats.getMean(), is(0));
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesWhenUnusedOnce() {
-        this.intStats.add(10);
-        assertThat(this.intStats.getCount(), is(1));
-        assertThat(this.intStats.getMinimum(), is(10));
-        assertThat(this.intStats.getMaximum(), is(10));
-        assertThat(this.intStats.getMeanValue(), is(10.0d));
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesWhenUsedAnOddNumberOfTimesButMoreThanOnce() {
-        this.intStats.add(1);
-        this.intStats.add(2);
-        this.intStats.add(3);
-        assertThat(this.intStats.getCount(), is(3));
-        assertThat(this.intStats.getMinimum(), is(1));
-        assertThat(this.intStats.getMaximum(), is(3));
-        assertThat(this.intStats.getMeanValue(), is(2.0d));
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesWhenUsedAnEvenNumberOfTimes() {
-        this.intStats.add(2);
-        this.intStats.add(4);
-        this.intStats.add(1);
-        this.intStats.add(3);
-        assertThat(this.intStats.getCount(), is(4));
-        assertThat(this.intStats.getMinimum(), is(1));
-        assertThat(this.intStats.getMaximum(), is(4));
-        assertThat(this.intStats.getMeanValue(), is(2.5d));
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesWhenAllValuesAreTheSame() {
-        this.intStats.add(2);
-        this.intStats.add(2);
-        this.intStats.add(2);
-        this.intStats.add(2);
-        assertThat(this.intStats.getCount(), is(4));
-        assertThat(this.intStats.getMinimum(), is(2));
-        assertThat(this.intStats.getMaximum(), is(2));
-        assertThat(this.intStats.getMeanValue(), is(2.0d));
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesForComplexIntegerData() {
-        this.intStats.add(19);
-        this.intStats.add(10);
-        this.intStats.add(20);
-        this.intStats.add(7);
-        this.intStats.add(73);
-        this.intStats.add(72);
-        this.intStats.add(42);
-        this.intStats.add(9);
-        this.intStats.add(47);
-        this.intStats.add(24);
-        System.out.println(this.intStats);
-        assertThat(this.intStats.getCount(), is(10));
-        assertThat(this.intStats.getMinimum(), is(7));
-        assertThat(this.intStats.getMaximum(), is(73));
-        assertEquals(32.3d, this.intStats.getMeanValue(), 0.0001d);
-    }
-
-    @Test
-    public void shouldCorrectStatisitcValuesForComplexFloatData() {
-        this.floatStats.add(1.9f);
-        this.floatStats.add(1.0f);
-        this.floatStats.add(2.0f);
-        this.floatStats.add(0.7f);
-        this.floatStats.add(7.3f);
-        this.floatStats.add(7.2f);
-        this.floatStats.add(4.2f);
-        this.floatStats.add(0.9f);
-        this.floatStats.add(4.7f);
-        this.floatStats.add(2.4f);
-        System.out.println(this.floatStats);
-        assertThat(this.floatStats.getCount(), is(10));
-        assertThat(this.floatStats.getMinimum(), is(0.7f));
-        assertThat(this.floatStats.getMaximum(), is(7.3f));
-        assertEquals(3.23f, this.floatStats.getMeanValue(), 0.0001f);
-    }
-
-    @Test
-    public void shouldHaveNoStatisticValuesAfterUnusedAndReset() {
-        this.intStats.add(19);
-        this.intStats.add(10);
-        this.intStats.add(20);
-        assertThat(this.intStats.getCount(), is(3));
-        this.intStats.reset();
-        assertThat(this.intStats.getCount(), is(0));
-        assertThat(this.intStats.getMinimum(), is(0));
-        assertThat(this.intStats.getMaximum(), is(0));
-        assertThat(this.intStats.getMean(), is(0));
-    }
-
-    @Test
-    public void shouldHaveStringRepresentationWithoutStatisticsForSingleSample() {
-        this.intStats.add(19);
-        String str = this.intStats.toString();
-        System.out.println(str);
-        assertTrue(str.matches("1 sample.*"));
-        assertTrue(str.matches(".*min=\\d{1,5}.*"));
-        assertTrue(str.matches(".*max=\\d{1,5}.*"));
-        assertTrue(str.matches(".*avg=\\d{1,5}.*"));
-    }
-
-    @Test
-    public void shouldHaveStringRepresentationWithStatisticsForMultipleSample() {
-        this.intStats.add(19);
-        this.intStats.add(10);
-        this.intStats.add(20);
-        String str = this.intStats.toString();
-        System.out.println(str);
-        assertTrue(str.matches("^\\d{1,5}.*"));
-        assertTrue(str.matches(".*3 samples.*"));
-        assertTrue(str.matches(".*min=\\d{1,5}.*"));
-        assertTrue(str.matches(".*max=\\d{1,5}.*"));
-        assertTrue(str.matches(".*avg=\\d{1,5}.*"));
-    }
-
-}

Copied: trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/SimpleStatisticsTest.java (from rev 706, trunk/dna-common/src/test/java/org/jboss/dna/common/stats/SimpleStatisticsTest.java)
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/SimpleStatisticsTest.java	                        (rev 0)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/SimpleStatisticsTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,168 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.statistic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import org.jboss.dna.common.math.FloatOperations;
+import org.jboss.dna.common.math.IntegerOperations;
+import org.jboss.dna.common.statistic.SimpleStatistics;
+import org.junit.Test;
+
+public class SimpleStatisticsTest {
+
+    private SimpleStatistics<Integer> intStats = new SimpleStatistics<Integer>(new IntegerOperations());
+    private SimpleStatistics<Float> floatStats = new SimpleStatistics<Float>(new FloatOperations());
+
+    // private Logger logger = Logger.getLogger(SimpleStatisticsTest.class);
+
+    @Test
+    public void shouldHaveValidValuesWhenUnused() {
+        assertThat(this.intStats.getCount(), is(0));
+        assertThat(this.intStats.getMinimum(), is(0));
+        assertThat(this.intStats.getMaximum(), is(0));
+        assertThat(this.intStats.getMean(), is(0));
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesWhenUnusedOnce() {
+        this.intStats.add(10);
+        assertThat(this.intStats.getCount(), is(1));
+        assertThat(this.intStats.getMinimum(), is(10));
+        assertThat(this.intStats.getMaximum(), is(10));
+        assertThat(this.intStats.getMeanValue(), is(10.0d));
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesWhenUsedAnOddNumberOfTimesButMoreThanOnce() {
+        this.intStats.add(1);
+        this.intStats.add(2);
+        this.intStats.add(3);
+        assertThat(this.intStats.getCount(), is(3));
+        assertThat(this.intStats.getMinimum(), is(1));
+        assertThat(this.intStats.getMaximum(), is(3));
+        assertThat(this.intStats.getMeanValue(), is(2.0d));
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesWhenUsedAnEvenNumberOfTimes() {
+        this.intStats.add(2);
+        this.intStats.add(4);
+        this.intStats.add(1);
+        this.intStats.add(3);
+        assertThat(this.intStats.getCount(), is(4));
+        assertThat(this.intStats.getMinimum(), is(1));
+        assertThat(this.intStats.getMaximum(), is(4));
+        assertThat(this.intStats.getMeanValue(), is(2.5d));
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesWhenAllValuesAreTheSame() {
+        this.intStats.add(2);
+        this.intStats.add(2);
+        this.intStats.add(2);
+        this.intStats.add(2);
+        assertThat(this.intStats.getCount(), is(4));
+        assertThat(this.intStats.getMinimum(), is(2));
+        assertThat(this.intStats.getMaximum(), is(2));
+        assertThat(this.intStats.getMeanValue(), is(2.0d));
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesForComplexIntegerData() {
+        this.intStats.add(19);
+        this.intStats.add(10);
+        this.intStats.add(20);
+        this.intStats.add(7);
+        this.intStats.add(73);
+        this.intStats.add(72);
+        this.intStats.add(42);
+        this.intStats.add(9);
+        this.intStats.add(47);
+        this.intStats.add(24);
+        System.out.println(this.intStats);
+        assertThat(this.intStats.getCount(), is(10));
+        assertThat(this.intStats.getMinimum(), is(7));
+        assertThat(this.intStats.getMaximum(), is(73));
+        assertEquals(32.3d, this.intStats.getMeanValue(), 0.0001d);
+    }
+
+    @Test
+    public void shouldCorrectStatisitcValuesForComplexFloatData() {
+        this.floatStats.add(1.9f);
+        this.floatStats.add(1.0f);
+        this.floatStats.add(2.0f);
+        this.floatStats.add(0.7f);
+        this.floatStats.add(7.3f);
+        this.floatStats.add(7.2f);
+        this.floatStats.add(4.2f);
+        this.floatStats.add(0.9f);
+        this.floatStats.add(4.7f);
+        this.floatStats.add(2.4f);
+        System.out.println(this.floatStats);
+        assertThat(this.floatStats.getCount(), is(10));
+        assertThat(this.floatStats.getMinimum(), is(0.7f));
+        assertThat(this.floatStats.getMaximum(), is(7.3f));
+        assertEquals(3.23f, this.floatStats.getMeanValue(), 0.0001f);
+    }
+
+    @Test
+    public void shouldHaveNoStatisticValuesAfterUnusedAndReset() {
+        this.intStats.add(19);
+        this.intStats.add(10);
+        this.intStats.add(20);
+        assertThat(this.intStats.getCount(), is(3));
+        this.intStats.reset();
+        assertThat(this.intStats.getCount(), is(0));
+        assertThat(this.intStats.getMinimum(), is(0));
+        assertThat(this.intStats.getMaximum(), is(0));
+        assertThat(this.intStats.getMean(), is(0));
+    }
+
+    @Test
+    public void shouldHaveStringRepresentationWithoutStatisticsForSingleSample() {
+        this.intStats.add(19);
+        String str = this.intStats.toString();
+        System.out.println(str);
+        assertTrue(str.matches("1 sample.*"));
+        assertTrue(str.matches(".*min=\\d{1,5}.*"));
+        assertTrue(str.matches(".*max=\\d{1,5}.*"));
+        assertTrue(str.matches(".*avg=\\d{1,5}.*"));
+    }
+
+    @Test
+    public void shouldHaveStringRepresentationWithStatisticsForMultipleSample() {
+        this.intStats.add(19);
+        this.intStats.add(10);
+        this.intStats.add(20);
+        String str = this.intStats.toString();
+        System.out.println(str);
+        assertTrue(str.matches("^\\d{1,5}.*"));
+        assertTrue(str.matches(".*3 samples.*"));
+        assertTrue(str.matches(".*min=\\d{1,5}.*"));
+        assertTrue(str.matches(".*max=\\d{1,5}.*"));
+        assertTrue(str.matches(".*avg=\\d{1,5}.*"));
+    }
+
+}

Deleted: trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/StopwatchTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/stats/StopwatchTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/StopwatchTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,231 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.common.stats;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.number.IsCloseTo.closeTo;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import java.util.concurrent.TimeUnit;
-import org.junit.Before;
-import org.junit.Test;
-
-public class StopwatchTest {
-
-    private Stopwatch stopwatch;
-    private long totalPauseTimeInMillis;
-
-    @Before
-    public void beforeEach() {
-        this.stopwatch = new Stopwatch();
-    }
-
-    private void pause( int numberOfMilliseconds ) {
-        try {
-            Thread.sleep(numberOfMilliseconds);
-            this.totalPauseTimeInMillis += numberOfMilliseconds;
-        } catch (InterruptedException e) {
-            fail("Error while sleeping for " + numberOfMilliseconds + " milliseconds");
-        }
-    }
-
-    @Test
-    public void shouldAllowStartingAndStoppingOnce() {
-        stopwatch.start();
-        pause(100);
-        stopwatch.stop();
-        assertEquals(1, stopwatch.getCount());
-    }
-
-    @Test
-    public void shouldAllowStartingAndStoppingMultipleTimes() {
-        for (int i = 0; i != 3; ++i) {
-            assertEquals(false, stopwatch.isRunning());
-            stopwatch.start();
-            assertEquals(true, stopwatch.isRunning());
-            pause(100);
-            stopwatch.stop();
-            assertEquals(false, stopwatch.isRunning());
-        }
-    }
-
-    @Test
-    public void shouldKnowWhenItsRunning() {
-        assertEquals(false, stopwatch.isRunning());
-        stopwatch.start();
-        assertEquals(true, stopwatch.isRunning());
-        stopwatch.stop();
-        assertEquals(false, stopwatch.isRunning());
-    }
-
-    @Test
-    public void shouldAllowStopToBeCalledWhenNotRunning() {
-        assertEquals(false, stopwatch.isRunning());
-        stopwatch.stop();
-        stopwatch.stop();
-        assertEquals(false, stopwatch.isRunning());
-    }
-
-    @Test
-    public void shouldAllowStartToBeCalledWhenAlreadyRunning() {
-        assertEquals(false, stopwatch.isRunning());
-        stopwatch.start();
-        assertEquals(true, stopwatch.isRunning());
-        stopwatch.start();
-        assertEquals(true, stopwatch.isRunning());
-    }
-
-    @Test
-    public void shouldReportNumberOfTimesStartedAndStopped() {
-        for (int i = 0; i != 3; ++i) {
-            stopwatch.start();
-            pause(10);
-            stopwatch.stop();
-        }
-        assertEquals(3, stopwatch.getCount());
-    }
-
-    @Test
-    public void shouldReportTotalTime() {
-        for (int i = 0; i != 4; ++i) {
-            stopwatch.start();
-            pause(100);
-            stopwatch.stop();
-        }
-        assertThat((double)stopwatch.getTotalDuration().getDuration(TimeUnit.MILLISECONDS), is(closeTo(400, 100)));
-    }
-
-    @Test
-    public void shouldReportAverageTime() {
-        for (int i = 0; i != 4; ++i) {
-            stopwatch.start();
-            pause(100);
-            stopwatch.stop();
-        }
-        assertThat((double)stopwatch.getAverageDuration().getDuration(TimeUnit.MILLISECONDS), is(closeTo(100, 25)));
-    }
-
-    @Test
-    public void shouldReportMinimumTime() {
-        for (int i = 0; i != 3; ++i) {
-            stopwatch.start();
-            pause(50 * (i + 1));
-            stopwatch.stop();
-        }
-        assertThat((double)stopwatch.getMinimumDuration().getDuration(TimeUnit.MILLISECONDS), is(closeTo(50, 20)));
-    }
-
-    @Test
-    public void shouldReportMaximumTime() {
-        for (int i = 0; i != 3; ++i) {
-            stopwatch.start();
-            pause(50 * (i + 1));
-            stopwatch.stop();
-        }
-        assertThat((double)stopwatch.getMaximumDuration().getDuration(TimeUnit.MILLISECONDS), is(closeTo(150, 25)));
-    }
-
-    @Test
-    public void shouldReportValidStatisticsEvenBeforeBeingUsed() {
-        assertEquals(0, stopwatch.getCount());
-
-        assertEquals(0.0d, stopwatch.getTotalDuration().getDuration(TimeUnit.SECONDS), 0.00001);
-        assertEquals(0.0d, stopwatch.getAverageDuration().getDuration(TimeUnit.SECONDS), 0.00001);
-        assertEquals(0.0d, stopwatch.getMinimumDuration().getDuration(TimeUnit.SECONDS), 0.00001);
-        assertEquals(0.0d, stopwatch.getMaximumDuration().getDuration(TimeUnit.SECONDS), 0.00001);
-    }
-
-    @Test
-    public void shouldReportValidStatisticsAfterBeingReset() {
-        for (int i = 0; i != 3; ++i) {
-            stopwatch.start();
-            pause(10 * (i + 1));
-            stopwatch.stop();
-        }
-
-        stopwatch.reset();
-
-        assertEquals(0, stopwatch.getCount());
-
-        assertEquals(0.0d, stopwatch.getTotalDuration().getDuration(TimeUnit.SECONDS), 0.00001);
-        assertEquals(0.0d, stopwatch.getAverageDuration().getDuration(TimeUnit.SECONDS), 0.00001);
-        assertEquals(0.0d, stopwatch.getMinimumDuration().getDuration(TimeUnit.SECONDS), 0.00001);
-        assertEquals(0.0d, stopwatch.getMaximumDuration().getDuration(TimeUnit.SECONDS), 0.00001);
-    }
-
-    @Test
-    public void shouldHaveStringRepresentationWithoutStatisticsForSingleSample() {
-        stopwatch.start();
-        pause(12);
-        stopwatch.stop();
-        String str = stopwatch.toString();
-        System.out.println(str);
-        assertTrue(str.matches("^\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-        assertFalse(str.matches(".*1 sample.*"));
-        assertFalse(str.matches(".*min=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-        assertFalse(str.matches(".*max=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-        assertFalse(str.matches(".*avg=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-        assertFalse(str.matches(".*median=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-    }
-
-    @Test
-    public void shouldHaveStringRepresentationWithStatisticsForMultipleSample() {
-        for (int i = 0; i != 3; ++i) {
-            stopwatch.start();
-            pause(12);
-            stopwatch.stop();
-        }
-        String str = stopwatch.toString();
-        System.out.println(str);
-        assertTrue(str.matches("^\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-        assertTrue(str.matches(".*3 samples.*"));
-        assertTrue(str.matches(".*min=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-        assertTrue(str.matches(".*max=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-        assertTrue(str.matches(".*avg=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-        assertTrue(str.matches(".*median=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
-    }
-
-    @Test
-    public void shouldHaveAHistogramWithZeroSigma() {
-        for (int i = 0; i != 3; ++i) {
-            stopwatch.start();
-            pause(12);
-            stopwatch.stop();
-        }
-        assertNotNull(stopwatch.getHistogram(0));
-    }
-
-    @Test
-    public void shouldHaveAHistogramWithOneSigma() {
-        for (int i = 0; i != 3; ++i) {
-            stopwatch.start();
-            pause(12);
-            stopwatch.stop();
-        }
-        assertNotNull(stopwatch.getHistogram(1));
-    }
-
-}

Copied: trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/StopwatchTest.java (from rev 706, trunk/dna-common/src/test/java/org/jboss/dna/common/stats/StopwatchTest.java)
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/StopwatchTest.java	                        (rev 0)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/statistic/StopwatchTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,232 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.statistic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.number.IsCloseTo.closeTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import java.util.concurrent.TimeUnit;
+import org.jboss.dna.common.statistic.Stopwatch;
+import org.junit.Before;
+import org.junit.Test;
+
+public class StopwatchTest {
+
+    private Stopwatch stopwatch;
+    private long totalPauseTimeInMillis;
+
+    @Before
+    public void beforeEach() {
+        this.stopwatch = new Stopwatch();
+    }
+
+    private void pause( int numberOfMilliseconds ) {
+        try {
+            Thread.sleep(numberOfMilliseconds);
+            this.totalPauseTimeInMillis += numberOfMilliseconds;
+        } catch (InterruptedException e) {
+            fail("Error while sleeping for " + numberOfMilliseconds + " milliseconds");
+        }
+    }
+
+    @Test
+    public void shouldAllowStartingAndStoppingOnce() {
+        stopwatch.start();
+        pause(100);
+        stopwatch.stop();
+        assertEquals(1, stopwatch.getCount());
+    }
+
+    @Test
+    public void shouldAllowStartingAndStoppingMultipleTimes() {
+        for (int i = 0; i != 3; ++i) {
+            assertEquals(false, stopwatch.isRunning());
+            stopwatch.start();
+            assertEquals(true, stopwatch.isRunning());
+            pause(100);
+            stopwatch.stop();
+            assertEquals(false, stopwatch.isRunning());
+        }
+    }
+
+    @Test
+    public void shouldKnowWhenItsRunning() {
+        assertEquals(false, stopwatch.isRunning());
+        stopwatch.start();
+        assertEquals(true, stopwatch.isRunning());
+        stopwatch.stop();
+        assertEquals(false, stopwatch.isRunning());
+    }
+
+    @Test
+    public void shouldAllowStopToBeCalledWhenNotRunning() {
+        assertEquals(false, stopwatch.isRunning());
+        stopwatch.stop();
+        stopwatch.stop();
+        assertEquals(false, stopwatch.isRunning());
+    }
+
+    @Test
+    public void shouldAllowStartToBeCalledWhenAlreadyRunning() {
+        assertEquals(false, stopwatch.isRunning());
+        stopwatch.start();
+        assertEquals(true, stopwatch.isRunning());
+        stopwatch.start();
+        assertEquals(true, stopwatch.isRunning());
+    }
+
+    @Test
+    public void shouldReportNumberOfTimesStartedAndStopped() {
+        for (int i = 0; i != 3; ++i) {
+            stopwatch.start();
+            pause(10);
+            stopwatch.stop();
+        }
+        assertEquals(3, stopwatch.getCount());
+    }
+
+    @Test
+    public void shouldReportTotalTime() {
+        for (int i = 0; i != 4; ++i) {
+            stopwatch.start();
+            pause(100);
+            stopwatch.stop();
+        }
+        assertThat((double)stopwatch.getTotalDuration().getDuration(TimeUnit.MILLISECONDS), is(closeTo(400, 100)));
+    }
+
+    @Test
+    public void shouldReportAverageTime() {
+        for (int i = 0; i != 4; ++i) {
+            stopwatch.start();
+            pause(100);
+            stopwatch.stop();
+        }
+        assertThat((double)stopwatch.getAverageDuration().getDuration(TimeUnit.MILLISECONDS), is(closeTo(100, 25)));
+    }
+
+    @Test
+    public void shouldReportMinimumTime() {
+        for (int i = 0; i != 3; ++i) {
+            stopwatch.start();
+            pause(50 * (i + 1));
+            stopwatch.stop();
+        }
+        assertThat((double)stopwatch.getMinimumDuration().getDuration(TimeUnit.MILLISECONDS), is(closeTo(50, 20)));
+    }
+
+    @Test
+    public void shouldReportMaximumTime() {
+        for (int i = 0; i != 3; ++i) {
+            stopwatch.start();
+            pause(50 * (i + 1));
+            stopwatch.stop();
+        }
+        assertThat((double)stopwatch.getMaximumDuration().getDuration(TimeUnit.MILLISECONDS), is(closeTo(150, 25)));
+    }
+
+    @Test
+    public void shouldReportValidStatisticsEvenBeforeBeingUsed() {
+        assertEquals(0, stopwatch.getCount());
+
+        assertEquals(0.0d, stopwatch.getTotalDuration().getDuration(TimeUnit.SECONDS), 0.00001);
+        assertEquals(0.0d, stopwatch.getAverageDuration().getDuration(TimeUnit.SECONDS), 0.00001);
+        assertEquals(0.0d, stopwatch.getMinimumDuration().getDuration(TimeUnit.SECONDS), 0.00001);
+        assertEquals(0.0d, stopwatch.getMaximumDuration().getDuration(TimeUnit.SECONDS), 0.00001);
+    }
+
+    @Test
+    public void shouldReportValidStatisticsAfterBeingReset() {
+        for (int i = 0; i != 3; ++i) {
+            stopwatch.start();
+            pause(10 * (i + 1));
+            stopwatch.stop();
+        }
+
+        stopwatch.reset();
+
+        assertEquals(0, stopwatch.getCount());
+
+        assertEquals(0.0d, stopwatch.getTotalDuration().getDuration(TimeUnit.SECONDS), 0.00001);
+        assertEquals(0.0d, stopwatch.getAverageDuration().getDuration(TimeUnit.SECONDS), 0.00001);
+        assertEquals(0.0d, stopwatch.getMinimumDuration().getDuration(TimeUnit.SECONDS), 0.00001);
+        assertEquals(0.0d, stopwatch.getMaximumDuration().getDuration(TimeUnit.SECONDS), 0.00001);
+    }
+
+    @Test
+    public void shouldHaveStringRepresentationWithoutStatisticsForSingleSample() {
+        stopwatch.start();
+        pause(12);
+        stopwatch.stop();
+        String str = stopwatch.toString();
+        System.out.println(str);
+        assertTrue(str.matches("^\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+        assertFalse(str.matches(".*1 sample.*"));
+        assertFalse(str.matches(".*min=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+        assertFalse(str.matches(".*max=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+        assertFalse(str.matches(".*avg=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+        assertFalse(str.matches(".*median=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+    }
+
+    @Test
+    public void shouldHaveStringRepresentationWithStatisticsForMultipleSample() {
+        for (int i = 0; i != 3; ++i) {
+            stopwatch.start();
+            pause(12);
+            stopwatch.stop();
+        }
+        String str = stopwatch.toString();
+        System.out.println(str);
+        assertTrue(str.matches("^\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+        assertTrue(str.matches(".*3 samples.*"));
+        assertTrue(str.matches(".*min=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+        assertTrue(str.matches(".*max=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+        assertTrue(str.matches(".*avg=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+        assertTrue(str.matches(".*median=\\d{2,}:\\d{2}:\\d{2}\\.\\d{3}(,\\d{1,3})?.*"));
+    }
+
+    @Test
+    public void shouldHaveAHistogramWithZeroSigma() {
+        for (int i = 0; i != 3; ++i) {
+            stopwatch.start();
+            pause(12);
+            stopwatch.stop();
+        }
+        assertNotNull(stopwatch.getHistogram(0));
+    }
+
+    @Test
+    public void shouldHaveAHistogramWithOneSigma() {
+        for (int i = 0; i != 3; ++i) {
+            stopwatch.start();
+            pause(12);
+            stopwatch.stop();
+        }
+        assertNotNull(stopwatch.getHistogram(1));
+    }
+
+}

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaLexicon.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaLexicon.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.graph;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
 
 /**
  * @author Randall Hauch

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -35,13 +35,13 @@
 import org.jboss.dna.common.util.Logger;
 import org.jboss.dna.graph.mimetype.ExtensionBasedMimeTypeDetector;
 import org.jboss.dna.graph.mimetype.MimeTypeDetector;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
-import org.jboss.dna.graph.properties.basic.BasicPropertyFactory;
-import org.jboss.dna.graph.properties.basic.StandardValueFactories;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.BasicPropertyFactory;
+import org.jboss.dna.graph.property.basic.StandardValueFactories;
 
 /**
  * An ExecutionContext is a representation of the environment or context in which a component or operation is operating. Some

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -42,35 +42,35 @@
 import net.jcip.annotations.NotThreadSafe;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.Path.Segment;
-import org.jboss.dna.graph.requests.CompositeRequest;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadBranchRequest;
-import org.jboss.dna.graph.requests.ReadNextBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
-import org.jboss.dna.graph.requests.ReadPropertyRequest;
-import org.jboss.dna.graph.requests.RemovePropertiesRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.Path.Segment;
+import org.jboss.dna.graph.request.CompositeRequest;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadBranchRequest;
+import org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+import org.jboss.dna.graph.request.ReadPropertyRequest;
+import org.jboss.dna.graph.request.RemovePropertiesRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
 import org.xml.sax.SAXException;
 
 /**

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,12 +28,12 @@
 import net.jcip.annotations.NotThreadSafe;
 import org.jboss.dna.common.text.TextDecoder;
 import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
 import org.jboss.dna.graph.xml.XmlHandler;
 import org.jboss.dna.graph.xml.XmlHandler.Destination;
 import org.xml.sax.InputSource;

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrLexicon.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrLexicon.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.graph;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
 
 /**
  * @author Randall Hauch

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrMixLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrMixLexicon.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrMixLexicon.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.graph;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
 
 /**
  * @author Randall Hauch

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrNtLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrNtLexicon.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrNtLexicon.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.graph;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
 
 /**
  * @author Randall Hauch

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -31,11 +31,11 @@
 import org.jboss.dna.common.text.TextEncoder;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.common.util.HashCode;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
 
 /**
  * The location of a node, as specified by either its path, UUID, and/or identification properties.

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Node.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Node.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Node.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -25,9 +25,9 @@
 import java.util.List;
 import java.util.Map;
 import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
 
 /**
  * A node in a {@link Graph graph}, with methods to access the properties and children.

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -22,7 +22,7 @@
 package org.jboss.dna.graph;
 
 import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.property.Path;
 
 /**
  * A set of nodes returned from a {@link Graph graph}, with methods to access the properties and children of the nodes in the

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Subgraph.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Subgraph.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Subgraph.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -22,7 +22,7 @@
 package org.jboss.dna.graph;
 
 import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.property.Path;
 
 /**
  * A subgraph returned by the {@link Graph}, containing the nodes in the subgraph as well as the properties and children for each

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/cache/Cacheable.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/cache/Cacheable.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/cache/Cacheable.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -22,7 +22,7 @@
 package org.jboss.dna.graph.cache;
 
 import java.io.Serializable;
-import org.jboss.dna.graph.properties.DateTime;
+import org.jboss.dna.graph.property.DateTime;
 
 /**
  * Interface defining an object that can be cached according to a {@link CachePolicy}.

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/cache/package-info.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/cache/package-info.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/cache/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,6 +1,6 @@
 /**
  * Caching of graph content is controlled with {@link CachePolicy cache policies}, and these are used
- * in {@link org.jboss.dna.graph.connectors connectors} and in {@link org.jboss.dna.graph.requests.CacheableRequest requests}
+ * in {@link org.jboss.dna.graph.connector connectors} and in {@link org.jboss.dna.graph.request.CacheableRequest requests}
  * (among other places).
  */
 

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors)

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnection.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnection.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,180 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import java.util.concurrent.TimeUnit;
-import javax.transaction.xa.XAResource;
-import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.ReferentialIntegrityException;
-import org.jboss.dna.graph.requests.CompositeRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
-
-/**
- * A connection to a repository source.
- * <p>
- * These connections need not support concurrent operations by multiple threads.
- * </p>
- * <h3>Implementing a connector</h3>
- * <p>
- * While most of these methods are straightforward, a few warrant additional information. The {@link #ping(long, TimeUnit)} method
- * allows DNA to check the connection to see if it is alive. This method can be used in a variety of situations, ranging from
- * verifying that a {@link RepositorySource}'s JavaBean properties are correct to ensuring that a connection is still alive before
- * returning the connection from a connection pool.
- * </p>
- * <p>
- * DNA hasn't yet defined the event mechanism, so connectors don't have any methods to invoke on the
- * {@link RepositorySourceListener}. This will be defined in the next release, so feel free to manage the listeners now. Note that
- * by default the {@link RepositorySourceCapabilities} returns false for supportsEvents().
- * </p>
- * <p>
- * The most important method on this interface, though, is the {@link #execute(ExecutionContext, Request)} method, which serves as
- * the mechanism by which the component using the connector access and manipulates the content exposed by the connector. The first
- * parameter to this method is the {@link ExecutionContext}, which contains the information about environment as well as the
- * subject performing the request.
- * </p>
- * <p>
- * The second parameter, however, represents a request that is to be processed by the connector. {@link Request} objects can take
- * many different forms, as there are different classes for each kind of request (see the {org.jboss.dna.graph.request} package
- * for more detail). Each request contains the information a connector needs to do the processing, and it also is the place where
- * the connector places the results (or the error, if one occurs).
- * </p>
- * <p>
- * Although there are over a dozen different kinds of requests, we do anticipate adding more in future releases. For example, DNA
- * will likely support searching repository content in sources through an additional subclass of {@link Request}. Getting the
- * version history for a node will likely be another kind of request added in an upcoming release.
- * </p>
- * <p>
- * A connector is technically free to implement the {@link #execute(ExecutionContext, Request)} method in any way, as long as the
- * semantics are maintained. But DNA provides a {@link RequestProcessor} class that can simplify writing your own connector and at
- * the same time help insulate your connector from new kinds of requests that may be added in the future. The
- * {@link RequestProcessor} is an abstract class that defines a <code>process(...)</code> method for each concrete {@link Request}
- * subclass. In other words, there is a {@link RequestProcessor#process(org.jboss.dna.graph.requests.CompositeRequest)} method, a
- * {@link RequestProcessor#process(org.jboss.dna.graph.requests.ReadNodeRequest)} method, and so on.
- * </p>
- * <p>
- * To use a request processor in your connector, simply subclass {@link RequestProcessor} and override all of the abstract methods
- * and optionally override any of the other methods that have a default implementation. In many cases, the default implementations
- * of the <code>process(...)</code> methods are <i>sufficient</i> but probably not <i>efficient or optimum.</i> If that is the
- * case, simply provide your own methods that perform the request in a manner that is efficient for your source. However, if
- * performance is not a big issue, all of the concrete methods will provide the correct behavior. And remember, you can always
- * provide better implementations later, so it's often best to keep things simple at first.
- * </p>
- * <p>
- * Then, in your connector's {@link #execute(ExecutionContext, Request)} method, instantiate your {@link RequestProcessor}
- * subclass and pass the {@link #execute(ExecutionContext, Request) execute(...)} method's Request parameter directly into the the
- * request processor's {@link RequestProcessor#process(Request)} method, which will determine the appropriate method given the
- * actual Request object and will then invoke that method. For example:
- * 
- * <pre>
- * public void execute( ExecutionContext context,
- *                      Request request ) throws RepositorySourceException {
- *     RequestProcessor processor = new RequestProcessor(context);
- *     try {
- *         proc.process(request);
- *     } finally {
- *         proc.close();
- *     }
- * }
- * </pre>
- * 
- * If you do this, the bulk of your connector implementation will be in the RequestProcessor implementation methods. This not only
- * is more maintainable, it also lends itself to easier testing. And should any new request types be added in the future, your
- * connector may work just fine without any changes. In fact, if the {@link RequestProcessor} class can implement meaningful
- * methods for those new request types, your connector may "just work". Or, at least your connector will still be binary
- * compatible, even if your connector won't support any of the new features.
- * </p>
- * <p>
- * Finally, how should the connector handle exceptions? As mentioned above, each {@link Request} object has a
- * {@link Request#setError(Throwable) slot} where the connector can set any exception encountered during processing. This not only
- * handles the exception, but in the case of a {@link CompositeRequest} it also correctly associates the problem with the request.
- * However, it is perfectly acceptable to throw an exception if the connection becomes invalid (e.g., there is a communication
- * failure) or if a fatal error would prevent subsequent requests from being processed.
- * </p>
- * 
- * @author Randall Hauch
- */
- at NotThreadSafe
-public interface RepositoryConnection {
-
-    /**
-     * Get the name for this repository source. This value should be the same as that {@link RepositorySource#getName() returned}
-     * by the same {@link RepositorySource} that created this connection.
-     * 
-     * @return the identifier; never null or empty
-     */
-    String getSourceName();
-
-    /**
-     * Return the transactional resource associated with this connection. The transaction manager will use this resource to manage
-     * the participation of this connection in a distributed transaction.
-     * 
-     * @return the XA resource, or null if this connection is not aware of distributed transactions
-     */
-    XAResource getXAResource();
-
-    /**
-     * Ping the underlying system to determine if the connection is still valid and alive.
-     * 
-     * @param time the length of time to wait before timing out
-     * @param unit the time unit to use; may not be null
-     * @return true if this connection is still valid and can still be used, or false otherwise
-     * @throws InterruptedException if the thread has been interrupted during the operation
-     */
-    boolean ping( long time,
-                  TimeUnit unit ) throws InterruptedException;
-
-    /**
-     * Set the listener that is to receive notifications to changes to content within this source.
-     * 
-     * @param listener the new listener, or null if no component is interested in the change notifications
-     */
-    void setListener( RepositorySourceListener listener );
-
-    /**
-     * Get the default cache policy for this repository. If none is provided, a global cache policy will be used.
-     * 
-     * @return the default cache policy
-     */
-    CachePolicy getDefaultCachePolicy();
-
-    /**
-     * Execute the supplied commands against this repository source.
-     * 
-     * @param context the environment in which the commands are being executed; never null
-     * @param request the request to be executed; never null
-     * @throws PathNotFoundException if the request(s) contain paths to nodes that do not exist
-     * @throws ReferentialIntegrityException if the request is or contains a delete operation, where the delete could not be
-     *         performed because some references to deleted nodes would have remained after the delete operation completed
-     * @throws RepositorySourceException if there is a problem loading the node data
-     */
-    void execute( ExecutionContext context,
-                  Request request ) throws RepositorySourceException;
-
-    /**
-     * Close this connection to signal that it is no longer needed and that any accumulated resources are to be released.
-     */
-    void close();
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnection.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnection.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnection.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,180 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import java.util.concurrent.TimeUnit;
+import javax.transaction.xa.XAResource;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.cache.CachePolicy;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.ReferentialIntegrityException;
+import org.jboss.dna.graph.request.CompositeRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
+
+/**
+ * A connection to a repository source.
+ * <p>
+ * These connections need not support concurrent operations by multiple threads.
+ * </p>
+ * <h3>Implementing a connector</h3>
+ * <p>
+ * While most of these methods are straightforward, a few warrant additional information. The {@link #ping(long, TimeUnit)} method
+ * allows DNA to check the connection to see if it is alive. This method can be used in a variety of situations, ranging from
+ * verifying that a {@link RepositorySource}'s JavaBean properties are correct to ensuring that a connection is still alive before
+ * returning the connection from a connection pool.
+ * </p>
+ * <p>
+ * DNA hasn't yet defined the event mechanism, so connectors don't have any methods to invoke on the
+ * {@link RepositorySourceListener}. This will be defined in the next release, so feel free to manage the listeners now. Note that
+ * by default the {@link RepositorySourceCapabilities} returns false for supportsEvents().
+ * </p>
+ * <p>
+ * The most important method on this interface, though, is the {@link #execute(ExecutionContext, Request)} method, which serves as
+ * the mechanism by which the component using the connector access and manipulates the content exposed by the connector. The first
+ * parameter to this method is the {@link ExecutionContext}, which contains the information about environment as well as the
+ * subject performing the request.
+ * </p>
+ * <p>
+ * The second parameter, however, represents a request that is to be processed by the connector. {@link Request} objects can take
+ * many different forms, as there are different classes for each kind of request (see the {org.jboss.dna.graph.request} package
+ * for more detail). Each request contains the information a connector needs to do the processing, and it also is the place where
+ * the connector places the results (or the error, if one occurs).
+ * </p>
+ * <p>
+ * Although there are over a dozen different kinds of requests, we do anticipate adding more in future releases. For example, DNA
+ * will likely support searching repository content in sources through an additional subclass of {@link Request}. Getting the
+ * version history for a node will likely be another kind of request added in an upcoming release.
+ * </p>
+ * <p>
+ * A connector is technically free to implement the {@link #execute(ExecutionContext, Request)} method in any way, as long as the
+ * semantics are maintained. But DNA provides a {@link RequestProcessor} class that can simplify writing your own connector and at
+ * the same time help insulate your connector from new kinds of requests that may be added in the future. The
+ * {@link RequestProcessor} is an abstract class that defines a <code>process(...)</code> method for each concrete {@link Request}
+ * subclass. In other words, there is a {@link RequestProcessor#process(org.jboss.dna.graph.request.CompositeRequest)} method, a
+ * {@link RequestProcessor#process(org.jboss.dna.graph.request.ReadNodeRequest)} method, and so on.
+ * </p>
+ * <p>
+ * To use a request processor in your connector, simply subclass {@link RequestProcessor} and override all of the abstract methods
+ * and optionally override any of the other methods that have a default implementation. In many cases, the default implementations
+ * of the <code>process(...)</code> methods are <i>sufficient</i> but probably not <i>efficient or optimum.</i> If that is the
+ * case, simply provide your own methods that perform the request in a manner that is efficient for your source. However, if
+ * performance is not a big issue, all of the concrete methods will provide the correct behavior. And remember, you can always
+ * provide better implementations later, so it's often best to keep things simple at first.
+ * </p>
+ * <p>
+ * Then, in your connector's {@link #execute(ExecutionContext, Request)} method, instantiate your {@link RequestProcessor}
+ * subclass and pass the {@link #execute(ExecutionContext, Request) execute(...)} method's Request parameter directly into the the
+ * request processor's {@link RequestProcessor#process(Request)} method, which will determine the appropriate method given the
+ * actual Request object and will then invoke that method. For example:
+ * 
+ * <pre>
+ * public void execute( ExecutionContext context,
+ *                      Request request ) throws RepositorySourceException {
+ *     RequestProcessor processor = new RequestProcessor(context);
+ *     try {
+ *         proc.process(request);
+ *     } finally {
+ *         proc.close();
+ *     }
+ * }
+ * </pre>
+ * 
+ * If you do this, the bulk of your connector implementation will be in the RequestProcessor implementation methods. This not only
+ * is more maintainable, it also lends itself to easier testing. And should any new request types be added in the future, your
+ * connector may work just fine without any changes. In fact, if the {@link RequestProcessor} class can implement meaningful
+ * methods for those new request types, your connector may "just work". Or, at least your connector will still be binary
+ * compatible, even if your connector won't support any of the new features.
+ * </p>
+ * <p>
+ * Finally, how should the connector handle exceptions? As mentioned above, each {@link Request} object has a
+ * {@link Request#setError(Throwable) slot} where the connector can set any exception encountered during processing. This not only
+ * handles the exception, but in the case of a {@link CompositeRequest} it also correctly associates the problem with the request.
+ * However, it is perfectly acceptable to throw an exception if the connection becomes invalid (e.g., there is a communication
+ * failure) or if a fatal error would prevent subsequent requests from being processed.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+ at NotThreadSafe
+public interface RepositoryConnection {
+
+    /**
+     * Get the name for this repository source. This value should be the same as that {@link RepositorySource#getName() returned}
+     * by the same {@link RepositorySource} that created this connection.
+     * 
+     * @return the identifier; never null or empty
+     */
+    String getSourceName();
+
+    /**
+     * Return the transactional resource associated with this connection. The transaction manager will use this resource to manage
+     * the participation of this connection in a distributed transaction.
+     * 
+     * @return the XA resource, or null if this connection is not aware of distributed transactions
+     */
+    XAResource getXAResource();
+
+    /**
+     * Ping the underlying system to determine if the connection is still valid and alive.
+     * 
+     * @param time the length of time to wait before timing out
+     * @param unit the time unit to use; may not be null
+     * @return true if this connection is still valid and can still be used, or false otherwise
+     * @throws InterruptedException if the thread has been interrupted during the operation
+     */
+    boolean ping( long time,
+                  TimeUnit unit ) throws InterruptedException;
+
+    /**
+     * Set the listener that is to receive notifications to changes to content within this source.
+     * 
+     * @param listener the new listener, or null if no component is interested in the change notifications
+     */
+    void setListener( RepositorySourceListener listener );
+
+    /**
+     * Get the default cache policy for this repository. If none is provided, a global cache policy will be used.
+     * 
+     * @return the default cache policy
+     */
+    CachePolicy getDefaultCachePolicy();
+
+    /**
+     * Execute the supplied commands against this repository source.
+     * 
+     * @param context the environment in which the commands are being executed; never null
+     * @param request the request to be executed; never null
+     * @throws PathNotFoundException if the request(s) contain paths to nodes that do not exist
+     * @throws ReferentialIntegrityException if the request is or contains a delete operation, where the delete could not be
+     *         performed because some references to deleted nodes would have remained after the delete operation completed
+     * @throws RepositorySourceException if there is a problem loading the node data
+     */
+    void execute( ExecutionContext context,
+                  Request request ) throws RepositorySourceException;
+
+    /**
+     * Close this connection to signal that it is no longer needed and that any accumulated resources are to be released.
+     */
+    void close();
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnectionFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,42 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-/**
- * An interface for a factory of {@link RepositoryConnection}s using the names of the {@link RepositorySource} from which the
- * connections are to be obtained. This interface need not be implemented by a {@link RepositorySource}, as implementations are
- * usually provided by the system.
- * 
- * @author Randall Hauch
- */
-public interface RepositoryConnectionFactory {
-
-    /**
-     * Create a {@link RepositoryConnection} using the given {@link RepositorySource} name.
-     * 
-     * @param sourceName the name of the source from which a connection should be obtained
-     * @return the source, or null if no such source could be found (or created)
-     * @throws RepositorySourceException if there was an error obtaining the new connection
-     */
-    RepositoryConnection createConnection( String sourceName ) throws RepositorySourceException;
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnectionFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+/**
+ * An interface for a factory of {@link RepositoryConnection}s using the names of the {@link RepositorySource} from which the
+ * connections are to be obtained. This interface need not be implemented by a {@link RepositorySource}, as implementations are
+ * usually provided by the system.
+ * 
+ * @author Randall Hauch
+ */
+public interface RepositoryConnectionFactory {
+
+    /**
+     * Create a {@link RepositoryConnection} using the given {@link RepositorySource} name.
+     * 
+     * @param sourceName the name of the source from which a connection should be obtained
+     * @return the source, or null if no such source could be found (or created)
+     * @throws RepositorySourceException if there was an error obtaining the new connection
+     */
+    RepositoryConnection createConnection( String sourceName ) throws RepositorySourceException;
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionPool.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnectionPool.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionPool.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,1022 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Set;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-import javax.transaction.xa.XAResource;
-import net.jcip.annotations.GuardedBy;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.requests.Request;
-
-/**
- * A reusable implementation of a managed pool of connections that is optimized for safe concurrent operations.
- * 
- * @author Randall Hauch
- */
- at ThreadSafe
-public class RepositoryConnectionPool {
-
-    /**
-     * The core pool size for default-constructed pools is {@value} .
-     */
-    public static final int DEFAULT_CORE_POOL_SIZE = 1;
-
-    /**
-     * The maximum pool size for default-constructed pools is {@value} .
-     */
-    public static final int DEFAULT_MAXIMUM_POOL_SIZE = 10;
-
-    /**
-     * The keep-alive time for connections in default-constructed pools is {@value} seconds.
-     */
-    public static final long DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS = 30;
-
-    /**
-     * Permission for checking shutdown
-     */
-    private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread");
-
-    /**
-     * The source that this pool uses to create new connections.
-     */
-    private final RepositorySource source;
-
-    /**
-     * Lock held on updates to poolSize, corePoolSize, maximumPoolSize, and workers set.
-     */
-    private final ReentrantLock mainLock = new ReentrantLock();
-
-    /**
-     * Wait condition to support awaitTermination
-     */
-    private final Condition termination = mainLock.newCondition();
-
-    /**
-     * Set containing all connections that are available for use.
-     */
-    @GuardedBy( "mainLock" )
-    private final BlockingQueue<ConnectionWrapper> availableConnections = new LinkedBlockingQueue<ConnectionWrapper>();
-
-    /**
-     * The connections that are currently in use.
-     */
-    @GuardedBy( "mainLock" )
-    private final Set<ConnectionWrapper> inUseConnections = new HashSet<ConnectionWrapper>();
-
-    /**
-     * Timeout in nanoseconds for idle connections waiting to be used. Threads use this timeout only when there are more than
-     * corePoolSize present. Otherwise they wait forever to be used.
-     */
-    private volatile long keepAliveTime;
-
-    /**
-     * The target pool size, updated only while holding mainLock, but volatile to allow concurrent readability even during
-     * updates.
-     */
-    @GuardedBy( "mainLock" )
-    private volatile int corePoolSize;
-
-    /**
-     * Maximum pool size, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
-     */
-    @GuardedBy( "mainLock" )
-    private volatile int maximumPoolSize;
-
-    /**
-     * Current pool size, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
-     */
-    @GuardedBy( "mainLock" )
-    private volatile int poolSize;
-
-    /**
-     * Lifecycle state, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
-     */
-    @GuardedBy( "mainLock" )
-    private volatile int runState;
-
-    // Special values for runState
-    /** Normal, not-shutdown mode */
-    static final int RUNNING = 0;
-    /** Controlled shutdown mode */
-    static final int SHUTDOWN = 1;
-    /** Immediate shutdown mode */
-    static final int STOP = 2;
-    /** Final state */
-    static final int TERMINATED = 3;
-
-    /**
-     * Flag specifying whether a connection should be validated before returning it from the {@link #getConnection()} method.
-     */
-    private final AtomicBoolean validateConnectionBeforeUse = new AtomicBoolean(false);
-
-    /**
-     * The time in nanoseconds that ping should wait before timing out and failing.
-     */
-    private final AtomicLong pingTimeout = new AtomicLong(0);
-
-    /**
-     * The number of times an attempt to obtain a connection should fail with invalid connections before throwing an exception.
-     */
-    private final AtomicInteger maxFailedAttemptsBeforeError = new AtomicInteger(10);
-
-    private final AtomicLong totalConnectionsCreated = new AtomicLong(0);
-
-    private final AtomicLong totalConnectionsUsed = new AtomicLong(0);
-
-    private final Logger logger = Logger.getLogger(this.getClass());
-
-    /**
-     * Create the pool to use the supplied connection factory, which is typically a {@link RepositorySource}. This constructor
-     * uses the {@link #DEFAULT_CORE_POOL_SIZE default core pool size}, {@link #DEFAULT_MAXIMUM_POOL_SIZE default maximum pool
-     * size}, and {@link #DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS default keep-alive time (in seconds)}.
-     * 
-     * @param source the source for connections
-     * @throws IllegalArgumentException if the connection factory is null or any of the supplied arguments are invalid
-     */
-    public RepositoryConnectionPool( RepositorySource source ) {
-        this(source, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAXIMUM_POOL_SIZE, DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS, TimeUnit.SECONDS);
-    }
-
-    /**
-     * Create the pool to use the supplied connection factory, which is typically a {@link RepositorySource}.
-     * 
-     * @param source the source for connections
-     * @param corePoolSize the number of connections to keep in the pool, even if they are idle.
-     * @param maximumPoolSize the maximum number of connections to allow in the pool.
-     * @param keepAliveTime when the number of connection is greater than the core, this is the maximum time that excess idle
-     *        connections will be kept before terminating.
-     * @param unit the time unit for the keepAliveTime argument.
-     * @throws IllegalArgumentException if the connection factory is null or any of the supplied arguments are invalid
-     */
-    public RepositoryConnectionPool( RepositorySource source,
-                                     int corePoolSize,
-                                     int maximumPoolSize,
-                                     long keepAliveTime,
-                                     TimeUnit unit ) {
-        CheckArg.isNonNegative(corePoolSize, "corePoolSize");
-        CheckArg.isPositive(maximumPoolSize, "maximumPoolSize");
-        CheckArg.isNonNegative(keepAliveTime, "keepAliveTime");
-        CheckArg.isNotNull(source, "source");
-        if (maximumPoolSize < corePoolSize) {
-            throw new IllegalArgumentException(GraphI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
-        }
-        this.source = source;
-        this.corePoolSize = corePoolSize;
-        this.maximumPoolSize = maximumPoolSize;
-        this.keepAliveTime = unit.toNanos(keepAliveTime);
-        this.setPingTimeout(100, TimeUnit.MILLISECONDS);
-    }
-
-    /**
-     * Get the {@link RepositorySource} that's used by this pool.
-     * 
-     * @return the repository source; never null
-     */
-    public final RepositorySource getRepositorySource() {
-        return source;
-    }
-
-    /**
-     * Get the name of this pool, which delegates to the connection factory.
-     * 
-     * @return the name of the source
-     */
-    protected String getSourceName() {
-        return source.getName();
-    }
-
-    // -------------------------------------------------
-    // Property settings ...
-    // -------------------------------------------------
-
-    /**
-     * @return validateConnectionBeforeUse
-     */
-    public boolean getValidateConnectionBeforeUse() {
-        return this.validateConnectionBeforeUse.get();
-    }
-
-    /**
-     * @param validateConnectionBeforeUse Sets validateConnectionBeforeUse to the specified value.
-     */
-    public void setValidateConnectionBeforeUse( boolean validateConnectionBeforeUse ) {
-        this.validateConnectionBeforeUse.set(validateConnectionBeforeUse);
-    }
-
-    /**
-     * @return pingTimeout
-     */
-    public long getPingTimeoutInNanos() {
-        return this.pingTimeout.get();
-    }
-
-    /**
-     * @param pingTimeout the time to wait for a ping to complete
-     * @param unit the time unit of the time argument
-     */
-    public void setPingTimeout( long pingTimeout,
-                                TimeUnit unit ) {
-        CheckArg.isNonNegative(pingTimeout, "time");
-        this.pingTimeout.set(unit.toNanos(pingTimeout));
-    }
-
-    /**
-     * @return maxFailedAttemptsBeforeError
-     */
-    public int getMaxFailedAttemptsBeforeError() {
-        return this.maxFailedAttemptsBeforeError.get();
-    }
-
-    /**
-     * @param maxFailedAttemptsBeforeError Sets maxFailedAttemptsBeforeError to the specified value.
-     */
-    public void setMaxFailedAttemptsBeforeError( int maxFailedAttemptsBeforeError ) {
-        this.maxFailedAttemptsBeforeError.set(maxFailedAttemptsBeforeError);
-    }
-
-    /**
-     * Sets the time limit for which connections may remain idle before being closed. If there are more than the core number of
-     * connections currently in the pool, after waiting this amount of time without being used, excess threads will be terminated.
-     * This overrides any value set in the constructor.
-     * 
-     * @param time the time to wait. A time value of zero will cause excess connections to terminate immediately after being
-     *        returned.
-     * @param unit the time unit of the time argument
-     * @throws IllegalArgumentException if time less than zero
-     * @see #getKeepAliveTime
-     */
-    public void setKeepAliveTime( long time,
-                                  TimeUnit unit ) {
-        CheckArg.isNonNegative(time, "time");
-        this.keepAliveTime = unit.toNanos(time);
-    }
-
-    /**
-     * Returns the connection keep-alive time, which is the amount of time which connections in excess of the core pool size may
-     * remain idle before being closed.
-     * 
-     * @param unit the desired time unit of the result
-     * @return the time limit
-     * @see #setKeepAliveTime
-     */
-    public long getKeepAliveTime( TimeUnit unit ) {
-        assert unit != null;
-        return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
-    }
-
-    /**
-     * @return maximumPoolSize
-     */
-    public int getMaximumPoolSize() {
-        return this.maximumPoolSize;
-    }
-
-    /**
-     * Sets the maximum allowed number of connections. This overrides any value set in the constructor. If the new value is
-     * smaller than the current value, excess existing but unused connections will be closed.
-     * 
-     * @param maximumPoolSize the new maximum
-     * @throws IllegalArgumentException if maximumPoolSize less than zero or the {@link #getCorePoolSize() core pool size}
-     * @see #getMaximumPoolSize
-     */
-    public void setMaximumPoolSize( int maximumPoolSize ) {
-        CheckArg.isPositive(maximumPoolSize, "maximum pool size");
-        if (maximumPoolSize < corePoolSize) {
-            throw new IllegalArgumentException(GraphI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
-        }
-        final ReentrantLock mainLock = this.mainLock;
-        try {
-            mainLock.lock();
-            int extra = this.maximumPoolSize - maximumPoolSize;
-            this.maximumPoolSize = maximumPoolSize;
-            if (extra > 0 && poolSize > maximumPoolSize) {
-                // Drain the extra connections from those available ...
-                drainUnusedConnections(extra);
-            }
-        } finally {
-            mainLock.unlock();
-        }
-    }
-
-    /**
-     * Returns the core number of connections.
-     * 
-     * @return the core number of connections
-     * @see #setCorePoolSize(int)
-     */
-    public int getCorePoolSize() {
-        return this.corePoolSize;
-    }
-
-    /**
-     * Sets the core number of connections. This overrides any value set in the constructor. If the new value is smaller than the
-     * current value, excess existing and unused connections will be closed. If larger, new connections will, if needed, be
-     * created.
-     * 
-     * @param corePoolSize the new core size
-     * @throws RepositorySourceException if there was an error obtaining the new connection
-     * @throws InterruptedException if the thread was interrupted during the operation
-     * @throws IllegalArgumentException if <tt>corePoolSize</tt> less than zero
-     * @see #getCorePoolSize()
-     */
-    public void setCorePoolSize( int corePoolSize ) throws RepositorySourceException, InterruptedException {
-        CheckArg.isNonNegative(corePoolSize, "core pool size");
-        if (maximumPoolSize < corePoolSize) {
-            throw new IllegalArgumentException(GraphI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
-        }
-        final ReentrantLock mainLock = this.mainLock;
-        try {
-            mainLock.lock();
-            int extra = this.corePoolSize - corePoolSize;
-            this.corePoolSize = corePoolSize;
-            if (extra < 0) {
-                // Add connections ...
-                addConnectionsIfUnderCorePoolSize();
-            } else if (extra > 0 && poolSize > corePoolSize) {
-                // Drain the extra connections from those available ...
-                drainUnusedConnections(extra);
-            }
-        } finally {
-            mainLock.unlock();
-        }
-    }
-
-    // -------------------------------------------------
-    // Statistics ...
-    // -------------------------------------------------
-
-    /**
-     * Returns the current number of connections in the pool, including those that are checked out (in use) and those that are not
-     * being used.
-     * 
-     * @return the number of connections
-     */
-    public int getPoolSize() {
-        return poolSize;
-    }
-
-    /**
-     * Returns the approximate number of connections that are currently checked out from the pool.
-     * 
-     * @return the number of checked-out connections
-     */
-    public int getInUseCount() {
-        final ReentrantLock mainLock = this.mainLock;
-        try {
-            mainLock.lock();
-            return this.inUseConnections.size();
-        } finally {
-            mainLock.unlock();
-        }
-    }
-
-    /**
-     * Get the total number of connections that have been created by this pool.
-     * 
-     * @return the total number of connections created by this pool
-     */
-    public long getTotalConnectionsCreated() {
-        return this.totalConnectionsCreated.get();
-    }
-
-    /**
-     * Get the total number of times connections have been {@link #getConnection()} used.
-     * 
-     * @return the total number
-     */
-    public long getTotalConnectionsUsed() {
-        return this.totalConnectionsUsed.get();
-    }
-
-    // -------------------------------------------------
-    // State management methods ...
-    // -------------------------------------------------
-
-    /**
-     * Starts a core connection, causing it to idly wait for use. This overrides the default policy of starting core connections
-     * only when they are {@link #getConnection() needed}. This method will return <tt>false</tt> if all core connections have
-     * already been started.
-     * 
-     * @return true if a connection was started
-     * @throws RepositorySourceException if there was an error obtaining the new connection
-     * @throws InterruptedException if the thread was interrupted during the operation
-     */
-    public boolean prestartCoreConnection() throws RepositorySourceException, InterruptedException {
-        final ReentrantLock mainLock = this.mainLock;
-        try {
-            mainLock.lock();
-            return addConnectionIfUnderCorePoolSize();
-        } finally {
-            mainLock.unlock();
-        }
-    }
-
-    /**
-     * Starts all core connections, causing them to idly wait for use. This overrides the default policy of starting core
-     * connections only when they are {@link #getConnection() needed}.
-     * 
-     * @return the number of connections started.
-     * @throws RepositorySourceException if there was an error obtaining the new connection
-     * @throws InterruptedException if the thread was interrupted during the operation
-     */
-    public int prestartAllCoreConnections() throws RepositorySourceException, InterruptedException {
-        final ReentrantLock mainLock = this.mainLock;
-        try {
-            mainLock.lock();
-            return addConnectionsIfUnderCorePoolSize();
-        } finally {
-            mainLock.unlock();
-        }
-    }
-
-    /**
-     * Initiates an orderly shutdown of the pool in which connections that are currently in use are allowed to be used and closed
-     * as normal, but no new connections will be created. Invocation has no additional effect if already shut down.
-     * <p>
-     * Once the pool has been shutdown, it may not be used to {@link #getConnection() get connections}.
-     * </p>
-     * 
-     * @throws SecurityException if a security manager exists and shutting down this pool may manipulate threads that the caller
-     *         is not permitted to modify because it does not hold {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
-     *         or the security manager's <tt>checkAccess</tt> method denies access.
-     * @see #shutdownNow()
-     */
-    public void shutdown() {
-        // Fail if caller doesn't have modifyThread permission. We
-        // explicitly check permissions directly because we can't trust
-        // implementations of SecurityManager to correctly override
-        // the "check access" methods such that our documented
-        // security policy is implemented.
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) java.security.AccessController.checkPermission(shutdownPerm);
-
-        this.logger.debug("Shutting down repository connection pool for {0}", getSourceName());
-        boolean fullyTerminated = false;
-        final ReentrantLock mainLock = this.mainLock;
-        try {
-            mainLock.lock();
-            int state = this.runState;
-            if (state == RUNNING) {
-                // don't override shutdownNow
-                this.runState = SHUTDOWN;
-            }
-
-            // Kill the maintenance thread ...
-
-            // Remove and close all available connections ...
-            if (!this.availableConnections.isEmpty()) {
-                // Drain the extra connections from those available ...
-                drainUnusedConnections(this.availableConnections.size());
-            }
-
-            // If there are no connections being used, trigger full termination now ...
-            if (this.inUseConnections.isEmpty()) {
-                fullyTerminated = true;
-                this.logger.trace("Signalling termination of repository connection pool for {0}", getSourceName());
-                runState = TERMINATED;
-                termination.signalAll();
-                this.logger.debug("Terminated repository connection pool for {0}", getSourceName());
-            }
-            // Otherwise the last connection that is closed will transition the runState to TERMINATED ...
-        } finally {
-            mainLock.unlock();
-        }
-        if (fullyTerminated) terminated();
-    }
-
-    /**
-     * Attempts to close all connections in the pool, including those connections currently in use, and prevent the use of other
-     * connections.
-     * 
-     * @throws SecurityException if a security manager exists and shutting down this pool may manipulate threads that the caller
-     *         is not permitted to modify because it does not hold {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
-     *         or the security manager's <tt>checkAccess</tt> method denies access.
-     * @see #shutdown()
-     */
-    public void shutdownNow() {
-        // Almost the same code as shutdown()
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) java.security.AccessController.checkPermission(shutdownPerm);
-
-        this.logger.debug("Shutting down (immediately) repository connection pool for {0}", getSourceName());
-        boolean fullyTerminated = false;
-        final ReentrantLock mainLock = this.mainLock;
-        try {
-            mainLock.lock();
-            int state = this.runState;
-            if (state != TERMINATED) {
-                // don't override shutdownNow
-                this.runState = STOP;
-            }
-
-            // Kill the maintenance thread ...
-
-            // Remove and close all available connections ...
-            if (!this.availableConnections.isEmpty()) {
-                // Drain the extra connections from those available ...
-                drainUnusedConnections(this.availableConnections.size());
-            }
-
-            // If there are connections being used, close them now ...
-            if (!this.inUseConnections.isEmpty()) {
-                for (ConnectionWrapper connectionInUse : this.inUseConnections) {
-                    this.logger.trace("Closing repository connection to {0}", getSourceName());
-                    connectionInUse.getOriginal().close();
-                }
-                this.poolSize -= this.inUseConnections.size();
-                // The last connection that is closed will transition the runState to TERMINATED ...
-            } else {
-                // There are no connections in use, so trigger full termination now ...
-                fullyTerminated = true;
-                this.logger.trace("Signalling termination of repository connection pool for {0}", getSourceName());
-                runState = TERMINATED;
-                termination.signalAll();
-                this.logger.debug("Terminated repository connection pool for {0}", getSourceName());
-            }
-
-        } finally {
-            mainLock.unlock();
-        }
-        if (fullyTerminated) terminated();
-    }
-
-    /**
-     * Return whether this connection pool is running and is able to {@link #getConnection() provide connections}. Note that this
-     * method is effectively <code>!isShutdown()</code>.
-     * 
-     * @return true if this pool is running, or false otherwise
-     * @see #isShutdown()
-     * @see #isTerminated()
-     * @see #isTerminating()
-     */
-    public boolean isRunning() {
-        return runState == RUNNING;
-    }
-
-    /**
-     * Return whether this connection pool is in the process of shutting down or has already been shut down. A result of
-     * <code>true</code> signals that the pool may no longer be used. Note that this method is effectively
-     * <code>!isRunning()</code>.
-     * 
-     * @return true if this pool has been shut down, or false otherwise
-     * @see #isShutdown()
-     * @see #isTerminated()
-     * @see #isTerminating()
-     */
-    public boolean isShutdown() {
-        return runState != RUNNING;
-    }
-
-    /**
-     * Returns true if this pool is in the process of terminating after {@link #shutdown()} or {@link #shutdownNow()} has been
-     * called but has not completely terminated. This method may be useful for debugging. A return of <tt>true</tt> reported a
-     * sufficient period after shutdown may indicate that submitted tasks have ignored or suppressed interruption, causing this
-     * executor not to properly terminate.
-     * 
-     * @return true if terminating but not yet terminated, or false otherwise
-     * @see #isTerminated()
-     */
-    public boolean isTerminating() {
-        return runState == STOP;
-    }
-
-    /**
-     * Return true if this pool has completed its termination and no longer has any open connections.
-     * 
-     * @return true if terminated, or false otherwise
-     * @see #isTerminating()
-     */
-    public boolean isTerminated() {
-        return runState == TERMINATED;
-    }
-
-    /**
-     * Method that can be called after {@link #shutdown()} or {@link #shutdownNow()} to wait until all connections in use at the
-     * time those methods were called have been closed normally. This method accepts a maximum time duration, after which it will
-     * return even if all connections have not been closed.
-     * 
-     * @param timeout the maximum time to wait for all connections to be closed and returned to the pool
-     * @param unit the time unit for <code>timeout</code>
-     * @return true if the pool was terminated in the supplied time (or was already terminated), or false if the timeout occurred
-     *         before all the connections were closed
-     * @throws InterruptedException if the thread was interrupted
-     */
-    public boolean awaitTermination( long timeout,
-                                     TimeUnit unit ) throws InterruptedException {
-        this.logger.trace("Awaiting termination");
-        long nanos = unit.toNanos(timeout);
-        final ReentrantLock mainLock = this.mainLock;
-        try {
-            mainLock.lock();
-            for (;;) {
-                // this.logger.trace("---> Run state = {0}; condition = {1}, {2} open", runState, termination, poolSize);
-                if (runState == TERMINATED) return true;
-                if (nanos <= 0) return false;
-                nanos = termination.awaitNanos(nanos);
-                //this.logger.trace("---> Done waiting: run state = {0}; condition = {1}, {2} open",runState,termination,poolSize)
-                // ;
-            }
-        } finally {
-            mainLock.unlock();
-            this.logger.trace("Finished awaiting termination");
-        }
-    }
-
-    /**
-     * Method invoked when the pool has terminated. Default implementation does nothing. Note: To properly nest multiple
-     * overridings, subclasses should generally invoke <tt>super.terminated</tt> within this method.
-     */
-    protected void terminated() {
-    }
-
-    /**
-     * Invokes <tt>shutdown</tt> when this pool is no longer referenced.
-     */
-    @Override
-    protected void finalize() {
-        shutdown();
-    }
-
-    // -------------------------------------------------
-    // Connection management methods ...
-    // -------------------------------------------------
-
-    /**
-     * Get a connection from the pool. This method either returns an unused connection if one is available, creates a connection
-     * if there is still room in the pool, or blocks until a connection becomes available if the pool already contains the maximum
-     * number of connections and all connections are currently being used.
-     * 
-     * @return a connection
-     * @throws RepositorySourceException if there is a problem obtaining a connection
-     * @throws IllegalStateException if the factory is not in a state to create or return connections
-     */
-    public RepositoryConnection getConnection() throws RepositorySourceException {
-        int attemptsAllowed = this.maxFailedAttemptsBeforeError.get();
-        ConnectionWrapper connection = null;
-        // Do this until we get a good connection ...
-        int attemptsRemaining = attemptsAllowed;
-        while (connection == null && attemptsRemaining > 0) {
-            --attemptsRemaining;
-            ReentrantLock mainLock = this.mainLock;
-            try {
-                mainLock.lock();
-                // If we're shutting down the pool, then just close the connection ...
-                if (this.runState != RUNNING) {
-                    throw new IllegalStateException(GraphI18n.repositoryConnectionPoolIsNotRunning.text());
-                }
-                // If there are fewer total connections than the core size ...
-                if (this.poolSize < this.corePoolSize) {
-                    // Immediately create a wrapped connection and return it ...
-                    connection = newWrappedConnection();
-                }
-                // Peek to see if there is a connection available ...
-                else if (this.availableConnections.peek() != null) {
-                    // There is, so take it and return it ...
-                    try {
-                        connection = this.availableConnections.take();
-                    } catch (InterruptedException e) {
-                        this.logger.trace("Cancelled obtaining a repository connection from pool {0}", getSourceName());
-                        Thread.interrupted();
-                        throw new RepositorySourceException(getSourceName(), e);
-                    }
-                }
-                // There is no connection available. If there are fewer total connections than the maximum size ...
-                else if (this.poolSize < this.maximumPoolSize) {
-                    // Immediately create a wrapped connection and return it ...
-                    connection = newWrappedConnection();
-                }
-                if (connection != null) {
-                    this.inUseConnections.add(connection);
-                }
-            } finally {
-                mainLock.unlock();
-            }
-            if (connection == null) {
-                // There are not enough connections, so wait in line for the next available connection ...
-                this.logger.trace("Waiting for a repository connection from pool {0}", getSourceName());
-                try {
-                    connection = this.availableConnections.take();
-                } catch (InterruptedException e) {
-                    this.logger.trace("Cancelled obtaining a repository connection from pool {0}", getSourceName());
-                    Thread.interrupted();
-                    throw new RepositorySourceException(getSourceName(), e);
-                }
-                mainLock = this.mainLock;
-                mainLock.lock();
-                try {
-                    if (connection != null) {
-                        this.inUseConnections.add(connection);
-                    }
-                } finally {
-                    mainLock.unlock();
-                }
-                this.logger.trace("Recieved a repository connection from pool {0}", getSourceName());
-            }
-            if (connection != null && this.validateConnectionBeforeUse.get()) {
-                try {
-                    connection = validateConnection(connection);
-                } catch (InterruptedException e) {
-                    this.logger.trace("Cancelled validating a repository connection obtained from pool {0}", getSourceName());
-                    returnConnection(connection);
-                    Thread.interrupted();
-                    throw new RepositorySourceException(getSourceName(), e);
-                }
-            }
-        }
-        if (connection == null) {
-            // We were unable to obtain a usable connection, so fail ...
-            throw new RepositorySourceException(GraphI18n.unableToObtainValidRepositoryAfterAttempts.text(attemptsAllowed));
-        }
-        this.totalConnectionsUsed.incrementAndGet();
-        return connection;
-    }
-
-    /**
-     * This method is automatically called by the {@link ConnectionWrapper} when it is {@link ConnectionWrapper#close() closed}.
-     * 
-     * @param wrapper the wrapper to the connection that is being returned to the pool
-     */
-    protected void returnConnection( ConnectionWrapper wrapper ) {
-        assert wrapper != null;
-        ConnectionWrapper wrapperToClose = null;
-        final ReentrantLock mainLock = this.mainLock;
-        try {
-            mainLock.lock();
-            // Remove the connection from the in-use set ...
-            boolean removed = this.inUseConnections.remove(wrapper);
-            assert removed;
-
-            // If we're shutting down the pool, then just close the connection ...
-            if (this.runState != RUNNING) {
-                wrapperToClose = wrapper;
-            }
-            // If there are more connections than the maximum size...
-            else if (this.poolSize > this.maximumPoolSize) {
-                // Immediately close this connection ...
-                wrapperToClose = wrapper;
-            }
-            // Attempt to make the connection available (this should generally work, unless there is an upper limit
-            // to the number of available connections) ...
-            else if (!this.availableConnections.offer(new ConnectionWrapper(wrapper.getOriginal()))) {
-                // The pool of available connection is full, so release it ...
-                wrapperToClose = wrapper;
-            }
-        } finally {
-            mainLock.unlock();
-        }
-        // Close the connection if we're supposed to (do it outside of the main lock)...
-        if (wrapperToClose != null) {
-            closeConnection(wrapperToClose);
-        }
-    }
-
-    /**
-     * Validate the supplied connection, returning the connection if valid or null if the connection is not valid.
-     * 
-     * @param connection the connection to be validated; may not be null
-     * @return the validated connection, or null if the connection did not validate and was removed from the pool
-     * @throws InterruptedException if the thread is interrupted while validating the connection
-     */
-    protected ConnectionWrapper validateConnection( ConnectionWrapper connection ) throws InterruptedException {
-        assert connection != null;
-        ConnectionWrapper invalidConnection = null;
-        try {
-            if (!connection.ping(this.pingTimeout.get(), TimeUnit.NANOSECONDS)) {
-                invalidConnection = connection;
-            }
-        } finally {
-            if (invalidConnection != null) {
-                connection = null;
-                returnConnection(invalidConnection);
-            }
-        }
-        return connection;
-    }
-
-    /**
-     * Obtain a new connection wrapped in a {@link ConnectionWrapper}. This method does not check whether creating the new
-     * connection would violate the {@link #maximumPoolSize maximum pool size} nor does it add the new connection to the
-     * {@link #availableConnections available connections} (as the caller may want it immediately), but it does increment the
-     * {@link #poolSize pool size}.
-     * 
-     * @return the connection wrapper with a new connection
-     * @throws RepositorySourceException if there was an error obtaining the new connection
-     */
-    @GuardedBy( "mainLock" )
-    protected ConnectionWrapper newWrappedConnection() throws RepositorySourceException {
-        RepositoryConnection connection = this.source.getConnection();
-        ++this.poolSize;
-        this.totalConnectionsCreated.incrementAndGet();
-        return new ConnectionWrapper(connection);
-    }
-
-    /**
-     * Close a connection that is in the pool but no longer in the {@link #availableConnections available connections}. This
-     * method does decrement the {@link #poolSize pool size}.
-     * 
-     * @param wrapper the wrapper for the connection to be closed
-     */
-    protected void closeConnection( ConnectionWrapper wrapper ) {
-        assert wrapper != null;
-        RepositoryConnection original = wrapper.getOriginal();
-        assert original != null;
-        try {
-            this.logger.debug("Closing repository connection to {0} ({1} open connections remain)", getSourceName(), poolSize);
-            original.close();
-        } finally {
-            final ReentrantLock mainLock = this.mainLock;
-            try {
-                mainLock.lock();
-                // No matter what reduce the pool size count
-                --this.poolSize;
-                // And if shutting down and this was the last connection being used...
-                if ((runState == SHUTDOWN || runState == STOP) && this.poolSize <= 0) {
-                    // then signal anybody that has called "awaitTermination(...)"
-                    this.logger.trace("Signalling termination of repository connection pool for {0}", getSourceName());
-                    this.runState = TERMINATED;
-                    this.termination.signalAll();
-                    this.logger.trace("Terminated repository connection pool for {0}", getSourceName());
-
-                    // fall through to call terminate() outside of lock.
-                }
-            } finally {
-                mainLock.unlock();
-            }
-        }
-    }
-
-    @GuardedBy( "mainLock" )
-    protected int drainUnusedConnections( int count ) {
-        if (count <= 0) return 0;
-        this.logger.trace("Draining up to {0} unused repository connections to {1}", count, getSourceName());
-        // Drain the extra connections from those available ...
-        Collection<ConnectionWrapper> extraConnections = new LinkedList<ConnectionWrapper>();
-        this.availableConnections.drainTo(extraConnections, count);
-        for (ConnectionWrapper connection : extraConnections) {
-            this.logger.trace("Closing repository connection to {0}", getSourceName());
-            connection.getOriginal().close();
-        }
-        int numClosed = extraConnections.size();
-        this.poolSize -= numClosed;
-        this.logger.trace("Drained {0} unused connections ({1} open connections remain)", numClosed, poolSize);
-        return numClosed;
-    }
-
-    @GuardedBy( "mainLock" )
-    protected boolean addConnectionIfUnderCorePoolSize() throws RepositorySourceException {
-        // Add connection ...
-        if (this.poolSize < this.corePoolSize) {
-            this.availableConnections.offer(newWrappedConnection());
-            this.logger.trace("Added connection to {0} in undersized pool", getSourceName());
-            return true;
-        }
-        return false;
-    }
-
-    @GuardedBy( "mainLock" )
-    protected int addConnectionsIfUnderCorePoolSize() throws RepositorySourceException {
-        // Add connections ...
-        int n = 0;
-        while (this.poolSize < this.corePoolSize) {
-            this.availableConnections.offer(newWrappedConnection());
-            ++n;
-        }
-        this.logger.trace("Added {0} connection(s) to {1} in undersized pool", n, getSourceName());
-        return n;
-    }
-
-    protected class ConnectionWrapper implements RepositoryConnection {
-
-        private final RepositoryConnection original;
-        private final long timeCreated;
-        private long lastUsed;
-        private boolean closed = false;
-
-        protected ConnectionWrapper( RepositoryConnection connection ) {
-            assert connection != null;
-            this.original = connection;
-            this.timeCreated = System.currentTimeMillis();
-        }
-
-        /**
-         * @return original
-         */
-        protected RepositoryConnection getOriginal() {
-            return this.original;
-        }
-
-        /**
-         * @return lastUsed
-         */
-        public long getTimeLastUsed() {
-            return this.lastUsed;
-        }
-
-        /**
-         * @return timeCreated
-         */
-        public long getTimeCreated() {
-            return this.timeCreated;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public String getSourceName() {
-            return this.original.getSourceName();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public XAResource getXAResource() {
-            if (closed) throw new IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
-            return this.original.getXAResource();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public CachePolicy getDefaultCachePolicy() {
-            if (closed) throw new IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
-            return this.original.getDefaultCachePolicy();
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-         *      org.jboss.dna.graph.requests.Request)
-         */
-        public void execute( ExecutionContext context,
-                             Request request ) throws RepositorySourceException {
-            if (closed) throw new IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
-            this.original.execute(context, request);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean ping( long time,
-                             TimeUnit unit ) throws InterruptedException {
-            if (closed) throw new IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
-            return this.original.ping(time, unit);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void close() {
-            if (!closed) {
-                this.lastUsed = System.currentTimeMillis();
-                this.original.close();
-                this.closed = true;
-                returnConnection(this);
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void setListener( RepositorySourceListener listener ) {
-            if (!closed) this.original.setListener(listener);
-        }
-
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionPool.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnectionPool.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionPool.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryConnectionPool.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,1022 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.transaction.xa.XAResource;
+import net.jcip.annotations.GuardedBy;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.cache.CachePolicy;
+import org.jboss.dna.graph.request.Request;
+
+/**
+ * A reusable implementation of a managed pool of connections that is optimized for safe concurrent operations.
+ * 
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public class RepositoryConnectionPool {
+
+    /**
+     * The core pool size for default-constructed pools is {@value} .
+     */
+    public static final int DEFAULT_CORE_POOL_SIZE = 1;
+
+    /**
+     * The maximum pool size for default-constructed pools is {@value} .
+     */
+    public static final int DEFAULT_MAXIMUM_POOL_SIZE = 10;
+
+    /**
+     * The keep-alive time for connections in default-constructed pools is {@value} seconds.
+     */
+    public static final long DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS = 30;
+
+    /**
+     * Permission for checking shutdown
+     */
+    private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread");
+
+    /**
+     * The source that this pool uses to create new connections.
+     */
+    private final RepositorySource source;
+
+    /**
+     * Lock held on updates to poolSize, corePoolSize, maximumPoolSize, and workers set.
+     */
+    private final ReentrantLock mainLock = new ReentrantLock();
+
+    /**
+     * Wait condition to support awaitTermination
+     */
+    private final Condition termination = mainLock.newCondition();
+
+    /**
+     * Set containing all connections that are available for use.
+     */
+    @GuardedBy( "mainLock" )
+    private final BlockingQueue<ConnectionWrapper> availableConnections = new LinkedBlockingQueue<ConnectionWrapper>();
+
+    /**
+     * The connections that are currently in use.
+     */
+    @GuardedBy( "mainLock" )
+    private final Set<ConnectionWrapper> inUseConnections = new HashSet<ConnectionWrapper>();
+
+    /**
+     * Timeout in nanoseconds for idle connections waiting to be used. Threads use this timeout only when there are more than
+     * corePoolSize present. Otherwise they wait forever to be used.
+     */
+    private volatile long keepAliveTime;
+
+    /**
+     * The target pool size, updated only while holding mainLock, but volatile to allow concurrent readability even during
+     * updates.
+     */
+    @GuardedBy( "mainLock" )
+    private volatile int corePoolSize;
+
+    /**
+     * Maximum pool size, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
+     */
+    @GuardedBy( "mainLock" )
+    private volatile int maximumPoolSize;
+
+    /**
+     * Current pool size, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
+     */
+    @GuardedBy( "mainLock" )
+    private volatile int poolSize;
+
+    /**
+     * Lifecycle state, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
+     */
+    @GuardedBy( "mainLock" )
+    private volatile int runState;
+
+    // Special values for runState
+    /** Normal, not-shutdown mode */
+    static final int RUNNING = 0;
+    /** Controlled shutdown mode */
+    static final int SHUTDOWN = 1;
+    /** Immediate shutdown mode */
+    static final int STOP = 2;
+    /** Final state */
+    static final int TERMINATED = 3;
+
+    /**
+     * Flag specifying whether a connection should be validated before returning it from the {@link #getConnection()} method.
+     */
+    private final AtomicBoolean validateConnectionBeforeUse = new AtomicBoolean(false);
+
+    /**
+     * The time in nanoseconds that ping should wait before timing out and failing.
+     */
+    private final AtomicLong pingTimeout = new AtomicLong(0);
+
+    /**
+     * The number of times an attempt to obtain a connection should fail with invalid connections before throwing an exception.
+     */
+    private final AtomicInteger maxFailedAttemptsBeforeError = new AtomicInteger(10);
+
+    private final AtomicLong totalConnectionsCreated = new AtomicLong(0);
+
+    private final AtomicLong totalConnectionsUsed = new AtomicLong(0);
+
+    private final Logger logger = Logger.getLogger(this.getClass());
+
+    /**
+     * Create the pool to use the supplied connection factory, which is typically a {@link RepositorySource}. This constructor
+     * uses the {@link #DEFAULT_CORE_POOL_SIZE default core pool size}, {@link #DEFAULT_MAXIMUM_POOL_SIZE default maximum pool
+     * size}, and {@link #DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS default keep-alive time (in seconds)}.
+     * 
+     * @param source the source for connections
+     * @throws IllegalArgumentException if the connection factory is null or any of the supplied arguments are invalid
+     */
+    public RepositoryConnectionPool( RepositorySource source ) {
+        this(source, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAXIMUM_POOL_SIZE, DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS, TimeUnit.SECONDS);
+    }
+
+    /**
+     * Create the pool to use the supplied connection factory, which is typically a {@link RepositorySource}.
+     * 
+     * @param source the source for connections
+     * @param corePoolSize the number of connections to keep in the pool, even if they are idle.
+     * @param maximumPoolSize the maximum number of connections to allow in the pool.
+     * @param keepAliveTime when the number of connection is greater than the core, this is the maximum time that excess idle
+     *        connections will be kept before terminating.
+     * @param unit the time unit for the keepAliveTime argument.
+     * @throws IllegalArgumentException if the connection factory is null or any of the supplied arguments are invalid
+     */
+    public RepositoryConnectionPool( RepositorySource source,
+                                     int corePoolSize,
+                                     int maximumPoolSize,
+                                     long keepAliveTime,
+                                     TimeUnit unit ) {
+        CheckArg.isNonNegative(corePoolSize, "corePoolSize");
+        CheckArg.isPositive(maximumPoolSize, "maximumPoolSize");
+        CheckArg.isNonNegative(keepAliveTime, "keepAliveTime");
+        CheckArg.isNotNull(source, "source");
+        if (maximumPoolSize < corePoolSize) {
+            throw new IllegalArgumentException(GraphI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
+        }
+        this.source = source;
+        this.corePoolSize = corePoolSize;
+        this.maximumPoolSize = maximumPoolSize;
+        this.keepAliveTime = unit.toNanos(keepAliveTime);
+        this.setPingTimeout(100, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Get the {@link RepositorySource} that's used by this pool.
+     * 
+     * @return the repository source; never null
+     */
+    public final RepositorySource getRepositorySource() {
+        return source;
+    }
+
+    /**
+     * Get the name of this pool, which delegates to the connection factory.
+     * 
+     * @return the name of the source
+     */
+    protected String getSourceName() {
+        return source.getName();
+    }
+
+    // -------------------------------------------------
+    // Property settings ...
+    // -------------------------------------------------
+
+    /**
+     * @return validateConnectionBeforeUse
+     */
+    public boolean getValidateConnectionBeforeUse() {
+        return this.validateConnectionBeforeUse.get();
+    }
+
+    /**
+     * @param validateConnectionBeforeUse Sets validateConnectionBeforeUse to the specified value.
+     */
+    public void setValidateConnectionBeforeUse( boolean validateConnectionBeforeUse ) {
+        this.validateConnectionBeforeUse.set(validateConnectionBeforeUse);
+    }
+
+    /**
+     * @return pingTimeout
+     */
+    public long getPingTimeoutInNanos() {
+        return this.pingTimeout.get();
+    }
+
+    /**
+     * @param pingTimeout the time to wait for a ping to complete
+     * @param unit the time unit of the time argument
+     */
+    public void setPingTimeout( long pingTimeout,
+                                TimeUnit unit ) {
+        CheckArg.isNonNegative(pingTimeout, "time");
+        this.pingTimeout.set(unit.toNanos(pingTimeout));
+    }
+
+    /**
+     * @return maxFailedAttemptsBeforeError
+     */
+    public int getMaxFailedAttemptsBeforeError() {
+        return this.maxFailedAttemptsBeforeError.get();
+    }
+
+    /**
+     * @param maxFailedAttemptsBeforeError Sets maxFailedAttemptsBeforeError to the specified value.
+     */
+    public void setMaxFailedAttemptsBeforeError( int maxFailedAttemptsBeforeError ) {
+        this.maxFailedAttemptsBeforeError.set(maxFailedAttemptsBeforeError);
+    }
+
+    /**
+     * Sets the time limit for which connections may remain idle before being closed. If there are more than the core number of
+     * connections currently in the pool, after waiting this amount of time without being used, excess threads will be terminated.
+     * This overrides any value set in the constructor.
+     * 
+     * @param time the time to wait. A time value of zero will cause excess connections to terminate immediately after being
+     *        returned.
+     * @param unit the time unit of the time argument
+     * @throws IllegalArgumentException if time less than zero
+     * @see #getKeepAliveTime
+     */
+    public void setKeepAliveTime( long time,
+                                  TimeUnit unit ) {
+        CheckArg.isNonNegative(time, "time");
+        this.keepAliveTime = unit.toNanos(time);
+    }
+
+    /**
+     * Returns the connection keep-alive time, which is the amount of time which connections in excess of the core pool size may
+     * remain idle before being closed.
+     * 
+     * @param unit the desired time unit of the result
+     * @return the time limit
+     * @see #setKeepAliveTime
+     */
+    public long getKeepAliveTime( TimeUnit unit ) {
+        assert unit != null;
+        return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
+    }
+
+    /**
+     * @return maximumPoolSize
+     */
+    public int getMaximumPoolSize() {
+        return this.maximumPoolSize;
+    }
+
+    /**
+     * Sets the maximum allowed number of connections. This overrides any value set in the constructor. If the new value is
+     * smaller than the current value, excess existing but unused connections will be closed.
+     * 
+     * @param maximumPoolSize the new maximum
+     * @throws IllegalArgumentException if maximumPoolSize less than zero or the {@link #getCorePoolSize() core pool size}
+     * @see #getMaximumPoolSize
+     */
+    public void setMaximumPoolSize( int maximumPoolSize ) {
+        CheckArg.isPositive(maximumPoolSize, "maximum pool size");
+        if (maximumPoolSize < corePoolSize) {
+            throw new IllegalArgumentException(GraphI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
+        }
+        final ReentrantLock mainLock = this.mainLock;
+        try {
+            mainLock.lock();
+            int extra = this.maximumPoolSize - maximumPoolSize;
+            this.maximumPoolSize = maximumPoolSize;
+            if (extra > 0 && poolSize > maximumPoolSize) {
+                // Drain the extra connections from those available ...
+                drainUnusedConnections(extra);
+            }
+        } finally {
+            mainLock.unlock();
+        }
+    }
+
+    /**
+     * Returns the core number of connections.
+     * 
+     * @return the core number of connections
+     * @see #setCorePoolSize(int)
+     */
+    public int getCorePoolSize() {
+        return this.corePoolSize;
+    }
+
+    /**
+     * Sets the core number of connections. This overrides any value set in the constructor. If the new value is smaller than the
+     * current value, excess existing and unused connections will be closed. If larger, new connections will, if needed, be
+     * created.
+     * 
+     * @param corePoolSize the new core size
+     * @throws RepositorySourceException if there was an error obtaining the new connection
+     * @throws InterruptedException if the thread was interrupted during the operation
+     * @throws IllegalArgumentException if <tt>corePoolSize</tt> less than zero
+     * @see #getCorePoolSize()
+     */
+    public void setCorePoolSize( int corePoolSize ) throws RepositorySourceException, InterruptedException {
+        CheckArg.isNonNegative(corePoolSize, "core pool size");
+        if (maximumPoolSize < corePoolSize) {
+            throw new IllegalArgumentException(GraphI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
+        }
+        final ReentrantLock mainLock = this.mainLock;
+        try {
+            mainLock.lock();
+            int extra = this.corePoolSize - corePoolSize;
+            this.corePoolSize = corePoolSize;
+            if (extra < 0) {
+                // Add connections ...
+                addConnectionsIfUnderCorePoolSize();
+            } else if (extra > 0 && poolSize > corePoolSize) {
+                // Drain the extra connections from those available ...
+                drainUnusedConnections(extra);
+            }
+        } finally {
+            mainLock.unlock();
+        }
+    }
+
+    // -------------------------------------------------
+    // Statistics ...
+    // -------------------------------------------------
+
+    /**
+     * Returns the current number of connections in the pool, including those that are checked out (in use) and those that are not
+     * being used.
+     * 
+     * @return the number of connections
+     */
+    public int getPoolSize() {
+        return poolSize;
+    }
+
+    /**
+     * Returns the approximate number of connections that are currently checked out from the pool.
+     * 
+     * @return the number of checked-out connections
+     */
+    public int getInUseCount() {
+        final ReentrantLock mainLock = this.mainLock;
+        try {
+            mainLock.lock();
+            return this.inUseConnections.size();
+        } finally {
+            mainLock.unlock();
+        }
+    }
+
+    /**
+     * Get the total number of connections that have been created by this pool.
+     * 
+     * @return the total number of connections created by this pool
+     */
+    public long getTotalConnectionsCreated() {
+        return this.totalConnectionsCreated.get();
+    }
+
+    /**
+     * Get the total number of times connections have been {@link #getConnection()} used.
+     * 
+     * @return the total number
+     */
+    public long getTotalConnectionsUsed() {
+        return this.totalConnectionsUsed.get();
+    }
+
+    // -------------------------------------------------
+    // State management methods ...
+    // -------------------------------------------------
+
+    /**
+     * Starts a core connection, causing it to idly wait for use. This overrides the default policy of starting core connections
+     * only when they are {@link #getConnection() needed}. This method will return <tt>false</tt> if all core connections have
+     * already been started.
+     * 
+     * @return true if a connection was started
+     * @throws RepositorySourceException if there was an error obtaining the new connection
+     * @throws InterruptedException if the thread was interrupted during the operation
+     */
+    public boolean prestartCoreConnection() throws RepositorySourceException, InterruptedException {
+        final ReentrantLock mainLock = this.mainLock;
+        try {
+            mainLock.lock();
+            return addConnectionIfUnderCorePoolSize();
+        } finally {
+            mainLock.unlock();
+        }
+    }
+
+    /**
+     * Starts all core connections, causing them to idly wait for use. This overrides the default policy of starting core
+     * connections only when they are {@link #getConnection() needed}.
+     * 
+     * @return the number of connections started.
+     * @throws RepositorySourceException if there was an error obtaining the new connection
+     * @throws InterruptedException if the thread was interrupted during the operation
+     */
+    public int prestartAllCoreConnections() throws RepositorySourceException, InterruptedException {
+        final ReentrantLock mainLock = this.mainLock;
+        try {
+            mainLock.lock();
+            return addConnectionsIfUnderCorePoolSize();
+        } finally {
+            mainLock.unlock();
+        }
+    }
+
+    /**
+     * Initiates an orderly shutdown of the pool in which connections that are currently in use are allowed to be used and closed
+     * as normal, but no new connections will be created. Invocation has no additional effect if already shut down.
+     * <p>
+     * Once the pool has been shutdown, it may not be used to {@link #getConnection() get connections}.
+     * </p>
+     * 
+     * @throws SecurityException if a security manager exists and shutting down this pool may manipulate threads that the caller
+     *         is not permitted to modify because it does not hold {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+     *         or the security manager's <tt>checkAccess</tt> method denies access.
+     * @see #shutdownNow()
+     */
+    public void shutdown() {
+        // Fail if caller doesn't have modifyThread permission. We
+        // explicitly check permissions directly because we can't trust
+        // implementations of SecurityManager to correctly override
+        // the "check access" methods such that our documented
+        // security policy is implemented.
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) java.security.AccessController.checkPermission(shutdownPerm);
+
+        this.logger.debug("Shutting down repository connection pool for {0}", getSourceName());
+        boolean fullyTerminated = false;
+        final ReentrantLock mainLock = this.mainLock;
+        try {
+            mainLock.lock();
+            int state = this.runState;
+            if (state == RUNNING) {
+                // don't override shutdownNow
+                this.runState = SHUTDOWN;
+            }
+
+            // Kill the maintenance thread ...
+
+            // Remove and close all available connections ...
+            if (!this.availableConnections.isEmpty()) {
+                // Drain the extra connections from those available ...
+                drainUnusedConnections(this.availableConnections.size());
+            }
+
+            // If there are no connections being used, trigger full termination now ...
+            if (this.inUseConnections.isEmpty()) {
+                fullyTerminated = true;
+                this.logger.trace("Signalling termination of repository connection pool for {0}", getSourceName());
+                runState = TERMINATED;
+                termination.signalAll();
+                this.logger.debug("Terminated repository connection pool for {0}", getSourceName());
+            }
+            // Otherwise the last connection that is closed will transition the runState to TERMINATED ...
+        } finally {
+            mainLock.unlock();
+        }
+        if (fullyTerminated) terminated();
+    }
+
+    /**
+     * Attempts to close all connections in the pool, including those connections currently in use, and prevent the use of other
+     * connections.
+     * 
+     * @throws SecurityException if a security manager exists and shutting down this pool may manipulate threads that the caller
+     *         is not permitted to modify because it does not hold {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+     *         or the security manager's <tt>checkAccess</tt> method denies access.
+     * @see #shutdown()
+     */
+    public void shutdownNow() {
+        // Almost the same code as shutdown()
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) java.security.AccessController.checkPermission(shutdownPerm);
+
+        this.logger.debug("Shutting down (immediately) repository connection pool for {0}", getSourceName());
+        boolean fullyTerminated = false;
+        final ReentrantLock mainLock = this.mainLock;
+        try {
+            mainLock.lock();
+            int state = this.runState;
+            if (state != TERMINATED) {
+                // don't override shutdownNow
+                this.runState = STOP;
+            }
+
+            // Kill the maintenance thread ...
+
+            // Remove and close all available connections ...
+            if (!this.availableConnections.isEmpty()) {
+                // Drain the extra connections from those available ...
+                drainUnusedConnections(this.availableConnections.size());
+            }
+
+            // If there are connections being used, close them now ...
+            if (!this.inUseConnections.isEmpty()) {
+                for (ConnectionWrapper connectionInUse : this.inUseConnections) {
+                    this.logger.trace("Closing repository connection to {0}", getSourceName());
+                    connectionInUse.getOriginal().close();
+                }
+                this.poolSize -= this.inUseConnections.size();
+                // The last connection that is closed will transition the runState to TERMINATED ...
+            } else {
+                // There are no connections in use, so trigger full termination now ...
+                fullyTerminated = true;
+                this.logger.trace("Signalling termination of repository connection pool for {0}", getSourceName());
+                runState = TERMINATED;
+                termination.signalAll();
+                this.logger.debug("Terminated repository connection pool for {0}", getSourceName());
+            }
+
+        } finally {
+            mainLock.unlock();
+        }
+        if (fullyTerminated) terminated();
+    }
+
+    /**
+     * Return whether this connection pool is running and is able to {@link #getConnection() provide connections}. Note that this
+     * method is effectively <code>!isShutdown()</code>.
+     * 
+     * @return true if this pool is running, or false otherwise
+     * @see #isShutdown()
+     * @see #isTerminated()
+     * @see #isTerminating()
+     */
+    public boolean isRunning() {
+        return runState == RUNNING;
+    }
+
+    /**
+     * Return whether this connection pool is in the process of shutting down or has already been shut down. A result of
+     * <code>true</code> signals that the pool may no longer be used. Note that this method is effectively
+     * <code>!isRunning()</code>.
+     * 
+     * @return true if this pool has been shut down, or false otherwise
+     * @see #isShutdown()
+     * @see #isTerminated()
+     * @see #isTerminating()
+     */
+    public boolean isShutdown() {
+        return runState != RUNNING;
+    }
+
+    /**
+     * Returns true if this pool is in the process of terminating after {@link #shutdown()} or {@link #shutdownNow()} has been
+     * called but has not completely terminated. This method may be useful for debugging. A return of <tt>true</tt> reported a
+     * sufficient period after shutdown may indicate that submitted tasks have ignored or suppressed interruption, causing this
+     * executor not to properly terminate.
+     * 
+     * @return true if terminating but not yet terminated, or false otherwise
+     * @see #isTerminated()
+     */
+    public boolean isTerminating() {
+        return runState == STOP;
+    }
+
+    /**
+     * Return true if this pool has completed its termination and no longer has any open connections.
+     * 
+     * @return true if terminated, or false otherwise
+     * @see #isTerminating()
+     */
+    public boolean isTerminated() {
+        return runState == TERMINATED;
+    }
+
+    /**
+     * Method that can be called after {@link #shutdown()} or {@link #shutdownNow()} to wait until all connections in use at the
+     * time those methods were called have been closed normally. This method accepts a maximum time duration, after which it will
+     * return even if all connections have not been closed.
+     * 
+     * @param timeout the maximum time to wait for all connections to be closed and returned to the pool
+     * @param unit the time unit for <code>timeout</code>
+     * @return true if the pool was terminated in the supplied time (or was already terminated), or false if the timeout occurred
+     *         before all the connections were closed
+     * @throws InterruptedException if the thread was interrupted
+     */
+    public boolean awaitTermination( long timeout,
+                                     TimeUnit unit ) throws InterruptedException {
+        this.logger.trace("Awaiting termination");
+        long nanos = unit.toNanos(timeout);
+        final ReentrantLock mainLock = this.mainLock;
+        try {
+            mainLock.lock();
+            for (;;) {
+                // this.logger.trace("---> Run state = {0}; condition = {1}, {2} open", runState, termination, poolSize);
+                if (runState == TERMINATED) return true;
+                if (nanos <= 0) return false;
+                nanos = termination.awaitNanos(nanos);
+                //this.logger.trace("---> Done waiting: run state = {0}; condition = {1}, {2} open",runState,termination,poolSize)
+                // ;
+            }
+        } finally {
+            mainLock.unlock();
+            this.logger.trace("Finished awaiting termination");
+        }
+    }
+
+    /**
+     * Method invoked when the pool has terminated. Default implementation does nothing. Note: To properly nest multiple
+     * overridings, subclasses should generally invoke <tt>super.terminated</tt> within this method.
+     */
+    protected void terminated() {
+    }
+
+    /**
+     * Invokes <tt>shutdown</tt> when this pool is no longer referenced.
+     */
+    @Override
+    protected void finalize() {
+        shutdown();
+    }
+
+    // -------------------------------------------------
+    // Connection management methods ...
+    // -------------------------------------------------
+
+    /**
+     * Get a connection from the pool. This method either returns an unused connection if one is available, creates a connection
+     * if there is still room in the pool, or blocks until a connection becomes available if the pool already contains the maximum
+     * number of connections and all connections are currently being used.
+     * 
+     * @return a connection
+     * @throws RepositorySourceException if there is a problem obtaining a connection
+     * @throws IllegalStateException if the factory is not in a state to create or return connections
+     */
+    public RepositoryConnection getConnection() throws RepositorySourceException {
+        int attemptsAllowed = this.maxFailedAttemptsBeforeError.get();
+        ConnectionWrapper connection = null;
+        // Do this until we get a good connection ...
+        int attemptsRemaining = attemptsAllowed;
+        while (connection == null && attemptsRemaining > 0) {
+            --attemptsRemaining;
+            ReentrantLock mainLock = this.mainLock;
+            try {
+                mainLock.lock();
+                // If we're shutting down the pool, then just close the connection ...
+                if (this.runState != RUNNING) {
+                    throw new IllegalStateException(GraphI18n.repositoryConnectionPoolIsNotRunning.text());
+                }
+                // If there are fewer total connections than the core size ...
+                if (this.poolSize < this.corePoolSize) {
+                    // Immediately create a wrapped connection and return it ...
+                    connection = newWrappedConnection();
+                }
+                // Peek to see if there is a connection available ...
+                else if (this.availableConnections.peek() != null) {
+                    // There is, so take it and return it ...
+                    try {
+                        connection = this.availableConnections.take();
+                    } catch (InterruptedException e) {
+                        this.logger.trace("Cancelled obtaining a repository connection from pool {0}", getSourceName());
+                        Thread.interrupted();
+                        throw new RepositorySourceException(getSourceName(), e);
+                    }
+                }
+                // There is no connection available. If there are fewer total connections than the maximum size ...
+                else if (this.poolSize < this.maximumPoolSize) {
+                    // Immediately create a wrapped connection and return it ...
+                    connection = newWrappedConnection();
+                }
+                if (connection != null) {
+                    this.inUseConnections.add(connection);
+                }
+            } finally {
+                mainLock.unlock();
+            }
+            if (connection == null) {
+                // There are not enough connections, so wait in line for the next available connection ...
+                this.logger.trace("Waiting for a repository connection from pool {0}", getSourceName());
+                try {
+                    connection = this.availableConnections.take();
+                } catch (InterruptedException e) {
+                    this.logger.trace("Cancelled obtaining a repository connection from pool {0}", getSourceName());
+                    Thread.interrupted();
+                    throw new RepositorySourceException(getSourceName(), e);
+                }
+                mainLock = this.mainLock;
+                mainLock.lock();
+                try {
+                    if (connection != null) {
+                        this.inUseConnections.add(connection);
+                    }
+                } finally {
+                    mainLock.unlock();
+                }
+                this.logger.trace("Recieved a repository connection from pool {0}", getSourceName());
+            }
+            if (connection != null && this.validateConnectionBeforeUse.get()) {
+                try {
+                    connection = validateConnection(connection);
+                } catch (InterruptedException e) {
+                    this.logger.trace("Cancelled validating a repository connection obtained from pool {0}", getSourceName());
+                    returnConnection(connection);
+                    Thread.interrupted();
+                    throw new RepositorySourceException(getSourceName(), e);
+                }
+            }
+        }
+        if (connection == null) {
+            // We were unable to obtain a usable connection, so fail ...
+            throw new RepositorySourceException(GraphI18n.unableToObtainValidRepositoryAfterAttempts.text(attemptsAllowed));
+        }
+        this.totalConnectionsUsed.incrementAndGet();
+        return connection;
+    }
+
+    /**
+     * This method is automatically called by the {@link ConnectionWrapper} when it is {@link ConnectionWrapper#close() closed}.
+     * 
+     * @param wrapper the wrapper to the connection that is being returned to the pool
+     */
+    protected void returnConnection( ConnectionWrapper wrapper ) {
+        assert wrapper != null;
+        ConnectionWrapper wrapperToClose = null;
+        final ReentrantLock mainLock = this.mainLock;
+        try {
+            mainLock.lock();
+            // Remove the connection from the in-use set ...
+            boolean removed = this.inUseConnections.remove(wrapper);
+            assert removed;
+
+            // If we're shutting down the pool, then just close the connection ...
+            if (this.runState != RUNNING) {
+                wrapperToClose = wrapper;
+            }
+            // If there are more connections than the maximum size...
+            else if (this.poolSize > this.maximumPoolSize) {
+                // Immediately close this connection ...
+                wrapperToClose = wrapper;
+            }
+            // Attempt to make the connection available (this should generally work, unless there is an upper limit
+            // to the number of available connections) ...
+            else if (!this.availableConnections.offer(new ConnectionWrapper(wrapper.getOriginal()))) {
+                // The pool of available connection is full, so release it ...
+                wrapperToClose = wrapper;
+            }
+        } finally {
+            mainLock.unlock();
+        }
+        // Close the connection if we're supposed to (do it outside of the main lock)...
+        if (wrapperToClose != null) {
+            closeConnection(wrapperToClose);
+        }
+    }
+
+    /**
+     * Validate the supplied connection, returning the connection if valid or null if the connection is not valid.
+     * 
+     * @param connection the connection to be validated; may not be null
+     * @return the validated connection, or null if the connection did not validate and was removed from the pool
+     * @throws InterruptedException if the thread is interrupted while validating the connection
+     */
+    protected ConnectionWrapper validateConnection( ConnectionWrapper connection ) throws InterruptedException {
+        assert connection != null;
+        ConnectionWrapper invalidConnection = null;
+        try {
+            if (!connection.ping(this.pingTimeout.get(), TimeUnit.NANOSECONDS)) {
+                invalidConnection = connection;
+            }
+        } finally {
+            if (invalidConnection != null) {
+                connection = null;
+                returnConnection(invalidConnection);
+            }
+        }
+        return connection;
+    }
+
+    /**
+     * Obtain a new connection wrapped in a {@link ConnectionWrapper}. This method does not check whether creating the new
+     * connection would violate the {@link #maximumPoolSize maximum pool size} nor does it add the new connection to the
+     * {@link #availableConnections available connections} (as the caller may want it immediately), but it does increment the
+     * {@link #poolSize pool size}.
+     * 
+     * @return the connection wrapper with a new connection
+     * @throws RepositorySourceException if there was an error obtaining the new connection
+     */
+    @GuardedBy( "mainLock" )
+    protected ConnectionWrapper newWrappedConnection() throws RepositorySourceException {
+        RepositoryConnection connection = this.source.getConnection();
+        ++this.poolSize;
+        this.totalConnectionsCreated.incrementAndGet();
+        return new ConnectionWrapper(connection);
+    }
+
+    /**
+     * Close a connection that is in the pool but no longer in the {@link #availableConnections available connections}. This
+     * method does decrement the {@link #poolSize pool size}.
+     * 
+     * @param wrapper the wrapper for the connection to be closed
+     */
+    protected void closeConnection( ConnectionWrapper wrapper ) {
+        assert wrapper != null;
+        RepositoryConnection original = wrapper.getOriginal();
+        assert original != null;
+        try {
+            this.logger.debug("Closing repository connection to {0} ({1} open connections remain)", getSourceName(), poolSize);
+            original.close();
+        } finally {
+            final ReentrantLock mainLock = this.mainLock;
+            try {
+                mainLock.lock();
+                // No matter what reduce the pool size count
+                --this.poolSize;
+                // And if shutting down and this was the last connection being used...
+                if ((runState == SHUTDOWN || runState == STOP) && this.poolSize <= 0) {
+                    // then signal anybody that has called "awaitTermination(...)"
+                    this.logger.trace("Signalling termination of repository connection pool for {0}", getSourceName());
+                    this.runState = TERMINATED;
+                    this.termination.signalAll();
+                    this.logger.trace("Terminated repository connection pool for {0}", getSourceName());
+
+                    // fall through to call terminate() outside of lock.
+                }
+            } finally {
+                mainLock.unlock();
+            }
+        }
+    }
+
+    @GuardedBy( "mainLock" )
+    protected int drainUnusedConnections( int count ) {
+        if (count <= 0) return 0;
+        this.logger.trace("Draining up to {0} unused repository connections to {1}", count, getSourceName());
+        // Drain the extra connections from those available ...
+        Collection<ConnectionWrapper> extraConnections = new LinkedList<ConnectionWrapper>();
+        this.availableConnections.drainTo(extraConnections, count);
+        for (ConnectionWrapper connection : extraConnections) {
+            this.logger.trace("Closing repository connection to {0}", getSourceName());
+            connection.getOriginal().close();
+        }
+        int numClosed = extraConnections.size();
+        this.poolSize -= numClosed;
+        this.logger.trace("Drained {0} unused connections ({1} open connections remain)", numClosed, poolSize);
+        return numClosed;
+    }
+
+    @GuardedBy( "mainLock" )
+    protected boolean addConnectionIfUnderCorePoolSize() throws RepositorySourceException {
+        // Add connection ...
+        if (this.poolSize < this.corePoolSize) {
+            this.availableConnections.offer(newWrappedConnection());
+            this.logger.trace("Added connection to {0} in undersized pool", getSourceName());
+            return true;
+        }
+        return false;
+    }
+
+    @GuardedBy( "mainLock" )
+    protected int addConnectionsIfUnderCorePoolSize() throws RepositorySourceException {
+        // Add connections ...
+        int n = 0;
+        while (this.poolSize < this.corePoolSize) {
+            this.availableConnections.offer(newWrappedConnection());
+            ++n;
+        }
+        this.logger.trace("Added {0} connection(s) to {1} in undersized pool", n, getSourceName());
+        return n;
+    }
+
+    protected class ConnectionWrapper implements RepositoryConnection {
+
+        private final RepositoryConnection original;
+        private final long timeCreated;
+        private long lastUsed;
+        private boolean closed = false;
+
+        protected ConnectionWrapper( RepositoryConnection connection ) {
+            assert connection != null;
+            this.original = connection;
+            this.timeCreated = System.currentTimeMillis();
+        }
+
+        /**
+         * @return original
+         */
+        protected RepositoryConnection getOriginal() {
+            return this.original;
+        }
+
+        /**
+         * @return lastUsed
+         */
+        public long getTimeLastUsed() {
+            return this.lastUsed;
+        }
+
+        /**
+         * @return timeCreated
+         */
+        public long getTimeCreated() {
+            return this.timeCreated;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public String getSourceName() {
+            return this.original.getSourceName();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public XAResource getXAResource() {
+            if (closed) throw new IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
+            return this.original.getXAResource();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public CachePolicy getDefaultCachePolicy() {
+            if (closed) throw new IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
+            return this.original.getDefaultCachePolicy();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+         *      org.jboss.dna.graph.request.Request)
+         */
+        public void execute( ExecutionContext context,
+                             Request request ) throws RepositorySourceException {
+            if (closed) throw new IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
+            this.original.execute(context, request);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean ping( long time,
+                             TimeUnit unit ) throws InterruptedException {
+            if (closed) throw new IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
+            return this.original.ping(time, unit);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void close() {
+            if (!closed) {
+                this.lastUsed = System.currentTimeMillis();
+                this.original.close();
+                this.closed = true;
+                returnConnection(this);
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void setListener( RepositorySourceListener listener ) {
+            if (!closed) this.original.setListener(listener);
+        }
+
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryContext.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryContext.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryContext.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,48 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import org.jboss.dna.graph.ExecutionContextFactory;
-
-/**
- * The context for a repository. This interface need not be implemented by a {@link RepositorySource}, as it is normally provided
- * to the source when {@link RepositorySource#initialize(RepositoryContext) initialized}.
- * 
- * @author Randall Hauch
- */
-public interface RepositoryContext {
-
-    /**
-     * Get the factory that can be used to create execution contexts.
-     * 
-     * @return the execution context factory
-     */
-    ExecutionContextFactory getExecutionContextFactory();
-
-    /**
-     * Get the factory for {@link RepositoryConnection connections} to other sources.
-     * 
-     * @return the connection factory
-     */
-    RepositoryConnectionFactory getRepositoryConnectionFactory();
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryContext.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryContext.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryContext.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositoryContext.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import org.jboss.dna.graph.ExecutionContextFactory;
+
+/**
+ * The context for a repository. This interface need not be implemented by a {@link RepositorySource}, as it is normally provided
+ * to the source when {@link RepositorySource#initialize(RepositoryContext) initialized}.
+ * 
+ * @author Randall Hauch
+ */
+public interface RepositoryContext {
+
+    /**
+     * Get the factory that can be used to create execution contexts.
+     * 
+     * @return the execution context factory
+     */
+    ExecutionContextFactory getExecutionContextFactory();
+
+    /**
+     * Get the factory for {@link RepositoryConnection connections} to other sources.
+     * 
+     * @return the connection factory
+     */
+    RepositoryConnectionFactory getRepositoryConnectionFactory();
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositorySource.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,177 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import java.io.Serializable;
-import javax.naming.Referenceable;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.requests.CacheableRequest;
-
-/**
- * A repository source is a description of a resource that can be used to access or store repository information. This class
- * serves as a factory for {@link RepositoryConnection} instances and provides some basic configuration information.
- * <p>
- * Typically this interface is implemented by classes that provide standard-style getters and setters for the various properties
- * necessary for proper configuration via reflection or introspection. This interface expects nor defines any such properties,
- * leaving that entirely to the implementation classes.
- * </p>
- * <p>
- * Implementations should also provide a no-arg constructor so that it is possible to easily create instances and initialize using
- * the standard getters and setters. One example where this is required is when a RepositorySource instance is recorded in a
- * repository (e.g., in a configuration area), and needs to be reinstantiated.
- * </p>
- * <p>
- * Objects that implement this <code>RepositorySource</code> interface are typically registered with a naming service such as Java
- * Naming and Directory Interface<sup><font size=-3>TM</font></sup> (JNDI). This interface extends both {@link Referenceable} and
- * {@link Serializable} so that such objects can be stored in any JNDI naming context and enable proper system recovery,
- * </p>
- * <h3>Pooling connections</h3>
- * <p>
- * If the connections created by a RepositorySource are expensive to create, then connection pooling is recommended. DNA provides
- * this capability with a powerful and flexible {@link RepositoryConnectionPool} class. This is the pooling mechanism used by
- * JBoss DNA, but you are free to use your own pools.
- * </p>
- * <h3>Cache Policy</h3>
- * <p>
- * Each connector is responsible for determining whether and how long DNA is to cache the content made available by the connector.
- * This is referred to as the caching policy, and consists of a time to live value representing the number of milliseconds that a
- * piece of data may be cached. After the TTL has passed, the information is no longer used.
- * </p>
- * <p>
- * DNA allows a connector to use a flexible and powerful caching policy. First, each connection returns the default caching policy
- * for all information returned by that connection. Often this policy can be configured via properties on the
- * {@link RepositorySource} implementation. This is optional, meaning the connector can return null if it does not wish to have a
- * default caching policy.
- * </p>
- * <p>
- * Second, the connector is able to override its default caching policy on {@link CacheableRequest individual requests}. Again,
- * this is optional, meaning that a null caching policy on a request implies that the request has no overridden caching policy.
- * </p>
- * <p>
- * Third, if the connector has no default caching policy and none is set on the individual requests, DNA uses whatever caching
- * policy is set up for that component using the connector. For example, the federating connector allows a default caching policy
- * to be specified, and this policy is used should the sources being federated not define their own caching policy.
- * </p>
- * <p>
- * In summary, a connector has total control over whether and for how long the information it provides is cached.
- * </p>
- * <h3>Leveraging JNDI</h3>
- * <p>
- * Sometimes it is necessary (or easier) for a RepositorySource implementation to look up an object in JNDI. One example of this
- * is the JBoss Cache connector: while the connector can instantiate a new JBoss Cache instance, more interesting use cases
- * involve JBoss Cache instances that are set up for clustering and replication, something that is generally difficult to
- * configure in a single JavaBean. Therefore the JBossCacheSource has optional JavaBean properties that define how it is to look
- * up a JBoss Cache instance in JNDI.
- * </p>
- * <p>
- * This is a simple pattern that you may find useful in your connector. Basically, if your source implementation can look up an
- * object in JNDI, simply use a single JavaBean String property that defines the full name that should be used to locate that
- * object in JNDI. Usually it's best to include "Jndi" in the JavaBean property name so that administrative users understand the
- * purpose of the property. (And some may suggest that any optional property also use the word "optional" in the property name.)
- * </p>
- * <h3>Capabilities</h3>
- * <p>
- * Each RepositorySource implementation provides some hint as to its capabilities by returning a
- * {@link RepositorySourceCapabilities} object. This class currently provides methods that say whether the connector supports
- * updates, whether it supports same-name-siblings (SNS), and whether the connector supports listeners and events. These may be
- * hard-coded values, or the capabilities object {@link #getCapabilities() returned by the connector} may determine them at
- * runtime based upon the system its connecting to. For example, a connector may interrogate the underlying system to decide
- * whether it can support updates. The only criteria is that the capabilities must remain constant throughout the lifetime of the
- * RepositorySource instance (assuming it doesn't change).
- * </p>
- * <p>
- * The {@link RepositorySourceCapabilities} can be used as is (the class is immutable), or it can be subclassed to provide more
- * complex behavior. Why is this a concrete class and not an interface? By using a concrete class, connectors inherit the default
- * behavior. If additional capabilities need to be added to the class in future releases, connectors may not have to override the
- * defaults. This provides some insulation against future enhancements to the connector framework.
- * </p>
- * <h3>Security and authentication</h3>
- * <p>
- * The main method connectors have to process requests takes an {@link ExecutionContext}, which contains the JAAS security
- * information of the subject performing the request. This means that the connector can use this to determine authentication and
- * authorization information for each request.
- * </p>
- * <p>
- * Sometimes that is not sufficient. For example, it may be that the connector needs its own authorization information so that it
- * can establish a connection (even if user-level privileges still use the {@link ExecutionContext} provided with each request).
- * In this case, the RepositorySource implementation will probably need JavaBean properties that represent the connector's
- * authentication information. This may take the form of a username and password, or it may be properties that are used to
- * delegate authentication to JAAS. Either way, just realize that it's perfectly acceptable for the connector to require its own
- * security properties.
- * </p>
- * 
- * @author Randall Hauch
- */
-public interface RepositorySource extends Referenceable, Serializable {
-
-    /**
-     * Initialize this source to use the supplied {@link RepositoryContext}, from which this source can obtain
-     * {@link RepositoryContext#getRepositoryConnectionFactory() connections} to other {@link RepositorySource sources} as well as
-     * {@link RepositoryContext#getExecutionContextFactory() execution contexts}.
-     * 
-     * @param context
-     * @throws RepositorySourceException
-     */
-    void initialize( RepositoryContext context ) throws RepositorySourceException;
-
-    /**
-     * Get the name for this repository source.
-     * 
-     * @return the name; never null or empty
-     */
-    String getName();
-
-    /**
-     * Get a connection from this source.
-     * 
-     * @return a connection
-     * @throws RepositorySourceException if there is a problem obtaining a connection
-     * @throws IllegalStateException if the factory is not in a state to create or return connections
-     */
-    RepositoryConnection getConnection() throws RepositorySourceException;
-
-    /**
-     * Get the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
-     * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
-     * user is not required to retry any operations.
-     * 
-     * @return the maximum number of allowable retries, or 0 if the source has no limit
-     */
-    int getRetryLimit();
-
-    /**
-     * Set the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
-     * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
-     * user is not required to retry any operations.
-     * 
-     * @param limit the maximum number of allowable retries, or 0 if the source has no limit
-     */
-    void setRetryLimit( int limit );
-
-    /**
-     * Get the capabilities for this source.
-     * 
-     * @return the capabilities for this source; never null
-     */
-    RepositorySourceCapabilities getCapabilities();
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositorySource.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,177 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import java.io.Serializable;
+import javax.naming.Referenceable;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.request.CacheableRequest;
+
+/**
+ * A repository source is a description of a resource that can be used to access or store repository information. This class
+ * serves as a factory for {@link RepositoryConnection} instances and provides some basic configuration information.
+ * <p>
+ * Typically this interface is implemented by classes that provide standard-style getters and setters for the various properties
+ * necessary for proper configuration via reflection or introspection. This interface expects nor defines any such properties,
+ * leaving that entirely to the implementation classes.
+ * </p>
+ * <p>
+ * Implementations should also provide a no-arg constructor so that it is possible to easily create instances and initialize using
+ * the standard getters and setters. One example where this is required is when a RepositorySource instance is recorded in a
+ * repository (e.g., in a configuration area), and needs to be reinstantiated.
+ * </p>
+ * <p>
+ * Objects that implement this <code>RepositorySource</code> interface are typically registered with a naming service such as Java
+ * Naming and Directory Interface<sup><font size=-3>TM</font></sup> (JNDI). This interface extends both {@link Referenceable} and
+ * {@link Serializable} so that such objects can be stored in any JNDI naming context and enable proper system recovery,
+ * </p>
+ * <h3>Pooling connections</h3>
+ * <p>
+ * If the connections created by a RepositorySource are expensive to create, then connection pooling is recommended. DNA provides
+ * this capability with a powerful and flexible {@link RepositoryConnectionPool} class. This is the pooling mechanism used by
+ * JBoss DNA, but you are free to use your own pools.
+ * </p>
+ * <h3>Cache Policy</h3>
+ * <p>
+ * Each connector is responsible for determining whether and how long DNA is to cache the content made available by the connector.
+ * This is referred to as the caching policy, and consists of a time to live value representing the number of milliseconds that a
+ * piece of data may be cached. After the TTL has passed, the information is no longer used.
+ * </p>
+ * <p>
+ * DNA allows a connector to use a flexible and powerful caching policy. First, each connection returns the default caching policy
+ * for all information returned by that connection. Often this policy can be configured via properties on the
+ * {@link RepositorySource} implementation. This is optional, meaning the connector can return null if it does not wish to have a
+ * default caching policy.
+ * </p>
+ * <p>
+ * Second, the connector is able to override its default caching policy on {@link CacheableRequest individual requests}. Again,
+ * this is optional, meaning that a null caching policy on a request implies that the request has no overridden caching policy.
+ * </p>
+ * <p>
+ * Third, if the connector has no default caching policy and none is set on the individual requests, DNA uses whatever caching
+ * policy is set up for that component using the connector. For example, the federating connector allows a default caching policy
+ * to be specified, and this policy is used should the sources being federated not define their own caching policy.
+ * </p>
+ * <p>
+ * In summary, a connector has total control over whether and for how long the information it provides is cached.
+ * </p>
+ * <h3>Leveraging JNDI</h3>
+ * <p>
+ * Sometimes it is necessary (or easier) for a RepositorySource implementation to look up an object in JNDI. One example of this
+ * is the JBoss Cache connector: while the connector can instantiate a new JBoss Cache instance, more interesting use cases
+ * involve JBoss Cache instances that are set up for clustering and replication, something that is generally difficult to
+ * configure in a single JavaBean. Therefore the JBossCacheSource has optional JavaBean properties that define how it is to look
+ * up a JBoss Cache instance in JNDI.
+ * </p>
+ * <p>
+ * This is a simple pattern that you may find useful in your connector. Basically, if your source implementation can look up an
+ * object in JNDI, simply use a single JavaBean String property that defines the full name that should be used to locate that
+ * object in JNDI. Usually it's best to include "Jndi" in the JavaBean property name so that administrative users understand the
+ * purpose of the property. (And some may suggest that any optional property also use the word "optional" in the property name.)
+ * </p>
+ * <h3>Capabilities</h3>
+ * <p>
+ * Each RepositorySource implementation provides some hint as to its capabilities by returning a
+ * {@link RepositorySourceCapabilities} object. This class currently provides methods that say whether the connector supports
+ * updates, whether it supports same-name-siblings (SNS), and whether the connector supports listeners and events. These may be
+ * hard-coded values, or the capabilities object {@link #getCapabilities() returned by the connector} may determine them at
+ * runtime based upon the system its connecting to. For example, a connector may interrogate the underlying system to decide
+ * whether it can support updates. The only criteria is that the capabilities must remain constant throughout the lifetime of the
+ * RepositorySource instance (assuming it doesn't change).
+ * </p>
+ * <p>
+ * The {@link RepositorySourceCapabilities} can be used as is (the class is immutable), or it can be subclassed to provide more
+ * complex behavior. Why is this a concrete class and not an interface? By using a concrete class, connectors inherit the default
+ * behavior. If additional capabilities need to be added to the class in future releases, connectors may not have to override the
+ * defaults. This provides some insulation against future enhancements to the connector framework.
+ * </p>
+ * <h3>Security and authentication</h3>
+ * <p>
+ * The main method connectors have to process requests takes an {@link ExecutionContext}, which contains the JAAS security
+ * information of the subject performing the request. This means that the connector can use this to determine authentication and
+ * authorization information for each request.
+ * </p>
+ * <p>
+ * Sometimes that is not sufficient. For example, it may be that the connector needs its own authorization information so that it
+ * can establish a connection (even if user-level privileges still use the {@link ExecutionContext} provided with each request).
+ * In this case, the RepositorySource implementation will probably need JavaBean properties that represent the connector's
+ * authentication information. This may take the form of a username and password, or it may be properties that are used to
+ * delegate authentication to JAAS. Either way, just realize that it's perfectly acceptable for the connector to require its own
+ * security properties.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+public interface RepositorySource extends Referenceable, Serializable {
+
+    /**
+     * Initialize this source to use the supplied {@link RepositoryContext}, from which this source can obtain
+     * {@link RepositoryContext#getRepositoryConnectionFactory() connections} to other {@link RepositorySource sources} as well as
+     * {@link RepositoryContext#getExecutionContextFactory() execution contexts}.
+     * 
+     * @param context
+     * @throws RepositorySourceException
+     */
+    void initialize( RepositoryContext context ) throws RepositorySourceException;
+
+    /**
+     * Get the name for this repository source.
+     * 
+     * @return the name; never null or empty
+     */
+    String getName();
+
+    /**
+     * Get a connection from this source.
+     * 
+     * @return a connection
+     * @throws RepositorySourceException if there is a problem obtaining a connection
+     * @throws IllegalStateException if the factory is not in a state to create or return connections
+     */
+    RepositoryConnection getConnection() throws RepositorySourceException;
+
+    /**
+     * Get the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
+     * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
+     * user is not required to retry any operations.
+     * 
+     * @return the maximum number of allowable retries, or 0 if the source has no limit
+     */
+    int getRetryLimit();
+
+    /**
+     * Set the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
+     * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
+     * user is not required to retry any operations.
+     * 
+     * @param limit the maximum number of allowable retries, or 0 if the source has no limit
+     */
+    void setRetryLimit( int limit );
+
+    /**
+     * Get the capabilities for this source.
+     * 
+     * @return the capabilities for this source; never null
+     */
+    RepositorySourceCapabilities getCapabilities();
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceCapabilities.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositorySourceCapabilities.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceCapabilities.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,103 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import net.jcip.annotations.Immutable;
-
-/**
- * The capabilities of a {@link RepositorySource}. This class can be used as is, or subclassed by a connector to define more
- * complex behavior.
- * 
- * @see RepositorySource#getCapabilities()
- * @author Randall Hauch
- */
- at Immutable
-public class RepositorySourceCapabilities {
-
-    /**
-     * The default support for same-name-siblings is {@value} .
-     */
-    public static final boolean DEFAULT_SUPPORT_SAME_NAME_SIBLINGS = true;
-
-    /**
-     * The default support for updates is {@value} .
-     */
-    public static final boolean DEFAULT_SUPPORT_UPDATES = false;
-
-    /**
-     * The default support for updates is {@value} .
-     */
-    public static final boolean DEFAULT_SUPPORT_EVENTS = false;
-
-    private boolean sameNameSiblings;
-    private boolean updates;
-    private boolean events;
-
-    /**
-     * Create a capabilities object using the defaults, .
-     */
-    public RepositorySourceCapabilities() {
-        this(DEFAULT_SUPPORT_SAME_NAME_SIBLINGS, DEFAULT_SUPPORT_UPDATES, DEFAULT_SUPPORT_EVENTS);
-    }
-
-    public RepositorySourceCapabilities( boolean supportsSameNameSiblings,
-                                         boolean supportsUpdates ) {
-        this(supportsSameNameSiblings, supportsUpdates, DEFAULT_SUPPORT_EVENTS);
-    }
-
-    public RepositorySourceCapabilities( boolean supportsSameNameSiblings,
-                                         boolean supportsUpdates,
-                                         boolean supportsEvents ) {
-        this.sameNameSiblings = supportsSameNameSiblings;
-        this.updates = supportsUpdates;
-        this.events = supportsEvents;
-    }
-
-    /**
-     * Return whether the source supports same name siblings. If not, then no two siblings may share the same name.
-     * 
-     * @return true if same name siblings are supported, or false otherwise
-     */
-    public boolean supportsSameNameSiblings() {
-        return sameNameSiblings;
-    }
-
-    /**
-     * Return whether the source supports updates. This may be true, even though a particular connection made on behalf of a user
-     * may not have any update privileges. In other words, returning <code>false</code> implies that no connections would allow
-     * updates to the content.
-     * 
-     * @return true if updates are supported, or false if the source only supports reads.
-     */
-    public boolean supportsUpdates() {
-        return updates;
-    }
-
-    /**
-     * Return whether the source supports events through {@link RepositorySourceListener}s.
-     * 
-     * @return true if events are supported, or false if the source is not capable of generating events
-     */
-    public boolean supportsEvents() {
-        return events;
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceCapabilities.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositorySourceCapabilities.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceCapabilities.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceCapabilities.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,103 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import net.jcip.annotations.Immutable;
+
+/**
+ * The capabilities of a {@link RepositorySource}. This class can be used as is, or subclassed by a connector to define more
+ * complex behavior.
+ * 
+ * @see RepositorySource#getCapabilities()
+ * @author Randall Hauch
+ */
+ at Immutable
+public class RepositorySourceCapabilities {
+
+    /**
+     * The default support for same-name-siblings is {@value} .
+     */
+    public static final boolean DEFAULT_SUPPORT_SAME_NAME_SIBLINGS = true;
+
+    /**
+     * The default support for updates is {@value} .
+     */
+    public static final boolean DEFAULT_SUPPORT_UPDATES = false;
+
+    /**
+     * The default support for updates is {@value} .
+     */
+    public static final boolean DEFAULT_SUPPORT_EVENTS = false;
+
+    private boolean sameNameSiblings;
+    private boolean updates;
+    private boolean events;
+
+    /**
+     * Create a capabilities object using the defaults, .
+     */
+    public RepositorySourceCapabilities() {
+        this(DEFAULT_SUPPORT_SAME_NAME_SIBLINGS, DEFAULT_SUPPORT_UPDATES, DEFAULT_SUPPORT_EVENTS);
+    }
+
+    public RepositorySourceCapabilities( boolean supportsSameNameSiblings,
+                                         boolean supportsUpdates ) {
+        this(supportsSameNameSiblings, supportsUpdates, DEFAULT_SUPPORT_EVENTS);
+    }
+
+    public RepositorySourceCapabilities( boolean supportsSameNameSiblings,
+                                         boolean supportsUpdates,
+                                         boolean supportsEvents ) {
+        this.sameNameSiblings = supportsSameNameSiblings;
+        this.updates = supportsUpdates;
+        this.events = supportsEvents;
+    }
+
+    /**
+     * Return whether the source supports same name siblings. If not, then no two siblings may share the same name.
+     * 
+     * @return true if same name siblings are supported, or false otherwise
+     */
+    public boolean supportsSameNameSiblings() {
+        return sameNameSiblings;
+    }
+
+    /**
+     * Return whether the source supports updates. This may be true, even though a particular connection made on behalf of a user
+     * may not have any update privileges. In other words, returning <code>false</code> implies that no connections would allow
+     * updates to the content.
+     * 
+     * @return true if updates are supported, or false if the source only supports reads.
+     */
+    public boolean supportsUpdates() {
+        return updates;
+    }
+
+    /**
+     * Return whether the source supports events through {@link RepositorySourceListener}s.
+     * 
+     * @return true if events are supported, or false if the source is not capable of generating events
+     */
+    public boolean supportsEvents() {
+        return events;
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceException.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositorySourceException.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,84 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-/**
- * @author Randall Hauch
- */
-public class RepositorySourceException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = -7704170453962924565L;
-    private final String sourceName;
-
-    /**
-     * @param sourceName the identifier of the source from which this exception eminates
-     */
-    public RepositorySourceException( String sourceName ) {
-        this.sourceName = sourceName;
-    }
-
-    /**
-     * @param sourceName the identifier of the source from which this exception eminates
-     * @param message
-     */
-    public RepositorySourceException( String sourceName, String message ) {
-        super(message);
-        this.sourceName = sourceName;
-    }
-
-    /**
-     * @param sourceName the identifier of the source from which this exception eminates
-     * @param cause
-     */
-    public RepositorySourceException( String sourceName, Throwable cause ) {
-        super(cause);
-        this.sourceName = sourceName;
-    }
-
-    /**
-     * @param sourceName the identifier of the source from which this exception eminates
-     * @param message
-     * @param cause
-     */
-    public RepositorySourceException( String sourceName, String message, Throwable cause ) {
-        super(message, cause);
-        this.sourceName = sourceName;
-    }
-
-    /**
-     * @return sourceName
-     */
-    public String getSourceName() {
-        return this.sourceName;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return super.toString();
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceException.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositorySourceException.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceException.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,84 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+/**
+ * @author Randall Hauch
+ */
+public class RepositorySourceException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = -7704170453962924565L;
+    private final String sourceName;
+
+    /**
+     * @param sourceName the identifier of the source from which this exception eminates
+     */
+    public RepositorySourceException( String sourceName ) {
+        this.sourceName = sourceName;
+    }
+
+    /**
+     * @param sourceName the identifier of the source from which this exception eminates
+     * @param message
+     */
+    public RepositorySourceException( String sourceName, String message ) {
+        super(message);
+        this.sourceName = sourceName;
+    }
+
+    /**
+     * @param sourceName the identifier of the source from which this exception eminates
+     * @param cause
+     */
+    public RepositorySourceException( String sourceName, Throwable cause ) {
+        super(cause);
+        this.sourceName = sourceName;
+    }
+
+    /**
+     * @param sourceName the identifier of the source from which this exception eminates
+     * @param message
+     * @param cause
+     */
+    public RepositorySourceException( String sourceName, String message, Throwable cause ) {
+        super(message, cause);
+        this.sourceName = sourceName;
+    }
+
+    /**
+     * @return sourceName
+     */
+    public String getSourceName() {
+        return this.sourceName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceListener.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositorySourceListener.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceListener.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,33 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-/**
- * Interface for a component that wants to listen to changes occurring in a {@link RepositorySource}.
- * 
- * @author Randall Hauch
- */
-public interface RepositorySourceListener {
-
-    void notify( String sourceName,
-                 Object... events );
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceListener.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositorySourceListener.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceListener.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySourceListener.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,33 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+/**
+ * Interface for a component that wants to listen to changes occurring in a {@link RepositorySource}.
+ * 
+ * @author Randall Hauch
+ */
+public interface RepositorySourceListener {
+
+    void notify( String sourceName,
+                 Object... events );
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/package-info.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/package-info.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,100 +0,0 @@
-/**
- * JBoss DNA uses <i>connectors</i> to access information from external systems (such as databases, 
- * other repositories, services, applications, etc.) and create graph representations of that information.
- * This package defines the interfaces that a connector must implement.
- * 
- * <h3>Concepts</h3>
- * <p>
- * A <strong>connector</strong> is the runnable code packaged in one or more JAR files that contains implementations
- * of several interfaces (described below). A Java developer writes a connector to a type of source, 
- * such as a particular database management system, LDAP directory, source code management system, etc. 
- * It is then packaged into one or more JAR files (including dependent JARs) and deployed for use in 
- * applications that use JBoss DNA repositories.
- * </p>
- * <p>
- * The description of a particular source system (e.g., the "Customer" database, or the company LDAP system) is 
- * called a <strong>repository source</strong>. JBoss DNA defines a {@link RepositorySource} interface that defines methods 
- * describing the behavior and supported features and a method for establishing connections. A connector will 
- * have a class that implements this interface and that has JavaBean properties for all of the connector-specific 
- * properties required to fully describe an instance of the system. Use of JavaBean properties is not required, 
- * but it is highly recommended, as it enables reflective configuration and administration. Applications that 
- * use JBoss DNA create an instance of the connector's {@link RepositorySource} implementation and set the properties 
- * for the external source that the application wants to access with that connector.
- * </p>
- * <p>
- * A repository source instance is then used to establish <strong>connections</strong> to that source. 
- * A connector provides an implementation of the {@link RepositoryConnection} interface, which defines methods for 
- * interacting with the external system. In particular, the execute(...) method takes an {@link org.jboss.dna.graph.ExecutionContext} 
- * instance and a {@link org.jboss.dna.graph.requests.Request} object. The object defines the environment in which 
- * the processing is occurring, including information about the JAAS Subject and LoginContext. The 
- * {@link org.jboss.dna.graph.requests.Request} object describes the requested 
- * operations on the content, with different concrete subclasses representing each type of activity. 
- * Examples of commands include (but not limited to) getting a node, moving a node, creating a node, 
- * changing a node, and deleting a node. And, if the repository source is able to participate in JTA/JTS 
- * distributed transactions, then the {@link RepositoryConnection} must implement the {@link RepositoryConnection#getXAResource()}
- * method by returning a valid {@link javax.transaction.xa.XAResource} object that can be used by the transaction monitor. 
- * </p>
- * 
- * <h3>Example connector</h3>
- * <p>
- * As an example, consider that we want JBoss DNA to give us access through JCR to the schema information contained
- * in a relational databases. We first have to develop a connector that allows us to interact with relational
- * databases using JDBC. That connector would contain a <code>JdbcRepositorySource</code> Java class that 
- * implements {@link RepositorySource}, and that has all of the various JavaBean properties for setting the 
- * name of the driver class, URL, username, password, and other properties. (Or we might have a JavaBean property 
- * that defines the JNDI name where we can find a JDBC DataSource instance pointing to our JDBC database.)
- * </p>
- * <p>
- * Our new connector would also have a <code>JdbcRepositoryConnection</code> Java class that implements the 
- * {@link RepositoryConnection} interface. This class would probably wrap a {@link java.sql.Connection JDBC database connection}, 
- * and would implement the {@link RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext, org.jboss.dna.graph.requests.Request)}
- * method such that the nodes exposed by the connector describe the database schema of the database. For example, 
- * the connector might represent each database table as a node with the table's name, with properties that describe 
- * the table (e.g., the description, whether it's a temporary table), and with child nodes that represent each of 
- * the columns, keys and constraints.
- * </p>
- * <p>
- * To use our connector in an application that uses JBoss DNA, we need to create an instance of the 
- * <code>JdbcRepositorySource</code> for each database instance that we want to access. If we have 3 MySQL databases, 
- * 9 Oracle databases, and 4 PostgreSQL databases, then we'd need to create a total of 16 <code>JdbcRepositorySource</code> instances, 
- * each with the properties describing a single database instance. Those sources are then available for use by 
- * JBoss DNA components, including the JCR implementation.
- * </p>
- * 
- * <h3>Implementing a connector</h3>
- * <p>
- * As mentioned earlier, a connector consists of the Java code that is used to access content from a system. 
- * Perhaps the most important class that makes up a connector is the implementation of the {@link RepositorySource}. 
- * This class is analogous to JDBC's {@link javax.sql.DataSource} in that it is instantiated to represent a single 
- * instance of a system that will be accessed, and it contains enough information (in the form of JavaBean properties) 
- * so that it can create connections to the source.
- * </p>
- * <p>
- * Why is the RepositorySource implementation a JavaBean? Well, this is the class that is instantiated, usually reflectively, 
- * and so a no-arg constructor is required. Using JavaBean properties makes it possible to reflect upon the object's 
- * class to determine the properties that can be set (using setters) and read (using getters). This means that an 
- * administrative application can instantiate, configure, and manage the objects that represent the actual sources, 
- * without having to know anything about the actual implementation.
- * </p>
- * 
- * <h3>Testing a connector implementation</h3>
- * <p>
- * Testing connectors is not really that much different than testing other classes. Using mocks may help to isolate 
- * your instances so you can create more unit tests that don't require the underlying source system.
- * </p>
- * <p>
- * JBoss DNA does provide a set of {@link org.jboss.dna.graph.connectors.test unit tests} that you can use to
- * verify that your connector "behaves correctly".  These are useful because you only have to set up the test case
- * classes (by extending one of the provided test case classes and overriding the appropriate set up methods),
- * but you don't have to write any test methods (since they're all inherited).
- * </p>
- * <p>
- * However, there may be times when you have to use the underlying source system in your tests. If this is the case, 
- * we recommend using Maven integration tests, which run at a different point in the Maven lifecycle. 
- * The benefit of using integration tests is that by convention they're able to rely upon external systems. 
- * Plus, your unit tests don't become polluted with slow-running tests that break if the external system is not available.
- * </p>
- */
-
-package org.jboss.dna.graph.connectors;
-

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/package-info.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/package-info.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/package-info.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,100 @@
+/**
+ * JBoss DNA uses <i>connectors</i> to access information from external systems (such as databases, 
+ * other repositories, services, applications, etc.) and create graph representations of that information.
+ * This package defines the interfaces that a connector must implement.
+ * 
+ * <h3>Concepts</h3>
+ * <p>
+ * A <strong>connector</strong> is the runnable code packaged in one or more JAR files that contains implementations
+ * of several interfaces (described below). A Java developer writes a connector to a type of source, 
+ * such as a particular database management system, LDAP directory, source code management system, etc. 
+ * It is then packaged into one or more JAR files (including dependent JARs) and deployed for use in 
+ * applications that use JBoss DNA repositories.
+ * </p>
+ * <p>
+ * The description of a particular source system (e.g., the "Customer" database, or the company LDAP system) is 
+ * called a <strong>repository source</strong>. JBoss DNA defines a {@link RepositorySource} interface that defines methods 
+ * describing the behavior and supported features and a method for establishing connections. A connector will 
+ * have a class that implements this interface and that has JavaBean properties for all of the connector-specific 
+ * properties required to fully describe an instance of the system. Use of JavaBean properties is not required, 
+ * but it is highly recommended, as it enables reflective configuration and administration. Applications that 
+ * use JBoss DNA create an instance of the connector's {@link RepositorySource} implementation and set the properties 
+ * for the external source that the application wants to access with that connector.
+ * </p>
+ * <p>
+ * A repository source instance is then used to establish <strong>connections</strong> to that source. 
+ * A connector provides an implementation of the {@link RepositoryConnection} interface, which defines methods for 
+ * interacting with the external system. In particular, the execute(...) method takes an {@link org.jboss.dna.graph.ExecutionContext} 
+ * instance and a {@link org.jboss.dna.graph.request.Request} object. The object defines the environment in which 
+ * the processing is occurring, including information about the JAAS Subject and LoginContext. The 
+ * {@link org.jboss.dna.graph.request.Request} object describes the requested 
+ * operations on the content, with different concrete subclasses representing each type of activity. 
+ * Examples of commands include (but not limited to) getting a node, moving a node, creating a node, 
+ * changing a node, and deleting a node. And, if the repository source is able to participate in JTA/JTS 
+ * distributed transactions, then the {@link RepositoryConnection} must implement the {@link RepositoryConnection#getXAResource()}
+ * method by returning a valid {@link javax.transaction.xa.XAResource} object that can be used by the transaction monitor. 
+ * </p>
+ * 
+ * <h3>Example connector</h3>
+ * <p>
+ * As an example, consider that we want JBoss DNA to give us access through JCR to the schema information contained
+ * in a relational databases. We first have to develop a connector that allows us to interact with relational
+ * databases using JDBC. That connector would contain a <code>JdbcRepositorySource</code> Java class that 
+ * implements {@link RepositorySource}, and that has all of the various JavaBean properties for setting the 
+ * name of the driver class, URL, username, password, and other properties. (Or we might have a JavaBean property 
+ * that defines the JNDI name where we can find a JDBC DataSource instance pointing to our JDBC database.)
+ * </p>
+ * <p>
+ * Our new connector would also have a <code>JdbcRepositoryConnection</code> Java class that implements the 
+ * {@link RepositoryConnection} interface. This class would probably wrap a {@link java.sql.Connection JDBC database connection}, 
+ * and would implement the {@link RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext, org.jboss.dna.graph.request.Request)}
+ * method such that the nodes exposed by the connector describe the database schema of the database. For example, 
+ * the connector might represent each database table as a node with the table's name, with properties that describe 
+ * the table (e.g., the description, whether it's a temporary table), and with child nodes that represent each of 
+ * the columns, keys and constraints.
+ * </p>
+ * <p>
+ * To use our connector in an application that uses JBoss DNA, we need to create an instance of the 
+ * <code>JdbcRepositorySource</code> for each database instance that we want to access. If we have 3 MySQL databases, 
+ * 9 Oracle databases, and 4 PostgreSQL databases, then we'd need to create a total of 16 <code>JdbcRepositorySource</code> instances, 
+ * each with the properties describing a single database instance. Those sources are then available for use by 
+ * JBoss DNA components, including the JCR implementation.
+ * </p>
+ * 
+ * <h3>Implementing a connector</h3>
+ * <p>
+ * As mentioned earlier, a connector consists of the Java code that is used to access content from a system. 
+ * Perhaps the most important class that makes up a connector is the implementation of the {@link RepositorySource}. 
+ * This class is analogous to JDBC's {@link javax.sql.DataSource} in that it is instantiated to represent a single 
+ * instance of a system that will be accessed, and it contains enough information (in the form of JavaBean properties) 
+ * so that it can create connections to the source.
+ * </p>
+ * <p>
+ * Why is the RepositorySource implementation a JavaBean? Well, this is the class that is instantiated, usually reflectively, 
+ * and so a no-arg constructor is required. Using JavaBean properties makes it possible to reflect upon the object's 
+ * class to determine the properties that can be set (using setters) and read (using getters). This means that an 
+ * administrative application can instantiate, configure, and manage the objects that represent the actual sources, 
+ * without having to know anything about the actual implementation.
+ * </p>
+ * 
+ * <h3>Testing a connector implementation</h3>
+ * <p>
+ * Testing connectors is not really that much different than testing other classes. Using mocks may help to isolate 
+ * your instances so you can create more unit tests that don't require the underlying source system.
+ * </p>
+ * <p>
+ * JBoss DNA does provide a set of {@link org.jboss.dna.graph.connector.test unit tests} that you can use to
+ * verify that your connector "behaves correctly".  These are useful because you only have to set up the test case
+ * classes (by extending one of the provided test case classes and overriding the appropriate set up methods),
+ * but you don't have to write any test methods (since they're all inherited).
+ * </p>
+ * <p>
+ * However, there may be times when you have to use the underlying source system in your tests. If this is the case, 
+ * we recommend using Maven integration tests, which run at a different point in the Maven lifecycle. 
+ * The benefit of using integration tests is that by convention they're able to rely upon external systems. 
+ * Plus, your unit tests don't become polluted with slow-running tests that break if the external system is not available.
+ * </p>
+ */
+
+package org.jboss.dna.graph.connector;
+

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Binary.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Binary.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Binary.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,91 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.io.InputStream;
-import java.io.Serializable;
-import java.security.MessageDigest;
-import net.jcip.annotations.Immutable;
-
-/**
- * Value holder for binary data. Binary instances are not mutable.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public interface Binary extends Comparable<Binary>, Serializable {
-
-    /**
-     * Get the length of this binary data.
-     * 
-     * @return the number of bytes in this binary data
-     * @see #acquire()
-     */
-    public long getSize();
-
-    /**
-     * Get the SHA-1 hash of the contents. This hash can be used to determine whether two Binary instances contain the same
-     * content.
-     * <p>
-     * Repeatedly calling this method should generally be efficient, as it most implementations will compute the hash only once.
-     * </p>
-     * 
-     * @return the hash of the contents as a byte array, or an empty array if the hash could not be computed.
-     * @see #acquire()
-     * @see MessageDigest#digest(byte[])
-     * @see MessageDigest#getInstance(String)
-     */
-    public byte[] getHash();
-
-    /**
-     * Get the contents of this data as a stream.
-     * 
-     * @return the stream to this data's contents
-     * @see #acquire()
-     * @throws IoException if there is a problem returning the stream
-     */
-    public InputStream getStream();
-
-    /**
-     * Get the contents of this data as a byte array.
-     * 
-     * @return the data as an array
-     * @see #acquire()
-     * @throws IoException if there is a problem returning the bytes
-     */
-    public byte[] getBytes();
-
-    /**
-     * Acquire any resources for this data. This method must be called before any other method on this object.
-     * 
-     * @see #release()
-     */
-    public void acquire();
-
-    /**
-     * Release any acquired resources. This method must be called after a client is finished with this value.
-     * 
-     * @see #acquire()
-     */
-    public void release();
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/BinaryFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/BinaryFactory.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/BinaryFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,94 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-
-/**
- * A factory for creating {@link Binary} instances. This interface extends the {@link ValueFactory} generic interface and adds
- * specific methods for creating binary objects.
- * 
- * @author Randall Hauch
- */
-public interface BinaryFactory extends ValueFactory<Binary> {
-
-    /**
-     * Create a value from the binary content given by the supplied stream, the approximate length, and the SHA-1 secure hash of
-     * the content. If the secure hash is null, then a secure hash is computed from the content. If the secure hash is not null,
-     * it is assumed to be the hash for the content and may not be checked.
-     * 
-     * @param stream the stream containing the content to be used to create the value
-     * @param approximateLength the approximate length of the content (in bytes)
-     * @param secureHash the secure hash of the content in the <code>stream</code>; if null, the secure hash is computed from the
-     *        content, and if not null it is assumed to be the correct secure hash (and is not checked)
-     * @return the value, or null if the supplied stream is null
-     * @throws ValueFormatException if the conversion from an input stream could not be performed
-     * @throws IoException If an unexpected problem occurs while accessing the supplied stream (such as an {@link IOException}).
-     * @throws IllegalArgumentException if the secure hash was discovered to be incorrect
-     */
-    Binary create( InputStream stream,
-                   long approximateLength,
-                   byte[] secureHash ) throws ValueFormatException, IoException;
-
-    /**
-     * Create a value from the binary content given by the supplied reader, the approximate length, and the SHA-1 secure hash of
-     * the content. If the secure hash is null, then a secure hash is computed from the content. If the secure hash is not null,
-     * it is assumed to be the hash for the content and may not be checked.
-     * 
-     * @param reader the reader containing the content to be used to create the value
-     * @param approximateLength the approximate length of the content (in bytes)
-     * @param secureHash the secure hash of the content in the <code>stream</code>; if null, the secure hash is computed from the
-     *        content, and if not null it is assumed to be the correct secure hash (and is not checked)
-     * @return the value, or null if the supplied string is null
-     * @throws ValueFormatException if the conversion from a reader could not be performed
-     * @throws IoException If an unexpected problem occurs while accessing the supplied reader (such as an {@link IOException}).
-     * @throws IllegalArgumentException if the secure hash was discovered to be incorrect
-     */
-    Binary create( Reader reader,
-                   long approximateLength,
-                   byte[] secureHash ) throws ValueFormatException, IoException;
-
-    /**
-     * Create a binary value from the given file.
-     * 
-     * @param file the file containing the content to be used
-     * @return the binary value, or null if the file parameter was null
-     * @throws ValueFormatException if the conversion from the file could not be performed
-     * @throws IoException If an unexpected problem occurs while accessing the supplied file (such as an {@link IOException}).
-     */
-    Binary create( File file ) throws ValueFormatException, IoException;
-
-    /**
-     * Find an existing binary value given the supplied secure hash. If no such binary value exists, null is returned. This method
-     * can be used when the caller knows the secure hash (e.g., from a previously-held Binary object), and would like to reuse an
-     * existing binary value (if possible) rather than recreate the binary value by processing the stream contents. This is
-     * especially true when the size of the binary is quite large.
-     * 
-     * @param secureHash the secure hash of the binary content, which was probably {@link Binary#getHash() obtained} from a
-     *        previously-held {@link Binary} object; a null or empty value is allowed, but will always result in returning null
-     * @return the existing Binary value that has the same secure hash, or null if there is no such value available at this time
-     */
-    Binary find( byte[] secureHash );
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTime.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTime.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTime.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,422 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.io.Serializable;
-import java.util.Locale;
-import java.util.concurrent.TimeUnit;
-import net.jcip.annotations.Immutable;
-
-/**
- * An immutable date-time class that represents an instance in time. This class is designed to hide the horrible implementations
- * of the JDK date and calendar classes, which are being overhauled (and replaced) under <a
- * href="http://jcp.org/en/jsr/detail?id=310">JSR-310</a>, which will be based upon <a
- * href="http://joda-time.sourceforge.net/">Joda-Time</a>. This class serves as a stable migration path toward the new JSR 310
- * classes.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public interface DateTime extends Comparable<DateTime>, Serializable {
-
-    /**
-     * Get the ISO-8601 representation of this instance in time. The month-based ISO-8601 representation is the most common format
-     * of ISO8601, and is the format used in the XML standards for passing dates and times:
-     * 
-     * <pre>
-     * yyyy-mm-ddTHH:MM:SS.SSSZ
-     * </pre>
-     * 
-     * The fields are separated by dashes and consist of:
-     * <ul>
-     * <li>four digit year;</li>
-     * <li>two digit month, where 01 is Janurary and 12 is December;</li>
-     * <li>two digit day of month, from 01 to 31;</li>
-     * <li>two digit hour, from 00 to 23;</li>
-     * <li>two digit minute, from 00 to 59;</li>
-     * <li>two digit second, from 00 to 59;</li>
-     * <li>three decimal places for milliseconds, if required;</li>
-     * <li>time zone offset of the form <code>±HH:mm</code> (or '0' if UTC)</li>
-     * </ul>
-     * 
-     * @return the string representation; never null
-     */
-    String getString();
-
-    /**
-     * Get the number of milliseconds from 1970-01-01T00:00Z. This value is consistent with the JDK {@link java.util.Date Date}
-     * and {@link java.util.Calendar Calendar} classes.
-     * 
-     * @return the number of milliseconds from 1970-01-01T00:00Z
-     */
-    long getMilliseconds();
-
-    /**
-     * Get this instance represented as a standard JDK {@link java.util.Date} instance. Note that this conversion loses the time
-     * zone information, as the standard JDK {@link java.util.Date} does not represent time zones.
-     * 
-     * @return this instance in time as a JDK Date; never null
-     */
-    java.util.Date toDate();
-
-    /**
-     * Get this instance represented as a standard JDK {@link java.util.Calendar} instance, in the {@link Locale#getDefault()
-     * default locale}.
-     * 
-     * @return this instance in time as a JDK Calendar; never null
-     */
-    java.util.Calendar toCalendar();
-
-    /**
-     * Get this instance represented as a standard JDK {@link java.util.Calendar} instance, in the specified {@link Locale locale}
-     * .
-     * 
-     * @param locale the locale in which the Calendar instance is desired; may be null if the {@link Locale#getDefault() default
-     *        locale} is to be used.
-     * @return this instance in time as a JDK Calendar; never null
-     */
-    java.util.Calendar toCalendar( Locale locale );
-
-    /**
-     * Get this instance represented as a standard JDK {@link java.util.GregorianCalendar} instance.
-     * 
-     * @return this instance in time as a JDK GregorianCalendar; never null
-     */
-    java.util.GregorianCalendar toGregorianCalendar();
-
-    /**
-     * Get the era of this instance in time.
-     * 
-     * @return the era
-     */
-    int getEra();
-
-    /**
-     * Get the era of this instance in time.
-     * 
-     * @return the era
-     */
-    int getYear();
-
-    /**
-     * Get the era of this instance in time.
-     * 
-     * @return the era
-     */
-    int getWeekyear();
-
-    /**
-     * Get the era of this instance in time.
-     * 
-     * @return the era
-     */
-    int getCenturyOfEra();
-
-    /**
-     * Get the year of the era of this instance in time.
-     * 
-     * @return the year of the era
-     */
-    int getYearOfEra();
-
-    /**
-     * Get the year of this century of this instance in time.
-     * 
-     * @return the year of the century
-     */
-    int getYearOfCentury();
-
-    /**
-     * Get the month of the year of this instance in time.
-     * 
-     * @return the month number
-     */
-    int getMonthOfYear();
-
-    /**
-     * Get the week of the weekyear of this instance in time.
-     * 
-     * @return the week of the weekyear
-     */
-    int getWeekOfWeekyear();
-
-    /**
-     * Get the day of the year of this instance in time.
-     * 
-     * @return the day of the year
-     */
-    int getDayOfYear();
-
-    /**
-     * Get the day of the month value of this instance in time.
-     * 
-     * @return the day of the month
-     */
-    int getDayOfMonth();
-
-    /**
-     * Get the day of the week value of this instance in time.
-     * 
-     * @return the day of the week
-     */
-    int getDayOfWeek();
-
-    /**
-     * Get the hour of the day of this instance in time.
-     * 
-     * @return the hour of the day
-     */
-    int getHourOfDay();
-
-    /**
-     * Get the minute of this instance in time.
-     * 
-     * @return the minute of the hour
-     */
-    int getMinuteOfHour();
-
-    /**
-     * Get the seconds of the minute value of this instance in time.
-     * 
-     * @return the seconds of the minute
-     */
-    int getSecondOfMinute();
-
-    /**
-     * Get the milliseconds of the second value of this instance in time.
-     * 
-     * @return the milliseconds
-     */
-    int getMillisOfSecond();
-
-    /**
-     * Get the number of hours that this time zone is offset from UTC.
-     * 
-     * @return the number of hours
-     */
-    int getTimeZoneOffsetHours();
-
-    /**
-     * Get the identifier of the time zone in which this instant is defined
-     * 
-     * @return the time zone identifier; never null
-     */
-    String getTimeZoneId();
-
-    /**
-     * Convert this time to the same instant in the UTC time zone.
-     * 
-     * @return this instant in time in the specified time zone
-     */
-    DateTime toUtcTimeZone();
-
-    /**
-     * Convert this time to the time zone given by the supplied identifier.
-     * 
-     * @param timeZoneId the time zone identifier
-     * @return the instant in the specified time zone
-     * @throws IllegalArgumentException if the time zone identifier is null or is invalid
-     */
-    DateTime toTimeZone( String timeZoneId );
-
-    /**
-     * Return whether this date-time is earlier than the supplied date-time.
-     * 
-     * @param other the date-time to compare with
-     * @return true if this date-time is earliar than the other, or false otherwise
-     * @see #compareTo(DateTime)
-     * @see #isSameAs(DateTime)
-     * @see #isAfter(DateTime)
-     */
-    boolean isBefore( DateTime other );
-
-    /**
-     * Return whether this date-time is later than the supplied date-time.
-     * 
-     * @param other the date-time to compare with
-     * @return true if this date-time is later than the other, or false otherwise
-     * @see #compareTo(DateTime)
-     * @see #isBefore(DateTime)
-     * @see #isSameAs(DateTime)
-     */
-    boolean isAfter( DateTime other );
-
-    /**
-     * Return whether this date-time is at the same time as the supplied date-time.
-     * 
-     * @param other the date-time to compare with
-     * @return true if this date-time is later than the other, or false otherwise
-     * @see #compareTo(DateTime)
-     * @see #isBefore(DateTime)
-     * @see #isAfter(DateTime)
-     */
-    boolean isSameAs( DateTime other );
-
-    /**
-     * Subtract the specified about of time in the supplied units.
-     * 
-     * @param timeAmount the amount of time to subtract
-     * @param unit the units of the amount of time; may not be null
-     * @return the instance in time the specified number of time before this instant
-     */
-    DateTime minus( long timeAmount,
-                    TimeUnit unit );
-
-    /**
-     * Subtract the specified number of days from this time instant.
-     * 
-     * @param days the number of days to subtract
-     * @return the instance in time the specified number of days before this instant
-     */
-    DateTime minusDays( int days );
-
-    /**
-     * Subtract the specified number of hours from this time instant.
-     * 
-     * @param hours the number of hours to subtract
-     * @return the instance in time the specified number of hours before this instant
-     */
-    DateTime minusHours( int hours );
-
-    /**
-     * Subtract the specified number of milliseconds from this time instant.
-     * 
-     * @param milliseconds the number of milliseconds to subtract
-     * @return the instance in time the specified number of milliseconds before this instant
-     */
-    DateTime minusMillis( int milliseconds );
-
-    /**
-     * Subtract the specified number of minutes from this time instant.
-     * 
-     * @param minutes the number of minutes to subtract
-     * @return the instance in time the specified number of minutes before this instant
-     */
-    DateTime minusMinutes( int minutes );
-
-    /**
-     * Subtract the specified number of months from this time instant.
-     * 
-     * @param months the number of months to subtract
-     * @return the instance in time the specified number of months before this instant
-     */
-    DateTime minusMonths( int months );
-
-    /**
-     * Subtract the specified number of seconds from this time instant.
-     * 
-     * @param seconds the number of seconds to subtract
-     * @return the instance in time the specified number of seconds before this instant
-     */
-    DateTime minusSeconds( int seconds );
-
-    /**
-     * Subtract the specified number of weeks from this time instant.
-     * 
-     * @param weeks the number of weeks to subtract
-     * @return the instance in time the specified number of weeks before this instant
-     */
-    DateTime minusWeeks( int weeks );
-
-    /**
-     * Subtract the specified number of years from this time instant.
-     * 
-     * @param years the number of years to subtract
-     * @return the instance in time the specified number of years before this instant
-     */
-    DateTime minusYears( int years );
-
-    /**
-     * Add the specified about of time in the supplied units.
-     * 
-     * @param timeAmount the amount of time to add
-     * @param unit the units of the amount of time; may not be null
-     * @return the instance in time the specified number of time after this instant
-     */
-    DateTime plus( long timeAmount,
-                   TimeUnit unit );
-
-    /**
-     * Add the specified number of days from this time instant.
-     * 
-     * @param days the number of days to add
-     * @return the instance in time the specified number of days after this instant
-     */
-    DateTime plusDays( int days );
-
-    /**
-     * Add the specified number of hours from this time instant.
-     * 
-     * @param hours the number of hours to add
-     * @return the instance in time the specified number of hours after this instant
-     */
-    DateTime plusHours( int hours );
-
-    /**
-     * Add the specified number of milliseconds from this time instant.
-     * 
-     * @param milliseconds the number of milliseconds to add
-     * @return the instance in time the specified number of milliseconds after this instant
-     */
-    DateTime plusMillis( int milliseconds );
-
-    /**
-     * Add the specified number of minutes from this time instant.
-     * 
-     * @param minutes the number of minutes to add
-     * @return the instance in time the specified number of minutes after this instant
-     */
-    DateTime plusMinutes( int minutes );
-
-    /**
-     * Add the specified number of months from this time instant.
-     * 
-     * @param months the number of months to add
-     * @return the instance in time the specified number of months after this instant
-     */
-    DateTime plusMonths( int months );
-
-    /**
-     * Add the specified number of seconds from this time instant.
-     * 
-     * @param seconds the number of seconds to add
-     * @return the instance in time the specified number of seconds after this instant
-     */
-    DateTime plusSeconds( int seconds );
-
-    /**
-     * Add the specified number of weeks from this time instant.
-     * 
-     * @param weeks the number of weeks to add
-     * @return the instance in time the specified number of weeks after this instant
-     */
-    DateTime plusWeeks( int weeks );
-
-    /**
-     * Add the specified number of years from this time instant.
-     * 
-     * @param years the number of years to add
-     * @return the instance in time the specified number of years after this instant
-     */
-    DateTime plusYears( int years );
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTimeFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTimeFactory.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTimeFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,194 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-
-/**
- * A factory for creating {@link DateTime date-time instants}. This interface extends the {@link ValueFactory} generic interface
- * and adds specific methods for creating instants for the current time (and time zone) as well as various combinations of
- * individual field values. <h2>ISO-8601</h2>
- * <p>
- * The factory creates date-time instants from strings that are in the standard ISO-8601 format. There are three supported styles:
- * month-based, day-of-year-based, and week-based.
- * </p>
- * <h3>Month-Based</h3>
- * <p>
- * The month-based representation is the most common format of ISO8601, and is the format used in the XML standards for passing
- * dates and times:
- * 
- * <pre>
- * yyyy-mm-ddTHH:MM:SS.SSSZ
- * </pre>
- * 
- * The fields are separated by dashes and consist of:
- * <ul>
- * <li>four digit year;</li>
- * <li>two digit month, where 01 is Janurary and 12 is December;</li>
- * <li>two digit day of month, from 01 to 31;</li>
- * <li>two digit hour, from 00 to 23;</li>
- * <li>two digit minute, from 00 to 59;</li>
- * <li>two digit second, from 00 to 59;</li>
- * <li>three decimal places for milliseconds, if required;</li>
- * <li>time zone offset of the form <code>±HH:mm</code> (or '0' if UTC)</li>
- * </ul>
- * </p>
- * <h3>Day of Year Based</h3>
- * <p>
- * This format of ISO-8601 uses a single field to represent the day of the year:
- * 
- * <pre>
- * yyyy-dddTHH:MM:SS.SSSZ
- * </pre>
- * 
- * The fields are separated by dashes and consist of:
- * <ul>
- * <li>four digit year</li>
- * <li>three digit day of year, from 001 to 366;</li>
- * <li>two digit hour, from 00 to 23;</li>
- * <li>two digit minute, from 00 to 59;</li>
- * <li>two digit second, from 00 to 59;</li>
- * <li>three decimal places for milliseconds, if required;</li>
- * <li>time zone offset of the form <code>±HH:mm</code> (or '0' if UTC)</li>
- * </ul>
- * </p>
- * <h3>Week Based</h3>
- * <p>
- * This format of ISO-8601 uses a single field to represent the day of the year:
- * 
- * <pre>
- * yyyy-Www-dTHH:MM:SS.SSSZ
- * </pre>
- * 
- * The fields are separated by dashes and consist of:
- * <ul>
- * <li>four digit weekyear (see below)</li>
- * <li>two digit week of year, from 01 to 53;</li>
- * <li>one digit day of week, from 1 to 7 where 1 is Monday and 7 is Sunday;</li>
- * <li>two digit hour, from 00 to 23;</li>
- * <li>two digit minute, from 00 to 59;</li>
- * <li>two digit second, from 00 to 59;</li>
- * <li>three decimal places for milliseconds, if required;</li>
- * <li>time zone offset of the form <code>±HH:mm</code> (or '0' if UTC)</li>
- * </ul>
- * </p>
- * <p>
- * From <a href="http://joda-time.sourceforge.net/cal_iso.html">Joda-Time</a>: Weeks are always complete, and the first week of a
- * year is the one that includes the first Thursday of the year. This definition can mean that the first week of a year starts in
- * the previous year, and the last week finishes in the next year. The weekyear field is defined to refer to the year that owns
- * the week, which may differ from the actual year.
- * </p>
- * 
- * @author Randall Hauch
- */
-public interface DateTimeFactory extends ValueFactory<DateTime> {
-
-    /**
-     * Create a date-time instance for the current time in the local time zone.
-     * 
-     * @return the current date-time instance
-     * @see #createUtc()
-     */
-    DateTime create();
-
-    /**
-     * Create a date-time instance for the current time in UTC.
-     * 
-     * @return the current date-time instance (in UTC)
-     * @see #create()
-     */
-    DateTime createUtc();
-
-    /**
-     * Create a date-time instance that is offset from the original by the specified amount.
-     * 
-     * @param original
-     * @param offsetInMillis the offset in milliseconds (positive or negative)
-     * @return the offset date-time instance
-     */
-    DateTime create( DateTime original,
-                     long offsetInMillis );
-
-    /**
-     * Create a date-time instance given the individual values for the fields
-     * 
-     * @param year the year of the era
-     * @param monthOfYear the month of the year
-     * @param dayOfMonth the day of the month
-     * @param hourOfDay the hour of the day
-     * @param minuteOfHour the minute of the hour
-     * @param secondOfMinute the second of the minute
-     * @param millisecondsOfSecond the milliseconds of the second
-     * @return the date-time instance
-     */
-    DateTime create( int year,
-                     int monthOfYear,
-                     int dayOfMonth,
-                     int hourOfDay,
-                     int minuteOfHour,
-                     int secondOfMinute,
-                     int millisecondsOfSecond );
-
-    /**
-     * Create a date-time instance given the individual values for the fields
-     * 
-     * @param year the year of the era
-     * @param monthOfYear the month of the year
-     * @param dayOfMonth the day of the month
-     * @param hourOfDay the hour of the day
-     * @param minuteOfHour the minute of the hour
-     * @param secondOfMinute the second of the minute
-     * @param millisecondsOfSecond the milliseconds of the second
-     * @param timeZoneOffsetHours the number of hours offset from UTC for the time zone
-     * @return the date-time instance
-     */
-    DateTime create( int year,
-                     int monthOfYear,
-                     int dayOfMonth,
-                     int hourOfDay,
-                     int minuteOfHour,
-                     int secondOfMinute,
-                     int millisecondsOfSecond,
-                     int timeZoneOffsetHours );
-
-    /**
-     * Create a date-time instance given the individual values for the fields
-     * 
-     * @param year the year of the era
-     * @param monthOfYear the month of the year
-     * @param dayOfMonth the day of the month
-     * @param hourOfDay the hour of the day
-     * @param minuteOfHour the minute of the hour
-     * @param secondOfMinute the second of the minute
-     * @param millisecondsOfSecond the milliseconds of the second
-     * @param timeZoneId the ID of the time zone (e.g, "PST", "UTC", "EDT"); may not be null
-     * @return the date-time instance
-     */
-    DateTime create( int year,
-                     int monthOfYear,
-                     int dayOfMonth,
-                     int hourOfDay,
-                     int minuteOfHour,
-                     int secondOfMinute,
-                     int millisecondsOfSecond,
-                     String timeZoneId );
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathException.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathException.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,71 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-/**
- * @author Randall Hauch
- */
-public class InvalidPathException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = 6034512896518552227L;
-
-    /**
-     * 
-     */
-    public InvalidPathException() {
-    }
-
-    /**
-     * @param message
-     */
-    public InvalidPathException( String message ) {
-        super(message);
-
-    }
-
-    /**
-     * @param cause
-     */
-    public InvalidPathException( Throwable cause ) {
-        super(cause);
-
-    }
-
-    /**
-     * @param message
-     * @param cause
-     */
-    public InvalidPathException( String message, Throwable cause ) {
-        super(message, cause);
-
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return super.toString();
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathExpressionException.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathExpressionException.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathExpressionException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,65 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-/**
- * @author Randall Hauch
- */
-public class InvalidPathExpressionException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = 358951801604727022L;
-
-    /**
-     * 
-     */
-    public InvalidPathExpressionException() {
-    }
-
-    /**
-     * @param message
-     */
-    public InvalidPathExpressionException( String message ) {
-        super(message);
-
-    }
-
-    /**
-     * @param cause
-     */
-    public InvalidPathExpressionException( Throwable cause ) {
-        super(cause);
-
-    }
-
-    /**
-     * @param message
-     * @param cause
-     */
-    public InvalidPathExpressionException( String message,
-                                           Throwable cause ) {
-        super(message, cause);
-
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/IoException.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/IoException.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/IoException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,73 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class IoException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = -2015526722307950714L;
-
-    /**
-     * 
-     */
-    public IoException() {
-    }
-
-    /**
-     * @param message
-     */
-    public IoException( String message ) {
-        super(message);
-
-    }
-
-    /**
-     * @param cause
-     */
-    public IoException( Throwable cause ) {
-        super(cause);
-
-    }
-
-    /**
-     * @param message
-     * @param cause
-     */
-    public IoException( String message,
-                                 Throwable cause ) {
-        super(message, cause);
-
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return super.toString();
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Name.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Name.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Name.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,115 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.io.Serializable;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.properties.Path.Segment;
-
-/**
- * A qualified name consisting of a namespace and a local name.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public interface Name extends Comparable<Name>, Serializable {
-
-    /**
-     * Get the local name part of this qualified name.
-     * 
-     * @return the local name; never null
-     */
-    String getLocalName();
-
-    /**
-     * Get the URI for the namespace used in this qualified name.
-     * 
-     * @return the URI; never null but possibly empty
-     */
-    String getNamespaceUri();
-
-    /**
-     * Get the string form of the name. The {@link Path#DEFAULT_ENCODER default encoder} is used to encode characters in the local
-     * name and namespace.
-     * 
-     * @return the encoded string
-     * @see #getString(TextEncoder)
-     */
-    public String getString();
-
-    /**
-     * Get the encoded string form of the name, using the supplied encoder to encode characters in the local name and namespace.
-     * 
-     * @param encoder the encoder to use, or null if the {@link Path#DEFAULT_ENCODER default encoder} should be used
-     * @return the encoded string
-     * @see #getString()
-     */
-    public String getString( TextEncoder encoder );
-
-    /**
-     * Get the string form of the name, using the supplied namespace registry to convert the {@link #getNamespaceUri() namespace
-     * URI} to a prefix. The {@link Path#DEFAULT_ENCODER default encoder} is used to encode characters in each of the path
-     * segments.
-     * 
-     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-     *        {@link Name#getNamespaceUri() namespace URI}
-     * @return the encoded string
-     * @throws IllegalArgumentException if the namespace registry is null
-     * @see #getString(NamespaceRegistry,TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry );
-
-    /**
-     * Get the encoded string form of the name, using the supplied namespace registry to convert the {@link #getNamespaceUri()
-     * namespace URI} to a prefix.
-     * 
-     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-     *        {@link Name#getNamespaceUri() namespace URI}
-     * @param encoder the encoder to use, or null if the {@link Path#DEFAULT_ENCODER default encoder} should be used
-     * @return the encoded string
-     * @throws IllegalArgumentException if the namespace registry is null
-     * @see #getString(NamespaceRegistry)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder );
-
-    /**
-     * Get the encoded string form of the name, using the supplied namespace registry to convert the names' namespace URIs to
-     * prefixes and the supplied encoder to encode characters in each of the path segments, and using the second delimiter to
-     * encode (or convert) the delimiter used between the namespace prefix and the local part.
-     * 
-     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-     *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
-     * @param encoder the encoder to use for encoding the {@link Name#getLocalName() local part} and
-     *        {@link Name#getNamespaceUri() namespace prefix}, or null if the {@link Path#DEFAULT_ENCODER default encoder} should
-     *        be used
-     * @param delimiterEncoder the encoder to use for encoding the delimiter between the {@link Name#getLocalName() local part}
-     *        and {@link Name#getNamespaceUri() namespace prefix}, or null if the standard delimiter should be used
-     * @return the encoded string
-     * @see #getString(NamespaceRegistry)
-     * @see #getString(NamespaceRegistry, TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder,
-                             TextEncoder delimiterEncoder );
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NameFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NameFactory.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NameFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,66 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import org.jboss.dna.common.text.TextDecoder;
-
-/**
- * A factory for creating {@link Name names}.
- * 
- * @author Randall Hauch
- */
-public interface NameFactory extends ValueFactory<Name> {
-
-    /**
-     * Create a name from the given namespace URI and local name.
-     * <p>
-     * This method is equivalent to calling {@link #create(String, String, TextDecoder)} with a null encoder.
-     * </p>
-     * 
-     * @param namespaceUri the namespace URI
-     * @param localName the local name
-     * @return the new name
-     * @throws IllegalArgumentException if the local name is <code>null</code> or empty
-     */
-    Name create( String namespaceUri,
-                 String localName );
-
-    /**
-     * Create a name from the given namespace URI and local name.
-     * 
-     * @param namespaceUri the namespace URI
-     * @param localName the local name
-     * @param decoder the decoder that should be used to decode the qualified name
-     * @return the new name
-     * @throws IllegalArgumentException if the local name is <code>null</code> or empty
-     */
-    Name create( String namespaceUri,
-                 String localName,
-                 TextDecoder decoder );
-
-    /**
-     * Get the namespace registry.
-     * 
-     * @return the namespace registry; never <code>null</code>
-     */
-    NamespaceRegistry getNamespaceRegistry();
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceException.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceException.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,71 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-/**
- * @author Randall Hauch
- */
-public class NamespaceException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = 1300642242538881207L;
-
-    /**
-     * 
-     */
-    public NamespaceException() {
-    }
-
-    /**
-     * @param message
-     */
-    public NamespaceException( String message ) {
-        super(message);
-
-    }
-
-    /**
-     * @param cause
-     */
-    public NamespaceException( Throwable cause ) {
-        super(cause);
-
-    }
-
-    /**
-     * @param message
-     * @param cause
-     */
-    public NamespaceException( String message, Throwable cause ) {
-        super(message, cause);
-
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return super.toString();
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceRegistry.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceRegistry.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceRegistry.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,136 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.util.Set;
-import net.jcip.annotations.Immutable;
-import net.jcip.annotations.ThreadSafe;
-
-/**
- * Registry of namespaces, which are used to provide isolated and independent domains for {@link Name names}.
- * 
- * @author Randall Hauch
- */
- at ThreadSafe
-public interface NamespaceRegistry {
-
-    /**
-     * Return the namespace URI that is currently mapped to the empty prefix, or null if there is no current default namespace.
-     * 
-     * @return the namespace URI that represents the default namespace, or null if there is no default namespace
-     */
-    String getDefaultNamespaceUri();
-
-    /**
-     * Get the namespace URI for the supplied prefix.
-     * 
-     * @param prefix the namespace prefix
-     * @return the namespace URI for the supplied prefix, or null if there is no namespace currently registered to use that prefix
-     * @throws IllegalArgumentException if the prefix is null
-     */
-    String getNamespaceForPrefix( String prefix );
-
-    /**
-     * Return the prefix used for the supplied namespace URI.
-     * 
-     * @param namespaceUri the namespace URI
-     * @param generateIfMissing true if the namespace URI has not already been registered and the method should auto-register the
-     *        namespace with a generated prefix, or false if the method should never auto-register the namespace
-     * @return the prefix currently being used for the namespace, or <code>null</code> if the namespace has not been registered
-     *         and <code>generateIfMissing</code> is <code>false</code>
-     * @throws IllegalArgumentException if the namespace URI is null
-     * @see #isRegisteredNamespaceUri(String)
-     */
-    String getPrefixForNamespaceUri( String namespaceUri,
-                                     boolean generateIfMissing );
-
-    /**
-     * Return whether there is a registered prefix for the supplied namespace URI.
-     * 
-     * @param namespaceUri the namespace URI
-     * @return true if the supplied namespace has been registered with a prefix, or false otherwise
-     * @throws IllegalArgumentException if the namespace URI is null
-     */
-    boolean isRegisteredNamespaceUri( String namespaceUri );
-
-    /**
-     * Register a new namespace using the supplied prefix, returning the namespace URI previously registered under that prefix.
-     * 
-     * @param prefix the prefix for the namespace, or null if a namesapce prefix should be generated automatically
-     * @param namespaceUri the namespace URI
-     * @return the namespace URI that was previously registered with the supplied prefix, or null if the prefix was not previously
-     *         bound to a namespace URI
-     * @throws IllegalArgumentException if the namespace URI is null
-     */
-    String register( String prefix,
-                     String namespaceUri );
-
-    /**
-     * Unregister the namespace with the supplied URI.
-     * 
-     * @param namespaceUri the namespace URI
-     * @return true if the namespace was removed, or false if the namespace was not registered
-     * @throws IllegalArgumentException if the namespace URI is null
-     * @throws NamespaceException if there is a problem unregistering the namespace
-     */
-    boolean unregister( String namespaceUri );
-
-    /**
-     * Obtain the set of namespaces that are registered.
-     * 
-     * @return the set of
-     */
-    Set<String> getRegisteredNamespaceUris();
-
-    /**
-     * Obtain a snapshot of all of the {@link Namespace namespaces} registered at the time this method is called. The resulting
-     * set is immutable, and will <i>not</i> reflect changes made to the registry.
-     * 
-     * @return an immutable set of {@link Namespace} objects reflecting a snapshot of the registry; never null
-     */
-    Set<Namespace> getNamespaces();
-
-    /**
-     * Representation of a single namespace at a single point in time. This object does not change to reflect changes made to the
-     * {@link NamespaceRegistry registry}.
-     * 
-     * @see NamespaceRegistry#getNamespaces()
-     * @author Randall Hauch
-     */
-    @Immutable
-    interface Namespace {
-        /**
-         * Get the prefix for the namespace
-         * 
-         * @return the prefix; never null but possibly the empty string
-         */
-        String getPrefix();
-
-        /**
-         * Get the URI for the namespace
-         * 
-         * @return the namespace URI; never null but possibly the empty string
-         */
-        String getNamespaceUri();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Path.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Path.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Path.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,579 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.io.Serializable;
-import java.util.Iterator;
-import java.util.List;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.Jsr283Encoder;
-import org.jboss.dna.common.text.NoOpEncoder;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.common.text.UrlEncoder;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicPathSegment;
-
-/**
- * An object representation of a node path within a repository.
- * <p>
- * A path consists of zero or more segments that can contain any characters, although the string representation may require some
- * characters to be encoded. For example, if a path contains a segment with a forward slash, then this forward slash must be
- * escaped when writing the whole path to a string (since a forward slash is used as the {@link #DELIMITER delimiter} between
- * segments).
- * </p>
- * <p>
- * Because of this encoding and decoding issue, there is no standard representation of a path as a string. Instead, this class
- * uses {@link TextEncoder text encoders} to escape certain characters when writing to a string or unescaping the string
- * representation. These encoders and used only with individual segments, and therefore are not used to encode the
- * {@link #DELIMITER delimiter}. Three standard encoders are provided, although others can certainly be used:
- * <ul>
- * <li>{@link #JSR283_ENCODER Jsr283Encoder} - an encoder and decoder that is compliant with <a
- * href="http://jcp.org/en/jsr/detail?id=283">JSR-283</a> by converting the reserved characters (namely '*', '/', ':', '[', ']'
- * and '|') to their unicode equivalent.</td>
- * </li>
- * <li>{@link #URL_ENCODER UrlEncoder} - an encoder and decoder that is useful for converting text to be used within a URL, as
- * defined by Section 2.3 of <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>. This encoder does encode many characters
- * (including '`', '@', '#', '$', '^', '&', '{', '[', '}', ']', '|', ':', ';', '\', '"', '<', ',', '>', '?', '/', and ' '), while
- * others are not encoded (including '-', '_', '.', '!', '~', '*', '\', ''', '(', and ')'). Note that only the '*' character is
- * the only character reserved by JSR-283 that is not encoded by the URL encoder.</li>
- * <li>{@link #NO_OP_ENCODER NoOpEncoder} - an {@link TextEncoder encoder} implementation that does nothing.</li>
- * </ul>
- * </p>
- * <p>
- * This class simplifies working with paths and using a <code>Path</code> is often more efficient that processing and
- * manipulating the equivalent <code>String</code>. This class can easily {@link #iterator() iterate} over the segments, return
- * the {@link #size() number of segments}, {@link #compareTo(Path) compare} with other paths, {@link #resolve(Path) resolve}
- * relative paths, return the {@link #getParent() ancestor (or parent)}, determine whether one path is an
- * {@link #isAncestorOf(Path) ancestor} or {@link #isDecendantOf(Path) decendent} of another path, and
- * {@link #getCommonAncestor(Path) finding a common ancestor}.
- * </p>
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public interface Path extends Comparable<Path>, Iterable<Path.Segment>, Serializable {
-
-    /**
-     * The text encoder that does nothing.
-     */
-    public static final TextEncoder NO_OP_ENCODER = new NoOpEncoder();
-
-    /**
-     * The text encoder that encodes according to JSR-283.
-     */
-    public static final TextEncoder JSR283_ENCODER = new Jsr283Encoder();
-
-    /**
-     * The text encoder that encodes text according to the rules of <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
-     */
-    public static final TextEncoder URL_ENCODER = new UrlEncoder().setSlashEncoded(true);
-
-    /**
-     * The text decoder that does nothing.
-     */
-    public static final TextDecoder NO_OP_DECODER = new NoOpEncoder();
-
-    /**
-     * The text decoder that decodes according to JSR-283.
-     */
-    public static final TextDecoder JSR283_DECODER = new Jsr283Encoder();
-
-    /**
-     * The text decoder that decodes text according to the rules of <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
-     */
-    public static final TextDecoder URL_DECODER = new UrlEncoder().setSlashEncoded(true);
-
-    /**
-     * The default text encoder to be used when none is otherwise specified. This is currently the {@link #JSR283_ENCODER JSR-283
-     * encoder}.
-     */
-    public static final TextEncoder DEFAULT_ENCODER = JSR283_ENCODER;
-
-    /**
-     * The default text decoder to be used when none is otherwise specified. This is currently the {@link #JSR283_ENCODER JSR-283
-     * encoder}.
-     */
-    public static final TextDecoder DEFAULT_DECODER = JSR283_DECODER;
-
-    /**
-     * The delimiter character used to separate segments within a path.
-     */
-    public static final char DELIMITER = '/';
-
-    /**
-     * String form of the delimiter used to separate segments within a path.
-     */
-    public static final String DELIMITER_STR = new String(new char[] {DELIMITER});
-
-    /**
-     * String representation of the segment that references a parent.
-     */
-    public static final String PARENT = "..";
-
-    /**
-     * String representation of the segment that references the same segment.
-     */
-    public static final String SELF = ".";
-
-    /**
-     * The index that will be returned for a {@link Segment} that {@link Segment#hasIndex() has no index}.
-     */
-    public static final int NO_INDEX = -1;
-
-    /**
-     * Representation of the segments that occur within a path.
-     * 
-     * @author Randall Hauch
-     */
-    @Immutable
-    public static interface Segment extends Cloneable, Comparable<Segment>, Serializable {
-
-        /**
-         * Get the name component of this segment.
-         * 
-         * @return the segment's name
-         */
-        public Name getName();
-
-        /**
-         * Get the index for this segment, which will be {@link Path#NO_INDEX -1} if this segment has no specific index.
-         * 
-         * @return the index
-         */
-        public int getIndex();
-
-        /**
-         * Return whether this segment has an index.
-         * 
-         * @return true if this segment has an index, or false otherwise.
-         */
-        public boolean hasIndex();
-
-        /**
-         * Return whether this segment is a self-reference.
-         * 
-         * @return true if the segment is a self-reference, or false otherwise.
-         */
-        public boolean isSelfReference();
-
-        /**
-         * Return whether this segment is a reference to a parent.
-         * 
-         * @return true if the segment is a parent-reference, or false otherwise.
-         */
-        public boolean isParentReference();
-
-        /**
-         * Get the raw string form of the segment using the {@link Path#NO_OP_ENCODER no-op encoder}. This is equivalent to
-         * calling <code>getString(Path.NO_OP_ENCODER)</code>.
-         * 
-         * @return the un-encoded string
-         * @see #getString(TextEncoder)
-         */
-        public String getUnencodedString();
-
-        /**
-         * Get the string form of the segment. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each
-         * of the path segments.
-         * 
-         * @return the encoded string
-         * @see #getString(TextEncoder)
-         */
-        public String getString();
-
-        /**
-         * Get the encoded string form of the segment, using the supplied encoder to encode characters in each of the path
-         * segments.
-         * 
-         * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
-         * @return the encoded string
-         * @see #getString()
-         */
-        public String getString( TextEncoder encoder );
-
-        /**
-         * Get the string form of the segment, using the supplied namespace registry to convert the name's namespace URI to a
-         * prefix. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
-         * 
-         * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-         *        {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
-         * @return the encoded string
-         * @throws IllegalArgumentException if the namespace registry is null
-         * @see #getString(NamespaceRegistry,TextEncoder)
-         */
-        public String getString( NamespaceRegistry namespaceRegistry );
-
-        /**
-         * Get the encoded string form of the segment, using the supplied namespace registry to convert the name's namespace URI
-         * to a prefix and the supplied encoder to encode characters in each of the path segments.
-         * 
-         * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-         *        {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
-         * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
-         * @return the encoded string
-         * @throws IllegalArgumentException if the namespace registry is null
-         * @see #getString(NamespaceRegistry)
-         */
-        public String getString( NamespaceRegistry namespaceRegistry,
-                                 TextEncoder encoder );
-
-        /**
-         * Get the encoded string form of the segment, using the supplied namespace registry to convert the names' namespace URIs
-         * to prefixes and the supplied encoder to encode characters in each of the path segments. The second encoder is used to
-         * encode (or convert) the delimiter between the {@link Name#getNamespaceUri() namespace prefix} and the
-         * {@link Name#getLocalName() local part}.
-         * 
-         * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-         *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
-         * @param encoder the encoder to use for encoding the {@link Name#getLocalName() local part} and
-         *        {@link Name#getNamespaceUri() namespace prefix} in the segment's {@link #getName() name}, or null if the
-         *        {@link #DEFAULT_ENCODER default encoder} should be used
-         * @param delimiterEncoder the encoder to use for encoding the delimiter between the {@link Name#getLocalName() local
-         *        part} and {@link Name#getNamespaceUri() namespace prefix} of each {@link Path#getSegmentsList() segment}, or
-         *        null if the standard delimiters should be used
-         * @return the encoded string
-         * @see #getString(NamespaceRegistry)
-         * @see #getString(NamespaceRegistry, TextEncoder)
-         */
-        public String getString( NamespaceRegistry namespaceRegistry,
-                                 TextEncoder encoder,
-                                 TextEncoder delimiterEncoder );
-    }
-
-    /**
-     * Singleton instance of the name referencing a self, provided as a convenience.
-     */
-    public static final Name SELF_NAME = new BasicName(null, SELF);
-
-    /**
-     * Singleton instance of the name referencing a parent, provided as a convenience.
-     */
-    public static final Name PARENT_NAME = new BasicName(null, PARENT);
-
-    /**
-     * Singleton instance of the path segment referencing a parent, provided as a convenience.
-     */
-    public static final Path.Segment SELF_SEGMENT = new BasicPathSegment(SELF_NAME);
-
-    /**
-     * Singleton instance of the path segment referencing a parent, provided as a convenience.
-     */
-    public static final Path.Segment PARENT_SEGMENT = new BasicPathSegment(PARENT_NAME);
-
-    /**
-     * Return the number of segments in this path.
-     * 
-     * @return the number of path segments
-     */
-    public int size();
-
-    /**
-     * Return whether this path represents the root path.
-     * 
-     * @return true if this path is the root path, or false otherwise
-     */
-    public boolean isRoot();
-
-    /**
-     * Determine whether this path represents the same as the supplied path. This is equivalent to calling <code>
-     * this.compareTo(other) == 0 </code>.
-     * 
-     * @param other the other path to compare with this path; may be null
-     * @return true if the paths are equivalent, or false otherwise
-     */
-    public boolean isSameAs( Path other );
-
-    /**
-     * Determine whether this path is the {@link #isSameAs(Path) same as} to or a {@link #isAncestorOf(Path) ancestor of} the
-     * supplied path. This method is equivalent to (but may be more efficient than) calling <code>isSame(other) ||
-     * isAncestor(other)</code>, and is a convenience method that is identical to calling <code>other.isAtOrBelow(this)</code>.
-     * 
-     * @param other the other path to compare with this path; may be null
-     * @return true if the paths are equivalent or if this path is considered an ancestor of the other path, or false otherwise
-     */
-    public boolean isAtOrAbove( Path other );
-
-    /**
-     * Determine whether this path is the {@link #isSameAs(Path) same as} to or a {@link #isDecendantOf(Path) decendant of} the
-     * supplied path. This method is equivalent to (but may be more efficient than) calling <code>isSame(other) ||
-     * isAncestor(other)</code>.
-     * 
-     * @param other the other path to compare with this path; may be null
-     * @return true if the paths are equivalent or if this path is considered a decendant of the other path, or false otherwise
-     */
-    public boolean isAtOrBelow( Path other );
-
-    /**
-     * Determine whether this path is an ancestor of the supplied path. A path is considered an ancestor of another path if the
-     * the ancestor path appears in its entirety at the beginning of the decendant path, and where the decendant path contains at
-     * least one additional segment.
-     * 
-     * @param decendant the path that may be the decendant; may be null
-     * @return true if this path is an ancestor of the supplied path, or false otherwise
-     */
-    public boolean isAncestorOf( Path decendant );
-
-    /**
-     * Determine whether this path is an decendant of the supplied path. A path is considered a decendant of another path if the
-     * the decendant path starts exactly with the entire ancestor path but contains at least one additional segment.
-     * 
-     * @param ancestor the path that may be the ancestor; may be null
-     * @return true if this path is an decendant of the supplied path, or false otherwise
-     */
-    public boolean isDecendantOf( Path ancestor );
-
-    /**
-     * Return whether this path is an absolute path. A path is either relative or {@link #isAbsolute() absolute}. An absolute path
-     * starts with a "/".
-     * 
-     * @return true if the path is absolute, or false otherwise
-     */
-    public boolean isAbsolute();
-
-    /**
-     * Return whether this path is normalized and contains no "." segments and as few ".." segments as possible. For example, the
-     * path "../a" is normalized, while "/a/b/c/../d" is not normalized.
-     * 
-     * @return true if this path is normalized, or false otherwise
-     */
-    public boolean isNormalized();
-
-    /**
-     * Get a normalized path with as many ".." segments and all "." resolved. The relative path ".", however, will return itself
-     * as the normalized path, since it cannot be resolved any further.
-     * 
-     * @return the normalized path, or this object if this path is already normalized
-     * @throws InvalidPathException if the normalized form would result in a path with negative length (e.g., "/a/../../..")
-     */
-    public Path getNormalizedPath();
-
-    /**
-     * Get the canonical form of this path. A canonical path has is {@link #isAbsolute() absolute} and {@link #isNormalized()}.
-     * 
-     * @return the canonical path, or this object if it is already in its canonical form
-     * @throws InvalidPathException if the path is not absolute and cannot be canonicalized
-     */
-    public Path getCanonicalPath();
-
-    /**
-     * Get a relative path from the supplied path to this path.
-     * 
-     * @param startingPath the path specifying the starting point for the new relative path; may not be null
-     * @return the relative path
-     * @throws IllegalArgumentException if the supplied path is null
-     * @throws PathNotFoundException if both this path and the supplied path are not absolute
-     */
-    public Path relativeTo( Path startingPath );
-
-    /**
-     * Get the absolute path by resolving the supplied relative (non-absolute) path against this absolute path.
-     * 
-     * @param relativePath the relative path that is to be resolved against this path
-     * @return the absolute and normalized path resolved from this path and the supplied absolute path
-     * @throws IllegalArgumentException if the supplied path is null
-     * @throws InvalidPathException if the this path is not absolute or if the supplied path is not relative.
-     */
-    public Path resolve( Path relativePath );
-
-    /**
-     * Get the absolute path by resolving this relative (non-absolute) path against the supplied absolute path.
-     * 
-     * @param absolutePath the absolute path to which this relative path should be resolve
-     * @return the absolute path resolved from this path and the supplied absolute path
-     * @throws IllegalArgumentException if the supplied path is null
-     * @throws InvalidPathException if the supplied path is not absolute or if this path is not relative.
-     */
-    public Path resolveAgainst( Path absolutePath );
-
-    /**
-     * Return the path to the parent, or this path if it is the {@link #isRoot() root}. This is an efficient operation that does
-     * not require copying any data.
-     * 
-     * @return the parent path, or this null if it is already the root
-     */
-    public Path getParent();
-
-    /**
-     * Return the path to the ancestor of the supplied degree. An ancestor of degree <code>x</code> is the path that is <code>x
-     * </code> levels up along the path. For example, <code>degree = 0</code> returns this path, while <code>degree = 1</code>
-     * returns the parent of this path, <code>degree = 2</code> returns the grandparent of this path, and so on. Note that the
-     * result may be unexpected if this path is not {@link #isNormalized() normalized}, as a non-normalized path contains ".." and
-     * "." segments.
-     * 
-     * @param degree
-     * @return the ancestor of the supplied degree
-     * @throws IllegalArgumentException if the degree is negative
-     * @throws InvalidPathException if the degree is greater than the {@link #size() length} of this path
-     */
-    public Path getAncestor( int degree );
-
-    /**
-     * Determine whether this path and the supplied path have the same immediate ancestor. In other words, this method determines
-     * whether the node represented by this path is a sibling of the node represented by the supplied path.
-     * 
-     * @param that the other path
-     * @return true if this path and the supplied path have the same immediate ancestor.
-     * @throws IllegalArgumentException if the supplied path is null
-     */
-    public boolean hasSameAncestor( Path that );
-
-    /**
-     * Find the lowest common ancestor of this path and the supplied path.
-     * 
-     * @param that the other path
-     * @return the lowest common ancestor, which may be the root path if there is no other.
-     * @throws IllegalArgumentException if the supplied path is null
-     */
-    public Path getCommonAncestor( Path that );
-
-    /**
-     * Get the last segment in this path.
-     * 
-     * @return the last segment, or null if the path is empty
-     */
-    public Segment getLastSegment();
-
-    /**
-     * Get the segment at the supplied index.
-     * 
-     * @param index the index
-     * @return the segment
-     * @throws IndexOutOfBoundsException if the index is out of bounds
-     */
-    public Segment getSegment( int index );
-
-    /**
-     * Return a new path consisting of the segments starting at <code>beginIndex</code> index (inclusive). This is equivalent to
-     * calling <code>path.subpath(beginIndex,path.size()-1)</code>.
-     * 
-     * @param beginIndex the beginning index, inclusive.
-     * @return the specified subpath
-     * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative or larger than the length of this <code>
-     *            Path</code> object
-     */
-    public Path subpath( int beginIndex );
-
-    /**
-     * Return a new path consisting of the segments between the <code>beginIndex</code> index (inclusive) and the <code>endIndex
-     * </code> index (exclusive).
-     * 
-     * @param beginIndex the beginning index, inclusive.
-     * @param endIndex the ending index, exclusive.
-     * @return the specified subpath
-     * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative, or <code>endIndex</code> is larger than
-     *            the length of this <code>Path</code> object, or <code>beginIndex</code> is larger than <code>endIndex</code>.
-     */
-    public Path subpath( int beginIndex,
-                         int endIndex );
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<Segment> iterator();
-
-    /**
-     * Obtain a copy of the segments in this path. None of the segments are encoded.
-     * 
-     * @return the array of segments as a copy
-     */
-    public Segment[] getSegmentsArray();
-
-    /**
-     * Get an unmodifiable list of the path segments.
-     * 
-     * @return the unmodifiable list of path segments; never null
-     */
-    public List<Segment> getSegmentsList();
-
-    /**
-     * Get the string form of the path. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the
-     * path segments.
-     * 
-     * @return the encoded string
-     * @see #getString(TextEncoder)
-     */
-    public String getString();
-
-    /**
-     * Get the encoded string form of the path, using the supplied encoder to encode characters in each of the path segments.
-     * 
-     * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
-     * @return the encoded string
-     * @see #getString()
-     */
-    public String getString( TextEncoder encoder );
-
-    /**
-     * Get the string form of the path, using the supplied namespace registry to convert the names' namespace URIs to prefixes.
-     * The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments. The second encoder
-     * is used to encode (or convert) the delimiter between the {@link Name#getNamespaceUri() namespace prefix} and the
-     * {@link Name#getLocalName() local part}.
-     * 
-     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-     *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
-     * @return the encoded string
-     * @throws IllegalArgumentException if the namespace registry is null
-     * @see #getString(NamespaceRegistry,TextEncoder)
-     * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry );
-
-    /**
-     * Get the encoded string form of the path, using the supplied namespace registry to convert the names' namespace URIs to
-     * prefixes and the supplied encoder to encode characters in each of the path segments.
-     * 
-     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-     *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}, or null if the
-     *        namespace registry should not be used
-     * @param encoder the encoder to use for encoding the {@link Name#getLocalName() local part} and
-     *        {@link Name#getNamespaceUri() namespace prefix} of each {@link Path#getSegmentsList() segment}, or null if the
-     *        {@link #DEFAULT_ENCODER default encoder} should be used
-     * @return the encoded string
-     * @see #getString(NamespaceRegistry)
-     * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder );
-
-    /**
-     * Get the encoded string form of the path, using the supplied namespace registry to convert the names' namespace URIs to
-     * prefixes and the supplied encoder to encode characters in each of the path segments.
-     * 
-     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-     *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
-     * @param encoder the encoder to use for encoding the {@link Name#getLocalName() local part} and
-     *        {@link Name#getNamespaceUri() namespace prefix} of each {@link Path#getSegmentsList() segment}, or null if the
-     *        {@link #DEFAULT_ENCODER default encoder} should be used
-     * @param delimiterEncoder the encoder to use for encoding the delimiter between the {@link Name#getLocalName() local part}
-     *        and {@link Name#getNamespaceUri() namespace prefix} of each {@link Path#getSegmentsList() segment}, and for encoding
-     *        the path delimiter, or null if the standard delimiters should be used
-     * @return the encoded string
-     * @see #getString(NamespaceRegistry)
-     * @see #getString(NamespaceRegistry, TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder,
-                             TextEncoder delimiterEncoder );
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathExpression.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathExpression.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathExpression.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,535 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.io.Serializable;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.HashCode;
-import org.jboss.dna.graph.GraphI18n;
-
-/**
- * An expression that defines an acceptable path using a regular-expression-like language. Path expressions can be used to
- * represent node paths or properties.
- * <p>
- * Path expressions consist of two parts: a selection criteria (or an input path) and an output path:
- * </p>
- * 
- * <pre>
- * inputPath =&gt; outputPath
- * </pre>
- * <p>
- * The <i>inputPath</i> part defines an expression for the path of a node that is to be sequenced. Input paths consist of '
- * <code>/</code>' separated segments, where each segment represents a pattern for a single node's name (including the
- * same-name-sibling indexes) and '<code>@</code>' signifies a property name.
- * </p>
- * <p>
- * Let's first look at some simple examples:
- * </p>
- * <table>
- * <tr>
- * <th>Input Path</th>
- * <th>Description</th>
- * </tr>
- * <tr>
- * <td>/a/b</td>
- * <td>Match node "<code>b</code>" that is a child of the top level node "<code>a</code>". Neither node may have any
- * same-name-sibilings.</td>
- * </tr>
- * <tr>
- * <td>/a/*</td>
- * <td>Match any child node of the top level node "<code>a</code>".</td>
- * </tr>
- * <tr>
- * <td>/a/*.txt</td>
- * <td>Match any child node of the top level node "<code>a</code>" that also has a name ending in "<code>.txt</code>".</td>
- * </tr>
- * <tr>
- * <td>/a/b at c</td>
- * <td>Match the property "<code>c</code>" of node "<code>/a/b</code>".</td>
- * </tr>
- * <tr>
- * <td>/a/b[2]</td>
- * <td>The second child named "<code>b</code>" below the top level node "<code>a</code>".</td>
- * </tr>
- * <tr>
- * <td>/a/b[2,3,4]</td>
- * <td>The second, third or fourth child named "<code>b</code>" below the top level node "<code>a</code>".</td>
- * </tr>
- * <tr>
- * <td>/a/b[*]</td>
- * <td>Any (and every) child named "<code>b</code>" below the top level node "<code>a</code>".</td>
- * </tr>
- * <tr>
- * <td>//a/b</td>
- * <td>Any node named "<code>b</code>" that exists below a node named "<code>a</code>", regardless of where node "<code>a</code>"
- * occurs. Again, neither node may have any same-name-sibilings.</td>
- * </tr>
- * </table>
- * <p>
- * With these simple examples, you can probably discern the most important rules. First, the '<code>*</code>' is a wildcard
- * character that matches any character or sequence of characters in a node's name (or index if appearing in between square
- * brackets), and can be used in conjunction with other characters (e.g., "<code>*.txt</code>").
- * </p>
- * <p>
- * Second, square brackets (i.e., '<code>[</code>' and '<code>]</code>') are used to match a node's same-name-sibiling index. You
- * can put a single non-negative number or a comma-separated list of non-negative numbers. Use '0' to match a node that has no
- * same-name-sibilings, or any positive number to match the specific same-name-sibling.
- * </p>
- * <p>
- * Third, combining two delimiters (e.g., "<code>//</code>") matches any sequence of nodes, regardless of what their names are or
- * how many nodes. Often used with other patterns to identify nodes at any level matching other patterns. Three or more sequential
- * slash characters are treated as two.
- * </p>
- * <p>
- * Many input paths can be created using just these simple rules. However, input paths can be more complicated. Here are some more
- * examples:
- * </p>
- * <table>
- * <tr>
- * <th>Input Path</th>
- * <th>Description</th>
- * </tr>
- * <tr>
- * <td>/a/(b|c|d)</td>
- * <td>Match children of the top level node "<code>a</code>" that are named "<code>a</code>", "<code>b</code>" or "<code>c</code>
- * ". None of the nodes may have same-name-sibling indexes.</td>
- * </tr>
- * <tr>
- * <td>/a/b[c/d]</td>
- * <td>Match node "<code>b</code>" child of the top level node "<code>a</code>", when node "<code>b</code>" has a child named "
- * <code>c</code>", and "<code>c</code>" has a child named "<code>d</code>". Node "<code>b</code>
- * " is the selected node, while nodes "<code>b</code>" and "<code>b</code>" are used as criteria but are not selected.</td>
- * </tr>
- * <tr>
- * <td>/a(/(b|c|d|)/e)[f/g/@something]</td>
- * <td>Match node "<code>/a/b/e</code>", "<code>/a/c/e</code>", "<code>/a/d/e</code>", or "<code>/a/e</code>
- * " when they also have a child "<code>f</code>" that itself has a child "<code>g</code>" with property "<code>something</code>".
- * None of the nodes may have same-name-sibling indexes.</td>
- * </tr>
- * </table>
- * <p>
- * These examples show a few more advanced rules. Parentheses (i.e., '<code>(</code>' and '<code>)</code>') can be used to define
- * a set of options for names, as shown in the first and third rules. Whatever part of the selected node's path appears between
- * the parentheses is captured for use within the output path. Thus, the first input path in the previous table would match node "
- * <code>/a/b</code>", and "b" would be captured and could be used within the output path using "<code>$1</code>", where the
- * number used in the output path identifies the parentheses.
- * </p>
- * <p>
- * Square brackets can also be used to specify criteria on a node's properties or children. Whatever appears in between the square
- * brackets does not appear in the selected node.
- * </p>
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class PathExpression implements Serializable {
-
-    /**
-     * Initial version
-     */
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Compile the supplied expression and return the resulting path expression instance.
-     * 
-     * @param expression the expression
-     * @return the path expression; never null
-     * @throws IllegalArgumentException if the expression is null
-     * @throws InvalidPathExpressionException if the expression is blank or is not a valid expression
-     */
-    public static final PathExpression compile( String expression ) throws InvalidPathExpressionException {
-        return new PathExpression(expression);
-    }
-
-    private static final String SEQUENCE_PATTERN_STRING = "\\[(\\d+(?:,\\d+)*)\\]"; // \[(\d+(,\d+)*)\]
-    private static final Pattern SEQUENCE_PATTERN = Pattern.compile(SEQUENCE_PATTERN_STRING);
-
-    /**
-     * Regular expression used to find unusable XPath predicates within an expression. This pattern results in unusable predicates
-     * in group 1. Note that some predicates may be valid at the end but not valid elsewhere.
-     * <p>
-     * Currently, only index-like predicates (including sequences) are allowed everywhere. Predicates with paths and properties
-     * are allowed only as the last predicate. Predicates with any operators are unused.
-     * </p>
-     * <p>
-     * Nested predicates are not currently allowed.
-     * </p>
-     */
-    // \[(?:(?:\d+(?:,\d+)*)|\*)\]|(?:\[[^\]\+\-\*=\!><'"\s]+\])$|(\[[^\]]+\])
-    private static final String UNUSABLE_PREDICATE_PATTERN_STRING = "\\[(?:(?:\\d+(?:,\\d+)*)|\\*)\\]|(?:\\[[^\\]\\+\\-\\*=\\!><'\"\\s]+\\])$|(\\[[^\\]]+\\])";
-    private static final Pattern UNUSABLE_PREDICATE_PATTERN = Pattern.compile(UNUSABLE_PREDICATE_PATTERN_STRING);
-
-    /**
-     * Regular expression used to find all XPath predicates except index and sequence patterns. This pattern results in the
-     * predicates to be removed in group 1.
-     */
-    // \[(?:(?:\d+(?:,\d+)*)|\*)\]|(\[[^\]]+\])
-    private static final String NON_INDEX_PREDICATE_PATTERN_STRING = "\\[(?:(?:\\d+(?:,\\d+)*)|\\*)\\]|(\\[[^\\]]+\\])";
-    private static final Pattern NON_INDEX_PREDICATE_PATTERN = Pattern.compile(NON_INDEX_PREDICATE_PATTERN_STRING);
-
-    private final String expression;
-    private final Pattern matchPattern;
-    private final Pattern selectPattern;
-
-    /**
-     * Create the supplied expression.
-     * 
-     * @param expression the expression
-     * @throws IllegalArgumentException if the expression is null
-     * @throws InvalidPathExpressionException if the expression is blank or is not a valid expression
-     */
-    public PathExpression( String expression ) throws InvalidPathExpressionException {
-        CheckArg.isNotNull(expression, "path expression");
-        this.expression = expression.trim();
-        if (this.expression.length() == 0) {
-            throw new InvalidPathExpressionException(GraphI18n.pathExpressionMayNotBeBlank.text());
-        }
-        // Build the match pattern, which determines whether a path matches the condition ...
-        String matchString = this.expression;
-        try {
-            matchString = removeUnusedPredicates(matchString);
-            matchString = replaceXPathPatterns(matchString);
-            this.matchPattern = Pattern.compile(matchString, Pattern.CASE_INSENSITIVE);
-        } catch (PatternSyntaxException e) {
-            String msg = GraphI18n.pathExpressionHasInvalidMatch.text(matchString, this.expression);
-            throw new InvalidPathExpressionException(msg, e);
-        }
-        // Build the select pattern, which determines the path that will be selected ...
-        String selectString = this.expression;
-        try {
-            selectString = removeAllPredicatesExceptIndexes(selectString);
-            selectString = replaceXPathPatterns(selectString);
-            selectString = "(" + selectString + ").*"; // group 1 will have selected path ...
-            this.selectPattern = Pattern.compile(selectString, Pattern.CASE_INSENSITIVE);
-        } catch (PatternSyntaxException e) {
-            String msg = GraphI18n.pathExpressionHasInvalidSelect.text(selectString, this.expression);
-            throw new InvalidPathExpressionException(msg, e);
-        }
-    }
-
-    /**
-     * @return expression
-     */
-    public String getExpression() {
-        return expression;
-    }
-
-    /**
-     * Replace certain XPath patterns that are not used or understood.
-     * 
-     * @param expression the input regular expressions string; may not be null
-     * @return the regular expression with all unused XPath patterns removed; never null
-     */
-    protected String removeUnusedPredicates( String expression ) {
-        assert expression != null;
-        java.util.regex.Matcher matcher = UNUSABLE_PREDICATE_PATTERN.matcher(expression);
-        StringBuffer sb = new StringBuffer();
-        if (matcher.find()) {
-            do {
-                // Remove those predicates that show up in group 1 ...
-                String predicateStr = matcher.group(0);
-                String unusablePredicateStr = matcher.group(1);
-                if (unusablePredicateStr != null) {
-                    predicateStr = "";
-                }
-                matcher.appendReplacement(sb, predicateStr);
-            } while (matcher.find());
-            matcher.appendTail(sb);
-            expression = sb.toString();
-        }
-        return expression;
-    }
-
-    /**
-     * Remove all XPath predicates from the supplied regular expression string.
-     * 
-     * @param expression the input regular expressions string; may not be null
-     * @return the regular expression with all XPath predicates removed; never null
-     */
-    protected String removeAllPredicatesExceptIndexes( String expression ) {
-        assert expression != null;
-        java.util.regex.Matcher matcher = NON_INDEX_PREDICATE_PATTERN.matcher(expression);
-        StringBuffer sb = new StringBuffer();
-        if (matcher.find()) {
-            do {
-                // Remove those predicates that show up in group 1 ...
-                String predicateStr = matcher.group(0);
-                String unusablePredicateStr = matcher.group(1);
-                if (unusablePredicateStr != null) {
-                    predicateStr = "";
-                }
-                matcher.appendReplacement(sb, predicateStr);
-            } while (matcher.find());
-            matcher.appendTail(sb);
-            expression = sb.toString();
-        }
-        return expression;
-    }
-
-    /**
-     * Replace certain XPath patterns, including some predicates, with substrings that are compatible with regular expressions.
-     * 
-     * @param expression the input regular expressions string; may not be null
-     * @return the regular expression with XPath patterns replaced with regular expression fragments; never null
-     */
-    protected String replaceXPathPatterns( String expression ) {
-        assert expression != null;
-        // replace 2 or more sequential '|' characters in an OR expression
-        expression = expression.replaceAll("[\\|]{2,}", "|");
-        // if there is an empty expression in an OR expression, make the whole segment optional ...
-        // (e.g., "/a/b/(c|)/d" => "a/b(/(c))?/d"
-        expression = expression.replaceAll("/(\\([^|]+)(\\|){2,}([^)]+\\))", "(/$1$2$3)?");
-        expression = expression.replaceAll("/\\(\\|+([^)]+)\\)", "(?:/($1))?");
-        expression = expression.replaceAll("/\\((([^|]+)(\\|[^|]+)*)\\|+\\)", "(?:/($1))?");
-
-        // // Allow any path (that doesn't contain an explicit counter) to contain a counter,
-        // // done by replacing any '/' or '|' that isn't preceded by ']' or '*' or '/' or '(' with '(\[\d+\])?/'...
-        // input = input.replaceAll("(?<=[^\\]\\*/(])([/|])", "(?:\\\\[\\\\d+\\\\])?$1");
-
-        // Does the path contain any '[]' or '[*]' or '[0]' or '[n]' (where n is any positive integers)...
-        // '[*]/' => '(\[\d+\])?/'
-        expression = expression.replaceAll("\\[\\]", "(?:\\\\[\\\\d+\\\\])?"); // index is optional
-        // '[]/' => '(\[\d+\])?/'
-        expression = expression.replaceAll("\\[[*]\\]", "(?:\\\\[\\\\d+\\\\])?"); // index is optional
-        // '[0]/' => '(\[0\])?/'
-        expression = expression.replaceAll("\\[0\\]", "(?:\\\\[0\\\\])?"); // index is optional
-        // '[n]/' => '\[n\]/'
-        expression = expression.replaceAll("\\[([1-9]\\d*)\\]", "\\\\[$1\\\\]"); // index is required
-
-        // Change any other end predicates to not be wrapped by braces but to begin with a slash ...
-        // ...'[x]' => ...'/x'
-        expression = expression.replaceAll("(?<!\\\\)\\[([^\\]]*)\\]$", "/$1");
-
-        // Replace all '[n,m,o,p]' type sequences with '[(n|m|o|p)]'
-        java.util.regex.Matcher matcher = SEQUENCE_PATTERN.matcher(expression);
-        StringBuffer sb = new StringBuffer();
-        boolean result = matcher.find();
-        if (result) {
-            do {
-                String sequenceStr = matcher.group(1);
-                boolean optional = false;
-                if (sequenceStr.startsWith("0,")) {
-                    sequenceStr = sequenceStr.replaceFirst("^0,", "");
-                    optional = true;
-                }
-                if (sequenceStr.endsWith(",0")) {
-                    sequenceStr = sequenceStr.replaceFirst(",0$", "");
-                    optional = true;
-                }
-                if (sequenceStr.contains(",0,")) {
-                    sequenceStr = sequenceStr.replaceAll(",0,", ",");
-                    optional = true;
-                }
-                sequenceStr = sequenceStr.replaceAll(",", "|");
-                String replacement = "\\\\[(?:" + sequenceStr + ")\\\\]";
-                if (optional) {
-                    replacement = "(?:" + replacement + ")?";
-                }
-                matcher.appendReplacement(sb, replacement);
-                result = matcher.find();
-            } while (result);
-            matcher.appendTail(sb);
-            expression = sb.toString();
-        }
-
-        // Order is important here
-        expression = expression.replaceAll("[*]([^/(\\\\])", "[^/$1]*$1"); // '*' not followed by '/', '\\', or '('
-        expression = expression.replaceAll("(?<!\\[\\^/\\])[*]", "[^/]*");
-        expression = expression.replaceAll("[/]{2,}$", "(?:/[^/]*)*"); // ending '//'
-        expression = expression.replaceAll("[/]{2,}", "(?:/[^/]*)*/"); // other '//'
-        return expression;
-    }
-
-    /**
-     * @return the expression
-     */
-    public String getSelectExpression() {
-        return this.expression;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return this.expression.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof PathExpression) {
-            PathExpression that = (PathExpression)obj;
-            if (!this.expression.equalsIgnoreCase(that.expression)) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return this.expression;
-    }
-
-    /**
-     * @param absolutePath
-     * @return the matcher
-     */
-    public Matcher matcher( String absolutePath ) {
-        // Determine if the input path match the select expression ...
-        String originalAbsolutePath = absolutePath;
-        // if (!absolutePath.endsWith("/")) absolutePath = absolutePath + "/";
-        // Remove all trailing '/' ...
-        absolutePath = absolutePath.replaceAll("/+$", "");
-
-        // See if the supplied absolute path matches the pattern ...
-        final java.util.regex.Matcher matcher = this.matchPattern.matcher(absolutePath);
-        if (!matcher.matches()) {
-            // No match, so return immediately ...
-            return new Matcher(matcher, originalAbsolutePath, null);
-        }
-
-        // The absolute path does match the pattern, so use the select pattern and try to grab the selected path ...
-        final java.util.regex.Matcher selectMatcher = this.selectPattern.matcher(absolutePath);
-        if (!selectMatcher.matches()) {
-            // Nothing can be selected, so return immediately ...
-            return new Matcher(matcher, null, null);
-        }
-        // Grab the selected path ...
-        String selectedPath = selectMatcher.group(1);
-
-        // Remove the trailing '/@property' ...
-        selectedPath = selectedPath.replaceAll("/@[^/\\[\\]]+$", "");
-
-        return new Matcher(matcher, originalAbsolutePath, selectedPath);
-    }
-
-    @Immutable
-    public static class Matcher {
-
-        private final String inputPath;
-        private final String selectedPath;
-        private final java.util.regex.Matcher inputMatcher;
-        private final int hc;
-
-        protected Matcher( java.util.regex.Matcher inputMatcher,
-                           String inputPath,
-                           String selectedPath ) {
-            this.inputMatcher = inputMatcher;
-            this.inputPath = inputPath;
-            this.selectedPath = selectedPath;
-            this.hc = HashCode.compute(this.inputPath, this.selectedPath);
-        }
-
-        public boolean matches() {
-            return this.selectedPath != null;
-        }
-
-        /**
-         * @return inputPath
-         */
-        public String getInputPath() {
-            return this.inputPath;
-        }
-
-        /**
-         * @return selectPattern
-         */
-        public String getSelectedNodePath() {
-            return this.selectedPath;
-        }
-
-        public int groupCount() {
-            return this.inputMatcher.groupCount();
-        }
-
-        public String group( int groupNumber ) {
-            return this.inputMatcher.group(groupNumber);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public int hashCode() {
-            return this.hc;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public boolean equals( Object obj ) {
-            if (obj == this) return true;
-            if (obj instanceof PathExpression.Matcher) {
-                PathExpression.Matcher that = (PathExpression.Matcher)obj;
-                if (!this.inputPath.equalsIgnoreCase(that.inputPath)) return false;
-                if (!this.selectedPath.equalsIgnoreCase(that.selectedPath)) return false;
-                return true;
-            }
-            return false;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public String toString() {
-            return this.selectedPath;
-        }
-    }
-
-    /**
-     * Regular expression used to determine if the expression matches any single-level wildcard.
-     */
-    // /*(?:[*.](?:\[\*?\])?/*)*
-    private static final String ANYTHING_PATTERN_STRING = "/*(?:[*.](?:\\[\\*?\\])?/*)*";
-    private static final Pattern ANYTHING_PATTERN = Pattern.compile(ANYTHING_PATTERN_STRING);
-
-    /**
-     * Return whether this expression matches anything and therefore is not restrictive. These include expressions of any nodes ("
-     * <code>/</code>"), any sequence of nodes ("<code>//</code>"), the self reference ("<code>.</code>"), or wildcard ("
-     * <code>*</code>", "<code>*[]</code>" or "<code>*[*]</code>"). Combinations of these individual expressions are also
-     * considered to match anything.
-     * 
-     * @return true if the expression matches anything, or false otherwise
-     */
-    public boolean matchesAnything() {
-        return ANYTHING_PATTERN.matcher(expression).matches();
-    }
-
-    public static PathExpression all() {
-        return ALL_PATHS_EXPRESSION;
-    }
-
-    private static final PathExpression ALL_PATHS_EXPRESSION = PathExpression.compile("//");
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathFactory.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,242 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import org.jboss.dna.common.text.TextDecoder;
-
-/**
- * A factory for creating {@link Path paths}. This interface extends the {@link ValueFactory} generic interface and adds specific
- * methods for creating paths (and relative paths) from a series of names, segments, or combinations.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public interface PathFactory extends ValueFactory<Path> {
-
-    /**
-     * Create an absolute root path. Subsequent calls will always return the same instance.
-     * 
-     * @return the new path
-     */
-    Path createRootPath();
-
-    /**
-     * Create an absolute path with the supplied segment names, in order. If no segments are provided, the result will be the root
-     * path.
-     * 
-     * @param segmentNames the names of the segments
-     * @return the new path
-     * @throws IllegalArgumentException if at least one segment name is provided and if any of the supplied segment names are null
-     */
-    Path createAbsolutePath( Name... segmentNames );
-
-    /**
-     * Create an absolute path with the supplied segments, in order. If no segments are provided, the result will be the root
-     * path.
-     * 
-     * @param segments the segments
-     * @return the new path
-     * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
-     */
-    Path createAbsolutePath( Path.Segment... segments );
-
-    /**
-     * Create an absolute path with the supplied segments, in order. If no segments are provided, the result will be the root
-     * path.
-     * 
-     * @param segments the segments
-     * @return the new path
-     * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
-     */
-    Path createAbsolutePath( Iterable<Path.Segment> segments );
-
-    /**
-     * Create an empty relative path (i.e., equivalent to {@link #createRelativePath(Path.Segment...) createRelativePath}(
-     * {@link Path#SELF_SEGMENT})). Subsequent calls will always return the same instance.
-     * 
-     * @return the new path
-     */
-    Path createRelativePath();
-
-    /**
-     * Create a relative path with the supplied segment names, in order. If no segments are provided, the result will be the root
-     * path.
-     * 
-     * @param segmentNames the names of the segments
-     * @return the new path
-     * @throws IllegalArgumentException if at least one segment name is provided and if any of the supplied segment names are null
-     */
-    Path createRelativePath( Name... segmentNames );
-
-    /**
-     * Create a relative path with the supplied segments, in order. If no segments are provided, the result will be the root path.
-     * 
-     * @param segments the segments
-     * @return the new path
-     * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
-     */
-    Path createRelativePath( Path.Segment... segments );
-
-    /**
-     * Create a relative path with the supplied segments, in order. If no segments are provided, the result will be the root path.
-     * 
-     * @param segments the segments
-     * @return the new path
-     * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
-     */
-    Path createRelativePath( Iterable<Path.Segment> segments );
-
-    /**
-     * Create a path by appending the supplied relative path to the supplied parent path. The resulting path will be
-     * {@link Path#isAbsolute() absolute} if the supplied parent path is absolute.
-     * 
-     * @param parentPath the path that is to provide the basis for the new path
-     * @param childPath the path that should be appended to the parent path
-     * @return the new path
-     * @throws IllegalArgumentException if the parent path reference or the child path reference is null
-     */
-    Path create( Path parentPath,
-                 Path childPath );
-
-    /**
-     * Create a path by appending the supplied names to the parent path.
-     * 
-     * @param parentPath the path that is to provide the basis for the new path
-     * @param segmentName the name of the segment to be appended to the parent path
-     * @param index the index for the new segment
-     * @return the new path
-     * @throws IllegalArgumentException if the parent path reference or the segment name is null, or if the index is invalid
-     */
-    Path create( Path parentPath,
-                 Name segmentName,
-                 int index );
-
-    /**
-     * Create a path by appending the supplied names to the parent path. If no names are appended, the parent path is returned.
-     * 
-     * @param parentPath the path that is to provide the basis for the new path
-     * @param segmentNames the names of the segments that are to be appended, in order, to the parent path
-     * @return the new path
-     * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
-     *         any of the supplied segment names are null
-     */
-    Path create( Path parentPath,
-                 Name... segmentNames );
-
-    /**
-     * Create a path by appending the supplied names to the parent path. If no names are appended, the parent path is returned.
-     * 
-     * @param parentPath the path that is to provide the basis for the new path
-     * @param segments the segments that are to be appended, in order, to the parent path
-     * @return the new path
-     * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
-     *         any of the supplied segment names are null
-     */
-    Path create( Path parentPath,
-                 Path.Segment... segments );
-
-    /**
-     * Create a path by appending the supplied names to the parent path. If no names are appended, the parent path is returned.
-     * 
-     * @param parentPath the path that is to provide the basis for the new path
-     * @param segments the segments that are to be appended, in order, to the parent path
-     * @return the new path
-     * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
-     *         any of the supplied segment names are null
-     */
-    Path create( Path parentPath,
-                 Iterable<Path.Segment> segments );
-
-    /**
-     * Create a path by appending the supplied names to the parent path.
-     * 
-     * @param parentPath the path that is to provide the basis for the new path
-     * @param subpath the subpath to be appended to the parent path, which must be in the form of a relative path
-     * @return the new path
-     * @throws IllegalArgumentException if the parent path reference or the segment name is null, or if the index is invalid
-     */
-    Path create( Path parentPath,
-                 String subpath );
-
-    /**
-     * Create a path segment given the supplied segment name. The supplied string may contain a same-name-sibling index in the
-     * form of "<code>[<i>n</i>]</code>" at the end of the name, where <i>n</i> is a positive integer. Note that the
-     * same-name-sibling index is 1-based, not zero-based.
-     * 
-     * @param segmentName the name of the segment
-     * @return the segment
-     * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created from
-     *         the supplied string
-     * @throws ValueFormatException if the same-name-sibling index is not an integer, or if the supplied string is not a valid
-     *         segment name
-     */
-    Path.Segment createSegment( String segmentName );
-
-    /**
-     * Create a path segment given the supplied segment name. The supplied string may contain a same-name-sibling index in the
-     * form of "<code>[<i>n</i>]</code>" at the end of the name, where <i>n</i> is a positive integer. Note that the
-     * same-name-sibling index is 1-based, not zero-based.
-     * 
-     * @param segmentName the name of the segment
-     * @param decoder the decoder that should be used to decode the qualified name
-     * @return the segment
-     * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created from
-     *         the supplied string
-     * @throws ValueFormatException if the same-name-sibling index is not an integer, or if the supplied string is not a valid
-     *         segment name
-     */
-    Path.Segment createSegment( String segmentName,
-                                TextDecoder decoder );
-
-    /**
-     * Create a path segment given the supplied segment name and index.
-     * 
-     * @param segmentName the name of the new segment
-     * @param index the index of the new segment
-     * @return the segment
-     * @throws IllegalArgumentException if the segment name reference is <code>null</code> or if the index is invalid
-     * @throws ValueFormatException if the supplied string is not a valid segment name
-     */
-    Path.Segment createSegment( String segmentName,
-                                int index );
-
-    /**
-     * Create a path segment given the supplied segment name. The resulting segment will have no index.
-     * 
-     * @param segmentName the name of the segment
-     * @return the segment
-     * @throws IllegalArgumentException if the segment name reference is null
-     */
-    Path.Segment createSegment( Name segmentName );
-
-    /**
-     * Create a path segment given the supplied segment name and index.
-     * 
-     * @param segmentName the name of the new segment
-     * @param index the index of the new segment
-     * @return the segment
-     * @throws IllegalArgumentException if the segment name reference is null or if the index is invalid
-     */
-    Path.Segment createSegment( Name segmentName,
-                                int index );
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathNotFoundException.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathNotFoundException.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathNotFoundException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,114 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import org.jboss.dna.graph.Location;
-
-/**
- * @author Randall Hauch
- */
-public class PathNotFoundException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = -3703984046286975978L;
-
-    private final Location location;
-    private final Path lowestAncestorThatDoesExist;
-
-    /**
-     * @param location the location of the node that does not exist
-     * @param lowestAncestorThatDoesExist the path of the lowest (closest) ancestor that does exist
-     */
-    public PathNotFoundException( Location location,
-                                  Path lowestAncestorThatDoesExist ) {
-        this.location = location;
-        this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
-    }
-
-    /**
-     * @param location the location of the node that does not exist
-     * @param lowestAncestorThatDoesExist the path of the lowest (closest) ancestor that does exist
-     * @param message
-     */
-    public PathNotFoundException( Location location,
-                                  Path lowestAncestorThatDoesExist,
-                                  String message ) {
-        super(message);
-        this.location = location;
-        this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
-    }
-
-    /**
-     * @param location the location of the node that does not exist
-     * @param lowestAncestorThatDoesExist the path of the lowest (closest) ancestor that does exist
-     * @param cause
-     */
-    public PathNotFoundException( Location location,
-                                  Path lowestAncestorThatDoesExist,
-                                  Throwable cause ) {
-        super(cause);
-        this.location = location;
-        this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
-    }
-
-    /**
-     * @param location the location of the node that does not exist
-     * @param lowestAncestorThatDoesExist the path of the lowest (closest) ancestor that does exist
-     * @param message
-     * @param cause
-     */
-    public PathNotFoundException( Location location,
-                                  Path lowestAncestorThatDoesExist,
-                                  String message,
-                                  Throwable cause ) {
-        super(message, cause);
-        this.location = location;
-        this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return super.toString();
-    }
-
-    /**
-     * Get the path that was not found
-     * 
-     * @return the path that was not found
-     */
-    public Location getLocation() {
-        return location;
-    }
-
-    /**
-     * Get the lowest (closest) existing {@link Path#getParent() ancestor} of the {@link #getLocation() non-existant location}.
-     * 
-     * @return the lowest ancestor that does exist
-     */
-    public Path getLowestAncestorThatDoesExist() {
-        return lowestAncestorThatDoesExist;
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Property.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Property.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Property.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,219 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.util.Iterator;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
-
-/**
- * Representation of a property consisting of a name and value(s). Note that this property is immutable, meaning that the property
- * values may not be changed through this interface.
- * <p>
- * This class is designed to be used with the {@link ValueFactories} interface and the particular {@link ValueFactory} that
- * corresponds to the type of value you'd like to use. The <code>ValueFactory</code> will then return the values (if no type
- * conversion is required) or will convert the values using the appropriate conversion algorithm.
- * </p>
- * <p>
- * The following example shows how to obtain the {@link String} representations of the {@link #getValues() property values}:
- * 
- * <pre>
- *   ValueFactories valueFactories = ...
- *   Property property = ...
- *   Iterator&lt;String&gt; iter = valueFactories.getStringFactory().create(property.getValues());
- *   while ( iter.hasNext() ) {
- *       System.out.println(iter.next());
- *   }
- * </pre>
- * 
- * Meanwhile, the {@link ValueFactories#getLongFactory() long value factory} converts the values to <code>long</code>, the
- * {@link ValueFactories#getDateFactory() date value factory} converts the values to {@link DateTime} instances, and so on.
- * </p>
- * <p>
- * This technique is much better and far safer than casting the values. It is possible that some Property instances contain
- * heterogeneous values, so casting may not always work. Also, this technique guarantees that the values are properly converted if
- * the type is not what you expected.
- * </p>
- * 
- * @author Randall Hauch
- */
- at Immutable
-public interface Property extends Iterable<Object>, Comparable<Property> {
-
-    /**
-     * Get the name of the property.
-     * 
-     * @return the property name; never null
-     */
-    Name getName();
-
-    /**
-     * Get the number of actual values in this property. If the property allows {@link #isMultiple() multiple values}, then this
-     * method may return a value greater than 1. If the property only allows a {@link #isSingle() single value}, then this method
-     * will return either 0 or 1. This method may return 0 regardless of whether the property allows a {@link #isSingle() single
-     * value}, or {@link #isMultiple() multiple values}.
-     * 
-     * @return the number of actual values in this property; always non-negative
-     */
-    int size();
-
-    /**
-     * Determine whether the property currently has multiple values.
-     * 
-     * @return true if the property has multiple values, or false otherwise.
-     * @see #isSingle()
-     * @see #isEmpty()
-     */
-    boolean isMultiple();
-
-    /**
-     * Determine whether the property currently has a single value.
-     * 
-     * @return true if the property has a single value, or false otherwise.
-     * @see #isMultiple()
-     * @see #isEmpty()
-     */
-    boolean isSingle();
-
-    /**
-     * Determine whether this property has no actual values. This method may return <code>true</code> regardless of whether the
-     * property allows a {@link #isSingle() single value}, or {@link #isMultiple() multiple values}.
-     * <p>
-     * This method is a convenience method that is equivalent to <code>size() == 0</code>.
-     * </p>
-     * 
-     * @return true if this property has no values, or false otherwise
-     * @see #isMultiple()
-     * @see #isSingle()
-     */
-    boolean isEmpty();
-
-    /**
-     * Obtain the property's first value in its natural form. This is equivalent to calling
-     * <code>isEmpty() ? null : iterator().next()</code>
-     * 
-     * @return the first value, or null if the property is {@link #isEmpty() empty}
-     * @see Iterable#iterator()
-     * @see #getValues()
-     * @see #getValuesAsArray()
-     * @see #isEmpty()
-     */
-    Object getFirstValue();
-
-    /**
-     * Obtain the property's values in their natural form. This is equivalent to calling {@link Iterable#iterator() iterator()}.
-     * <p>
-     * A valid iterator is returned if the property has {@link #isSingle() single valued} or {@link #isMultiple() multi-valued}.
-     * </p>
-     * <p>
-     * The resulting iterator is immutable, and all property values are immutable.
-     * </p>
-     * 
-     * @return an iterator over the values; never null
-     * @see #getFirstValue()
-     * @see Iterable#iterator()
-     * @see #getValuesAsArray()
-     * @see ValueFactory#create(Iterator)
-     */
-    Iterator<?> getValues();
-
-    /**
-     * Obtain the property's values as an array of objects in their natural form.
-     * <p>
-     * A valid array is return if the property has {@link #isSingle() single valued} or {@link #isMultiple() multi-valued}, or a
-     * null value is returned if the property is {@link #isEmpty() empty}.
-     * </p>
-     * <p>
-     * The resulting array is a copy, guaranteeing immutability for the property.
-     * </p>
-     * 
-     * @return the array of values
-     * @see #getFirstValue()
-     * @see Iterable#iterator()
-     * @see #getValues()
-     * @see ValueFactory#create(Object[])
-     */
-    Object[] getValuesAsArray();
-
-    /**
-     * Get the string form of the property, using the default encoder.
-     * 
-     * @return the encoded string
-     * @see #getString(TextEncoder)
-     */
-    public String getString();
-
-    /**
-     * Get the encoded string form of the property, using the supplied encoder to encode characters in the property's name and
-     * values.
-     * 
-     * @param encoder the encoder to use, or null if the default encoder should be used
-     * @return the encoded string
-     * @see #getString()
-     */
-    public String getString( TextEncoder encoder );
-
-    /**
-     * Get the string form of the property, using the supplied namespace registry to convert the property's name and values.
-     * 
-     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-     *        {@link Name#getNamespaceUri() namespace URIs} in the property {@link #getName() name}
-     * @return the string
-     * @throws IllegalArgumentException if the namespace registry is null
-     * @see #getString(NamespaceRegistry,TextEncoder)
-     * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry );
-
-    /**
-     * Get the encoded string form of the property, using the supplied namespace registry to convert the property's namespace URIs
-     * to prefixes and the supplied encoder to encode characters in the property's name and values.
-     * 
-     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-     *        {@link Name#getNamespaceUri() namespace URIs} in the property {@link #getName() name}, or null if the namespace
-     *        registry should not be used
-     * @param encoder the encoder to use for encoding the name and values, or null if the default encoder should be used
-     * @return the encoded string
-     * @see #getString(NamespaceRegistry)
-     * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder );
-
-    /**
-     * Get the encoded string form of the property, using the supplied namespace registry to convert the property's namespace URIs
-     * to prefixes and the supplied encoder to encode characters in the property's name and values.
-     * 
-     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
-     *        {@link Name#getNamespaceUri() namespace URIs} in the property {@link #getName() name}, or null if the namespace
-     *        registry should not be used
-     * @param encoder the encoder to use for encoding the name and values, or null if the default encoder should be used
-     * @param delimiterEncoder the encoder to use for encoding delimiters used in paths and names, or null if the standard
-     *        delimiters should be used
-     * @return the encoded string
-     * @see #getString(NamespaceRegistry)
-     * @see #getString(NamespaceRegistry, TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder,
-                             TextEncoder delimiterEncoder );
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyFactory.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,96 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.util.Iterator;
-
-/**
- * @author Randall Hauch
- */
-public interface PropertyFactory {
-    /**
-     * Create a property with the supplied name and values
-     * 
-     * @param name the property name; may not be null
-     * @param values the values
-     * @return the resulting property
-     */
-    Property create( Name name,
-                     Object... values );
-
-    /**
-     * Create a property with the supplied name and values
-     * 
-     * @param name the property name; may not be null
-     * @param values the values
-     * @return the resulting property
-     */
-    Property create( Name name,
-                     Iterable<?> values );
-
-    /**
-     * Create a property with the supplied name and values
-     * 
-     * @param name the property name; may not be null
-     * @param values the values
-     * @return the resulting property
-     */
-    Property create( Name name,
-                     Iterator<?> values );
-
-    /**
-     * Create a property with the supplied name and values
-     * 
-     * @param name the property name; may not be null
-     * @param desiredType the type that the objects should be converted to; if null, they will be used as is
-     * @param values the values
-     * @return the resulting property
-     */
-    Property create( Name name,
-                     PropertyType desiredType,
-                     Object... values );
-
-    /**
-     * Create a property with the supplied name and values
-     * 
-     * @param name the property name; may not be null
-     * @param desiredType the type that the objects should be converted to; if null, they will be used as is
-     * @param values the values
-     * @return the resulting property
-     */
-    Property create( Name name,
-                     PropertyType desiredType,
-                     Iterable<?> values );
-
-    /**
-     * Create a property with the supplied name and values
-     * 
-     * @param name the property name; may not be null
-     * @param desiredType the type that the objects should be converted to; if null, they will be used as is
-     * @param values the values
-     * @return the resulting property
-     */
-    Property create( Name name,
-                     PropertyType desiredType,
-                     Iterator<?> values );
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyType.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyType.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyType.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,127 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.GraphI18n;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public enum PropertyType {
-
-    STRING("String", ValueComparators.STRING_COMPARATOR, String.class),
-    BINARY("Binary", ValueComparators.BINARY_COMPARATOR, Binary.class),
-    LONG("Long", ValueComparators.LONG_COMPARATOR, Long.class),
-    DOUBLE("Double", ValueComparators.DOUBLE_COMPARATOR, Double.class),
-    DECIMAL("Decimal", ValueComparators.DECIMAL_COMPARATOR, BigDecimal.class),
-    DATE("Date", ValueComparators.DATE_TIME_COMPARATOR, DateTime.class),
-    BOOLEAN("Boolean", ValueComparators.BOOLEAN_COMPARATOR, Boolean.class),
-    NAME("Name", ValueComparators.NAME_COMPARATOR, Name.class),
-    PATH("Path", ValueComparators.PATH_COMPARATOR, Path.class),
-    UUID("UUID", ValueComparators.UUID_COMPARATOR, UUID.class),
-    REFERENCE("Reference", ValueComparators.REFERENCE_COMPARATOR, Reference.class),
-    URI("URI", ValueComparators.URI_COMPARATOR, URI.class),
-    OBJECT("Object", ValueComparators.OBJECT_COMPARATOR, Object.class);
-
-    private static final List<PropertyType> ALL_PROPERTY_TYPES;
-    static {
-        List<PropertyType> types = new ArrayList<PropertyType>();
-        for (PropertyType type : PropertyType.values()) {
-            types.add(type);
-        }
-        ALL_PROPERTY_TYPES = Collections.unmodifiableList(types);
-    }
-
-    private final String name;
-    private final Comparator<?> comparator;
-    private final Class<?> valueClass;
-
-    private PropertyType( String name,
-                          Comparator<?> comparator,
-                          Class<?> valueClass ) {
-        this.name = name;
-        this.comparator = comparator;
-        this.valueClass = valueClass;
-    }
-
-    public Class<?> getValueClass() {
-        return this.valueClass;
-    }
-
-    public String getName() {
-        return this.name;
-    }
-
-    public Comparator<?> getComparator() {
-        return this.comparator;
-    }
-
-    public boolean isTypeFor( Object value ) {
-        return this.valueClass.isInstance(value);
-    }
-
-    public boolean isTypeForEach( Iterable<?> values ) {
-        for (Object value : values) {
-            if (!this.valueClass.isInstance(value)) return false;
-        }
-        return true;
-    }
-
-    public boolean isTypeForEach( Iterator<?> values ) {
-        while (values.hasNext()) {
-            Object value = values.next();
-            if (!this.valueClass.isInstance(value)) return false;
-        }
-        return true;
-    }
-
-    public static PropertyType discoverType( Object value ) {
-        if (value == null) {
-            throw new IllegalArgumentException(GraphI18n.unableToDiscoverPropertyTypeForNullValue.text());
-        }
-        for (PropertyType type : PropertyType.values()) {
-            if (type == OBJECT) continue;
-            if (type.isTypeFor(value)) return type;
-        }
-        return OBJECT;
-    }
-
-    /**
-     * Return an iterator over all the property type enumeration literals.
-     * 
-     * @return an immutable iterator
-     */
-    public static Iterator<PropertyType> iterator() {
-        return ALL_PROPERTY_TYPES.iterator();
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Reference.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Reference.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Reference.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,51 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.io.Serializable;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
-
-/**
- * A representation of a reference to another node. Node references may not necessarily resolve to an existing node.
- * @author Randall Hauch
- */
- at Immutable
-public interface Reference extends Comparable<Reference>, Serializable {
-
-    /**
-     * Get the string form of the Reference. The {@link Path#DEFAULT_ENCODER default encoder} is used to encode characters in the
-     * reference.
-     * @return the encoded string
-     * @see #getString(TextEncoder)
-     */
-    public String getString();
-
-    /**
-     * Get the encoded string form of the Reference, using the supplied encoder to encode characters in the reference.
-     * @param encoder the encoder to use, or null if the {@link Path#DEFAULT_ENCODER default encoder} should be used
-     * @return the encoded string
-     * @see #getString()
-     */
-    public String getString( TextEncoder encoder );
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ReferentialIntegrityException.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ReferentialIntegrityException.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ReferentialIntegrityException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,116 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.jboss.dna.graph.Location;
-
-/**
- * @author Randall Hauch
- */
-public class ReferentialIntegrityException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = -3703984046286975978L;
-
-    private final Map<Location, List<Reference>> invalidReferences;
-
-    /**
-     * @param location the location of the node containing the bad reference(s)
-     * @param invalidReferences the invalid references
-     */
-    public ReferentialIntegrityException( Location location,
-                                          Reference... invalidReferences ) {
-        this.invalidReferences = new HashMap<Location, List<Reference>>();
-        List<Reference> invalidRefList = null;
-        if (invalidReferences == null || invalidReferences.length == 0) {
-            invalidRefList = Collections.emptyList();
-        } else if (invalidReferences.length == 1) {
-            invalidRefList = Collections.singletonList(invalidReferences[0]);
-        } else {
-            invalidRefList = new ArrayList<Reference>();
-            for (Reference ref : invalidReferences) {
-                invalidRefList.add(ref);
-            }
-        }
-        this.invalidReferences.put(location, invalidRefList);
-    }
-
-    /**
-     * @param invalidReferences the map of locations to invalid references
-     */
-    public ReferentialIntegrityException( Map<Location, List<Reference>> invalidReferences ) {
-        this.invalidReferences = invalidReferences;
-    }
-
-    /**
-     * @param invalidReferences the map of locations to invalid references
-     * @param message
-     */
-    public ReferentialIntegrityException( Map<Location, List<Reference>> invalidReferences,
-                                          String message ) {
-        super(message);
-        this.invalidReferences = invalidReferences;
-    }
-
-    /**
-     * @param invalidReferences the map of locations to invalid references
-     * @param cause
-     */
-    public ReferentialIntegrityException( Map<Location, List<Reference>> invalidReferences,
-                                          Throwable cause ) {
-        super(cause);
-        this.invalidReferences = invalidReferences;
-    }
-
-    /**
-     * @param invalidReferences the map of locations to invalid references
-     * @param message
-     * @param cause
-     */
-    public ReferentialIntegrityException( Map<Location, List<Reference>> invalidReferences,
-                                          String message,
-                                          Throwable cause ) {
-        super(message, cause);
-        this.invalidReferences = invalidReferences;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return super.toString();
-    }
-
-    /**
-     * @return invalidReferences
-     */
-    public Map<Location, List<Reference>> getInvalidReferences() {
-        return invalidReferences;
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/UuidFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/UuidFactory.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/UuidFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,41 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.util.UUID;
-
-/**
- * A factory for creating {@link UUID UUID instances}. This interface extends the {@link ValueFactory} generic interface and adds
- * specific methods for creating UUIDs.
- * 
- * @author Randall Hauch
- */
-public interface UuidFactory extends ValueFactory<UUID> {
-
-    /**
-     * Create a new random UUID.
-     * 
-     * @return the new randomly generated UUID
-     */
-    UUID create();
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueComparators.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueComparators.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueComparators.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,332 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.UUID;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-
-/**
- * @author Randall Hauch
- */
-public class ValueComparators {
-
-    /**
-     * A comparator of string values.
-     */
-    public static final Comparator<String> STRING_COMPARATOR = new Comparator<String>() {
-
-        public int compare( String o1,
-                            String o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of long values.
-     */
-    public static final Comparator<Long> LONG_COMPARATOR = new Comparator<Long>() {
-
-        public int compare( Long o1,
-                            Long o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of double values.
-     */
-    public static final Comparator<Double> DOUBLE_COMPARATOR = new Comparator<Double>() {
-
-        public int compare( Double o1,
-                            Double o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of decimal values.
-     */
-    public static final Comparator<BigDecimal> DECIMAL_COMPARATOR = new Comparator<BigDecimal>() {
-
-        public int compare( BigDecimal o1,
-                            BigDecimal o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of binary values. Although {@link Binary} is {@link Comparable}, this comparator does not rely upon any
-     * particular Binary implementation. Thus, Binary implementations can use this for their {@link Comparable#compareTo(Object)}
-     * implementation.
-     */
-    public static final Comparator<Binary> BINARY_COMPARATOR = new Comparator<Binary>() {
-
-        public int compare( Binary o1,
-                            Binary o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            try {
-                o1.acquire();
-                try {
-                    o2.acquire();
-                    final long len1 = o1.getSize();
-                    final long len2 = o2.getSize();
-                    if (len1 < len2) return -1;
-                    if (len1 > len2) return 1;
-
-                    // Compare using the hashes, if available
-                    byte[] hash1 = o1.getHash();
-                    byte[] hash2 = o2.getHash();
-                    if (hash1.length != 0 || hash2.length != 0) {
-                        assert hash1.length == hash2.length;
-                        for (int i = 0; i != hash1.length; ++i) {
-                            int diff = hash1[i] - hash2[i];
-                            if (diff != 0) return diff;
-                        }
-                        return 0;
-                    }
-
-                    // Otherwise they are the same length ...
-                    InputStream stream1 = null;
-                    InputStream stream2 = null;
-                    try {
-                        stream1 = o1.getStream();
-                        stream2 = o2.getStream();
-                        byte[] buffer1 = new byte[1024];
-                        byte[] buffer2 = new byte[1024];
-                        while (true) {
-                            int numRead1 = stream1.read(buffer1);
-                            if (numRead1 < 0) break;
-                            int numRead2 = stream2.read(buffer2);
-                            if (numRead1 != numRead2) {
-                                throw new IoException(GraphI18n.errorReadingPropertyValueBytes.text());
-                            }
-                            for (int i = 0; i != numRead1; ++i) {
-                                int diff = buffer1[i] - buffer2[i];
-                                if (diff != 0) return diff;
-                            }
-                        }
-                        return 0;
-                    } catch (IOException e) {
-                        throw new IoException(GraphI18n.errorReadingPropertyValueBytes.text());
-                    } finally {
-                        if (stream1 != null) {
-                            try {
-                                stream1.close();
-                            } catch (IOException e) {
-                                // do nothing
-                            }
-                        }
-                        if (stream2 != null) {
-                            try {
-                                stream2.close();
-                            } catch (IOException e) {
-                                // do nothing
-                            }
-                        }
-                    }
-                } finally {
-                    o2.release();
-                }
-            } finally {
-                o1.release();
-            }
-        }
-    };
-    /**
-     * A comparator of boolean values.
-     */
-    public static final Comparator<Boolean> BOOLEAN_COMPARATOR = new Comparator<Boolean>() {
-
-        public int compare( Boolean o1,
-                            Boolean o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of date-time instances.
-     */
-    public static final Comparator<DateTime> DATE_TIME_COMPARATOR = new Comparator<DateTime>() {
-
-        public int compare( DateTime o1,
-                            DateTime o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of date values.
-     */
-    public static final Comparator<Date> DATE_COMPARATOR = new Comparator<Date>() {
-
-        public int compare( Date o1,
-                            Date o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of calendar values.
-     */
-    public static final Comparator<Calendar> CALENDAR_COMPARATOR = new Comparator<Calendar>() {
-
-        public int compare( Calendar o1,
-                            Calendar o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of name values.
-     */
-    public static final Comparator<Name> NAME_COMPARATOR = new Comparator<Name>() {
-
-        public int compare( Name o1,
-                            Name o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of path values.
-     */
-    public static final Comparator<Path> PATH_COMPARATOR = new Comparator<Path>() {
-
-        public int compare( Path o1,
-                            Path o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of URI values.
-     */
-    public static final Comparator<URI> URI_COMPARATOR = new Comparator<URI>() {
-
-        public int compare( URI o1,
-                            URI o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of UUID values.
-     */
-    public static final Comparator<UUID> UUID_COMPARATOR = new Comparator<UUID>() {
-
-        public int compare( UUID o1,
-                            UUID o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of reference values.
-     */
-    public static final Comparator<Reference> REFERENCE_COMPARATOR = new Comparator<Reference>() {
-
-        public int compare( Reference o1,
-                            Reference o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            return o1.compareTo(o2);
-        }
-    };
-    /**
-     * A comparator of other values.
-     */
-    public static final Comparator<Object> OBJECT_COMPARATOR = new Comparator<Object>() {
-
-        @SuppressWarnings( "unchecked" )
-        public int compare( Object o1,
-                            Object o2 ) {
-            if (o1 == o2) return 0;
-            if (o1 == null) return -1;
-            if (o2 == null) return 1;
-            PropertyType type1 = PropertyType.discoverType(o1);
-            PropertyType type2 = PropertyType.discoverType(o2);
-            if (type1 != PropertyType.OBJECT && type2 != PropertyType.OBJECT) {
-                if (type1 == type2) return ((Comparator<Object>)type1.getComparator()).compare(o1, o2);
-
-                // The types are different but the classes are the same ...
-                if (type1.getValueClass().isAssignableFrom(type2.getValueClass())) {
-                    return ((Comparator<Object>)type1.getComparator()).compare(o1, o2);
-                }
-                if (type2.getValueClass().isAssignableFrom(type1.getValueClass())) {
-                    return ((Comparator<Object>)type2.getComparator()).compare(o1, o2);
-                }
-            }
-
-            // The types are different and must be converted ...
-            String value1 = getStringValueFactory().create(o1);
-            String value2 = getStringValueFactory().create(o2);
-            return value1.compareTo(value2);
-        }
-    };
-
-    // This is loaded lazily so that there is not a circular dependency between PropertyType (depends on this),
-    // StringValueFactory (depends on PropertyType), and OBJECT_COMPARATOR (which depends on StringValueFactory) ...
-    private static ValueFactory<String> STRING_VALUE_FACTORY;
-
-    protected static final ValueFactory<String> getStringValueFactory() {
-        // No locking is required, because it doesn't matter if we create several instances during initialization ...
-        if (STRING_VALUE_FACTORY == null) {
-            STRING_VALUE_FACTORY = new StringValueFactory(Path.NO_OP_DECODER, Path.NO_OP_ENCODER);
-        }
-        return STRING_VALUE_FACTORY;
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactories.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactories.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactories.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,143 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.math.BigDecimal;
-import java.net.URI;
-
-/**
- * The set of standard {@link ValueFactory} instances.
- * 
- * @author Randall Hauch
- */
-public interface ValueFactories extends Iterable<ValueFactory<?>> {
-
-    /**
-     * Get the value factory that creates values of the supplied {@link PropertyType type}.
-     * 
-     * @param type the type for the values
-     * @return the factory; never null
-     * @throws IllegalArgumentException if the property type is null
-     */
-    ValueFactory<?> getValueFactory( PropertyType type );
-
-    /**
-     * Get the value factory that is best able to create values with the most natural type given by the supplied value.
-     * 
-     * @param prototype the value that should be used to determine the best value factory
-     * @return the factory; never null
-     * @throws IllegalArgumentException if the prototype value is null
-     */
-    ValueFactory<?> getValueFactory( Object prototype );
-
-    /**
-     * Get the value factory for {@link PropertyType#STRING string} properties.
-     * 
-     * @return the factory; never null
-     */
-    ValueFactory<String> getStringFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#BINARY binary} properties.
-     * 
-     * @return the factory; never null
-     */
-    BinaryFactory getBinaryFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#LONG long} properties.
-     * 
-     * @return the factory; never null
-     */
-    ValueFactory<Long> getLongFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#DOUBLE double} properties.
-     * 
-     * @return the factory; never null
-     */
-    ValueFactory<Double> getDoubleFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#DECIMAL decimal} properties.
-     * 
-     * @return the factory; never null
-     */
-    ValueFactory<BigDecimal> getDecimalFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#DATE date} properties.
-     * 
-     * @return the factory; never null
-     */
-    DateTimeFactory getDateFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#BOOLEAN boolean} properties.
-     * 
-     * @return the factory; never null
-     */
-    ValueFactory<Boolean> getBooleanFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#NAME name} properties.
-     * 
-     * @return the factory; never null
-     */
-    NameFactory getNameFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#REFERENCE reference} properties.
-     * 
-     * @return the factory; never null
-     */
-    ValueFactory<Reference> getReferenceFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#PATH path} properties.
-     * 
-     * @return the factory; never null
-     */
-    PathFactory getPathFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#URI URI} properties.
-     * 
-     * @return the factory; never null
-     */
-    ValueFactory<URI> getUriFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#UUID UUID} properties.
-     * 
-     * @return the factory; never null
-     */
-    UuidFactory getUuidFactory();
-
-    /**
-     * Get the value factory for {@link PropertyType#OBJECT object} properties.
-     * 
-     * @return the factory; never null
-     */
-    ValueFactory<Object> getObjectFactory();
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactory.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,486 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.UUID;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.text.TextEncoder;
-
-/**
- * A factory for {@link Property} values. Each create method may throw one of these exceptions when attempting to convert a
- * supplied value to the {@link #getPropertyType() factory's type}:
- * <ul>
- * <li>{@link IllegalArgumentException} - If the supplied value is invalid in respect to the conversion being attempted.</li>
- * <li>{@link UnsupportedOperationException} - If a conversion from the supplied value is not supported.</li>
- * <li>{@link IoException} - If an unexpected problem occurs during the conversion (such as an {@link IOException}).</li>
- * </ul>
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- * @param <T> the type of value to create
- */
-public interface ValueFactory<T> {
-
-    static final TextDecoder DEFAULT_DECODER = Path.NO_OP_DECODER;
-    static final TextEncoder DEFAULT_ENCODER = Path.NO_OP_ENCODER;
-
-    /**
-     * Get the {@link PropertyType type} of values created by this factory.
-     * 
-     * @return the value type; never null
-     */
-    PropertyType getPropertyType();
-
-    /**
-     * Create a value from a string, using no decoding.
-     * 
-     * @param value the string from which the value is to be created
-     * @return the value, or null if the supplied string is null
-     * @throws ValueFormatException if the conversion from a string could not be performed
-     * @see #create(String, TextDecoder)
-     */
-    T create( String value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a string, using the supplied decoder.
-     * 
-     * @param value the string from which the value is to be created
-     * @param decoder the decoder that should be used; if null, the {@link #DEFAULT_DECODER default decoder} is used
-     * @return the value, or null if the supplied string is null
-     * @throws ValueFormatException if the conversion from a string could not be performed
-     * @see #create(String)
-     */
-    T create( String value,
-              TextDecoder decoder ) throws ValueFormatException;
-
-    /**
-     * Create a value from an integer.
-     * 
-     * @param value the integer from which the value is to be created
-     * @return the value; never null
-     * @throws ValueFormatException if the conversion from an integer could not be performed
-     */
-    T create( int value ) throws ValueFormatException;
-
-    /**
-     * Create a long from a string.
-     * 
-     * @param value the string from which the long is to be created
-     * @return the value; never null
-     * @throws ValueFormatException if the conversion from a long could not be performed
-     */
-    T create( long value ) throws ValueFormatException;
-
-    /**
-     * Create a boolean from a string.
-     * 
-     * @param value the boolean from which the value is to be created
-     * @return the value; never null
-     * @throws ValueFormatException if the conversion from a boolean could not be performed
-     */
-    T create( boolean value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a float.
-     * 
-     * @param value the float from which the value is to be created
-     * @return the value; never null
-     * @throws ValueFormatException if the conversion from a float could not be performed
-     */
-    T create( float value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a double.
-     * 
-     * @param value the double from which the value is to be created
-     * @return the value; never null
-     * @throws ValueFormatException if the conversion from a double could not be performed
-     */
-    T create( double value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a decimal.
-     * 
-     * @param value the decimal from which the value is to be created
-     * @return the value, or null if the supplied decimal is null
-     * @throws ValueFormatException if the conversion from a decimal could not be performed
-     */
-    T create( BigDecimal value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a Calendar instance.
-     * 
-     * @param value the Calendar instance from which the value is to be created
-     * @return the value, or null if the supplied Calendar is null
-     * @throws ValueFormatException if the conversion from a Calendar could not be performed
-     */
-    T create( Calendar value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a date.
-     * 
-     * @param value the date from which the value is to be created
-     * @return the value, or null if the supplied date is null
-     * @throws ValueFormatException if the conversion from a Date could not be performed
-     */
-    T create( Date value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a date-time instant.
-     * 
-     * @param value the date-time instant from which the value is to be created
-     * @return the value, or null if the supplied date is null
-     * @throws ValueFormatException if the conversion from a Date could not be performed
-     */
-    T create( DateTime value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a name.
-     * 
-     * @param value the name from which the value is to be created
-     * @return the value, or null if the supplied name is null
-     * @throws ValueFormatException if the conversion from a name could not be performed
-     */
-    T create( Name value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a path.
-     * 
-     * @param value the path from which the value is to be created
-     * @return the value, or null if the supplied path is null
-     * @throws ValueFormatException if the conversion from a path could not be performed
-     */
-    T create( Path value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a reference.
-     * 
-     * @param value the reference from which the value is to be created
-     * @return the value, or null if the supplied reference is null
-     * @throws ValueFormatException if the conversion from a reference could not be performed
-     */
-    T create( Reference value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a URI.
-     * 
-     * @param value the URI from which the value is to be created
-     * @return the value, or null if the supplied URI is null
-     * @throws ValueFormatException if the conversion from a URI could not be performed
-     */
-    T create( URI value ) throws ValueFormatException;
-
-    /**
-     * Create a value from a UUID.
-     * 
-     * @param value the UUID from which the value is to be created
-     * @return the value, or null if the supplied URI is null
-     * @throws ValueFormatException if the conversion from a UUID could not be performed
-     */
-    T create( UUID value ) throws ValueFormatException;
-
-    /**
-     * Create a value from the binary content given by the supplied array.
-     * 
-     * @param value the content to be used to create the value
-     * @return the value, or null if the supplied stream is null
-     * @throws ValueFormatException if the conversion from a byte array could not be performed
-     */
-    T create( byte[] value ) throws ValueFormatException;
-
-    /**
-     * Create a value from the binary content given by the supplied stream.
-     * 
-     * @param value the binary object to be used to create the value
-     * @return the value, or null if the supplied stream is null
-     * @throws ValueFormatException if the conversion from the binary object could not be performed
-     * @throws IoException If an unexpected problem occurs while accessing the supplied binary value (such as an
-     *         {@link IOException}).
-     */
-    T create( Binary value ) throws ValueFormatException, IoException;
-
-    /**
-     * Create a value from the binary content given by the supplied stream.
-     * 
-     * @param stream the stream containing the content to be used to create the value
-     * @param approximateLength the approximate length of the content (in bytes)
-     * @return the value, or null if the supplied stream is null
-     * @throws ValueFormatException if the conversion from an input stream could not be performed
-     * @throws IoException If an unexpected problem occurs while accessing the supplied stream (such as an {@link IOException}).
-     */
-    T create( InputStream stream,
-              long approximateLength ) throws ValueFormatException, IoException;
-
-    /**
-     * Create a value from a the binary content given by the supplied reader.
-     * 
-     * @param reader the reader containing the content to be used to create the value
-     * @param approximateLength the approximate length of the content (in bytes)
-     * @return the value, or null if the supplied string is null
-     * @throws ValueFormatException if the conversion from a reader could not be performed
-     * @throws IoException If an unexpected problem occurs while accessing the supplied reader (such as an {@link IOException}).
-     */
-    T create( Reader reader,
-              long approximateLength ) throws ValueFormatException, IoException;
-
-    /**
-     * Create a value from the specified information by determining which other <code>create</code> method applies and delegating
-     * to that method. Note that this method only will call <code>create</code> methods that take a single parameter; so this
-     * excludes {@link #create(InputStream, long)}, {@link #create(Reader, long)} and {@link #create(String, TextDecoder)}.
-     * 
-     * @param value the value
-     * @return the new value, or null if the supplied parameter is null
-     * @throws ValueFormatException if the conversion from an object could not be performed
-     * @throws IoException If an unexpected problem occurs while accessing the supplied binary value (such as an
-     *         {@link IOException}).
-     */
-    T create( Object value ) throws ValueFormatException, IoException;
-
-    /**
-     * Create an array of values from an array of string values, using no decoding.
-     * 
-     * @param values the values
-     * @return the values, or null if the supplied string is null
-     * @throws ValueFormatException if the conversion from a string array could not be performed
-     * @see #create(String[], TextDecoder)
-     */
-    T[] create( String[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of strings, using the supplied decoder.
-     * 
-     * @param values the string values from which the values are to be created
-     * @param decoder the decoder that should be used; if null, the {@link #DEFAULT_DECODER default decoder} is used
-     * @return the value, or null if the supplied string is null
-     * @throws ValueFormatException if the conversion from a string array could not be performed
-     * @see #create(String)
-     */
-    T[] create( String[] values,
-                TextDecoder decoder ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of integers.
-     * 
-     * @param values the integers from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an integer array could not be performed
-     */
-    T[] create( int[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of longs.
-     * 
-     * @param values the longs from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of longs could not be performed
-     */
-    T[] create( long[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of booleans.
-     * 
-     * @param values the booleans from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of booleans could not be performed
-     */
-    T[] create( boolean[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of floats.
-     * 
-     * @param values the floats from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of floats could not be performed
-     */
-    T[] create( float[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of doubles.
-     * 
-     * @param values the doubles from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of doubles could not be performed
-     */
-    T[] create( double[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of decimal values.
-     * 
-     * @param values the decimals from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of decimal values could not be performed
-     */
-    T[] create( BigDecimal[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of Calendar instances.
-     * 
-     * @param values the Calendar instances from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of calendar instances could not be performed
-     */
-    T[] create( Calendar[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of dates.
-     * 
-     * @param values the dates from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of date values could not be performed
-     */
-    T[] create( Date[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of {@link DateTime} instants.
-     * 
-     * @param values the instants from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of date values could not be performed
-     */
-    T[] create( DateTime[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of names.
-     * 
-     * @param values the names from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of names could not be performed
-     */
-    T[] create( Name[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of paths.
-     * 
-     * @param values the paths from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of paths could not be performed
-     */
-    T[] create( Path[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of references.
-     * 
-     * @param values the references from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of references could not be performed
-     */
-    T[] create( Reference[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of URIs.
-     * 
-     * @param values the URIs from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of URIs could not be performed
-     */
-    T[] create( URI[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from an array of UUIDs.
-     * 
-     * @param values the UUIDs from which the values are to be created
-     * @return the values, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of UUIDs could not be performed
-     */
-    T[] create( UUID[] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from the array of binary content.
-     * 
-     * @param values the array of content to be used to create the values
-     * @return the value, or null if the supplied array is null
-     * @throws ValueFormatException if the conversion from an array of byte arrays could not be performed
-     */
-    T[] create( byte[][] values ) throws ValueFormatException;
-
-    /**
-     * Create an array of values from the array of binary objects.
-     * 
-     * @param values the values
-     * @return the new value, or null if the supplied parameter is null
-     * @throws ValueFormatException if the conversion from an array of objects could not be performed
-     * @throws IoException If an unexpected problem occurs during the conversion.
-     */
-    T[] create( Binary[] values ) throws ValueFormatException, IoException;
-
-    /**
-     * Create an array of values from the specified information by determining which other <code>create</code> method applies for
-     * each object and then delegating to that method. Note that this method will not consider {@link #create(InputStream, long)},
-     * {@link #create(Reader, long)} and {@link #create(String, TextDecoder)}.
-     * 
-     * @param values the values
-     * @return the new value, or null if the supplied parameter is null
-     * @throws ValueFormatException if the conversion from an array of objects could not be performed
-     * @throws IoException If an unexpected problem occurs during the conversion.
-     */
-    T[] create( Object[] values ) throws ValueFormatException, IoException;
-
-    /**
-     * Create an iterator over the values (of an unknown type). The factory converts any values as required. Note that this method
-     * will not consider {@link #create(InputStream, long)}, {@link #create(Reader, long)} and
-     * {@link #create(String, TextDecoder)}.
-     * <p>
-     * This is useful to use when iterating over the {@link Property#getValues() values} of a {@link Property}.
-     * </p>
-     * 
-     * @param values the values
-     * @return the iterator of type <code>T</code> over the values, or null if the supplied parameter is null
-     * @throws ValueFormatException if the conversion from an iterator of objects could not be performed
-     * @throws IoException If an unexpected problem occurs during the conversion.
-     * @see Property#getValues()
-     */
-    Iterator<T> create( Iterator<?> values ) throws ValueFormatException, IoException;
-
-    /**
-     * Create an iterable with the values (of an unknown type). The factory converts any values as required. Note that this method
-     * will not consider {@link #create(InputStream, long)}, {@link #create(Reader, long)} and
-     * {@link #create(String, TextDecoder)}.
-     * <p>
-     * This is useful to use when converting all the {@link Property#getValues() values} of a {@link Property}.
-     * </p>
-     * Example:
-     * 
-     * <pre>
-     *      Property property = ...
-     *      ExecutionContext executionContext = ...
-     *      ValueFactory&lt;String&gt; stringFactory = executionContext.getValueFactories().getStringFactory();
-     *      for (String token : stringFactory.create(property)) {
-     *          ...
-     *      }
-     * </pre>
-     * 
-     * @param valueIterable the values
-     * @return the iterator of type <code>T</code> over the values, or null if the supplied parameter is null
-     * @throws ValueFormatException if the conversion from an iterator of objects could not be performed
-     * @throws IoException If an unexpected problem occurs during the conversion.
-     * @see Property#getValues()
-     */
-    Iterable<T> create( Iterable<?> valueIterable ) throws ValueFormatException, IoException;
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFormatException.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFormatException.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFormatException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,112 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-/**
- * @author Randall Hauch
- */
-public class ValueFormatException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = 1L;
-
-    private final Object value;
-    private final PropertyType targetType;
-
-    /**
-     * @param value the value that was not able to be converted
-     * @param targetType the {@link PropertyType} to which the value was being converted
-     */
-    public ValueFormatException( Object value,
-                                 PropertyType targetType ) {
-        this.value = value;
-        this.targetType = targetType;
-    }
-
-    /**
-     * @param value the value that was not able to be converted
-     * @param targetType the {@link PropertyType} to which the value was being converted
-     * @param message the message
-     */
-    public ValueFormatException( Object value,
-                                 PropertyType targetType,
-                                 String message ) {
-        super(message);
-        this.value = value;
-        this.targetType = targetType;
-    }
-
-    /**
-     * @param value the value that was not able to be converted
-     * @param targetType the {@link PropertyType} to which the value was being converted
-     * @param cause the cause of the exception
-     */
-    public ValueFormatException( Object value,
-                                 PropertyType targetType,
-                                 Throwable cause ) {
-        super(cause);
-        this.value = value;
-        this.targetType = targetType;
-    }
-
-    /**
-     * @param value the value that was not able to be converted
-     * @param targetType the {@link PropertyType} to which the value was being converted
-     * @param message the message
-     * @param cause the cause of the exception
-     */
-    public ValueFormatException( Object value,
-                                 PropertyType targetType,
-                                 String message,
-                                 Throwable cause ) {
-        super(message, cause);
-        this.value = value;
-        this.targetType = targetType;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return super.toString();
-    }
-
-    /**
-     * Get the {@link PropertyType} to which the {@link #getValue() value} was being converted.
-     * 
-     * @return the target type
-     */
-    public PropertyType getTargetType() {
-        return targetType;
-    }
-
-    /**
-     * Get the original value that was being converted.
-     * 
-     * @return the value
-     */
-    public Object getValue() {
-        return value;
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/package-info.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/package-info.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,158 +0,0 @@
-/**
- * Nodes in a graph contain properties, and this package defines the interfaces, classes and exceptions for
- * representing and working with properties and their values.
- * <p>
- * A <i>property</i> consists of a <i>name</i> and a set of <i>values</i>.  A property name is represented
- * by {@link Name}, and is defined as a {@link Name#getLocalName() local name} in a {@link Name#getNamespaceUri() namespace}.
- * Property values can be of any type, although there are specific interfaces for the known types:
- * <ul>
- *  <li>{@link PropertyType#STRING String} - A value represented with instances of the standard {@link String} class.</li>
- *  <li>{@link PropertyType#BINARY Binary} - A value represented with instances of the {@link Binary} interface.</li>
- *  <li>{@link PropertyType#LONG Long} - A value represented with instances of the standard {@link Long} class.</li>
- *  <li>{@link PropertyType#DOUBLE Double} - A value represented with instances of the standard {@link Double} class.</li>
- *  <li>{@link PropertyType#DECIMAL Decimal} - A value represented with instances of the standard {@link java.math.BigDecimal} class.</li>
- *  <li>{@link PropertyType#DATE Date} - A value represented with instances of the {@link DateTime} interface.
- *  This interface hides the mishmash of Java date representations, and is designed to follow the anticipated
- *  <code>ZonedDateTime</code> that is part of JSR-310.</li>
- *  <li>{@link PropertyType#BOOLEAN Boolean} - A value represented with instances of the standard {@link Boolean} class.</li>
- *  <li>{@link PropertyType#NAME Name} - A value represented with instances of the {@link Name} interface.</li>
- *  <li>{@link PropertyType#PATH Path} - A value represented with instances of the {@link Path} interface.</li>
- *  <li>{@link PropertyType#UUID UUID} - A value represented with instances of the standard {@link java.util.UUID} class.</li>
- *  <li>{@link PropertyType#REFERENCE Reference} - A value represented with instances of the {@link Reference} interface.</li>
- *  <li>{@link PropertyType#URI URI} - A value represented with instances of the standard {@link java.net.URI} class.</li>
- *  <li>{@link PropertyType#OBJECT Object} - A value represented with instances of any class, although the class
- *  should in all practicality implement {@link java.io.Serializable}.</li>
- * </ul>
- * </p>
- * 
- * <h3>Creating and converting property values</h3>
- * <p>
- * The design of properties and their values was centered around one key principle: when using a property value,
- * you often don't care what type the property value actually is, but instead care about converting it to a
- * property type that you know how to work with.  For example, you may be working with a property that represents
- * a date, and you want to work with the value as a {@link DateTime} object, regardless of whether the values
- * are actually String, {@link DateTime}, {@link Binary}, or even {@link java.util.Calendar} or {@link java.util.Date}
- * instances.  You know its should be a date, so you want to get a value that behaves as a date.
- * </p>
- * <p>
- * This notion of working with a <i>desired type</i> implies the ability to convert from one value type to another.
- * And in fact, creating values is really just converting from "other" types into a known type.
- * So, we can use the <i>factory</i> design pattern to have a single concept of a component that creates property values
- * from a variety of types.  But by using generics, we can use a single {@link ValueFactory factory} interface
- * that has the same methods for creating value objects, but make the return type specific to the type we want to create.
- * </p>
- * <p>
- * The {@link ValueFactory} interface is defined as follows:
- * <pre>
- *   public interface ValueFactory&lt;T> {
- *       T create( String value ) throws ValueFormatException;
- *       T create( int value ) throws ValueFormatException;
- *       T create( long value ) throws ValueFormatException;
- *       T create( double value ) throws ValueFormatException;
- *       ...
- *       T create( java.util.Date value ) throws ValueFormatException;
- *       T create( java.util.Calendar value ) throws ValueFormatException;
- *       T create( DateTime value ) throws ValueFormatException;
- *       ...
- *       T create( java.util.UUID value ) throws ValueFormatException;
- *       T create( java.net.URI value ) throws ValueFormatException;
- *       T create( Reference value ) throws ValueFormatException;
- *       T create( Name value ) throws ValueFormatException;
- *       T create( Path value ) throws ValueFormatException;
- *       ...
- *       T create( InputStream value, long approximateLength ) throws ValueFormatException;
- *       T create( Reader value, long approximateLength ) throws ValueFormatException;
- *       T create( Binary value ) throws ValueFormatException;
- *       ...
- *       T[] create( String[] value ) throws ValueFormatException;
- *       T[] create( int[] value ) throws ValueFormatException;
- *       T[] create( long[] value ) throws ValueFormatException;
- *       T[] create( double[] value ) throws ValueFormatException;
- *       ...
- *   }
- * </pre>
- * Notice that all the methods are called <code>create</code>, and most take a single parameter whose type is
- * one of the known types, a primitive, or a number of "other" types frequently encountered.  (The <code>create(...)</code>
- * methods that take an {@link java.io.InputStream} or {@link java.io.Reader} have a second parameter that specifies
- * the length of the data.)  Finally, note that almost all of the <code>create</code> methods have a form that each 
- * take an array of values and return an array of <code>T</code>.
- * </p>
- * <p>
- * These methods also all throw a {@link ValueFormatException}, in case the supplied
- * parameter cannot be converted to the desired type.  In many cases, there is a conversion (e.g., from the String "123"
- * to an integer), but there certainly are cases where no conversion is allowed (e.g., the String "a123" cannot be converted
- * to an integer, and a {@link Name} cannot be converted to a <code>boolean</code>).  All types can be converted
- * to a string, and all factories support converting that string back to its original form.
- * </p>
- * <p>
- * The factory for creating {@link DateTime} objects would then be an implementation of <code>ValueFactory&lt;DateTime></code>,
- * a factory for creating {@link Binary} objects would be an implementation of <code>ValueFactory&lt;Binary</code>,
- * and so on.  In some cases, we'd like to add additional forms of <code>create(...)</code> for specific values, and
- * we can do this by extending a typed {@link ValueFactory}.  For example, the {@link DateTimeFactory} adds
- * more methods for creating {@link DateTime} objects for the current time, current time in UTC, from another time
- * and an offset, and from individual field values:
- * <pre>
- *   public interface DateTimeFactory extends ValueFactories&lt;DateTime> {
- *       DateTime create();
- *       DateTime createUtc();
- *       DateTime create( DateTime original, long offsetInMillis );
- *       DateTime create( int year, int monthOfYear, int dayOfMonth,
- *                        int hourOfDay, int minuteOfHour, int secondOfMinute, int millisecondsOfSecond );
- *       DateTime create( int year, int monthOfYear, int dayOfMonth,
- *                        int hourOfDay, int minuteOfHour, int secondOfMinute, int millisecondsOfSecond,
- *                        int timeZoneOffsetHours );
- *       DateTime create( int year, int monthOfYear, int dayOfMonth,
- *                        int hourOfDay, int minuteOfHour, int secondOfMinute, int millisecondsOfSecond,
- *                        String timeZoneId );
- *   }
- * </pre>
- * There are specialized factory interfaces for several other types, including {@link PathFactory}, {@link NameFactory},
- * and {@link UuidFactory}.
- * </p>
- * <p>
- * The {@link ValueFactories} interface collects all the factories into a single spot:
- * <pre>
- *   public interface ValueFactories&lt;T> {
- *       ValueFactory&lt;String> getStringFactory();
- *       ValueFactory&lt;Binary> getBinaryFactory();
- *       ValueFactory&lt;Long> getLongFactory();
- *       ValueFactory&lt;Double> getDoubleFactory();
- *       ValueFactory&lt;BigDecimal> getDecimalFactory();
- *       DateTimeFactory getDateFactory();
- *       ValueFactory&lt;Boolean> getBooleanFactory();
- *       NameFactory getNameFactory();
- *       ValueFactory&lt;Reference> getReferenceFactory();
- *       PathFactory getPathFactory();
- *       ValueFactory&lt;URI> getUriFactory();
- *       UuidFactory getUuidFactory();
- *       ValueFactory&lt;Object> getObjectFactory();
- *       
- *       ValueFactory&lt;?> getValueFactory( PropertyType type );
- *       ValueFactory&lt;?> getValueFactory( Object prototype );
- *   }
- * </pre>
- * This allows us to programmatically get the correct factory for a type known at compile time, but also 
- * to obtain the correct factory given a prototype object or the enumeration literal representing
- * the desired type.  Thus, the following code compiles:
- * <pre>
- *    ValueFactories factories = ...
- *    DateTime now = factories.getDateFactory.create();
- *    String stringValue = factories.getStringFactory().create(now);
- * </pre>
- * A {@link ValueFactories} is provided as part of the {@link org.jboss.dna.graph.ExecutionContext}.  In this way,
- * the environment may use a different implementation of one or more factories.
- * </p>
- * 
- * <h3>Comparing property values</h3>
- * <p>
- * Because we have a mixture of standard Java types and custom interfaces for property values, we need
- * a set of {@link java.util.Comparator} implementations that allow us to compare property values.
- * The {@link ValueComparators} class defines a number of singleton comparators that can be used.
- * Plus, the {@link PropertyType} enumeration has the ability to {@link PropertyType#getComparator() get the comparator}
- * for the specific type (e.g., <code>PropertyType.BINARY.getComparator()</code>).
- * </p>
- * 
- */
-
-package org.jboss.dna.graph.properties;
-

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Binary.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Binary.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Binary.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Binary.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,91 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.io.InputStream;
+import java.io.Serializable;
+import java.security.MessageDigest;
+import net.jcip.annotations.Immutable;
+
+/**
+ * Value holder for binary data. Binary instances are not mutable.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public interface Binary extends Comparable<Binary>, Serializable {
+
+    /**
+     * Get the length of this binary data.
+     * 
+     * @return the number of bytes in this binary data
+     * @see #acquire()
+     */
+    public long getSize();
+
+    /**
+     * Get the SHA-1 hash of the contents. This hash can be used to determine whether two Binary instances contain the same
+     * content.
+     * <p>
+     * Repeatedly calling this method should generally be efficient, as it most implementations will compute the hash only once.
+     * </p>
+     * 
+     * @return the hash of the contents as a byte array, or an empty array if the hash could not be computed.
+     * @see #acquire()
+     * @see MessageDigest#digest(byte[])
+     * @see MessageDigest#getInstance(String)
+     */
+    public byte[] getHash();
+
+    /**
+     * Get the contents of this data as a stream.
+     * 
+     * @return the stream to this data's contents
+     * @see #acquire()
+     * @throws IoException if there is a problem returning the stream
+     */
+    public InputStream getStream();
+
+    /**
+     * Get the contents of this data as a byte array.
+     * 
+     * @return the data as an array
+     * @see #acquire()
+     * @throws IoException if there is a problem returning the bytes
+     */
+    public byte[] getBytes();
+
+    /**
+     * Acquire any resources for this data. This method must be called before any other method on this object.
+     * 
+     * @see #release()
+     */
+    public void acquire();
+
+    /**
+     * Release any acquired resources. This method must be called after a client is finished with this value.
+     * 
+     * @see #acquire()
+     */
+    public void release();
+
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/BinaryFactory.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/BinaryFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/BinaryFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/BinaryFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * A factory for creating {@link Binary} instances. This interface extends the {@link ValueFactory} generic interface and adds
+ * specific methods for creating binary objects.
+ * 
+ * @author Randall Hauch
+ */
+public interface BinaryFactory extends ValueFactory<Binary> {
+
+    /**
+     * Create a value from the binary content given by the supplied stream, the approximate length, and the SHA-1 secure hash of
+     * the content. If the secure hash is null, then a secure hash is computed from the content. If the secure hash is not null,
+     * it is assumed to be the hash for the content and may not be checked.
+     * 
+     * @param stream the stream containing the content to be used to create the value
+     * @param approximateLength the approximate length of the content (in bytes)
+     * @param secureHash the secure hash of the content in the <code>stream</code>; if null, the secure hash is computed from the
+     *        content, and if not null it is assumed to be the correct secure hash (and is not checked)
+     * @return the value, or null if the supplied stream is null
+     * @throws ValueFormatException if the conversion from an input stream could not be performed
+     * @throws IoException If an unexpected problem occurs while accessing the supplied stream (such as an {@link IOException}).
+     * @throws IllegalArgumentException if the secure hash was discovered to be incorrect
+     */
+    Binary create( InputStream stream,
+                   long approximateLength,
+                   byte[] secureHash ) throws ValueFormatException, IoException;
+
+    /**
+     * Create a value from the binary content given by the supplied reader, the approximate length, and the SHA-1 secure hash of
+     * the content. If the secure hash is null, then a secure hash is computed from the content. If the secure hash is not null,
+     * it is assumed to be the hash for the content and may not be checked.
+     * 
+     * @param reader the reader containing the content to be used to create the value
+     * @param approximateLength the approximate length of the content (in bytes)
+     * @param secureHash the secure hash of the content in the <code>stream</code>; if null, the secure hash is computed from the
+     *        content, and if not null it is assumed to be the correct secure hash (and is not checked)
+     * @return the value, or null if the supplied string is null
+     * @throws ValueFormatException if the conversion from a reader could not be performed
+     * @throws IoException If an unexpected problem occurs while accessing the supplied reader (such as an {@link IOException}).
+     * @throws IllegalArgumentException if the secure hash was discovered to be incorrect
+     */
+    Binary create( Reader reader,
+                   long approximateLength,
+                   byte[] secureHash ) throws ValueFormatException, IoException;
+
+    /**
+     * Create a binary value from the given file.
+     * 
+     * @param file the file containing the content to be used
+     * @return the binary value, or null if the file parameter was null
+     * @throws ValueFormatException if the conversion from the file could not be performed
+     * @throws IoException If an unexpected problem occurs while accessing the supplied file (such as an {@link IOException}).
+     */
+    Binary create( File file ) throws ValueFormatException, IoException;
+
+    /**
+     * Find an existing binary value given the supplied secure hash. If no such binary value exists, null is returned. This method
+     * can be used when the caller knows the secure hash (e.g., from a previously-held Binary object), and would like to reuse an
+     * existing binary value (if possible) rather than recreate the binary value by processing the stream contents. This is
+     * especially true when the size of the binary is quite large.
+     * 
+     * @param secureHash the secure hash of the binary content, which was probably {@link Binary#getHash() obtained} from a
+     *        previously-held {@link Binary} object; a null or empty value is allowed, but will always result in returning null
+     * @return the existing Binary value that has the same secure hash, or null if there is no such value available at this time
+     */
+    Binary find( byte[] secureHash );
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/BinaryFactory.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/DateTime.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTime.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/DateTime.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/DateTime.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,422 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.io.Serializable;
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+import net.jcip.annotations.Immutable;
+
+/**
+ * An immutable date-time class that represents an instance in time. This class is designed to hide the horrible implementations
+ * of the JDK date and calendar classes, which are being overhauled (and replaced) under <a
+ * href="http://jcp.org/en/jsr/detail?id=310">JSR-310</a>, which will be based upon <a
+ * href="http://joda-time.sourceforge.net/">Joda-Time</a>. This class serves as a stable migration path toward the new JSR 310
+ * classes.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public interface DateTime extends Comparable<DateTime>, Serializable {
+
+    /**
+     * Get the ISO-8601 representation of this instance in time. The month-based ISO-8601 representation is the most common format
+     * of ISO8601, and is the format used in the XML standards for passing dates and times:
+     * 
+     * <pre>
+     * yyyy-mm-ddTHH:MM:SS.SSSZ
+     * </pre>
+     * 
+     * The fields are separated by dashes and consist of:
+     * <ul>
+     * <li>four digit year;</li>
+     * <li>two digit month, where 01 is Janurary and 12 is December;</li>
+     * <li>two digit day of month, from 01 to 31;</li>
+     * <li>two digit hour, from 00 to 23;</li>
+     * <li>two digit minute, from 00 to 59;</li>
+     * <li>two digit second, from 00 to 59;</li>
+     * <li>three decimal places for milliseconds, if required;</li>
+     * <li>time zone offset of the form <code>±HH:mm</code> (or '0' if UTC)</li>
+     * </ul>
+     * 
+     * @return the string representation; never null
+     */
+    String getString();
+
+    /**
+     * Get the number of milliseconds from 1970-01-01T00:00Z. This value is consistent with the JDK {@link java.util.Date Date}
+     * and {@link java.util.Calendar Calendar} classes.
+     * 
+     * @return the number of milliseconds from 1970-01-01T00:00Z
+     */
+    long getMilliseconds();
+
+    /**
+     * Get this instance represented as a standard JDK {@link java.util.Date} instance. Note that this conversion loses the time
+     * zone information, as the standard JDK {@link java.util.Date} does not represent time zones.
+     * 
+     * @return this instance in time as a JDK Date; never null
+     */
+    java.util.Date toDate();
+
+    /**
+     * Get this instance represented as a standard JDK {@link java.util.Calendar} instance, in the {@link Locale#getDefault()
+     * default locale}.
+     * 
+     * @return this instance in time as a JDK Calendar; never null
+     */
+    java.util.Calendar toCalendar();
+
+    /**
+     * Get this instance represented as a standard JDK {@link java.util.Calendar} instance, in the specified {@link Locale locale}
+     * .
+     * 
+     * @param locale the locale in which the Calendar instance is desired; may be null if the {@link Locale#getDefault() default
+     *        locale} is to be used.
+     * @return this instance in time as a JDK Calendar; never null
+     */
+    java.util.Calendar toCalendar( Locale locale );
+
+    /**
+     * Get this instance represented as a standard JDK {@link java.util.GregorianCalendar} instance.
+     * 
+     * @return this instance in time as a JDK GregorianCalendar; never null
+     */
+    java.util.GregorianCalendar toGregorianCalendar();
+
+    /**
+     * Get the era of this instance in time.
+     * 
+     * @return the era
+     */
+    int getEra();
+
+    /**
+     * Get the era of this instance in time.
+     * 
+     * @return the era
+     */
+    int getYear();
+
+    /**
+     * Get the era of this instance in time.
+     * 
+     * @return the era
+     */
+    int getWeekyear();
+
+    /**
+     * Get the era of this instance in time.
+     * 
+     * @return the era
+     */
+    int getCenturyOfEra();
+
+    /**
+     * Get the year of the era of this instance in time.
+     * 
+     * @return the year of the era
+     */
+    int getYearOfEra();
+
+    /**
+     * Get the year of this century of this instance in time.
+     * 
+     * @return the year of the century
+     */
+    int getYearOfCentury();
+
+    /**
+     * Get the month of the year of this instance in time.
+     * 
+     * @return the month number
+     */
+    int getMonthOfYear();
+
+    /**
+     * Get the week of the weekyear of this instance in time.
+     * 
+     * @return the week of the weekyear
+     */
+    int getWeekOfWeekyear();
+
+    /**
+     * Get the day of the year of this instance in time.
+     * 
+     * @return the day of the year
+     */
+    int getDayOfYear();
+
+    /**
+     * Get the day of the month value of this instance in time.
+     * 
+     * @return the day of the month
+     */
+    int getDayOfMonth();
+
+    /**
+     * Get the day of the week value of this instance in time.
+     * 
+     * @return the day of the week
+     */
+    int getDayOfWeek();
+
+    /**
+     * Get the hour of the day of this instance in time.
+     * 
+     * @return the hour of the day
+     */
+    int getHourOfDay();
+
+    /**
+     * Get the minute of this instance in time.
+     * 
+     * @return the minute of the hour
+     */
+    int getMinuteOfHour();
+
+    /**
+     * Get the seconds of the minute value of this instance in time.
+     * 
+     * @return the seconds of the minute
+     */
+    int getSecondOfMinute();
+
+    /**
+     * Get the milliseconds of the second value of this instance in time.
+     * 
+     * @return the milliseconds
+     */
+    int getMillisOfSecond();
+
+    /**
+     * Get the number of hours that this time zone is offset from UTC.
+     * 
+     * @return the number of hours
+     */
+    int getTimeZoneOffsetHours();
+
+    /**
+     * Get the identifier of the time zone in which this instant is defined
+     * 
+     * @return the time zone identifier; never null
+     */
+    String getTimeZoneId();
+
+    /**
+     * Convert this time to the same instant in the UTC time zone.
+     * 
+     * @return this instant in time in the specified time zone
+     */
+    DateTime toUtcTimeZone();
+
+    /**
+     * Convert this time to the time zone given by the supplied identifier.
+     * 
+     * @param timeZoneId the time zone identifier
+     * @return the instant in the specified time zone
+     * @throws IllegalArgumentException if the time zone identifier is null or is invalid
+     */
+    DateTime toTimeZone( String timeZoneId );
+
+    /**
+     * Return whether this date-time is earlier than the supplied date-time.
+     * 
+     * @param other the date-time to compare with
+     * @return true if this date-time is earliar than the other, or false otherwise
+     * @see #compareTo(DateTime)
+     * @see #isSameAs(DateTime)
+     * @see #isAfter(DateTime)
+     */
+    boolean isBefore( DateTime other );
+
+    /**
+     * Return whether this date-time is later than the supplied date-time.
+     * 
+     * @param other the date-time to compare with
+     * @return true if this date-time is later than the other, or false otherwise
+     * @see #compareTo(DateTime)
+     * @see #isBefore(DateTime)
+     * @see #isSameAs(DateTime)
+     */
+    boolean isAfter( DateTime other );
+
+    /**
+     * Return whether this date-time is at the same time as the supplied date-time.
+     * 
+     * @param other the date-time to compare with
+     * @return true if this date-time is later than the other, or false otherwise
+     * @see #compareTo(DateTime)
+     * @see #isBefore(DateTime)
+     * @see #isAfter(DateTime)
+     */
+    boolean isSameAs( DateTime other );
+
+    /**
+     * Subtract the specified about of time in the supplied units.
+     * 
+     * @param timeAmount the amount of time to subtract
+     * @param unit the units of the amount of time; may not be null
+     * @return the instance in time the specified number of time before this instant
+     */
+    DateTime minus( long timeAmount,
+                    TimeUnit unit );
+
+    /**
+     * Subtract the specified number of days from this time instant.
+     * 
+     * @param days the number of days to subtract
+     * @return the instance in time the specified number of days before this instant
+     */
+    DateTime minusDays( int days );
+
+    /**
+     * Subtract the specified number of hours from this time instant.
+     * 
+     * @param hours the number of hours to subtract
+     * @return the instance in time the specified number of hours before this instant
+     */
+    DateTime minusHours( int hours );
+
+    /**
+     * Subtract the specified number of milliseconds from this time instant.
+     * 
+     * @param milliseconds the number of milliseconds to subtract
+     * @return the instance in time the specified number of milliseconds before this instant
+     */
+    DateTime minusMillis( int milliseconds );
+
+    /**
+     * Subtract the specified number of minutes from this time instant.
+     * 
+     * @param minutes the number of minutes to subtract
+     * @return the instance in time the specified number of minutes before this instant
+     */
+    DateTime minusMinutes( int minutes );
+
+    /**
+     * Subtract the specified number of months from this time instant.
+     * 
+     * @param months the number of months to subtract
+     * @return the instance in time the specified number of months before this instant
+     */
+    DateTime minusMonths( int months );
+
+    /**
+     * Subtract the specified number of seconds from this time instant.
+     * 
+     * @param seconds the number of seconds to subtract
+     * @return the instance in time the specified number of seconds before this instant
+     */
+    DateTime minusSeconds( int seconds );
+
+    /**
+     * Subtract the specified number of weeks from this time instant.
+     * 
+     * @param weeks the number of weeks to subtract
+     * @return the instance in time the specified number of weeks before this instant
+     */
+    DateTime minusWeeks( int weeks );
+
+    /**
+     * Subtract the specified number of years from this time instant.
+     * 
+     * @param years the number of years to subtract
+     * @return the instance in time the specified number of years before this instant
+     */
+    DateTime minusYears( int years );
+
+    /**
+     * Add the specified about of time in the supplied units.
+     * 
+     * @param timeAmount the amount of time to add
+     * @param unit the units of the amount of time; may not be null
+     * @return the instance in time the specified number of time after this instant
+     */
+    DateTime plus( long timeAmount,
+                   TimeUnit unit );
+
+    /**
+     * Add the specified number of days from this time instant.
+     * 
+     * @param days the number of days to add
+     * @return the instance in time the specified number of days after this instant
+     */
+    DateTime plusDays( int days );
+
+    /**
+     * Add the specified number of hours from this time instant.
+     * 
+     * @param hours the number of hours to add
+     * @return the instance in time the specified number of hours after this instant
+     */
+    DateTime plusHours( int hours );
+
+    /**
+     * Add the specified number of milliseconds from this time instant.
+     * 
+     * @param milliseconds the number of milliseconds to add
+     * @return the instance in time the specified number of milliseconds after this instant
+     */
+    DateTime plusMillis( int milliseconds );
+
+    /**
+     * Add the specified number of minutes from this time instant.
+     * 
+     * @param minutes the number of minutes to add
+     * @return the instance in time the specified number of minutes after this instant
+     */
+    DateTime plusMinutes( int minutes );
+
+    /**
+     * Add the specified number of months from this time instant.
+     * 
+     * @param months the number of months to add
+     * @return the instance in time the specified number of months after this instant
+     */
+    DateTime plusMonths( int months );
+
+    /**
+     * Add the specified number of seconds from this time instant.
+     * 
+     * @param seconds the number of seconds to add
+     * @return the instance in time the specified number of seconds after this instant
+     */
+    DateTime plusSeconds( int seconds );
+
+    /**
+     * Add the specified number of weeks from this time instant.
+     * 
+     * @param weeks the number of weeks to add
+     * @return the instance in time the specified number of weeks after this instant
+     */
+    DateTime plusWeeks( int weeks );
+
+    /**
+     * Add the specified number of years from this time instant.
+     * 
+     * @param years the number of years to add
+     * @return the instance in time the specified number of years after this instant
+     */
+    DateTime plusYears( int years );
+
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/DateTimeFactory.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/DateTimeFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/DateTimeFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/DateTimeFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,194 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+
+/**
+ * A factory for creating {@link DateTime date-time instants}. This interface extends the {@link ValueFactory} generic interface
+ * and adds specific methods for creating instants for the current time (and time zone) as well as various combinations of
+ * individual field values. <h2>ISO-8601</h2>
+ * <p>
+ * The factory creates date-time instants from strings that are in the standard ISO-8601 format. There are three supported styles:
+ * month-based, day-of-year-based, and week-based.
+ * </p>
+ * <h3>Month-Based</h3>
+ * <p>
+ * The month-based representation is the most common format of ISO8601, and is the format used in the XML standards for passing
+ * dates and times:
+ * 
+ * <pre>
+ * yyyy-mm-ddTHH:MM:SS.SSSZ
+ * </pre>
+ * 
+ * The fields are separated by dashes and consist of:
+ * <ul>
+ * <li>four digit year;</li>
+ * <li>two digit month, where 01 is Janurary and 12 is December;</li>
+ * <li>two digit day of month, from 01 to 31;</li>
+ * <li>two digit hour, from 00 to 23;</li>
+ * <li>two digit minute, from 00 to 59;</li>
+ * <li>two digit second, from 00 to 59;</li>
+ * <li>three decimal places for milliseconds, if required;</li>
+ * <li>time zone offset of the form <code>±HH:mm</code> (or '0' if UTC)</li>
+ * </ul>
+ * </p>
+ * <h3>Day of Year Based</h3>
+ * <p>
+ * This format of ISO-8601 uses a single field to represent the day of the year:
+ * 
+ * <pre>
+ * yyyy-dddTHH:MM:SS.SSSZ
+ * </pre>
+ * 
+ * The fields are separated by dashes and consist of:
+ * <ul>
+ * <li>four digit year</li>
+ * <li>three digit day of year, from 001 to 366;</li>
+ * <li>two digit hour, from 00 to 23;</li>
+ * <li>two digit minute, from 00 to 59;</li>
+ * <li>two digit second, from 00 to 59;</li>
+ * <li>three decimal places for milliseconds, if required;</li>
+ * <li>time zone offset of the form <code>±HH:mm</code> (or '0' if UTC)</li>
+ * </ul>
+ * </p>
+ * <h3>Week Based</h3>
+ * <p>
+ * This format of ISO-8601 uses a single field to represent the day of the year:
+ * 
+ * <pre>
+ * yyyy-Www-dTHH:MM:SS.SSSZ
+ * </pre>
+ * 
+ * The fields are separated by dashes and consist of:
+ * <ul>
+ * <li>four digit weekyear (see below)</li>
+ * <li>two digit week of year, from 01 to 53;</li>
+ * <li>one digit day of week, from 1 to 7 where 1 is Monday and 7 is Sunday;</li>
+ * <li>two digit hour, from 00 to 23;</li>
+ * <li>two digit minute, from 00 to 59;</li>
+ * <li>two digit second, from 00 to 59;</li>
+ * <li>three decimal places for milliseconds, if required;</li>
+ * <li>time zone offset of the form <code>±HH:mm</code> (or '0' if UTC)</li>
+ * </ul>
+ * </p>
+ * <p>
+ * From <a href="http://joda-time.sourceforge.net/cal_iso.html">Joda-Time</a>: Weeks are always complete, and the first week of a
+ * year is the one that includes the first Thursday of the year. This definition can mean that the first week of a year starts in
+ * the previous year, and the last week finishes in the next year. The weekyear field is defined to refer to the year that owns
+ * the week, which may differ from the actual year.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+public interface DateTimeFactory extends ValueFactory<DateTime> {
+
+    /**
+     * Create a date-time instance for the current time in the local time zone.
+     * 
+     * @return the current date-time instance
+     * @see #createUtc()
+     */
+    DateTime create();
+
+    /**
+     * Create a date-time instance for the current time in UTC.
+     * 
+     * @return the current date-time instance (in UTC)
+     * @see #create()
+     */
+    DateTime createUtc();
+
+    /**
+     * Create a date-time instance that is offset from the original by the specified amount.
+     * 
+     * @param original
+     * @param offsetInMillis the offset in milliseconds (positive or negative)
+     * @return the offset date-time instance
+     */
+    DateTime create( DateTime original,
+                     long offsetInMillis );
+
+    /**
+     * Create a date-time instance given the individual values for the fields
+     * 
+     * @param year the year of the era
+     * @param monthOfYear the month of the year
+     * @param dayOfMonth the day of the month
+     * @param hourOfDay the hour of the day
+     * @param minuteOfHour the minute of the hour
+     * @param secondOfMinute the second of the minute
+     * @param millisecondsOfSecond the milliseconds of the second
+     * @return the date-time instance
+     */
+    DateTime create( int year,
+                     int monthOfYear,
+                     int dayOfMonth,
+                     int hourOfDay,
+                     int minuteOfHour,
+                     int secondOfMinute,
+                     int millisecondsOfSecond );
+
+    /**
+     * Create a date-time instance given the individual values for the fields
+     * 
+     * @param year the year of the era
+     * @param monthOfYear the month of the year
+     * @param dayOfMonth the day of the month
+     * @param hourOfDay the hour of the day
+     * @param minuteOfHour the minute of the hour
+     * @param secondOfMinute the second of the minute
+     * @param millisecondsOfSecond the milliseconds of the second
+     * @param timeZoneOffsetHours the number of hours offset from UTC for the time zone
+     * @return the date-time instance
+     */
+    DateTime create( int year,
+                     int monthOfYear,
+                     int dayOfMonth,
+                     int hourOfDay,
+                     int minuteOfHour,
+                     int secondOfMinute,
+                     int millisecondsOfSecond,
+                     int timeZoneOffsetHours );
+
+    /**
+     * Create a date-time instance given the individual values for the fields
+     * 
+     * @param year the year of the era
+     * @param monthOfYear the month of the year
+     * @param dayOfMonth the day of the month
+     * @param hourOfDay the hour of the day
+     * @param minuteOfHour the minute of the hour
+     * @param secondOfMinute the second of the minute
+     * @param millisecondsOfSecond the milliseconds of the second
+     * @param timeZoneId the ID of the time zone (e.g, "PST", "UTC", "EDT"); may not be null
+     * @return the date-time instance
+     */
+    DateTime create( int year,
+                     int monthOfYear,
+                     int dayOfMonth,
+                     int hourOfDay,
+                     int minuteOfHour,
+                     int secondOfMinute,
+                     int millisecondsOfSecond,
+                     String timeZoneId );
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/DateTimeFactory.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/InvalidPathException.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathException.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/InvalidPathException.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/InvalidPathException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+/**
+ * @author Randall Hauch
+ */
+public class InvalidPathException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = 6034512896518552227L;
+
+    /**
+     * 
+     */
+    public InvalidPathException() {
+    }
+
+    /**
+     * @param message
+     */
+    public InvalidPathException( String message ) {
+        super(message);
+
+    }
+
+    /**
+     * @param cause
+     */
+    public InvalidPathException( Throwable cause ) {
+        super(cause);
+
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public InvalidPathException( String message, Throwable cause ) {
+        super(message, cause);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/InvalidPathExpressionException.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/InvalidPathExpressionException.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/InvalidPathExpressionException.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/InvalidPathExpressionException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+/**
+ * @author Randall Hauch
+ */
+public class InvalidPathExpressionException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = 358951801604727022L;
+
+    /**
+     * 
+     */
+    public InvalidPathExpressionException() {
+    }
+
+    /**
+     * @param message
+     */
+    public InvalidPathExpressionException( String message ) {
+        super(message);
+
+    }
+
+    /**
+     * @param cause
+     */
+    public InvalidPathExpressionException( Throwable cause ) {
+        super(cause);
+
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public InvalidPathExpressionException( String message,
+                                           Throwable cause ) {
+        super(message, cause);
+
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/InvalidPathExpressionException.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/IoException.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/IoException.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/IoException.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/IoException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,73 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class IoException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = -2015526722307950714L;
+
+    /**
+     * 
+     */
+    public IoException() {
+    }
+
+    /**
+     * @param message
+     */
+    public IoException( String message ) {
+        super(message);
+
+    }
+
+    /**
+     * @param cause
+     */
+    public IoException( Throwable cause ) {
+        super(cause);
+
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public IoException( String message,
+                                 Throwable cause ) {
+        super(message, cause);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Name.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Name.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Name.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Name.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,115 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.io.Serializable;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.property.Path.Segment;
+
+/**
+ * A qualified name consisting of a namespace and a local name.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public interface Name extends Comparable<Name>, Serializable {
+
+    /**
+     * Get the local name part of this qualified name.
+     * 
+     * @return the local name; never null
+     */
+    String getLocalName();
+
+    /**
+     * Get the URI for the namespace used in this qualified name.
+     * 
+     * @return the URI; never null but possibly empty
+     */
+    String getNamespaceUri();
+
+    /**
+     * Get the string form of the name. The {@link Path#DEFAULT_ENCODER default encoder} is used to encode characters in the local
+     * name and namespace.
+     * 
+     * @return the encoded string
+     * @see #getString(TextEncoder)
+     */
+    public String getString();
+
+    /**
+     * Get the encoded string form of the name, using the supplied encoder to encode characters in the local name and namespace.
+     * 
+     * @param encoder the encoder to use, or null if the {@link Path#DEFAULT_ENCODER default encoder} should be used
+     * @return the encoded string
+     * @see #getString()
+     */
+    public String getString( TextEncoder encoder );
+
+    /**
+     * Get the string form of the name, using the supplied namespace registry to convert the {@link #getNamespaceUri() namespace
+     * URI} to a prefix. The {@link Path#DEFAULT_ENCODER default encoder} is used to encode characters in each of the path
+     * segments.
+     * 
+     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+     *        {@link Name#getNamespaceUri() namespace URI}
+     * @return the encoded string
+     * @throws IllegalArgumentException if the namespace registry is null
+     * @see #getString(NamespaceRegistry,TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry );
+
+    /**
+     * Get the encoded string form of the name, using the supplied namespace registry to convert the {@link #getNamespaceUri()
+     * namespace URI} to a prefix.
+     * 
+     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+     *        {@link Name#getNamespaceUri() namespace URI}
+     * @param encoder the encoder to use, or null if the {@link Path#DEFAULT_ENCODER default encoder} should be used
+     * @return the encoded string
+     * @throws IllegalArgumentException if the namespace registry is null
+     * @see #getString(NamespaceRegistry)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder );
+
+    /**
+     * Get the encoded string form of the name, using the supplied namespace registry to convert the names' namespace URIs to
+     * prefixes and the supplied encoder to encode characters in each of the path segments, and using the second delimiter to
+     * encode (or convert) the delimiter used between the namespace prefix and the local part.
+     * 
+     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+     *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
+     * @param encoder the encoder to use for encoding the {@link Name#getLocalName() local part} and
+     *        {@link Name#getNamespaceUri() namespace prefix}, or null if the {@link Path#DEFAULT_ENCODER default encoder} should
+     *        be used
+     * @param delimiterEncoder the encoder to use for encoding the delimiter between the {@link Name#getLocalName() local part}
+     *        and {@link Name#getNamespaceUri() namespace prefix}, or null if the standard delimiter should be used
+     * @return the encoded string
+     * @see #getString(NamespaceRegistry)
+     * @see #getString(NamespaceRegistry, TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder,
+                             TextEncoder delimiterEncoder );
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NameFactory.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NameFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NameFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NameFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import org.jboss.dna.common.text.TextDecoder;
+
+/**
+ * A factory for creating {@link Name names}.
+ * 
+ * @author Randall Hauch
+ */
+public interface NameFactory extends ValueFactory<Name> {
+
+    /**
+     * Create a name from the given namespace URI and local name.
+     * <p>
+     * This method is equivalent to calling {@link #create(String, String, TextDecoder)} with a null encoder.
+     * </p>
+     * 
+     * @param namespaceUri the namespace URI
+     * @param localName the local name
+     * @return the new name
+     * @throws IllegalArgumentException if the local name is <code>null</code> or empty
+     */
+    Name create( String namespaceUri,
+                 String localName );
+
+    /**
+     * Create a name from the given namespace URI and local name.
+     * 
+     * @param namespaceUri the namespace URI
+     * @param localName the local name
+     * @param decoder the decoder that should be used to decode the qualified name
+     * @return the new name
+     * @throws IllegalArgumentException if the local name is <code>null</code> or empty
+     */
+    Name create( String namespaceUri,
+                 String localName,
+                 TextDecoder decoder );
+
+    /**
+     * Get the namespace registry.
+     * 
+     * @return the namespace registry; never <code>null</code>
+     */
+    NamespaceRegistry getNamespaceRegistry();
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceException.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceException.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceException.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+/**
+ * @author Randall Hauch
+ */
+public class NamespaceException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = 1300642242538881207L;
+
+    /**
+     * 
+     */
+    public NamespaceException() {
+    }
+
+    /**
+     * @param message
+     */
+    public NamespaceException( String message ) {
+        super(message);
+
+    }
+
+    /**
+     * @param cause
+     */
+    public NamespaceException( Throwable cause ) {
+        super(cause);
+
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public NamespaceException( String message, Throwable cause ) {
+        super(message, cause);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceException.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceRegistry.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NamespaceRegistry.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceRegistry.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceRegistry.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,136 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.util.Set;
+import net.jcip.annotations.Immutable;
+import net.jcip.annotations.ThreadSafe;
+
+/**
+ * Registry of namespaces, which are used to provide isolated and independent domains for {@link Name names}.
+ * 
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public interface NamespaceRegistry {
+
+    /**
+     * Return the namespace URI that is currently mapped to the empty prefix, or null if there is no current default namespace.
+     * 
+     * @return the namespace URI that represents the default namespace, or null if there is no default namespace
+     */
+    String getDefaultNamespaceUri();
+
+    /**
+     * Get the namespace URI for the supplied prefix.
+     * 
+     * @param prefix the namespace prefix
+     * @return the namespace URI for the supplied prefix, or null if there is no namespace currently registered to use that prefix
+     * @throws IllegalArgumentException if the prefix is null
+     */
+    String getNamespaceForPrefix( String prefix );
+
+    /**
+     * Return the prefix used for the supplied namespace URI.
+     * 
+     * @param namespaceUri the namespace URI
+     * @param generateIfMissing true if the namespace URI has not already been registered and the method should auto-register the
+     *        namespace with a generated prefix, or false if the method should never auto-register the namespace
+     * @return the prefix currently being used for the namespace, or <code>null</code> if the namespace has not been registered
+     *         and <code>generateIfMissing</code> is <code>false</code>
+     * @throws IllegalArgumentException if the namespace URI is null
+     * @see #isRegisteredNamespaceUri(String)
+     */
+    String getPrefixForNamespaceUri( String namespaceUri,
+                                     boolean generateIfMissing );
+
+    /**
+     * Return whether there is a registered prefix for the supplied namespace URI.
+     * 
+     * @param namespaceUri the namespace URI
+     * @return true if the supplied namespace has been registered with a prefix, or false otherwise
+     * @throws IllegalArgumentException if the namespace URI is null
+     */
+    boolean isRegisteredNamespaceUri( String namespaceUri );
+
+    /**
+     * Register a new namespace using the supplied prefix, returning the namespace URI previously registered under that prefix.
+     * 
+     * @param prefix the prefix for the namespace, or null if a namesapce prefix should be generated automatically
+     * @param namespaceUri the namespace URI
+     * @return the namespace URI that was previously registered with the supplied prefix, or null if the prefix was not previously
+     *         bound to a namespace URI
+     * @throws IllegalArgumentException if the namespace URI is null
+     */
+    String register( String prefix,
+                     String namespaceUri );
+
+    /**
+     * Unregister the namespace with the supplied URI.
+     * 
+     * @param namespaceUri the namespace URI
+     * @return true if the namespace was removed, or false if the namespace was not registered
+     * @throws IllegalArgumentException if the namespace URI is null
+     * @throws NamespaceException if there is a problem unregistering the namespace
+     */
+    boolean unregister( String namespaceUri );
+
+    /**
+     * Obtain the set of namespaces that are registered.
+     * 
+     * @return the set of
+     */
+    Set<String> getRegisteredNamespaceUris();
+
+    /**
+     * Obtain a snapshot of all of the {@link Namespace namespaces} registered at the time this method is called. The resulting
+     * set is immutable, and will <i>not</i> reflect changes made to the registry.
+     * 
+     * @return an immutable set of {@link Namespace} objects reflecting a snapshot of the registry; never null
+     */
+    Set<Namespace> getNamespaces();
+
+    /**
+     * Representation of a single namespace at a single point in time. This object does not change to reflect changes made to the
+     * {@link NamespaceRegistry registry}.
+     * 
+     * @see NamespaceRegistry#getNamespaces()
+     * @author Randall Hauch
+     */
+    @Immutable
+    interface Namespace {
+        /**
+         * Get the prefix for the namespace
+         * 
+         * @return the prefix; never null but possibly the empty string
+         */
+        String getPrefix();
+
+        /**
+         * Get the URI for the namespace
+         * 
+         * @return the namespace URI; never null but possibly the empty string
+         */
+        String getNamespaceUri();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/NamespaceRegistry.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Path.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,579 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.Jsr283Encoder;
+import org.jboss.dna.common.text.NoOpEncoder;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.UrlEncoder;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicPathSegment;
+
+/**
+ * An object representation of a node path within a repository.
+ * <p>
+ * A path consists of zero or more segments that can contain any characters, although the string representation may require some
+ * characters to be encoded. For example, if a path contains a segment with a forward slash, then this forward slash must be
+ * escaped when writing the whole path to a string (since a forward slash is used as the {@link #DELIMITER delimiter} between
+ * segments).
+ * </p>
+ * <p>
+ * Because of this encoding and decoding issue, there is no standard representation of a path as a string. Instead, this class
+ * uses {@link TextEncoder text encoders} to escape certain characters when writing to a string or unescaping the string
+ * representation. These encoders and used only with individual segments, and therefore are not used to encode the
+ * {@link #DELIMITER delimiter}. Three standard encoders are provided, although others can certainly be used:
+ * <ul>
+ * <li>{@link #JSR283_ENCODER Jsr283Encoder} - an encoder and decoder that is compliant with <a
+ * href="http://jcp.org/en/jsr/detail?id=283">JSR-283</a> by converting the reserved characters (namely '*', '/', ':', '[', ']'
+ * and '|') to their unicode equivalent.</td>
+ * </li>
+ * <li>{@link #URL_ENCODER UrlEncoder} - an encoder and decoder that is useful for converting text to be used within a URL, as
+ * defined by Section 2.3 of <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>. This encoder does encode many characters
+ * (including '`', '@', '#', '$', '^', '&', '{', '[', '}', ']', '|', ':', ';', '\', '"', '<', ',', '>', '?', '/', and ' '), while
+ * others are not encoded (including '-', '_', '.', '!', '~', '*', '\', ''', '(', and ')'). Note that only the '*' character is
+ * the only character reserved by JSR-283 that is not encoded by the URL encoder.</li>
+ * <li>{@link #NO_OP_ENCODER NoOpEncoder} - an {@link TextEncoder encoder} implementation that does nothing.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * This class simplifies working with paths and using a <code>Path</code> is often more efficient that processing and
+ * manipulating the equivalent <code>String</code>. This class can easily {@link #iterator() iterate} over the segments, return
+ * the {@link #size() number of segments}, {@link #compareTo(Path) compare} with other paths, {@link #resolve(Path) resolve}
+ * relative paths, return the {@link #getParent() ancestor (or parent)}, determine whether one path is an
+ * {@link #isAncestorOf(Path) ancestor} or {@link #isDecendantOf(Path) decendent} of another path, and
+ * {@link #getCommonAncestor(Path) finding a common ancestor}.
+ * </p>
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public interface Path extends Comparable<Path>, Iterable<Path.Segment>, Serializable {
+
+    /**
+     * The text encoder that does nothing.
+     */
+    public static final TextEncoder NO_OP_ENCODER = new NoOpEncoder();
+
+    /**
+     * The text encoder that encodes according to JSR-283.
+     */
+    public static final TextEncoder JSR283_ENCODER = new Jsr283Encoder();
+
+    /**
+     * The text encoder that encodes text according to the rules of <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
+     */
+    public static final TextEncoder URL_ENCODER = new UrlEncoder().setSlashEncoded(true);
+
+    /**
+     * The text decoder that does nothing.
+     */
+    public static final TextDecoder NO_OP_DECODER = new NoOpEncoder();
+
+    /**
+     * The text decoder that decodes according to JSR-283.
+     */
+    public static final TextDecoder JSR283_DECODER = new Jsr283Encoder();
+
+    /**
+     * The text decoder that decodes text according to the rules of <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
+     */
+    public static final TextDecoder URL_DECODER = new UrlEncoder().setSlashEncoded(true);
+
+    /**
+     * The default text encoder to be used when none is otherwise specified. This is currently the {@link #JSR283_ENCODER JSR-283
+     * encoder}.
+     */
+    public static final TextEncoder DEFAULT_ENCODER = JSR283_ENCODER;
+
+    /**
+     * The default text decoder to be used when none is otherwise specified. This is currently the {@link #JSR283_ENCODER JSR-283
+     * encoder}.
+     */
+    public static final TextDecoder DEFAULT_DECODER = JSR283_DECODER;
+
+    /**
+     * The delimiter character used to separate segments within a path.
+     */
+    public static final char DELIMITER = '/';
+
+    /**
+     * String form of the delimiter used to separate segments within a path.
+     */
+    public static final String DELIMITER_STR = new String(new char[] {DELIMITER});
+
+    /**
+     * String representation of the segment that references a parent.
+     */
+    public static final String PARENT = "..";
+
+    /**
+     * String representation of the segment that references the same segment.
+     */
+    public static final String SELF = ".";
+
+    /**
+     * The index that will be returned for a {@link Segment} that {@link Segment#hasIndex() has no index}.
+     */
+    public static final int NO_INDEX = -1;
+
+    /**
+     * Representation of the segments that occur within a path.
+     * 
+     * @author Randall Hauch
+     */
+    @Immutable
+    public static interface Segment extends Cloneable, Comparable<Segment>, Serializable {
+
+        /**
+         * Get the name component of this segment.
+         * 
+         * @return the segment's name
+         */
+        public Name getName();
+
+        /**
+         * Get the index for this segment, which will be {@link Path#NO_INDEX -1} if this segment has no specific index.
+         * 
+         * @return the index
+         */
+        public int getIndex();
+
+        /**
+         * Return whether this segment has an index.
+         * 
+         * @return true if this segment has an index, or false otherwise.
+         */
+        public boolean hasIndex();
+
+        /**
+         * Return whether this segment is a self-reference.
+         * 
+         * @return true if the segment is a self-reference, or false otherwise.
+         */
+        public boolean isSelfReference();
+
+        /**
+         * Return whether this segment is a reference to a parent.
+         * 
+         * @return true if the segment is a parent-reference, or false otherwise.
+         */
+        public boolean isParentReference();
+
+        /**
+         * Get the raw string form of the segment using the {@link Path#NO_OP_ENCODER no-op encoder}. This is equivalent to
+         * calling <code>getString(Path.NO_OP_ENCODER)</code>.
+         * 
+         * @return the un-encoded string
+         * @see #getString(TextEncoder)
+         */
+        public String getUnencodedString();
+
+        /**
+         * Get the string form of the segment. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each
+         * of the path segments.
+         * 
+         * @return the encoded string
+         * @see #getString(TextEncoder)
+         */
+        public String getString();
+
+        /**
+         * Get the encoded string form of the segment, using the supplied encoder to encode characters in each of the path
+         * segments.
+         * 
+         * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
+         * @return the encoded string
+         * @see #getString()
+         */
+        public String getString( TextEncoder encoder );
+
+        /**
+         * Get the string form of the segment, using the supplied namespace registry to convert the name's namespace URI to a
+         * prefix. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
+         * 
+         * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+         *        {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
+         * @return the encoded string
+         * @throws IllegalArgumentException if the namespace registry is null
+         * @see #getString(NamespaceRegistry,TextEncoder)
+         */
+        public String getString( NamespaceRegistry namespaceRegistry );
+
+        /**
+         * Get the encoded string form of the segment, using the supplied namespace registry to convert the name's namespace URI
+         * to a prefix and the supplied encoder to encode characters in each of the path segments.
+         * 
+         * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+         *        {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
+         * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
+         * @return the encoded string
+         * @throws IllegalArgumentException if the namespace registry is null
+         * @see #getString(NamespaceRegistry)
+         */
+        public String getString( NamespaceRegistry namespaceRegistry,
+                                 TextEncoder encoder );
+
+        /**
+         * Get the encoded string form of the segment, using the supplied namespace registry to convert the names' namespace URIs
+         * to prefixes and the supplied encoder to encode characters in each of the path segments. The second encoder is used to
+         * encode (or convert) the delimiter between the {@link Name#getNamespaceUri() namespace prefix} and the
+         * {@link Name#getLocalName() local part}.
+         * 
+         * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+         *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
+         * @param encoder the encoder to use for encoding the {@link Name#getLocalName() local part} and
+         *        {@link Name#getNamespaceUri() namespace prefix} in the segment's {@link #getName() name}, or null if the
+         *        {@link #DEFAULT_ENCODER default encoder} should be used
+         * @param delimiterEncoder the encoder to use for encoding the delimiter between the {@link Name#getLocalName() local
+         *        part} and {@link Name#getNamespaceUri() namespace prefix} of each {@link Path#getSegmentsList() segment}, or
+         *        null if the standard delimiters should be used
+         * @return the encoded string
+         * @see #getString(NamespaceRegistry)
+         * @see #getString(NamespaceRegistry, TextEncoder)
+         */
+        public String getString( NamespaceRegistry namespaceRegistry,
+                                 TextEncoder encoder,
+                                 TextEncoder delimiterEncoder );
+    }
+
+    /**
+     * Singleton instance of the name referencing a self, provided as a convenience.
+     */
+    public static final Name SELF_NAME = new BasicName(null, SELF);
+
+    /**
+     * Singleton instance of the name referencing a parent, provided as a convenience.
+     */
+    public static final Name PARENT_NAME = new BasicName(null, PARENT);
+
+    /**
+     * Singleton instance of the path segment referencing a parent, provided as a convenience.
+     */
+    public static final Path.Segment SELF_SEGMENT = new BasicPathSegment(SELF_NAME);
+
+    /**
+     * Singleton instance of the path segment referencing a parent, provided as a convenience.
+     */
+    public static final Path.Segment PARENT_SEGMENT = new BasicPathSegment(PARENT_NAME);
+
+    /**
+     * Return the number of segments in this path.
+     * 
+     * @return the number of path segments
+     */
+    public int size();
+
+    /**
+     * Return whether this path represents the root path.
+     * 
+     * @return true if this path is the root path, or false otherwise
+     */
+    public boolean isRoot();
+
+    /**
+     * Determine whether this path represents the same as the supplied path. This is equivalent to calling <code>
+     * this.compareTo(other) == 0 </code>.
+     * 
+     * @param other the other path to compare with this path; may be null
+     * @return true if the paths are equivalent, or false otherwise
+     */
+    public boolean isSameAs( Path other );
+
+    /**
+     * Determine whether this path is the {@link #isSameAs(Path) same as} to or a {@link #isAncestorOf(Path) ancestor of} the
+     * supplied path. This method is equivalent to (but may be more efficient than) calling <code>isSame(other) ||
+     * isAncestor(other)</code>, and is a convenience method that is identical to calling <code>other.isAtOrBelow(this)</code>.
+     * 
+     * @param other the other path to compare with this path; may be null
+     * @return true if the paths are equivalent or if this path is considered an ancestor of the other path, or false otherwise
+     */
+    public boolean isAtOrAbove( Path other );
+
+    /**
+     * Determine whether this path is the {@link #isSameAs(Path) same as} to or a {@link #isDecendantOf(Path) decendant of} the
+     * supplied path. This method is equivalent to (but may be more efficient than) calling <code>isSame(other) ||
+     * isAncestor(other)</code>.
+     * 
+     * @param other the other path to compare with this path; may be null
+     * @return true if the paths are equivalent or if this path is considered a decendant of the other path, or false otherwise
+     */
+    public boolean isAtOrBelow( Path other );
+
+    /**
+     * Determine whether this path is an ancestor of the supplied path. A path is considered an ancestor of another path if the
+     * the ancestor path appears in its entirety at the beginning of the decendant path, and where the decendant path contains at
+     * least one additional segment.
+     * 
+     * @param decendant the path that may be the decendant; may be null
+     * @return true if this path is an ancestor of the supplied path, or false otherwise
+     */
+    public boolean isAncestorOf( Path decendant );
+
+    /**
+     * Determine whether this path is an decendant of the supplied path. A path is considered a decendant of another path if the
+     * the decendant path starts exactly with the entire ancestor path but contains at least one additional segment.
+     * 
+     * @param ancestor the path that may be the ancestor; may be null
+     * @return true if this path is an decendant of the supplied path, or false otherwise
+     */
+    public boolean isDecendantOf( Path ancestor );
+
+    /**
+     * Return whether this path is an absolute path. A path is either relative or {@link #isAbsolute() absolute}. An absolute path
+     * starts with a "/".
+     * 
+     * @return true if the path is absolute, or false otherwise
+     */
+    public boolean isAbsolute();
+
+    /**
+     * Return whether this path is normalized and contains no "." segments and as few ".." segments as possible. For example, the
+     * path "../a" is normalized, while "/a/b/c/../d" is not normalized.
+     * 
+     * @return true if this path is normalized, or false otherwise
+     */
+    public boolean isNormalized();
+
+    /**
+     * Get a normalized path with as many ".." segments and all "." resolved. The relative path ".", however, will return itself
+     * as the normalized path, since it cannot be resolved any further.
+     * 
+     * @return the normalized path, or this object if this path is already normalized
+     * @throws InvalidPathException if the normalized form would result in a path with negative length (e.g., "/a/../../..")
+     */
+    public Path getNormalizedPath();
+
+    /**
+     * Get the canonical form of this path. A canonical path has is {@link #isAbsolute() absolute} and {@link #isNormalized()}.
+     * 
+     * @return the canonical path, or this object if it is already in its canonical form
+     * @throws InvalidPathException if the path is not absolute and cannot be canonicalized
+     */
+    public Path getCanonicalPath();
+
+    /**
+     * Get a relative path from the supplied path to this path.
+     * 
+     * @param startingPath the path specifying the starting point for the new relative path; may not be null
+     * @return the relative path
+     * @throws IllegalArgumentException if the supplied path is null
+     * @throws PathNotFoundException if both this path and the supplied path are not absolute
+     */
+    public Path relativeTo( Path startingPath );
+
+    /**
+     * Get the absolute path by resolving the supplied relative (non-absolute) path against this absolute path.
+     * 
+     * @param relativePath the relative path that is to be resolved against this path
+     * @return the absolute and normalized path resolved from this path and the supplied absolute path
+     * @throws IllegalArgumentException if the supplied path is null
+     * @throws InvalidPathException if the this path is not absolute or if the supplied path is not relative.
+     */
+    public Path resolve( Path relativePath );
+
+    /**
+     * Get the absolute path by resolving this relative (non-absolute) path against the supplied absolute path.
+     * 
+     * @param absolutePath the absolute path to which this relative path should be resolve
+     * @return the absolute path resolved from this path and the supplied absolute path
+     * @throws IllegalArgumentException if the supplied path is null
+     * @throws InvalidPathException if the supplied path is not absolute or if this path is not relative.
+     */
+    public Path resolveAgainst( Path absolutePath );
+
+    /**
+     * Return the path to the parent, or this path if it is the {@link #isRoot() root}. This is an efficient operation that does
+     * not require copying any data.
+     * 
+     * @return the parent path, or this null if it is already the root
+     */
+    public Path getParent();
+
+    /**
+     * Return the path to the ancestor of the supplied degree. An ancestor of degree <code>x</code> is the path that is <code>x
+     * </code> levels up along the path. For example, <code>degree = 0</code> returns this path, while <code>degree = 1</code>
+     * returns the parent of this path, <code>degree = 2</code> returns the grandparent of this path, and so on. Note that the
+     * result may be unexpected if this path is not {@link #isNormalized() normalized}, as a non-normalized path contains ".." and
+     * "." segments.
+     * 
+     * @param degree
+     * @return the ancestor of the supplied degree
+     * @throws IllegalArgumentException if the degree is negative
+     * @throws InvalidPathException if the degree is greater than the {@link #size() length} of this path
+     */
+    public Path getAncestor( int degree );
+
+    /**
+     * Determine whether this path and the supplied path have the same immediate ancestor. In other words, this method determines
+     * whether the node represented by this path is a sibling of the node represented by the supplied path.
+     * 
+     * @param that the other path
+     * @return true if this path and the supplied path have the same immediate ancestor.
+     * @throws IllegalArgumentException if the supplied path is null
+     */
+    public boolean hasSameAncestor( Path that );
+
+    /**
+     * Find the lowest common ancestor of this path and the supplied path.
+     * 
+     * @param that the other path
+     * @return the lowest common ancestor, which may be the root path if there is no other.
+     * @throws IllegalArgumentException if the supplied path is null
+     */
+    public Path getCommonAncestor( Path that );
+
+    /**
+     * Get the last segment in this path.
+     * 
+     * @return the last segment, or null if the path is empty
+     */
+    public Segment getLastSegment();
+
+    /**
+     * Get the segment at the supplied index.
+     * 
+     * @param index the index
+     * @return the segment
+     * @throws IndexOutOfBoundsException if the index is out of bounds
+     */
+    public Segment getSegment( int index );
+
+    /**
+     * Return a new path consisting of the segments starting at <code>beginIndex</code> index (inclusive). This is equivalent to
+     * calling <code>path.subpath(beginIndex,path.size()-1)</code>.
+     * 
+     * @param beginIndex the beginning index, inclusive.
+     * @return the specified subpath
+     * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative or larger than the length of this <code>
+     *            Path</code> object
+     */
+    public Path subpath( int beginIndex );
+
+    /**
+     * Return a new path consisting of the segments between the <code>beginIndex</code> index (inclusive) and the <code>endIndex
+     * </code> index (exclusive).
+     * 
+     * @param beginIndex the beginning index, inclusive.
+     * @param endIndex the ending index, exclusive.
+     * @return the specified subpath
+     * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative, or <code>endIndex</code> is larger than
+     *            the length of this <code>Path</code> object, or <code>beginIndex</code> is larger than <code>endIndex</code>.
+     */
+    public Path subpath( int beginIndex,
+                         int endIndex );
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<Segment> iterator();
+
+    /**
+     * Obtain a copy of the segments in this path. None of the segments are encoded.
+     * 
+     * @return the array of segments as a copy
+     */
+    public Segment[] getSegmentsArray();
+
+    /**
+     * Get an unmodifiable list of the path segments.
+     * 
+     * @return the unmodifiable list of path segments; never null
+     */
+    public List<Segment> getSegmentsList();
+
+    /**
+     * Get the string form of the path. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the
+     * path segments.
+     * 
+     * @return the encoded string
+     * @see #getString(TextEncoder)
+     */
+    public String getString();
+
+    /**
+     * Get the encoded string form of the path, using the supplied encoder to encode characters in each of the path segments.
+     * 
+     * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
+     * @return the encoded string
+     * @see #getString()
+     */
+    public String getString( TextEncoder encoder );
+
+    /**
+     * Get the string form of the path, using the supplied namespace registry to convert the names' namespace URIs to prefixes.
+     * The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments. The second encoder
+     * is used to encode (or convert) the delimiter between the {@link Name#getNamespaceUri() namespace prefix} and the
+     * {@link Name#getLocalName() local part}.
+     * 
+     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+     *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
+     * @return the encoded string
+     * @throws IllegalArgumentException if the namespace registry is null
+     * @see #getString(NamespaceRegistry,TextEncoder)
+     * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry );
+
+    /**
+     * Get the encoded string form of the path, using the supplied namespace registry to convert the names' namespace URIs to
+     * prefixes and the supplied encoder to encode characters in each of the path segments.
+     * 
+     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+     *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}, or null if the
+     *        namespace registry should not be used
+     * @param encoder the encoder to use for encoding the {@link Name#getLocalName() local part} and
+     *        {@link Name#getNamespaceUri() namespace prefix} of each {@link Path#getSegmentsList() segment}, or null if the
+     *        {@link #DEFAULT_ENCODER default encoder} should be used
+     * @return the encoded string
+     * @see #getString(NamespaceRegistry)
+     * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder );
+
+    /**
+     * Get the encoded string form of the path, using the supplied namespace registry to convert the names' namespace URIs to
+     * prefixes and the supplied encoder to encode characters in each of the path segments.
+     * 
+     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+     *        {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
+     * @param encoder the encoder to use for encoding the {@link Name#getLocalName() local part} and
+     *        {@link Name#getNamespaceUri() namespace prefix} of each {@link Path#getSegmentsList() segment}, or null if the
+     *        {@link #DEFAULT_ENCODER default encoder} should be used
+     * @param delimiterEncoder the encoder to use for encoding the delimiter between the {@link Name#getLocalName() local part}
+     *        and {@link Name#getNamespaceUri() namespace prefix} of each {@link Path#getSegmentsList() segment}, and for encoding
+     *        the path delimiter, or null if the standard delimiters should be used
+     * @return the encoded string
+     * @see #getString(NamespaceRegistry)
+     * @see #getString(NamespaceRegistry, TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder,
+                             TextEncoder delimiterEncoder );
+
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathExpression.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathExpression.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathExpression.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathExpression.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,535 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.io.Serializable;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.GraphI18n;
+
+/**
+ * An expression that defines an acceptable path using a regular-expression-like language. Path expressions can be used to
+ * represent node paths or properties.
+ * <p>
+ * Path expressions consist of two parts: a selection criteria (or an input path) and an output path:
+ * </p>
+ * 
+ * <pre>
+ * inputPath =&gt; outputPath
+ * </pre>
+ * <p>
+ * The <i>inputPath</i> part defines an expression for the path of a node that is to be sequenced. Input paths consist of '
+ * <code>/</code>' separated segments, where each segment represents a pattern for a single node's name (including the
+ * same-name-sibling indexes) and '<code>@</code>' signifies a property name.
+ * </p>
+ * <p>
+ * Let's first look at some simple examples:
+ * </p>
+ * <table>
+ * <tr>
+ * <th>Input Path</th>
+ * <th>Description</th>
+ * </tr>
+ * <tr>
+ * <td>/a/b</td>
+ * <td>Match node "<code>b</code>" that is a child of the top level node "<code>a</code>". Neither node may have any
+ * same-name-sibilings.</td>
+ * </tr>
+ * <tr>
+ * <td>/a/*</td>
+ * <td>Match any child node of the top level node "<code>a</code>".</td>
+ * </tr>
+ * <tr>
+ * <td>/a/*.txt</td>
+ * <td>Match any child node of the top level node "<code>a</code>" that also has a name ending in "<code>.txt</code>".</td>
+ * </tr>
+ * <tr>
+ * <td>/a/b at c</td>
+ * <td>Match the property "<code>c</code>" of node "<code>/a/b</code>".</td>
+ * </tr>
+ * <tr>
+ * <td>/a/b[2]</td>
+ * <td>The second child named "<code>b</code>" below the top level node "<code>a</code>".</td>
+ * </tr>
+ * <tr>
+ * <td>/a/b[2,3,4]</td>
+ * <td>The second, third or fourth child named "<code>b</code>" below the top level node "<code>a</code>".</td>
+ * </tr>
+ * <tr>
+ * <td>/a/b[*]</td>
+ * <td>Any (and every) child named "<code>b</code>" below the top level node "<code>a</code>".</td>
+ * </tr>
+ * <tr>
+ * <td>//a/b</td>
+ * <td>Any node named "<code>b</code>" that exists below a node named "<code>a</code>", regardless of where node "<code>a</code>"
+ * occurs. Again, neither node may have any same-name-sibilings.</td>
+ * </tr>
+ * </table>
+ * <p>
+ * With these simple examples, you can probably discern the most important rules. First, the '<code>*</code>' is a wildcard
+ * character that matches any character or sequence of characters in a node's name (or index if appearing in between square
+ * brackets), and can be used in conjunction with other characters (e.g., "<code>*.txt</code>").
+ * </p>
+ * <p>
+ * Second, square brackets (i.e., '<code>[</code>' and '<code>]</code>') are used to match a node's same-name-sibiling index. You
+ * can put a single non-negative number or a comma-separated list of non-negative numbers. Use '0' to match a node that has no
+ * same-name-sibilings, or any positive number to match the specific same-name-sibling.
+ * </p>
+ * <p>
+ * Third, combining two delimiters (e.g., "<code>//</code>") matches any sequence of nodes, regardless of what their names are or
+ * how many nodes. Often used with other patterns to identify nodes at any level matching other patterns. Three or more sequential
+ * slash characters are treated as two.
+ * </p>
+ * <p>
+ * Many input paths can be created using just these simple rules. However, input paths can be more complicated. Here are some more
+ * examples:
+ * </p>
+ * <table>
+ * <tr>
+ * <th>Input Path</th>
+ * <th>Description</th>
+ * </tr>
+ * <tr>
+ * <td>/a/(b|c|d)</td>
+ * <td>Match children of the top level node "<code>a</code>" that are named "<code>a</code>", "<code>b</code>" or "<code>c</code>
+ * ". None of the nodes may have same-name-sibling indexes.</td>
+ * </tr>
+ * <tr>
+ * <td>/a/b[c/d]</td>
+ * <td>Match node "<code>b</code>" child of the top level node "<code>a</code>", when node "<code>b</code>" has a child named "
+ * <code>c</code>", and "<code>c</code>" has a child named "<code>d</code>". Node "<code>b</code>
+ * " is the selected node, while nodes "<code>b</code>" and "<code>b</code>" are used as criteria but are not selected.</td>
+ * </tr>
+ * <tr>
+ * <td>/a(/(b|c|d|)/e)[f/g/@something]</td>
+ * <td>Match node "<code>/a/b/e</code>", "<code>/a/c/e</code>", "<code>/a/d/e</code>", or "<code>/a/e</code>
+ * " when they also have a child "<code>f</code>" that itself has a child "<code>g</code>" with property "<code>something</code>".
+ * None of the nodes may have same-name-sibling indexes.</td>
+ * </tr>
+ * </table>
+ * <p>
+ * These examples show a few more advanced rules. Parentheses (i.e., '<code>(</code>' and '<code>)</code>') can be used to define
+ * a set of options for names, as shown in the first and third rules. Whatever part of the selected node's path appears between
+ * the parentheses is captured for use within the output path. Thus, the first input path in the previous table would match node "
+ * <code>/a/b</code>", and "b" would be captured and could be used within the output path using "<code>$1</code>", where the
+ * number used in the output path identifies the parentheses.
+ * </p>
+ * <p>
+ * Square brackets can also be used to specify criteria on a node's properties or children. Whatever appears in between the square
+ * brackets does not appear in the selected node.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class PathExpression implements Serializable {
+
+    /**
+     * Initial version
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Compile the supplied expression and return the resulting path expression instance.
+     * 
+     * @param expression the expression
+     * @return the path expression; never null
+     * @throws IllegalArgumentException if the expression is null
+     * @throws InvalidPathExpressionException if the expression is blank or is not a valid expression
+     */
+    public static final PathExpression compile( String expression ) throws InvalidPathExpressionException {
+        return new PathExpression(expression);
+    }
+
+    private static final String SEQUENCE_PATTERN_STRING = "\\[(\\d+(?:,\\d+)*)\\]"; // \[(\d+(,\d+)*)\]
+    private static final Pattern SEQUENCE_PATTERN = Pattern.compile(SEQUENCE_PATTERN_STRING);
+
+    /**
+     * Regular expression used to find unusable XPath predicates within an expression. This pattern results in unusable predicates
+     * in group 1. Note that some predicates may be valid at the end but not valid elsewhere.
+     * <p>
+     * Currently, only index-like predicates (including sequences) are allowed everywhere. Predicates with paths and properties
+     * are allowed only as the last predicate. Predicates with any operators are unused.
+     * </p>
+     * <p>
+     * Nested predicates are not currently allowed.
+     * </p>
+     */
+    // \[(?:(?:\d+(?:,\d+)*)|\*)\]|(?:\[[^\]\+\-\*=\!><'"\s]+\])$|(\[[^\]]+\])
+    private static final String UNUSABLE_PREDICATE_PATTERN_STRING = "\\[(?:(?:\\d+(?:,\\d+)*)|\\*)\\]|(?:\\[[^\\]\\+\\-\\*=\\!><'\"\\s]+\\])$|(\\[[^\\]]+\\])";
+    private static final Pattern UNUSABLE_PREDICATE_PATTERN = Pattern.compile(UNUSABLE_PREDICATE_PATTERN_STRING);
+
+    /**
+     * Regular expression used to find all XPath predicates except index and sequence patterns. This pattern results in the
+     * predicates to be removed in group 1.
+     */
+    // \[(?:(?:\d+(?:,\d+)*)|\*)\]|(\[[^\]]+\])
+    private static final String NON_INDEX_PREDICATE_PATTERN_STRING = "\\[(?:(?:\\d+(?:,\\d+)*)|\\*)\\]|(\\[[^\\]]+\\])";
+    private static final Pattern NON_INDEX_PREDICATE_PATTERN = Pattern.compile(NON_INDEX_PREDICATE_PATTERN_STRING);
+
+    private final String expression;
+    private final Pattern matchPattern;
+    private final Pattern selectPattern;
+
+    /**
+     * Create the supplied expression.
+     * 
+     * @param expression the expression
+     * @throws IllegalArgumentException if the expression is null
+     * @throws InvalidPathExpressionException if the expression is blank or is not a valid expression
+     */
+    public PathExpression( String expression ) throws InvalidPathExpressionException {
+        CheckArg.isNotNull(expression, "path expression");
+        this.expression = expression.trim();
+        if (this.expression.length() == 0) {
+            throw new InvalidPathExpressionException(GraphI18n.pathExpressionMayNotBeBlank.text());
+        }
+        // Build the match pattern, which determines whether a path matches the condition ...
+        String matchString = this.expression;
+        try {
+            matchString = removeUnusedPredicates(matchString);
+            matchString = replaceXPathPatterns(matchString);
+            this.matchPattern = Pattern.compile(matchString, Pattern.CASE_INSENSITIVE);
+        } catch (PatternSyntaxException e) {
+            String msg = GraphI18n.pathExpressionHasInvalidMatch.text(matchString, this.expression);
+            throw new InvalidPathExpressionException(msg, e);
+        }
+        // Build the select pattern, which determines the path that will be selected ...
+        String selectString = this.expression;
+        try {
+            selectString = removeAllPredicatesExceptIndexes(selectString);
+            selectString = replaceXPathPatterns(selectString);
+            selectString = "(" + selectString + ").*"; // group 1 will have selected path ...
+            this.selectPattern = Pattern.compile(selectString, Pattern.CASE_INSENSITIVE);
+        } catch (PatternSyntaxException e) {
+            String msg = GraphI18n.pathExpressionHasInvalidSelect.text(selectString, this.expression);
+            throw new InvalidPathExpressionException(msg, e);
+        }
+    }
+
+    /**
+     * @return expression
+     */
+    public String getExpression() {
+        return expression;
+    }
+
+    /**
+     * Replace certain XPath patterns that are not used or understood.
+     * 
+     * @param expression the input regular expressions string; may not be null
+     * @return the regular expression with all unused XPath patterns removed; never null
+     */
+    protected String removeUnusedPredicates( String expression ) {
+        assert expression != null;
+        java.util.regex.Matcher matcher = UNUSABLE_PREDICATE_PATTERN.matcher(expression);
+        StringBuffer sb = new StringBuffer();
+        if (matcher.find()) {
+            do {
+                // Remove those predicates that show up in group 1 ...
+                String predicateStr = matcher.group(0);
+                String unusablePredicateStr = matcher.group(1);
+                if (unusablePredicateStr != null) {
+                    predicateStr = "";
+                }
+                matcher.appendReplacement(sb, predicateStr);
+            } while (matcher.find());
+            matcher.appendTail(sb);
+            expression = sb.toString();
+        }
+        return expression;
+    }
+
+    /**
+     * Remove all XPath predicates from the supplied regular expression string.
+     * 
+     * @param expression the input regular expressions string; may not be null
+     * @return the regular expression with all XPath predicates removed; never null
+     */
+    protected String removeAllPredicatesExceptIndexes( String expression ) {
+        assert expression != null;
+        java.util.regex.Matcher matcher = NON_INDEX_PREDICATE_PATTERN.matcher(expression);
+        StringBuffer sb = new StringBuffer();
+        if (matcher.find()) {
+            do {
+                // Remove those predicates that show up in group 1 ...
+                String predicateStr = matcher.group(0);
+                String unusablePredicateStr = matcher.group(1);
+                if (unusablePredicateStr != null) {
+                    predicateStr = "";
+                }
+                matcher.appendReplacement(sb, predicateStr);
+            } while (matcher.find());
+            matcher.appendTail(sb);
+            expression = sb.toString();
+        }
+        return expression;
+    }
+
+    /**
+     * Replace certain XPath patterns, including some predicates, with substrings that are compatible with regular expressions.
+     * 
+     * @param expression the input regular expressions string; may not be null
+     * @return the regular expression with XPath patterns replaced with regular expression fragments; never null
+     */
+    protected String replaceXPathPatterns( String expression ) {
+        assert expression != null;
+        // replace 2 or more sequential '|' characters in an OR expression
+        expression = expression.replaceAll("[\\|]{2,}", "|");
+        // if there is an empty expression in an OR expression, make the whole segment optional ...
+        // (e.g., "/a/b/(c|)/d" => "a/b(/(c))?/d"
+        expression = expression.replaceAll("/(\\([^|]+)(\\|){2,}([^)]+\\))", "(/$1$2$3)?");
+        expression = expression.replaceAll("/\\(\\|+([^)]+)\\)", "(?:/($1))?");
+        expression = expression.replaceAll("/\\((([^|]+)(\\|[^|]+)*)\\|+\\)", "(?:/($1))?");
+
+        // // Allow any path (that doesn't contain an explicit counter) to contain a counter,
+        // // done by replacing any '/' or '|' that isn't preceded by ']' or '*' or '/' or '(' with '(\[\d+\])?/'...
+        // input = input.replaceAll("(?<=[^\\]\\*/(])([/|])", "(?:\\\\[\\\\d+\\\\])?$1");
+
+        // Does the path contain any '[]' or '[*]' or '[0]' or '[n]' (where n is any positive integers)...
+        // '[*]/' => '(\[\d+\])?/'
+        expression = expression.replaceAll("\\[\\]", "(?:\\\\[\\\\d+\\\\])?"); // index is optional
+        // '[]/' => '(\[\d+\])?/'
+        expression = expression.replaceAll("\\[[*]\\]", "(?:\\\\[\\\\d+\\\\])?"); // index is optional
+        // '[0]/' => '(\[0\])?/'
+        expression = expression.replaceAll("\\[0\\]", "(?:\\\\[0\\\\])?"); // index is optional
+        // '[n]/' => '\[n\]/'
+        expression = expression.replaceAll("\\[([1-9]\\d*)\\]", "\\\\[$1\\\\]"); // index is required
+
+        // Change any other end predicates to not be wrapped by braces but to begin with a slash ...
+        // ...'[x]' => ...'/x'
+        expression = expression.replaceAll("(?<!\\\\)\\[([^\\]]*)\\]$", "/$1");
+
+        // Replace all '[n,m,o,p]' type sequences with '[(n|m|o|p)]'
+        java.util.regex.Matcher matcher = SEQUENCE_PATTERN.matcher(expression);
+        StringBuffer sb = new StringBuffer();
+        boolean result = matcher.find();
+        if (result) {
+            do {
+                String sequenceStr = matcher.group(1);
+                boolean optional = false;
+                if (sequenceStr.startsWith("0,")) {
+                    sequenceStr = sequenceStr.replaceFirst("^0,", "");
+                    optional = true;
+                }
+                if (sequenceStr.endsWith(",0")) {
+                    sequenceStr = sequenceStr.replaceFirst(",0$", "");
+                    optional = true;
+                }
+                if (sequenceStr.contains(",0,")) {
+                    sequenceStr = sequenceStr.replaceAll(",0,", ",");
+                    optional = true;
+                }
+                sequenceStr = sequenceStr.replaceAll(",", "|");
+                String replacement = "\\\\[(?:" + sequenceStr + ")\\\\]";
+                if (optional) {
+                    replacement = "(?:" + replacement + ")?";
+                }
+                matcher.appendReplacement(sb, replacement);
+                result = matcher.find();
+            } while (result);
+            matcher.appendTail(sb);
+            expression = sb.toString();
+        }
+
+        // Order is important here
+        expression = expression.replaceAll("[*]([^/(\\\\])", "[^/$1]*$1"); // '*' not followed by '/', '\\', or '('
+        expression = expression.replaceAll("(?<!\\[\\^/\\])[*]", "[^/]*");
+        expression = expression.replaceAll("[/]{2,}$", "(?:/[^/]*)*"); // ending '//'
+        expression = expression.replaceAll("[/]{2,}", "(?:/[^/]*)*/"); // other '//'
+        return expression;
+    }
+
+    /**
+     * @return the expression
+     */
+    public String getSelectExpression() {
+        return this.expression;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return this.expression.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof PathExpression) {
+            PathExpression that = (PathExpression)obj;
+            if (!this.expression.equalsIgnoreCase(that.expression)) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return this.expression;
+    }
+
+    /**
+     * @param absolutePath
+     * @return the matcher
+     */
+    public Matcher matcher( String absolutePath ) {
+        // Determine if the input path match the select expression ...
+        String originalAbsolutePath = absolutePath;
+        // if (!absolutePath.endsWith("/")) absolutePath = absolutePath + "/";
+        // Remove all trailing '/' ...
+        absolutePath = absolutePath.replaceAll("/+$", "");
+
+        // See if the supplied absolute path matches the pattern ...
+        final java.util.regex.Matcher matcher = this.matchPattern.matcher(absolutePath);
+        if (!matcher.matches()) {
+            // No match, so return immediately ...
+            return new Matcher(matcher, originalAbsolutePath, null);
+        }
+
+        // The absolute path does match the pattern, so use the select pattern and try to grab the selected path ...
+        final java.util.regex.Matcher selectMatcher = this.selectPattern.matcher(absolutePath);
+        if (!selectMatcher.matches()) {
+            // Nothing can be selected, so return immediately ...
+            return new Matcher(matcher, null, null);
+        }
+        // Grab the selected path ...
+        String selectedPath = selectMatcher.group(1);
+
+        // Remove the trailing '/@property' ...
+        selectedPath = selectedPath.replaceAll("/@[^/\\[\\]]+$", "");
+
+        return new Matcher(matcher, originalAbsolutePath, selectedPath);
+    }
+
+    @Immutable
+    public static class Matcher {
+
+        private final String inputPath;
+        private final String selectedPath;
+        private final java.util.regex.Matcher inputMatcher;
+        private final int hc;
+
+        protected Matcher( java.util.regex.Matcher inputMatcher,
+                           String inputPath,
+                           String selectedPath ) {
+            this.inputMatcher = inputMatcher;
+            this.inputPath = inputPath;
+            this.selectedPath = selectedPath;
+            this.hc = HashCode.compute(this.inputPath, this.selectedPath);
+        }
+
+        public boolean matches() {
+            return this.selectedPath != null;
+        }
+
+        /**
+         * @return inputPath
+         */
+        public String getInputPath() {
+            return this.inputPath;
+        }
+
+        /**
+         * @return selectPattern
+         */
+        public String getSelectedNodePath() {
+            return this.selectedPath;
+        }
+
+        public int groupCount() {
+            return this.inputMatcher.groupCount();
+        }
+
+        public String group( int groupNumber ) {
+            return this.inputMatcher.group(groupNumber);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int hashCode() {
+            return this.hc;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean equals( Object obj ) {
+            if (obj == this) return true;
+            if (obj instanceof PathExpression.Matcher) {
+                PathExpression.Matcher that = (PathExpression.Matcher)obj;
+                if (!this.inputPath.equalsIgnoreCase(that.inputPath)) return false;
+                if (!this.selectedPath.equalsIgnoreCase(that.selectedPath)) return false;
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public String toString() {
+            return this.selectedPath;
+        }
+    }
+
+    /**
+     * Regular expression used to determine if the expression matches any single-level wildcard.
+     */
+    // /*(?:[*.](?:\[\*?\])?/*)*
+    private static final String ANYTHING_PATTERN_STRING = "/*(?:[*.](?:\\[\\*?\\])?/*)*";
+    private static final Pattern ANYTHING_PATTERN = Pattern.compile(ANYTHING_PATTERN_STRING);
+
+    /**
+     * Return whether this expression matches anything and therefore is not restrictive. These include expressions of any nodes ("
+     * <code>/</code>"), any sequence of nodes ("<code>//</code>"), the self reference ("<code>.</code>"), or wildcard ("
+     * <code>*</code>", "<code>*[]</code>" or "<code>*[*]</code>"). Combinations of these individual expressions are also
+     * considered to match anything.
+     * 
+     * @return true if the expression matches anything, or false otherwise
+     */
+    public boolean matchesAnything() {
+        return ANYTHING_PATTERN.matcher(expression).matches();
+    }
+
+    public static PathExpression all() {
+        return ALL_PATHS_EXPRESSION;
+    }
+
+    private static final PathExpression ALL_PATHS_EXPRESSION = PathExpression.compile("//");
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathExpression.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathFactory.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,242 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import org.jboss.dna.common.text.TextDecoder;
+
+/**
+ * A factory for creating {@link Path paths}. This interface extends the {@link ValueFactory} generic interface and adds specific
+ * methods for creating paths (and relative paths) from a series of names, segments, or combinations.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public interface PathFactory extends ValueFactory<Path> {
+
+    /**
+     * Create an absolute root path. Subsequent calls will always return the same instance.
+     * 
+     * @return the new path
+     */
+    Path createRootPath();
+
+    /**
+     * Create an absolute path with the supplied segment names, in order. If no segments are provided, the result will be the root
+     * path.
+     * 
+     * @param segmentNames the names of the segments
+     * @return the new path
+     * @throws IllegalArgumentException if at least one segment name is provided and if any of the supplied segment names are null
+     */
+    Path createAbsolutePath( Name... segmentNames );
+
+    /**
+     * Create an absolute path with the supplied segments, in order. If no segments are provided, the result will be the root
+     * path.
+     * 
+     * @param segments the segments
+     * @return the new path
+     * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
+     */
+    Path createAbsolutePath( Path.Segment... segments );
+
+    /**
+     * Create an absolute path with the supplied segments, in order. If no segments are provided, the result will be the root
+     * path.
+     * 
+     * @param segments the segments
+     * @return the new path
+     * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
+     */
+    Path createAbsolutePath( Iterable<Path.Segment> segments );
+
+    /**
+     * Create an empty relative path (i.e., equivalent to {@link #createRelativePath(Path.Segment...) createRelativePath}(
+     * {@link Path#SELF_SEGMENT})). Subsequent calls will always return the same instance.
+     * 
+     * @return the new path
+     */
+    Path createRelativePath();
+
+    /**
+     * Create a relative path with the supplied segment names, in order. If no segments are provided, the result will be the root
+     * path.
+     * 
+     * @param segmentNames the names of the segments
+     * @return the new path
+     * @throws IllegalArgumentException if at least one segment name is provided and if any of the supplied segment names are null
+     */
+    Path createRelativePath( Name... segmentNames );
+
+    /**
+     * Create a relative path with the supplied segments, in order. If no segments are provided, the result will be the root path.
+     * 
+     * @param segments the segments
+     * @return the new path
+     * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
+     */
+    Path createRelativePath( Path.Segment... segments );
+
+    /**
+     * Create a relative path with the supplied segments, in order. If no segments are provided, the result will be the root path.
+     * 
+     * @param segments the segments
+     * @return the new path
+     * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
+     */
+    Path createRelativePath( Iterable<Path.Segment> segments );
+
+    /**
+     * Create a path by appending the supplied relative path to the supplied parent path. The resulting path will be
+     * {@link Path#isAbsolute() absolute} if the supplied parent path is absolute.
+     * 
+     * @param parentPath the path that is to provide the basis for the new path
+     * @param childPath the path that should be appended to the parent path
+     * @return the new path
+     * @throws IllegalArgumentException if the parent path reference or the child path reference is null
+     */
+    Path create( Path parentPath,
+                 Path childPath );
+
+    /**
+     * Create a path by appending the supplied names to the parent path.
+     * 
+     * @param parentPath the path that is to provide the basis for the new path
+     * @param segmentName the name of the segment to be appended to the parent path
+     * @param index the index for the new segment
+     * @return the new path
+     * @throws IllegalArgumentException if the parent path reference or the segment name is null, or if the index is invalid
+     */
+    Path create( Path parentPath,
+                 Name segmentName,
+                 int index );
+
+    /**
+     * Create a path by appending the supplied names to the parent path. If no names are appended, the parent path is returned.
+     * 
+     * @param parentPath the path that is to provide the basis for the new path
+     * @param segmentNames the names of the segments that are to be appended, in order, to the parent path
+     * @return the new path
+     * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
+     *         any of the supplied segment names are null
+     */
+    Path create( Path parentPath,
+                 Name... segmentNames );
+
+    /**
+     * Create a path by appending the supplied names to the parent path. If no names are appended, the parent path is returned.
+     * 
+     * @param parentPath the path that is to provide the basis for the new path
+     * @param segments the segments that are to be appended, in order, to the parent path
+     * @return the new path
+     * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
+     *         any of the supplied segment names are null
+     */
+    Path create( Path parentPath,
+                 Path.Segment... segments );
+
+    /**
+     * Create a path by appending the supplied names to the parent path. If no names are appended, the parent path is returned.
+     * 
+     * @param parentPath the path that is to provide the basis for the new path
+     * @param segments the segments that are to be appended, in order, to the parent path
+     * @return the new path
+     * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
+     *         any of the supplied segment names are null
+     */
+    Path create( Path parentPath,
+                 Iterable<Path.Segment> segments );
+
+    /**
+     * Create a path by appending the supplied names to the parent path.
+     * 
+     * @param parentPath the path that is to provide the basis for the new path
+     * @param subpath the subpath to be appended to the parent path, which must be in the form of a relative path
+     * @return the new path
+     * @throws IllegalArgumentException if the parent path reference or the segment name is null, or if the index is invalid
+     */
+    Path create( Path parentPath,
+                 String subpath );
+
+    /**
+     * Create a path segment given the supplied segment name. The supplied string may contain a same-name-sibling index in the
+     * form of "<code>[<i>n</i>]</code>" at the end of the name, where <i>n</i> is a positive integer. Note that the
+     * same-name-sibling index is 1-based, not zero-based.
+     * 
+     * @param segmentName the name of the segment
+     * @return the segment
+     * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created from
+     *         the supplied string
+     * @throws ValueFormatException if the same-name-sibling index is not an integer, or if the supplied string is not a valid
+     *         segment name
+     */
+    Path.Segment createSegment( String segmentName );
+
+    /**
+     * Create a path segment given the supplied segment name. The supplied string may contain a same-name-sibling index in the
+     * form of "<code>[<i>n</i>]</code>" at the end of the name, where <i>n</i> is a positive integer. Note that the
+     * same-name-sibling index is 1-based, not zero-based.
+     * 
+     * @param segmentName the name of the segment
+     * @param decoder the decoder that should be used to decode the qualified name
+     * @return the segment
+     * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created from
+     *         the supplied string
+     * @throws ValueFormatException if the same-name-sibling index is not an integer, or if the supplied string is not a valid
+     *         segment name
+     */
+    Path.Segment createSegment( String segmentName,
+                                TextDecoder decoder );
+
+    /**
+     * Create a path segment given the supplied segment name and index.
+     * 
+     * @param segmentName the name of the new segment
+     * @param index the index of the new segment
+     * @return the segment
+     * @throws IllegalArgumentException if the segment name reference is <code>null</code> or if the index is invalid
+     * @throws ValueFormatException if the supplied string is not a valid segment name
+     */
+    Path.Segment createSegment( String segmentName,
+                                int index );
+
+    /**
+     * Create a path segment given the supplied segment name. The resulting segment will have no index.
+     * 
+     * @param segmentName the name of the segment
+     * @return the segment
+     * @throws IllegalArgumentException if the segment name reference is null
+     */
+    Path.Segment createSegment( Name segmentName );
+
+    /**
+     * Create a path segment given the supplied segment name and index.
+     * 
+     * @param segmentName the name of the new segment
+     * @param index the index of the new segment
+     * @return the segment
+     * @throws IllegalArgumentException if the segment name reference is null or if the index is invalid
+     */
+    Path.Segment createSegment( Name segmentName,
+                                int index );
+
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathNotFoundException.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PathNotFoundException.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathNotFoundException.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PathNotFoundException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import org.jboss.dna.graph.Location;
+
+/**
+ * @author Randall Hauch
+ */
+public class PathNotFoundException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = -3703984046286975978L;
+
+    private final Location location;
+    private final Path lowestAncestorThatDoesExist;
+
+    /**
+     * @param location the location of the node that does not exist
+     * @param lowestAncestorThatDoesExist the path of the lowest (closest) ancestor that does exist
+     */
+    public PathNotFoundException( Location location,
+                                  Path lowestAncestorThatDoesExist ) {
+        this.location = location;
+        this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
+    }
+
+    /**
+     * @param location the location of the node that does not exist
+     * @param lowestAncestorThatDoesExist the path of the lowest (closest) ancestor that does exist
+     * @param message
+     */
+    public PathNotFoundException( Location location,
+                                  Path lowestAncestorThatDoesExist,
+                                  String message ) {
+        super(message);
+        this.location = location;
+        this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
+    }
+
+    /**
+     * @param location the location of the node that does not exist
+     * @param lowestAncestorThatDoesExist the path of the lowest (closest) ancestor that does exist
+     * @param cause
+     */
+    public PathNotFoundException( Location location,
+                                  Path lowestAncestorThatDoesExist,
+                                  Throwable cause ) {
+        super(cause);
+        this.location = location;
+        this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
+    }
+
+    /**
+     * @param location the location of the node that does not exist
+     * @param lowestAncestorThatDoesExist the path of the lowest (closest) ancestor that does exist
+     * @param message
+     * @param cause
+     */
+    public PathNotFoundException( Location location,
+                                  Path lowestAncestorThatDoesExist,
+                                  String message,
+                                  Throwable cause ) {
+        super(message, cause);
+        this.location = location;
+        this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+
+    /**
+     * Get the path that was not found
+     * 
+     * @return the path that was not found
+     */
+    public Location getLocation() {
+        return location;
+    }
+
+    /**
+     * Get the lowest (closest) existing {@link Path#getParent() ancestor} of the {@link #getLocation() non-existant location}.
+     * 
+     * @return the lowest ancestor that does exist
+     */
+    public Path getLowestAncestorThatDoesExist() {
+        return lowestAncestorThatDoesExist;
+    }
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Property.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Property.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Property.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Property.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,219 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.util.Iterator;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+
+/**
+ * Representation of a property consisting of a name and value(s). Note that this property is immutable, meaning that the property
+ * values may not be changed through this interface.
+ * <p>
+ * This class is designed to be used with the {@link ValueFactories} interface and the particular {@link ValueFactory} that
+ * corresponds to the type of value you'd like to use. The <code>ValueFactory</code> will then return the values (if no type
+ * conversion is required) or will convert the values using the appropriate conversion algorithm.
+ * </p>
+ * <p>
+ * The following example shows how to obtain the {@link String} representations of the {@link #getValues() property values}:
+ * 
+ * <pre>
+ *   ValueFactories valueFactories = ...
+ *   Property property = ...
+ *   Iterator&lt;String&gt; iter = valueFactories.getStringFactory().create(property.getValues());
+ *   while ( iter.hasNext() ) {
+ *       System.out.println(iter.next());
+ *   }
+ * </pre>
+ * 
+ * Meanwhile, the {@link ValueFactories#getLongFactory() long value factory} converts the values to <code>long</code>, the
+ * {@link ValueFactories#getDateFactory() date value factory} converts the values to {@link DateTime} instances, and so on.
+ * </p>
+ * <p>
+ * This technique is much better and far safer than casting the values. It is possible that some Property instances contain
+ * heterogeneous values, so casting may not always work. Also, this technique guarantees that the values are properly converted if
+ * the type is not what you expected.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public interface Property extends Iterable<Object>, Comparable<Property> {
+
+    /**
+     * Get the name of the property.
+     * 
+     * @return the property name; never null
+     */
+    Name getName();
+
+    /**
+     * Get the number of actual values in this property. If the property allows {@link #isMultiple() multiple values}, then this
+     * method may return a value greater than 1. If the property only allows a {@link #isSingle() single value}, then this method
+     * will return either 0 or 1. This method may return 0 regardless of whether the property allows a {@link #isSingle() single
+     * value}, or {@link #isMultiple() multiple values}.
+     * 
+     * @return the number of actual values in this property; always non-negative
+     */
+    int size();
+
+    /**
+     * Determine whether the property currently has multiple values.
+     * 
+     * @return true if the property has multiple values, or false otherwise.
+     * @see #isSingle()
+     * @see #isEmpty()
+     */
+    boolean isMultiple();
+
+    /**
+     * Determine whether the property currently has a single value.
+     * 
+     * @return true if the property has a single value, or false otherwise.
+     * @see #isMultiple()
+     * @see #isEmpty()
+     */
+    boolean isSingle();
+
+    /**
+     * Determine whether this property has no actual values. This method may return <code>true</code> regardless of whether the
+     * property allows a {@link #isSingle() single value}, or {@link #isMultiple() multiple values}.
+     * <p>
+     * This method is a convenience method that is equivalent to <code>size() == 0</code>.
+     * </p>
+     * 
+     * @return true if this property has no values, or false otherwise
+     * @see #isMultiple()
+     * @see #isSingle()
+     */
+    boolean isEmpty();
+
+    /**
+     * Obtain the property's first value in its natural form. This is equivalent to calling
+     * <code>isEmpty() ? null : iterator().next()</code>
+     * 
+     * @return the first value, or null if the property is {@link #isEmpty() empty}
+     * @see Iterable#iterator()
+     * @see #getValues()
+     * @see #getValuesAsArray()
+     * @see #isEmpty()
+     */
+    Object getFirstValue();
+
+    /**
+     * Obtain the property's values in their natural form. This is equivalent to calling {@link Iterable#iterator() iterator()}.
+     * <p>
+     * A valid iterator is returned if the property has {@link #isSingle() single valued} or {@link #isMultiple() multi-valued}.
+     * </p>
+     * <p>
+     * The resulting iterator is immutable, and all property values are immutable.
+     * </p>
+     * 
+     * @return an iterator over the values; never null
+     * @see #getFirstValue()
+     * @see Iterable#iterator()
+     * @see #getValuesAsArray()
+     * @see ValueFactory#create(Iterator)
+     */
+    Iterator<?> getValues();
+
+    /**
+     * Obtain the property's values as an array of objects in their natural form.
+     * <p>
+     * A valid array is return if the property has {@link #isSingle() single valued} or {@link #isMultiple() multi-valued}, or a
+     * null value is returned if the property is {@link #isEmpty() empty}.
+     * </p>
+     * <p>
+     * The resulting array is a copy, guaranteeing immutability for the property.
+     * </p>
+     * 
+     * @return the array of values
+     * @see #getFirstValue()
+     * @see Iterable#iterator()
+     * @see #getValues()
+     * @see ValueFactory#create(Object[])
+     */
+    Object[] getValuesAsArray();
+
+    /**
+     * Get the string form of the property, using the default encoder.
+     * 
+     * @return the encoded string
+     * @see #getString(TextEncoder)
+     */
+    public String getString();
+
+    /**
+     * Get the encoded string form of the property, using the supplied encoder to encode characters in the property's name and
+     * values.
+     * 
+     * @param encoder the encoder to use, or null if the default encoder should be used
+     * @return the encoded string
+     * @see #getString()
+     */
+    public String getString( TextEncoder encoder );
+
+    /**
+     * Get the string form of the property, using the supplied namespace registry to convert the property's name and values.
+     * 
+     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+     *        {@link Name#getNamespaceUri() namespace URIs} in the property {@link #getName() name}
+     * @return the string
+     * @throws IllegalArgumentException if the namespace registry is null
+     * @see #getString(NamespaceRegistry,TextEncoder)
+     * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry );
+
+    /**
+     * Get the encoded string form of the property, using the supplied namespace registry to convert the property's namespace URIs
+     * to prefixes and the supplied encoder to encode characters in the property's name and values.
+     * 
+     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+     *        {@link Name#getNamespaceUri() namespace URIs} in the property {@link #getName() name}, or null if the namespace
+     *        registry should not be used
+     * @param encoder the encoder to use for encoding the name and values, or null if the default encoder should be used
+     * @return the encoded string
+     * @see #getString(NamespaceRegistry)
+     * @see #getString(NamespaceRegistry, TextEncoder, TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder );
+
+    /**
+     * Get the encoded string form of the property, using the supplied namespace registry to convert the property's namespace URIs
+     * to prefixes and the supplied encoder to encode characters in the property's name and values.
+     * 
+     * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+     *        {@link Name#getNamespaceUri() namespace URIs} in the property {@link #getName() name}, or null if the namespace
+     *        registry should not be used
+     * @param encoder the encoder to use for encoding the name and values, or null if the default encoder should be used
+     * @param delimiterEncoder the encoder to use for encoding delimiters used in paths and names, or null if the standard
+     *        delimiters should be used
+     * @return the encoded string
+     * @see #getString(NamespaceRegistry)
+     * @see #getString(NamespaceRegistry, TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder,
+                             TextEncoder delimiterEncoder );
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyFactory.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,96 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.util.Iterator;
+
+/**
+ * @author Randall Hauch
+ */
+public interface PropertyFactory {
+    /**
+     * Create a property with the supplied name and values
+     * 
+     * @param name the property name; may not be null
+     * @param values the values
+     * @return the resulting property
+     */
+    Property create( Name name,
+                     Object... values );
+
+    /**
+     * Create a property with the supplied name and values
+     * 
+     * @param name the property name; may not be null
+     * @param values the values
+     * @return the resulting property
+     */
+    Property create( Name name,
+                     Iterable<?> values );
+
+    /**
+     * Create a property with the supplied name and values
+     * 
+     * @param name the property name; may not be null
+     * @param values the values
+     * @return the resulting property
+     */
+    Property create( Name name,
+                     Iterator<?> values );
+
+    /**
+     * Create a property with the supplied name and values
+     * 
+     * @param name the property name; may not be null
+     * @param desiredType the type that the objects should be converted to; if null, they will be used as is
+     * @param values the values
+     * @return the resulting property
+     */
+    Property create( Name name,
+                     PropertyType desiredType,
+                     Object... values );
+
+    /**
+     * Create a property with the supplied name and values
+     * 
+     * @param name the property name; may not be null
+     * @param desiredType the type that the objects should be converted to; if null, they will be used as is
+     * @param values the values
+     * @return the resulting property
+     */
+    Property create( Name name,
+                     PropertyType desiredType,
+                     Iterable<?> values );
+
+    /**
+     * Create a property with the supplied name and values
+     * 
+     * @param name the property name; may not be null
+     * @param desiredType the type that the objects should be converted to; if null, they will be used as is
+     * @param values the values
+     * @return the resulting property
+     */
+    Property create( Name name,
+                     PropertyType desiredType,
+                     Iterator<?> values );
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyFactory.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyType.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/PropertyType.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyType.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyType.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,127 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.GraphI18n;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public enum PropertyType {
+
+    STRING("String", ValueComparators.STRING_COMPARATOR, String.class),
+    BINARY("Binary", ValueComparators.BINARY_COMPARATOR, Binary.class),
+    LONG("Long", ValueComparators.LONG_COMPARATOR, Long.class),
+    DOUBLE("Double", ValueComparators.DOUBLE_COMPARATOR, Double.class),
+    DECIMAL("Decimal", ValueComparators.DECIMAL_COMPARATOR, BigDecimal.class),
+    DATE("Date", ValueComparators.DATE_TIME_COMPARATOR, DateTime.class),
+    BOOLEAN("Boolean", ValueComparators.BOOLEAN_COMPARATOR, Boolean.class),
+    NAME("Name", ValueComparators.NAME_COMPARATOR, Name.class),
+    PATH("Path", ValueComparators.PATH_COMPARATOR, Path.class),
+    UUID("UUID", ValueComparators.UUID_COMPARATOR, UUID.class),
+    REFERENCE("Reference", ValueComparators.REFERENCE_COMPARATOR, Reference.class),
+    URI("URI", ValueComparators.URI_COMPARATOR, URI.class),
+    OBJECT("Object", ValueComparators.OBJECT_COMPARATOR, Object.class);
+
+    private static final List<PropertyType> ALL_PROPERTY_TYPES;
+    static {
+        List<PropertyType> types = new ArrayList<PropertyType>();
+        for (PropertyType type : PropertyType.values()) {
+            types.add(type);
+        }
+        ALL_PROPERTY_TYPES = Collections.unmodifiableList(types);
+    }
+
+    private final String name;
+    private final Comparator<?> comparator;
+    private final Class<?> valueClass;
+
+    private PropertyType( String name,
+                          Comparator<?> comparator,
+                          Class<?> valueClass ) {
+        this.name = name;
+        this.comparator = comparator;
+        this.valueClass = valueClass;
+    }
+
+    public Class<?> getValueClass() {
+        return this.valueClass;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public Comparator<?> getComparator() {
+        return this.comparator;
+    }
+
+    public boolean isTypeFor( Object value ) {
+        return this.valueClass.isInstance(value);
+    }
+
+    public boolean isTypeForEach( Iterable<?> values ) {
+        for (Object value : values) {
+            if (!this.valueClass.isInstance(value)) return false;
+        }
+        return true;
+    }
+
+    public boolean isTypeForEach( Iterator<?> values ) {
+        while (values.hasNext()) {
+            Object value = values.next();
+            if (!this.valueClass.isInstance(value)) return false;
+        }
+        return true;
+    }
+
+    public static PropertyType discoverType( Object value ) {
+        if (value == null) {
+            throw new IllegalArgumentException(GraphI18n.unableToDiscoverPropertyTypeForNullValue.text());
+        }
+        for (PropertyType type : PropertyType.values()) {
+            if (type == OBJECT) continue;
+            if (type.isTypeFor(value)) return type;
+        }
+        return OBJECT;
+    }
+
+    /**
+     * Return an iterator over all the property type enumeration literals.
+     * 
+     * @return an immutable iterator
+     */
+    public static Iterator<PropertyType> iterator() {
+        return ALL_PROPERTY_TYPES.iterator();
+    }
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Reference.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Reference.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Reference.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Reference.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.io.Serializable;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+
+/**
+ * A representation of a reference to another node. Node references may not necessarily resolve to an existing node.
+ * @author Randall Hauch
+ */
+ at Immutable
+public interface Reference extends Comparable<Reference>, Serializable {
+
+    /**
+     * Get the string form of the Reference. The {@link Path#DEFAULT_ENCODER default encoder} is used to encode characters in the
+     * reference.
+     * @return the encoded string
+     * @see #getString(TextEncoder)
+     */
+    public String getString();
+
+    /**
+     * Get the encoded string form of the Reference, using the supplied encoder to encode characters in the reference.
+     * @param encoder the encoder to use, or null if the {@link Path#DEFAULT_ENCODER default encoder} should be used
+     * @return the encoded string
+     * @see #getString()
+     */
+    public String getString( TextEncoder encoder );
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Reference.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ReferentialIntegrityException.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ReferentialIntegrityException.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ReferentialIntegrityException.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ReferentialIntegrityException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,116 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.jboss.dna.graph.Location;
+
+/**
+ * @author Randall Hauch
+ */
+public class ReferentialIntegrityException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = -3703984046286975978L;
+
+    private final Map<Location, List<Reference>> invalidReferences;
+
+    /**
+     * @param location the location of the node containing the bad reference(s)
+     * @param invalidReferences the invalid references
+     */
+    public ReferentialIntegrityException( Location location,
+                                          Reference... invalidReferences ) {
+        this.invalidReferences = new HashMap<Location, List<Reference>>();
+        List<Reference> invalidRefList = null;
+        if (invalidReferences == null || invalidReferences.length == 0) {
+            invalidRefList = Collections.emptyList();
+        } else if (invalidReferences.length == 1) {
+            invalidRefList = Collections.singletonList(invalidReferences[0]);
+        } else {
+            invalidRefList = new ArrayList<Reference>();
+            for (Reference ref : invalidReferences) {
+                invalidRefList.add(ref);
+            }
+        }
+        this.invalidReferences.put(location, invalidRefList);
+    }
+
+    /**
+     * @param invalidReferences the map of locations to invalid references
+     */
+    public ReferentialIntegrityException( Map<Location, List<Reference>> invalidReferences ) {
+        this.invalidReferences = invalidReferences;
+    }
+
+    /**
+     * @param invalidReferences the map of locations to invalid references
+     * @param message
+     */
+    public ReferentialIntegrityException( Map<Location, List<Reference>> invalidReferences,
+                                          String message ) {
+        super(message);
+        this.invalidReferences = invalidReferences;
+    }
+
+    /**
+     * @param invalidReferences the map of locations to invalid references
+     * @param cause
+     */
+    public ReferentialIntegrityException( Map<Location, List<Reference>> invalidReferences,
+                                          Throwable cause ) {
+        super(cause);
+        this.invalidReferences = invalidReferences;
+    }
+
+    /**
+     * @param invalidReferences the map of locations to invalid references
+     * @param message
+     * @param cause
+     */
+    public ReferentialIntegrityException( Map<Location, List<Reference>> invalidReferences,
+                                          String message,
+                                          Throwable cause ) {
+        super(message, cause);
+        this.invalidReferences = invalidReferences;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+
+    /**
+     * @return invalidReferences
+     */
+    public Map<Location, List<Reference>> getInvalidReferences() {
+        return invalidReferences;
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ReferentialIntegrityException.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/UuidFactory.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/UuidFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/UuidFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/UuidFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.util.UUID;
+
+/**
+ * A factory for creating {@link UUID UUID instances}. This interface extends the {@link ValueFactory} generic interface and adds
+ * specific methods for creating UUIDs.
+ * 
+ * @author Randall Hauch
+ */
+public interface UuidFactory extends ValueFactory<UUID> {
+
+    /**
+     * Create a new random UUID.
+     * 
+     * @return the new randomly generated UUID
+     */
+    UUID create();
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/UuidFactory.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueComparators.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueComparators.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueComparators.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueComparators.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,332 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.UUID;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public class ValueComparators {
+
+    /**
+     * A comparator of string values.
+     */
+    public static final Comparator<String> STRING_COMPARATOR = new Comparator<String>() {
+
+        public int compare( String o1,
+                            String o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of long values.
+     */
+    public static final Comparator<Long> LONG_COMPARATOR = new Comparator<Long>() {
+
+        public int compare( Long o1,
+                            Long o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of double values.
+     */
+    public static final Comparator<Double> DOUBLE_COMPARATOR = new Comparator<Double>() {
+
+        public int compare( Double o1,
+                            Double o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of decimal values.
+     */
+    public static final Comparator<BigDecimal> DECIMAL_COMPARATOR = new Comparator<BigDecimal>() {
+
+        public int compare( BigDecimal o1,
+                            BigDecimal o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of binary values. Although {@link Binary} is {@link Comparable}, this comparator does not rely upon any
+     * particular Binary implementation. Thus, Binary implementations can use this for their {@link Comparable#compareTo(Object)}
+     * implementation.
+     */
+    public static final Comparator<Binary> BINARY_COMPARATOR = new Comparator<Binary>() {
+
+        public int compare( Binary o1,
+                            Binary o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            try {
+                o1.acquire();
+                try {
+                    o2.acquire();
+                    final long len1 = o1.getSize();
+                    final long len2 = o2.getSize();
+                    if (len1 < len2) return -1;
+                    if (len1 > len2) return 1;
+
+                    // Compare using the hashes, if available
+                    byte[] hash1 = o1.getHash();
+                    byte[] hash2 = o2.getHash();
+                    if (hash1.length != 0 || hash2.length != 0) {
+                        assert hash1.length == hash2.length;
+                        for (int i = 0; i != hash1.length; ++i) {
+                            int diff = hash1[i] - hash2[i];
+                            if (diff != 0) return diff;
+                        }
+                        return 0;
+                    }
+
+                    // Otherwise they are the same length ...
+                    InputStream stream1 = null;
+                    InputStream stream2 = null;
+                    try {
+                        stream1 = o1.getStream();
+                        stream2 = o2.getStream();
+                        byte[] buffer1 = new byte[1024];
+                        byte[] buffer2 = new byte[1024];
+                        while (true) {
+                            int numRead1 = stream1.read(buffer1);
+                            if (numRead1 < 0) break;
+                            int numRead2 = stream2.read(buffer2);
+                            if (numRead1 != numRead2) {
+                                throw new IoException(GraphI18n.errorReadingPropertyValueBytes.text());
+                            }
+                            for (int i = 0; i != numRead1; ++i) {
+                                int diff = buffer1[i] - buffer2[i];
+                                if (diff != 0) return diff;
+                            }
+                        }
+                        return 0;
+                    } catch (IOException e) {
+                        throw new IoException(GraphI18n.errorReadingPropertyValueBytes.text());
+                    } finally {
+                        if (stream1 != null) {
+                            try {
+                                stream1.close();
+                            } catch (IOException e) {
+                                // do nothing
+                            }
+                        }
+                        if (stream2 != null) {
+                            try {
+                                stream2.close();
+                            } catch (IOException e) {
+                                // do nothing
+                            }
+                        }
+                    }
+                } finally {
+                    o2.release();
+                }
+            } finally {
+                o1.release();
+            }
+        }
+    };
+    /**
+     * A comparator of boolean values.
+     */
+    public static final Comparator<Boolean> BOOLEAN_COMPARATOR = new Comparator<Boolean>() {
+
+        public int compare( Boolean o1,
+                            Boolean o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of date-time instances.
+     */
+    public static final Comparator<DateTime> DATE_TIME_COMPARATOR = new Comparator<DateTime>() {
+
+        public int compare( DateTime o1,
+                            DateTime o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of date values.
+     */
+    public static final Comparator<Date> DATE_COMPARATOR = new Comparator<Date>() {
+
+        public int compare( Date o1,
+                            Date o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of calendar values.
+     */
+    public static final Comparator<Calendar> CALENDAR_COMPARATOR = new Comparator<Calendar>() {
+
+        public int compare( Calendar o1,
+                            Calendar o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of name values.
+     */
+    public static final Comparator<Name> NAME_COMPARATOR = new Comparator<Name>() {
+
+        public int compare( Name o1,
+                            Name o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of path values.
+     */
+    public static final Comparator<Path> PATH_COMPARATOR = new Comparator<Path>() {
+
+        public int compare( Path o1,
+                            Path o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of URI values.
+     */
+    public static final Comparator<URI> URI_COMPARATOR = new Comparator<URI>() {
+
+        public int compare( URI o1,
+                            URI o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of UUID values.
+     */
+    public static final Comparator<UUID> UUID_COMPARATOR = new Comparator<UUID>() {
+
+        public int compare( UUID o1,
+                            UUID o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of reference values.
+     */
+    public static final Comparator<Reference> REFERENCE_COMPARATOR = new Comparator<Reference>() {
+
+        public int compare( Reference o1,
+                            Reference o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of other values.
+     */
+    public static final Comparator<Object> OBJECT_COMPARATOR = new Comparator<Object>() {
+
+        @SuppressWarnings( "unchecked" )
+        public int compare( Object o1,
+                            Object o2 ) {
+            if (o1 == o2) return 0;
+            if (o1 == null) return -1;
+            if (o2 == null) return 1;
+            PropertyType type1 = PropertyType.discoverType(o1);
+            PropertyType type2 = PropertyType.discoverType(o2);
+            if (type1 != PropertyType.OBJECT && type2 != PropertyType.OBJECT) {
+                if (type1 == type2) return ((Comparator<Object>)type1.getComparator()).compare(o1, o2);
+
+                // The types are different but the classes are the same ...
+                if (type1.getValueClass().isAssignableFrom(type2.getValueClass())) {
+                    return ((Comparator<Object>)type1.getComparator()).compare(o1, o2);
+                }
+                if (type2.getValueClass().isAssignableFrom(type1.getValueClass())) {
+                    return ((Comparator<Object>)type2.getComparator()).compare(o1, o2);
+                }
+            }
+
+            // The types are different and must be converted ...
+            String value1 = getStringValueFactory().create(o1);
+            String value2 = getStringValueFactory().create(o2);
+            return value1.compareTo(value2);
+        }
+    };
+
+    // This is loaded lazily so that there is not a circular dependency between PropertyType (depends on this),
+    // StringValueFactory (depends on PropertyType), and OBJECT_COMPARATOR (which depends on StringValueFactory) ...
+    private static ValueFactory<String> STRING_VALUE_FACTORY;
+
+    protected static final ValueFactory<String> getStringValueFactory() {
+        // No locking is required, because it doesn't matter if we create several instances during initialization ...
+        if (STRING_VALUE_FACTORY == null) {
+            STRING_VALUE_FACTORY = new StringValueFactory(Path.NO_OP_DECODER, Path.NO_OP_ENCODER);
+        }
+        return STRING_VALUE_FACTORY;
+    }
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactories.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactories.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactories.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactories.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,143 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.math.BigDecimal;
+import java.net.URI;
+
+/**
+ * The set of standard {@link ValueFactory} instances.
+ * 
+ * @author Randall Hauch
+ */
+public interface ValueFactories extends Iterable<ValueFactory<?>> {
+
+    /**
+     * Get the value factory that creates values of the supplied {@link PropertyType type}.
+     * 
+     * @param type the type for the values
+     * @return the factory; never null
+     * @throws IllegalArgumentException if the property type is null
+     */
+    ValueFactory<?> getValueFactory( PropertyType type );
+
+    /**
+     * Get the value factory that is best able to create values with the most natural type given by the supplied value.
+     * 
+     * @param prototype the value that should be used to determine the best value factory
+     * @return the factory; never null
+     * @throws IllegalArgumentException if the prototype value is null
+     */
+    ValueFactory<?> getValueFactory( Object prototype );
+
+    /**
+     * Get the value factory for {@link PropertyType#STRING string} properties.
+     * 
+     * @return the factory; never null
+     */
+    ValueFactory<String> getStringFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#BINARY binary} properties.
+     * 
+     * @return the factory; never null
+     */
+    BinaryFactory getBinaryFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#LONG long} properties.
+     * 
+     * @return the factory; never null
+     */
+    ValueFactory<Long> getLongFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#DOUBLE double} properties.
+     * 
+     * @return the factory; never null
+     */
+    ValueFactory<Double> getDoubleFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#DECIMAL decimal} properties.
+     * 
+     * @return the factory; never null
+     */
+    ValueFactory<BigDecimal> getDecimalFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#DATE date} properties.
+     * 
+     * @return the factory; never null
+     */
+    DateTimeFactory getDateFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#BOOLEAN boolean} properties.
+     * 
+     * @return the factory; never null
+     */
+    ValueFactory<Boolean> getBooleanFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#NAME name} properties.
+     * 
+     * @return the factory; never null
+     */
+    NameFactory getNameFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#REFERENCE reference} properties.
+     * 
+     * @return the factory; never null
+     */
+    ValueFactory<Reference> getReferenceFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#PATH path} properties.
+     * 
+     * @return the factory; never null
+     */
+    PathFactory getPathFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#URI URI} properties.
+     * 
+     * @return the factory; never null
+     */
+    ValueFactory<URI> getUriFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#UUID UUID} properties.
+     * 
+     * @return the factory; never null
+     */
+    UuidFactory getUuidFactory();
+
+    /**
+     * Get the value factory for {@link PropertyType#OBJECT object} properties.
+     * 
+     * @return the factory; never null
+     */
+    ValueFactory<Object> getObjectFactory();
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactories.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactory.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,486 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.UUID;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.text.TextEncoder;
+
+/**
+ * A factory for {@link Property} values. Each create method may throw one of these exceptions when attempting to convert a
+ * supplied value to the {@link #getPropertyType() factory's type}:
+ * <ul>
+ * <li>{@link IllegalArgumentException} - If the supplied value is invalid in respect to the conversion being attempted.</li>
+ * <li>{@link UnsupportedOperationException} - If a conversion from the supplied value is not supported.</li>
+ * <li>{@link IoException} - If an unexpected problem occurs during the conversion (such as an {@link IOException}).</li>
+ * </ul>
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ * @param <T> the type of value to create
+ */
+public interface ValueFactory<T> {
+
+    static final TextDecoder DEFAULT_DECODER = Path.NO_OP_DECODER;
+    static final TextEncoder DEFAULT_ENCODER = Path.NO_OP_ENCODER;
+
+    /**
+     * Get the {@link PropertyType type} of values created by this factory.
+     * 
+     * @return the value type; never null
+     */
+    PropertyType getPropertyType();
+
+    /**
+     * Create a value from a string, using no decoding.
+     * 
+     * @param value the string from which the value is to be created
+     * @return the value, or null if the supplied string is null
+     * @throws ValueFormatException if the conversion from a string could not be performed
+     * @see #create(String, TextDecoder)
+     */
+    T create( String value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a string, using the supplied decoder.
+     * 
+     * @param value the string from which the value is to be created
+     * @param decoder the decoder that should be used; if null, the {@link #DEFAULT_DECODER default decoder} is used
+     * @return the value, or null if the supplied string is null
+     * @throws ValueFormatException if the conversion from a string could not be performed
+     * @see #create(String)
+     */
+    T create( String value,
+              TextDecoder decoder ) throws ValueFormatException;
+
+    /**
+     * Create a value from an integer.
+     * 
+     * @param value the integer from which the value is to be created
+     * @return the value; never null
+     * @throws ValueFormatException if the conversion from an integer could not be performed
+     */
+    T create( int value ) throws ValueFormatException;
+
+    /**
+     * Create a long from a string.
+     * 
+     * @param value the string from which the long is to be created
+     * @return the value; never null
+     * @throws ValueFormatException if the conversion from a long could not be performed
+     */
+    T create( long value ) throws ValueFormatException;
+
+    /**
+     * Create a boolean from a string.
+     * 
+     * @param value the boolean from which the value is to be created
+     * @return the value; never null
+     * @throws ValueFormatException if the conversion from a boolean could not be performed
+     */
+    T create( boolean value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a float.
+     * 
+     * @param value the float from which the value is to be created
+     * @return the value; never null
+     * @throws ValueFormatException if the conversion from a float could not be performed
+     */
+    T create( float value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a double.
+     * 
+     * @param value the double from which the value is to be created
+     * @return the value; never null
+     * @throws ValueFormatException if the conversion from a double could not be performed
+     */
+    T create( double value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a decimal.
+     * 
+     * @param value the decimal from which the value is to be created
+     * @return the value, or null if the supplied decimal is null
+     * @throws ValueFormatException if the conversion from a decimal could not be performed
+     */
+    T create( BigDecimal value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a Calendar instance.
+     * 
+     * @param value the Calendar instance from which the value is to be created
+     * @return the value, or null if the supplied Calendar is null
+     * @throws ValueFormatException if the conversion from a Calendar could not be performed
+     */
+    T create( Calendar value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a date.
+     * 
+     * @param value the date from which the value is to be created
+     * @return the value, or null if the supplied date is null
+     * @throws ValueFormatException if the conversion from a Date could not be performed
+     */
+    T create( Date value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a date-time instant.
+     * 
+     * @param value the date-time instant from which the value is to be created
+     * @return the value, or null if the supplied date is null
+     * @throws ValueFormatException if the conversion from a Date could not be performed
+     */
+    T create( DateTime value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a name.
+     * 
+     * @param value the name from which the value is to be created
+     * @return the value, or null if the supplied name is null
+     * @throws ValueFormatException if the conversion from a name could not be performed
+     */
+    T create( Name value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a path.
+     * 
+     * @param value the path from which the value is to be created
+     * @return the value, or null if the supplied path is null
+     * @throws ValueFormatException if the conversion from a path could not be performed
+     */
+    T create( Path value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a reference.
+     * 
+     * @param value the reference from which the value is to be created
+     * @return the value, or null if the supplied reference is null
+     * @throws ValueFormatException if the conversion from a reference could not be performed
+     */
+    T create( Reference value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a URI.
+     * 
+     * @param value the URI from which the value is to be created
+     * @return the value, or null if the supplied URI is null
+     * @throws ValueFormatException if the conversion from a URI could not be performed
+     */
+    T create( URI value ) throws ValueFormatException;
+
+    /**
+     * Create a value from a UUID.
+     * 
+     * @param value the UUID from which the value is to be created
+     * @return the value, or null if the supplied URI is null
+     * @throws ValueFormatException if the conversion from a UUID could not be performed
+     */
+    T create( UUID value ) throws ValueFormatException;
+
+    /**
+     * Create a value from the binary content given by the supplied array.
+     * 
+     * @param value the content to be used to create the value
+     * @return the value, or null if the supplied stream is null
+     * @throws ValueFormatException if the conversion from a byte array could not be performed
+     */
+    T create( byte[] value ) throws ValueFormatException;
+
+    /**
+     * Create a value from the binary content given by the supplied stream.
+     * 
+     * @param value the binary object to be used to create the value
+     * @return the value, or null if the supplied stream is null
+     * @throws ValueFormatException if the conversion from the binary object could not be performed
+     * @throws IoException If an unexpected problem occurs while accessing the supplied binary value (such as an
+     *         {@link IOException}).
+     */
+    T create( Binary value ) throws ValueFormatException, IoException;
+
+    /**
+     * Create a value from the binary content given by the supplied stream.
+     * 
+     * @param stream the stream containing the content to be used to create the value
+     * @param approximateLength the approximate length of the content (in bytes)
+     * @return the value, or null if the supplied stream is null
+     * @throws ValueFormatException if the conversion from an input stream could not be performed
+     * @throws IoException If an unexpected problem occurs while accessing the supplied stream (such as an {@link IOException}).
+     */
+    T create( InputStream stream,
+              long approximateLength ) throws ValueFormatException, IoException;
+
+    /**
+     * Create a value from a the binary content given by the supplied reader.
+     * 
+     * @param reader the reader containing the content to be used to create the value
+     * @param approximateLength the approximate length of the content (in bytes)
+     * @return the value, or null if the supplied string is null
+     * @throws ValueFormatException if the conversion from a reader could not be performed
+     * @throws IoException If an unexpected problem occurs while accessing the supplied reader (such as an {@link IOException}).
+     */
+    T create( Reader reader,
+              long approximateLength ) throws ValueFormatException, IoException;
+
+    /**
+     * Create a value from the specified information by determining which other <code>create</code> method applies and delegating
+     * to that method. Note that this method only will call <code>create</code> methods that take a single parameter; so this
+     * excludes {@link #create(InputStream, long)}, {@link #create(Reader, long)} and {@link #create(String, TextDecoder)}.
+     * 
+     * @param value the value
+     * @return the new value, or null if the supplied parameter is null
+     * @throws ValueFormatException if the conversion from an object could not be performed
+     * @throws IoException If an unexpected problem occurs while accessing the supplied binary value (such as an
+     *         {@link IOException}).
+     */
+    T create( Object value ) throws ValueFormatException, IoException;
+
+    /**
+     * Create an array of values from an array of string values, using no decoding.
+     * 
+     * @param values the values
+     * @return the values, or null if the supplied string is null
+     * @throws ValueFormatException if the conversion from a string array could not be performed
+     * @see #create(String[], TextDecoder)
+     */
+    T[] create( String[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of strings, using the supplied decoder.
+     * 
+     * @param values the string values from which the values are to be created
+     * @param decoder the decoder that should be used; if null, the {@link #DEFAULT_DECODER default decoder} is used
+     * @return the value, or null if the supplied string is null
+     * @throws ValueFormatException if the conversion from a string array could not be performed
+     * @see #create(String)
+     */
+    T[] create( String[] values,
+                TextDecoder decoder ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of integers.
+     * 
+     * @param values the integers from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an integer array could not be performed
+     */
+    T[] create( int[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of longs.
+     * 
+     * @param values the longs from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of longs could not be performed
+     */
+    T[] create( long[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of booleans.
+     * 
+     * @param values the booleans from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of booleans could not be performed
+     */
+    T[] create( boolean[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of floats.
+     * 
+     * @param values the floats from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of floats could not be performed
+     */
+    T[] create( float[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of doubles.
+     * 
+     * @param values the doubles from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of doubles could not be performed
+     */
+    T[] create( double[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of decimal values.
+     * 
+     * @param values the decimals from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of decimal values could not be performed
+     */
+    T[] create( BigDecimal[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of Calendar instances.
+     * 
+     * @param values the Calendar instances from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of calendar instances could not be performed
+     */
+    T[] create( Calendar[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of dates.
+     * 
+     * @param values the dates from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of date values could not be performed
+     */
+    T[] create( Date[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of {@link DateTime} instants.
+     * 
+     * @param values the instants from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of date values could not be performed
+     */
+    T[] create( DateTime[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of names.
+     * 
+     * @param values the names from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of names could not be performed
+     */
+    T[] create( Name[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of paths.
+     * 
+     * @param values the paths from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of paths could not be performed
+     */
+    T[] create( Path[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of references.
+     * 
+     * @param values the references from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of references could not be performed
+     */
+    T[] create( Reference[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of URIs.
+     * 
+     * @param values the URIs from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of URIs could not be performed
+     */
+    T[] create( URI[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from an array of UUIDs.
+     * 
+     * @param values the UUIDs from which the values are to be created
+     * @return the values, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of UUIDs could not be performed
+     */
+    T[] create( UUID[] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from the array of binary content.
+     * 
+     * @param values the array of content to be used to create the values
+     * @return the value, or null if the supplied array is null
+     * @throws ValueFormatException if the conversion from an array of byte arrays could not be performed
+     */
+    T[] create( byte[][] values ) throws ValueFormatException;
+
+    /**
+     * Create an array of values from the array of binary objects.
+     * 
+     * @param values the values
+     * @return the new value, or null if the supplied parameter is null
+     * @throws ValueFormatException if the conversion from an array of objects could not be performed
+     * @throws IoException If an unexpected problem occurs during the conversion.
+     */
+    T[] create( Binary[] values ) throws ValueFormatException, IoException;
+
+    /**
+     * Create an array of values from the specified information by determining which other <code>create</code> method applies for
+     * each object and then delegating to that method. Note that this method will not consider {@link #create(InputStream, long)},
+     * {@link #create(Reader, long)} and {@link #create(String, TextDecoder)}.
+     * 
+     * @param values the values
+     * @return the new value, or null if the supplied parameter is null
+     * @throws ValueFormatException if the conversion from an array of objects could not be performed
+     * @throws IoException If an unexpected problem occurs during the conversion.
+     */
+    T[] create( Object[] values ) throws ValueFormatException, IoException;
+
+    /**
+     * Create an iterator over the values (of an unknown type). The factory converts any values as required. Note that this method
+     * will not consider {@link #create(InputStream, long)}, {@link #create(Reader, long)} and
+     * {@link #create(String, TextDecoder)}.
+     * <p>
+     * This is useful to use when iterating over the {@link Property#getValues() values} of a {@link Property}.
+     * </p>
+     * 
+     * @param values the values
+     * @return the iterator of type <code>T</code> over the values, or null if the supplied parameter is null
+     * @throws ValueFormatException if the conversion from an iterator of objects could not be performed
+     * @throws IoException If an unexpected problem occurs during the conversion.
+     * @see Property#getValues()
+     */
+    Iterator<T> create( Iterator<?> values ) throws ValueFormatException, IoException;
+
+    /**
+     * Create an iterable with the values (of an unknown type). The factory converts any values as required. Note that this method
+     * will not consider {@link #create(InputStream, long)}, {@link #create(Reader, long)} and
+     * {@link #create(String, TextDecoder)}.
+     * <p>
+     * This is useful to use when converting all the {@link Property#getValues() values} of a {@link Property}.
+     * </p>
+     * Example:
+     * 
+     * <pre>
+     *      Property property = ...
+     *      ExecutionContext executionContext = ...
+     *      ValueFactory&lt;String&gt; stringFactory = executionContext.getValueFactories().getStringFactory();
+     *      for (String token : stringFactory.create(property)) {
+     *          ...
+     *      }
+     * </pre>
+     * 
+     * @param valueIterable the values
+     * @return the iterator of type <code>T</code> over the values, or null if the supplied parameter is null
+     * @throws ValueFormatException if the conversion from an iterator of objects could not be performed
+     * @throws IoException If an unexpected problem occurs during the conversion.
+     * @see Property#getValues()
+     */
+    Iterable<T> create( Iterable<?> valueIterable ) throws ValueFormatException, IoException;
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFactory.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFormatException.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/ValueFormatException.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFormatException.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFormatException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,112 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+/**
+ * @author Randall Hauch
+ */
+public class ValueFormatException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = 1L;
+
+    private final Object value;
+    private final PropertyType targetType;
+
+    /**
+     * @param value the value that was not able to be converted
+     * @param targetType the {@link PropertyType} to which the value was being converted
+     */
+    public ValueFormatException( Object value,
+                                 PropertyType targetType ) {
+        this.value = value;
+        this.targetType = targetType;
+    }
+
+    /**
+     * @param value the value that was not able to be converted
+     * @param targetType the {@link PropertyType} to which the value was being converted
+     * @param message the message
+     */
+    public ValueFormatException( Object value,
+                                 PropertyType targetType,
+                                 String message ) {
+        super(message);
+        this.value = value;
+        this.targetType = targetType;
+    }
+
+    /**
+     * @param value the value that was not able to be converted
+     * @param targetType the {@link PropertyType} to which the value was being converted
+     * @param cause the cause of the exception
+     */
+    public ValueFormatException( Object value,
+                                 PropertyType targetType,
+                                 Throwable cause ) {
+        super(cause);
+        this.value = value;
+        this.targetType = targetType;
+    }
+
+    /**
+     * @param value the value that was not able to be converted
+     * @param targetType the {@link PropertyType} to which the value was being converted
+     * @param message the message
+     * @param cause the cause of the exception
+     */
+    public ValueFormatException( Object value,
+                                 PropertyType targetType,
+                                 String message,
+                                 Throwable cause ) {
+        super(message, cause);
+        this.value = value;
+        this.targetType = targetType;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+
+    /**
+     * Get the {@link PropertyType} to which the {@link #getValue() value} was being converted.
+     * 
+     * @return the target type
+     */
+    public PropertyType getTargetType() {
+        return targetType;
+    }
+
+    /**
+     * Get the original value that was being converted.
+     * 
+     * @return the value
+     */
+    public Object getValue() {
+        return value;
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueFormatException.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic)

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractBinary.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,140 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.NoSuchAlgorithmException;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.Base64;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.common.util.SecureHash;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.ValueComparators;
-
-/**
- * An abstract implementation of {@link Binary} that provides some common capabilities for other implementations.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public abstract class AbstractBinary implements Binary {
-
-    protected static final Set<String> ALGORITHMS_NOT_FOUND_AND_LOGGED = new CopyOnWriteArraySet<String>();
-    private static final SecureHash.Algorithm ALGORITHM = SecureHash.Algorithm.SHA_1;
-    private static final byte[] NO_HASH = new byte[] {};
-
-    protected static final byte[] EMPTY_CONTENT = new byte[0];
-
-    /**
-     * Version {@value} .
-     */
-    private static final long serialVersionUID = 1L;
-
-    protected AbstractBinary() {
-    }
-
-    protected byte[] computeHash( byte[] content ) {
-        try {
-            return SecureHash.getHash(ALGORITHM, content);
-        } catch (NoSuchAlgorithmException e) {
-            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
-                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
-            }
-            return NO_HASH;
-        }
-    }
-
-    protected byte[] computeHash( File file ) {
-        try {
-            return SecureHash.getHash(ALGORITHM, file);
-        } catch (NoSuchAlgorithmException e) {
-            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
-                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
-            }
-            return NO_HASH;
-        } catch (IOException e) {
-            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
-                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
-            }
-            return NO_HASH;
-        }
-    }
-
-    protected byte[] computeHash( InputStream stream ) {
-        try {
-            return SecureHash.getHash(ALGORITHM, stream);
-        } catch (NoSuchAlgorithmException e) {
-            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
-                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
-            }
-            return NO_HASH;
-        } catch (IOException e) {
-            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
-                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
-            }
-            return NO_HASH;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int compareTo( Binary o ) {
-        return ValueComparators.BINARY_COMPARATOR.compare(this, o);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof Binary) {
-            Binary that = (Binary)obj;
-            if (this.getSize() != that.getSize()) return false;
-            return ValueComparators.BINARY_COMPARATOR.compare(this, that) == 0;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        try {
-            acquire();
-            StringBuilder sb = new StringBuilder(super.toString());
-            sb.append(" len=").append(getSize()).append("; [");
-            sb.append(Base64.encodeBytes(getBytes()));
-            return sb.toString();
-        } finally {
-            release();
-        }
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractBinary.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,140 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.NoSuchAlgorithmException;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.Base64;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.common.util.SecureHash;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.ValueComparators;
+
+/**
+ * An abstract implementation of {@link Binary} that provides some common capabilities for other implementations.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public abstract class AbstractBinary implements Binary {
+
+    protected static final Set<String> ALGORITHMS_NOT_FOUND_AND_LOGGED = new CopyOnWriteArraySet<String>();
+    private static final SecureHash.Algorithm ALGORITHM = SecureHash.Algorithm.SHA_1;
+    private static final byte[] NO_HASH = new byte[] {};
+
+    protected static final byte[] EMPTY_CONTENT = new byte[0];
+
+    /**
+     * Version {@value} .
+     */
+    private static final long serialVersionUID = 1L;
+
+    protected AbstractBinary() {
+    }
+
+    protected byte[] computeHash( byte[] content ) {
+        try {
+            return SecureHash.getHash(ALGORITHM, content);
+        } catch (NoSuchAlgorithmException e) {
+            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
+                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
+            }
+            return NO_HASH;
+        }
+    }
+
+    protected byte[] computeHash( File file ) {
+        try {
+            return SecureHash.getHash(ALGORITHM, file);
+        } catch (NoSuchAlgorithmException e) {
+            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
+                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
+            }
+            return NO_HASH;
+        } catch (IOException e) {
+            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
+                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
+            }
+            return NO_HASH;
+        }
+    }
+
+    protected byte[] computeHash( InputStream stream ) {
+        try {
+            return SecureHash.getHash(ALGORITHM, stream);
+        } catch (NoSuchAlgorithmException e) {
+            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
+                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
+            }
+            return NO_HASH;
+        } catch (IOException e) {
+            if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(ALGORITHM.digestName())) {
+                Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, ALGORITHM.digestName());
+            }
+            return NO_HASH;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( Binary o ) {
+        return ValueComparators.BINARY_COMPARATOR.compare(this, o);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof Binary) {
+            Binary that = (Binary)obj;
+            if (this.getSize() != that.getSize()) return false;
+            return ValueComparators.BINARY_COMPARATOR.compare(this, that) == 0;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        try {
+            acquire();
+            StringBuilder sb = new StringBuilder(super.toString());
+            sb.append(" len=").append(getSize()).append("; [");
+            sb.append(Base64.encodeBytes(getBytes()));
+            return sb.toString();
+        } finally {
+            release();
+        }
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinaryValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractBinaryValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinaryValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,312 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.util.IoUtil;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.BinaryFactory;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * An abstract {@link BinaryFactory} implementation that contains many general methods that are likely to be appropriate for many
- * concrete implementations.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public abstract class AbstractBinaryValueFactory extends AbstractValueFactory<Binary> implements BinaryFactory {
-
-    private static final String CHAR_SET_NAME = "UTF-8";
-
-    protected AbstractBinaryValueFactory( TextDecoder decoder,
-                                          ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.BINARY, decoder, stringValueFactory);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( String value ) {
-        if (value == null) return null;
-        try {
-            return create(value.getBytes(CHAR_SET_NAME));
-        } catch (UnsupportedEncodingException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                              Binary.class.getSimpleName(),
-                                                                              value), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( String value,
-                          TextDecoder decoder ) {
-        if (value == null) return null;
-        return create(getDecoder(decoder).decode(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( int value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( long value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( boolean value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( float value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( double value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( BigDecimal value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( Calendar value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( Date value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public Binary create( DateTime value ) throws ValueFormatException {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( Name value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( Path value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( Reference value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( URI value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public Binary create( UUID value ) {
-        // Convert the value to a string, then to a binary ...
-        return create(this.getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public Binary create( Binary value ) throws ValueFormatException, IoException {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( InputStream stream,
-                          long approximateLength ) throws IoException {
-        if (stream == null) return null;
-        try {
-            byte[] value = IoUtil.readBytes(stream);
-            return create(value);
-        } catch (IOException err) {
-            throw new IoException(GraphI18n.errorConvertingIo.text(InputStream.class.getSimpleName(),
-                                                                   Binary.class.getSimpleName()), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( Reader reader,
-                          long approximateLength ) throws IoException {
-        if (reader == null) return null;
-        // Convert the value to a string, then to a binary ...
-        try {
-            String value = IoUtil.read(reader);
-            return create(this.getStringValueFactory().create(value));
-        } catch (IOException err) {
-            throw new IoException(GraphI18n.errorConvertingIo.text(Reader.class.getSimpleName(), Binary.class.getSimpleName()),
-                                  err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.BinaryFactory#create(java.io.File)
-     */
-    public Binary create( File file ) throws ValueFormatException, IoException {
-        if (file == null) return null;
-        if (!file.canRead()) return null;
-        if (!file.isFile()) return null;
-        try {
-            byte[] value = IoUtil.readBytes(file);
-            return create(value);
-        } catch (IOException err) {
-            throw new IoException(GraphI18n.errorConvertingIo.text(file, Binary.class.getSimpleName()), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * This implementation does not manage or share the in-memory binary values, so this implementation is identical to calling
-     * {@link #create(Reader, long)}.
-     * </p>
-     * 
-     * @see org.jboss.dna.graph.properties.BinaryFactory#create(java.io.Reader, long, byte[])
-     */
-    public Binary create( Reader reader,
-                          long approximateLength,
-                          byte[] secureHash ) throws ValueFormatException, IoException {
-        return create(reader, approximateLength);
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * This implementation does not manage or share the in-memory binary values, so this implementation is identical to calling
-     * {@link #create(InputStream, long)}.
-     * </p>
-     * 
-     * @see org.jboss.dna.graph.properties.BinaryFactory#create(java.io.InputStream, long, byte[])
-     */
-    public Binary create( InputStream stream,
-                          long approximateLength,
-                          byte[] secureHash ) throws ValueFormatException, IoException {
-        return create(stream, approximateLength);
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * This method always returns null, since the in-memory binary values are not managed or shared.
-     * </p>
-     * 
-     * @see org.jboss.dna.graph.properties.BinaryFactory#find(byte[])
-     */
-    public Binary find( byte[] secureHash ) {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Binary[] createEmptyArray( int length ) {
-        return new Binary[length];
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinaryValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractBinaryValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinaryValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinaryValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,312 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.util.IoUtil;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.BinaryFactory;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * An abstract {@link BinaryFactory} implementation that contains many general methods that are likely to be appropriate for many
+ * concrete implementations.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public abstract class AbstractBinaryValueFactory extends AbstractValueFactory<Binary> implements BinaryFactory {
+
+    private static final String CHAR_SET_NAME = "UTF-8";
+
+    protected AbstractBinaryValueFactory( TextDecoder decoder,
+                                          ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.BINARY, decoder, stringValueFactory);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( String value ) {
+        if (value == null) return null;
+        try {
+            return create(value.getBytes(CHAR_SET_NAME));
+        } catch (UnsupportedEncodingException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                              Binary.class.getSimpleName(),
+                                                                              value), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( String value,
+                          TextDecoder decoder ) {
+        if (value == null) return null;
+        return create(getDecoder(decoder).decode(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( int value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( long value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( boolean value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( float value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( double value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( BigDecimal value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( Calendar value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( Date value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public Binary create( DateTime value ) throws ValueFormatException {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( Name value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( Path value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( Reference value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( URI value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public Binary create( UUID value ) {
+        // Convert the value to a string, then to a binary ...
+        return create(this.getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public Binary create( Binary value ) throws ValueFormatException, IoException {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( InputStream stream,
+                          long approximateLength ) throws IoException {
+        if (stream == null) return null;
+        try {
+            byte[] value = IoUtil.readBytes(stream);
+            return create(value);
+        } catch (IOException err) {
+            throw new IoException(GraphI18n.errorConvertingIo.text(InputStream.class.getSimpleName(),
+                                                                   Binary.class.getSimpleName()), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( Reader reader,
+                          long approximateLength ) throws IoException {
+        if (reader == null) return null;
+        // Convert the value to a string, then to a binary ...
+        try {
+            String value = IoUtil.read(reader);
+            return create(this.getStringValueFactory().create(value));
+        } catch (IOException err) {
+            throw new IoException(GraphI18n.errorConvertingIo.text(Reader.class.getSimpleName(), Binary.class.getSimpleName()),
+                                  err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.BinaryFactory#create(java.io.File)
+     */
+    public Binary create( File file ) throws ValueFormatException, IoException {
+        if (file == null) return null;
+        if (!file.canRead()) return null;
+        if (!file.isFile()) return null;
+        try {
+            byte[] value = IoUtil.readBytes(file);
+            return create(value);
+        } catch (IOException err) {
+            throw new IoException(GraphI18n.errorConvertingIo.text(file, Binary.class.getSimpleName()), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * This implementation does not manage or share the in-memory binary values, so this implementation is identical to calling
+     * {@link #create(Reader, long)}.
+     * </p>
+     * 
+     * @see org.jboss.dna.graph.property.BinaryFactory#create(java.io.Reader, long, byte[])
+     */
+    public Binary create( Reader reader,
+                          long approximateLength,
+                          byte[] secureHash ) throws ValueFormatException, IoException {
+        return create(reader, approximateLength);
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * This implementation does not manage or share the in-memory binary values, so this implementation is identical to calling
+     * {@link #create(InputStream, long)}.
+     * </p>
+     * 
+     * @see org.jboss.dna.graph.property.BinaryFactory#create(java.io.InputStream, long, byte[])
+     */
+    public Binary create( InputStream stream,
+                          long approximateLength,
+                          byte[] secureHash ) throws ValueFormatException, IoException {
+        return create(stream, approximateLength);
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * This method always returns null, since the in-memory binary values are not managed or shared.
+     * </p>
+     * 
+     * @see org.jboss.dna.graph.property.BinaryFactory#find(byte[])
+     */
+    public Binary find( byte[] secureHash ) {
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Binary[] createEmptyArray( int length ) {
+        return new Binary[length];
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractPath.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,518 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import org.jboss.dna.common.CommonI18n;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-
-/**
- * An abstract foundation for different {@link Path} implementations. This class does not manage any of the {@link Path}'s state,
- * but it does provide implementations for most of the methods based upon a few abstract methods. For example, any implementaton
- * that requires the {@link Path.Segment path's segments} are written to use the {@link #iterator()}, since that is likely more
- * efficient for the majority of implementations.
- * 
- * @author Randall Hauch
- */
-public abstract class AbstractPath implements Path {
-
-    /**
-     * The initial serializable version. Version {@value}
-     */
-    private static final long serialVersionUID = 1L;
-
-    public static final Path SELF_PATH = new BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
-
-    private transient int hc = 0;
-
-    protected boolean isNormalized( List<Segment> segments ) {
-        for (Segment segment : segments) {
-            if (segment.isSelfReference() || segment.isParentReference()) return false;
-        }
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getCanonicalPath()
-     */
-    public Path getCanonicalPath() {
-        if (!this.isAbsolute()) {
-            String msg = GraphI18n.pathIsNotAbsolute.text(this);
-            throw new InvalidPathException(msg);
-        }
-        if (this.isNormalized()) return this;
-        return this.getNormalizedPath();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path getCommonAncestor( Path that ) {
-        CheckArg.isNotNull(that, "that");
-        if (that.isRoot()) return that;
-        Path normalizedPath = this.getNormalizedPath();
-        int lastIndex = 0;
-        Iterator<Segment> thisIter = normalizedPath.iterator();
-        Iterator<Segment> thatIter = that.getNormalizedPath().iterator();
-        while (thisIter.hasNext() && thatIter.hasNext()) {
-            Segment thisSeg = thisIter.next();
-            Segment thatSeg = thatIter.next();
-            if (thisSeg.equals(thatSeg)) {
-                ++lastIndex;
-            } else {
-                break;
-            }
-        }
-        if (lastIndex == 0) return RootPath.INSTANCE;
-        return normalizedPath.subpath(0, lastIndex);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path.Segment getLastSegment() {
-        return this.getSegmentsList().get(size() - 1);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getParent()
-     */
-    public Path getParent() {
-        return getAncestor(1);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Segment getSegment( int index ) {
-        CheckArg.isNonNegative(index, "index");
-        return this.getSegmentsList().get(index);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Segment[] getSegmentsArray() {
-        // By default, make a new array every time since arrays are mutable, and use the iterator
-        // since that is probably more efficient than creating a list ...
-        Segment[] result = new Path.Segment[size()];
-        int i = 0;
-        for (Segment segment : this) {
-            result[i] = segment;
-            ++i;
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path getNormalizedPath() {
-        if (this.isNormalized()) return this;
-        LinkedList<Segment> newSegments = new LinkedList<Segment>();
-        for (Segment segment : this) {
-            if (segment.isSelfReference()) continue;
-            if (segment.isParentReference()) {
-                if (newSegments.isEmpty()) {
-                    if (this.isAbsolute()) {
-                        throw new InvalidPathException(CommonI18n.pathCannotBeNormalized.text(this));
-                    }
-                } else if (!newSegments.getLast().isParentReference()) {
-                    newSegments.removeLast();
-                    continue;
-                }
-            }
-            newSegments.add(segment);
-        }
-        if (newSegments.isEmpty()) {
-            if (this.isAbsolute()) return RootPath.INSTANCE;
-            // Otherwise relative and it had contained nothing but self references ...
-            return SELF_PATH;
-        }
-        return new BasicPath(newSegments, this.isAbsolute());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString() {
-        return doGetString(null, DEFAULT_ENCODER, null);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( TextEncoder encoder ) {
-        return doGetString(null, encoder, null);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( NamespaceRegistry namespaceRegistry ) {
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        return doGetString(namespaceRegistry, null, null);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder ) {
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        return doGetString(namespaceRegistry, encoder, null);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
-     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder,
-                             TextEncoder delimiterEncoder ) {
-        return doGetString(namespaceRegistry, encoder, delimiterEncoder);
-    }
-
-    /**
-     * Method that creates the string representation. This method works two different ways depending upon whether the namespace
-     * registry is provided.
-     * 
-     * @param namespaceRegistry
-     * @param encoder
-     * @param delimiterEncoder
-     * @return this path as a string
-     */
-    protected String doGetString( NamespaceRegistry namespaceRegistry,
-                                  TextEncoder encoder,
-                                  TextEncoder delimiterEncoder ) {
-        if (encoder == null) encoder = DEFAULT_ENCODER;
-        final String delimiter = delimiterEncoder != null ? delimiterEncoder.encode(DELIMITER_STR) : DELIMITER_STR;
-
-        // Since the segments are immutable, this code need not be synchronized because concurrent threads
-        // may just compute the same value (with no harm done)
-        StringBuilder sb = new StringBuilder();
-        if (this.isAbsolute()) sb.append(delimiter);
-        boolean first = true;
-        for (Segment segment : this) {
-            if (first) {
-                first = false;
-            } else {
-                sb.append(delimiter);
-            }
-            assert segment != null;
-            sb.append(segment.getString(namespaceRegistry, encoder, delimiterEncoder));
-        }
-        String result = sb.toString();
-        // Save the result to the internal string if this the default encoder is used.
-        // This is not synchronized, but it's okay
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean hasSameAncestor( Path that ) {
-        CheckArg.isNotNull(that, "that");
-        if (that.size() != this.size()) return false;
-        if (this.size() == 1) return true; // both nodes are just under the root
-        for (int i = this.size() - 2; i >= 0; --i) {
-            Path.Segment thisSegment = this.getSegment(i);
-            Path.Segment thatSegment = that.getSegment(i);
-            if (!thisSegment.equals(thatSegment)) return false;
-        }
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isAncestorOf( Path decendant ) {
-        CheckArg.isNotNull(decendant, "that");
-        if (this == decendant) return false;
-        if (this.size() >= decendant.size()) return false;
-
-        Iterator<Path.Segment> thisIter = this.iterator();
-        Iterator<Path.Segment> thatIter = decendant.iterator();
-        while (thisIter.hasNext()) {
-            Path.Segment thisSeg = thisIter.next();
-            Path.Segment thatSeg = thatIter.next();
-            if (!thisSeg.equals(thatSeg)) return false;
-        }
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isAtOrBelow(org.jboss.dna.graph.properties.Path)
-     */
-    public boolean isAtOrBelow( Path other ) {
-        CheckArg.isNotNull(other, "other");
-        if (this == other) return true;
-        if (other.isRoot()) return true;
-        if (other.size() > this.size()) return false;
-        Iterator<Segment> thisIter = iterator();
-        Iterator<Segment> thatIter = other.iterator();
-        while (thisIter.hasNext() && thatIter.hasNext()) {
-            if (!thisIter.next().equals(thatIter.next())) return false;
-        }
-        if (thatIter.hasNext()) return false; // The other still has segments, but this doesn't
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isAtOrAbove(org.jboss.dna.graph.properties.Path)
-     */
-    public boolean isAtOrAbove( Path other ) {
-        CheckArg.isNotNull(other, "other");
-        if (this == other) return true;
-        if (this.size() > other.size()) return false;
-        Iterator<Segment> thisIter = iterator();
-        Iterator<Segment> thatIter = other.iterator();
-        while (thisIter.hasNext() && thatIter.hasNext()) {
-            if (!thisIter.next().equals(thatIter.next())) return false;
-        }
-        if (thisIter.hasNext()) return false; // This still has segments, but other doesn't
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isDecendantOf( Path ancestor ) {
-        CheckArg.isNotNull(ancestor, "ancestor");
-        return ancestor.isAncestorOf(this);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isSameAs( Path other ) {
-        return other != null && this.compareTo(other) == 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<Segment> iterator() {
-        return getSegmentsList().iterator();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path relativeTo( Path startingPath ) {
-        CheckArg.isNotNull(startingPath, "to");
-        if (!this.isAbsolute()) {
-            String msg = GraphI18n.pathIsNotAbsolute.text(this);
-            throw new InvalidPathException(msg);
-        }
-        if (!startingPath.isAbsolute()) {
-            String msg = GraphI18n.pathIsNotAbsolute.text(startingPath);
-            throw new InvalidPathException(msg);
-        }
-
-        // Count the number of segments up to the common ancestor (relative path is what remains) ...
-        int lengthOfCommonAncestor = 0;
-        Iterator<Segment> thisIter = this.getNormalizedPath().iterator();
-        Iterator<Segment> toIter = startingPath.getNormalizedPath().iterator();
-        while (thisIter.hasNext() && toIter.hasNext()) {
-            Segment thisSeg = thisIter.next();
-            Segment toSeg = toIter.next();
-            if (thisSeg.equals(toSeg)) {
-                ++lengthOfCommonAncestor;
-            } else {
-                break;
-            }
-        }
-        // Create the relative path, starting with parent references to the common ancestor ...
-        int numberOfParentReferences = startingPath.size() - lengthOfCommonAncestor;
-        List<Segment> relativeSegments = new ArrayList<Segment>();
-        for (int i = 0; i != numberOfParentReferences; ++i) {
-            relativeSegments.add(Path.PARENT_SEGMENT);
-        }
-        // Add the segments of this path from the common ancestor ...
-        for (int i = lengthOfCommonAncestor; i < this.size(); ++i) {
-            relativeSegments.add(getSegment(i));
-        }
-        if (relativeSegments.isEmpty()) {
-            relativeSegments.add(Path.SELF_SEGMENT);
-        }
-        return new BasicPath(relativeSegments, false);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path resolve( Path relativePath ) {
-        CheckArg.isNotNull(relativePath, "relative path");
-        if (!this.isAbsolute()) {
-            String msg = GraphI18n.pathIsNotAbsolute.text(this);
-            throw new InvalidPathException(msg);
-        }
-        if (relativePath.isAbsolute()) {
-            String msg = GraphI18n.pathIsNotRelative.text(relativePath);
-            throw new InvalidPathException(msg);
-        }
-        // If the relative path is the self or parent reference ...
-        relativePath = relativePath.getNormalizedPath();
-        if (relativePath.size() == 1) {
-            Segment onlySegment = relativePath.getSegment(0);
-            if (onlySegment.isSelfReference()) return this;
-            if (onlySegment.isParentReference()) return this.getParent();
-        }
-        List<Segment> segments = new ArrayList<Segment>(this.size() + relativePath.size());
-        for (Segment segment : this) {
-            segments.add(segment);
-        }
-        for (Segment segment : relativePath) {
-            segments.add(segment);
-        }
-        return new BasicPath(segments, true).getNormalizedPath();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path resolveAgainst( Path absolutePath ) {
-        CheckArg.isNotNull(absolutePath, "absolute path");
-        return absolutePath.resolve(this);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path subpath( int beginIndex ) {
-        return subpath(beginIndex, size());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path subpath( int beginIndex,
-                         int endIndex ) {
-        CheckArg.isNonNegative(beginIndex, "beginIndex");
-        CheckArg.isNonNegative(endIndex, "endIndex");
-        int size = size();
-        if (beginIndex == 0) {
-            if (endIndex == 0) return RootPath.INSTANCE;
-            if (endIndex == size) return this;
-        }
-        if (beginIndex >= size) {
-            throw new IndexOutOfBoundsException(
-                                                GraphI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToSize.text(beginIndex,
-                                                                                                                       size));
-        }
-        if (beginIndex > endIndex) {
-            throw new IndexOutOfBoundsException(
-                                                GraphI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex.text(beginIndex,
-                                                                                                                              endIndex));
-        }
-        // This reuses the same list, so it's pretty efficient ...
-        return new BasicPath(createSegmentsSubList(beginIndex, endIndex), this.isAbsolute());
-    }
-
-    protected List<Segment> createSegmentsSubList( int validBeginIndex,
-                                                   int validEndIndex ) {
-        return this.getSegmentsList().subList(validBeginIndex, validEndIndex);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        if (hc == 0) {
-            int hashCode = 1;
-            for (Segment segment : this) {
-                hashCode = 31 * hashCode + segment.hashCode();
-            }
-            hc = hashCode;
-        }
-        return hc;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof Path) {
-            Path that = (Path)obj;
-            if (this.size() != that.size()) return false;
-            if (this.hashCode() != that.hashCode()) return false;
-            Iterator<Segment> thisIter = this.iterator();
-            Iterator<Segment> thatIter = that.iterator();
-            while (thisIter.hasNext()) {
-                Segment thisSegment = thisIter.next();
-                Segment thatSegment = thatIter.next();
-                if (!thisSegment.equals(thatSegment)) return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int compareTo( Path that ) {
-        if (this == that) return 0;
-        Iterator<Segment> thisIter = getSegmentsList().iterator();
-        Iterator<Segment> thatIter = that.iterator();
-        while (thisIter.hasNext() && thatIter.hasNext()) {
-            Segment thisSegment = thisIter.next();
-            Segment thatSegment = thatIter.next();
-            int diff = thisSegment.compareTo(thatSegment);
-            if (diff != 0) return diff;
-        }
-        if (thisIter.hasNext()) return 1;
-        if (thatIter.hasNext()) return -1;
-        return 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return getString(Path.URL_ENCODER);
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractPath.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,518 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.jboss.dna.common.CommonI18n;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * An abstract foundation for different {@link Path} implementations. This class does not manage any of the {@link Path}'s state,
+ * but it does provide implementations for most of the methods based upon a few abstract methods. For example, any implementaton
+ * that requires the {@link Path.Segment path's segments} are written to use the {@link #iterator()}, since that is likely more
+ * efficient for the majority of implementations.
+ * 
+ * @author Randall Hauch
+ */
+public abstract class AbstractPath implements Path {
+
+    /**
+     * The initial serializable version. Version {@value}
+     */
+    private static final long serialVersionUID = 1L;
+
+    public static final Path SELF_PATH = new BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
+
+    private transient int hc = 0;
+
+    protected boolean isNormalized( List<Segment> segments ) {
+        for (Segment segment : segments) {
+            if (segment.isSelfReference() || segment.isParentReference()) return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getCanonicalPath()
+     */
+    public Path getCanonicalPath() {
+        if (!this.isAbsolute()) {
+            String msg = GraphI18n.pathIsNotAbsolute.text(this);
+            throw new InvalidPathException(msg);
+        }
+        if (this.isNormalized()) return this;
+        return this.getNormalizedPath();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path getCommonAncestor( Path that ) {
+        CheckArg.isNotNull(that, "that");
+        if (that.isRoot()) return that;
+        Path normalizedPath = this.getNormalizedPath();
+        int lastIndex = 0;
+        Iterator<Segment> thisIter = normalizedPath.iterator();
+        Iterator<Segment> thatIter = that.getNormalizedPath().iterator();
+        while (thisIter.hasNext() && thatIter.hasNext()) {
+            Segment thisSeg = thisIter.next();
+            Segment thatSeg = thatIter.next();
+            if (thisSeg.equals(thatSeg)) {
+                ++lastIndex;
+            } else {
+                break;
+            }
+        }
+        if (lastIndex == 0) return RootPath.INSTANCE;
+        return normalizedPath.subpath(0, lastIndex);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path.Segment getLastSegment() {
+        return this.getSegmentsList().get(size() - 1);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getParent()
+     */
+    public Path getParent() {
+        return getAncestor(1);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Segment getSegment( int index ) {
+        CheckArg.isNonNegative(index, "index");
+        return this.getSegmentsList().get(index);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Segment[] getSegmentsArray() {
+        // By default, make a new array every time since arrays are mutable, and use the iterator
+        // since that is probably more efficient than creating a list ...
+        Segment[] result = new Path.Segment[size()];
+        int i = 0;
+        for (Segment segment : this) {
+            result[i] = segment;
+            ++i;
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path getNormalizedPath() {
+        if (this.isNormalized()) return this;
+        LinkedList<Segment> newSegments = new LinkedList<Segment>();
+        for (Segment segment : this) {
+            if (segment.isSelfReference()) continue;
+            if (segment.isParentReference()) {
+                if (newSegments.isEmpty()) {
+                    if (this.isAbsolute()) {
+                        throw new InvalidPathException(CommonI18n.pathCannotBeNormalized.text(this));
+                    }
+                } else if (!newSegments.getLast().isParentReference()) {
+                    newSegments.removeLast();
+                    continue;
+                }
+            }
+            newSegments.add(segment);
+        }
+        if (newSegments.isEmpty()) {
+            if (this.isAbsolute()) return RootPath.INSTANCE;
+            // Otherwise relative and it had contained nothing but self references ...
+            return SELF_PATH;
+        }
+        return new BasicPath(newSegments, this.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString() {
+        return doGetString(null, DEFAULT_ENCODER, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( TextEncoder encoder ) {
+        return doGetString(null, encoder, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( NamespaceRegistry namespaceRegistry ) {
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        return doGetString(namespaceRegistry, null, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder ) {
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        return doGetString(namespaceRegistry, encoder, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getString(org.jboss.dna.graph.property.NamespaceRegistry,
+     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder,
+                             TextEncoder delimiterEncoder ) {
+        return doGetString(namespaceRegistry, encoder, delimiterEncoder);
+    }
+
+    /**
+     * Method that creates the string representation. This method works two different ways depending upon whether the namespace
+     * registry is provided.
+     * 
+     * @param namespaceRegistry
+     * @param encoder
+     * @param delimiterEncoder
+     * @return this path as a string
+     */
+    protected String doGetString( NamespaceRegistry namespaceRegistry,
+                                  TextEncoder encoder,
+                                  TextEncoder delimiterEncoder ) {
+        if (encoder == null) encoder = DEFAULT_ENCODER;
+        final String delimiter = delimiterEncoder != null ? delimiterEncoder.encode(DELIMITER_STR) : DELIMITER_STR;
+
+        // Since the segments are immutable, this code need not be synchronized because concurrent threads
+        // may just compute the same value (with no harm done)
+        StringBuilder sb = new StringBuilder();
+        if (this.isAbsolute()) sb.append(delimiter);
+        boolean first = true;
+        for (Segment segment : this) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(delimiter);
+            }
+            assert segment != null;
+            sb.append(segment.getString(namespaceRegistry, encoder, delimiterEncoder));
+        }
+        String result = sb.toString();
+        // Save the result to the internal string if this the default encoder is used.
+        // This is not synchronized, but it's okay
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasSameAncestor( Path that ) {
+        CheckArg.isNotNull(that, "that");
+        if (that.size() != this.size()) return false;
+        if (this.size() == 1) return true; // both nodes are just under the root
+        for (int i = this.size() - 2; i >= 0; --i) {
+            Path.Segment thisSegment = this.getSegment(i);
+            Path.Segment thatSegment = that.getSegment(i);
+            if (!thisSegment.equals(thatSegment)) return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAncestorOf( Path decendant ) {
+        CheckArg.isNotNull(decendant, "that");
+        if (this == decendant) return false;
+        if (this.size() >= decendant.size()) return false;
+
+        Iterator<Path.Segment> thisIter = this.iterator();
+        Iterator<Path.Segment> thatIter = decendant.iterator();
+        while (thisIter.hasNext()) {
+            Path.Segment thisSeg = thisIter.next();
+            Path.Segment thatSeg = thatIter.next();
+            if (!thisSeg.equals(thatSeg)) return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isAtOrBelow(org.jboss.dna.graph.property.Path)
+     */
+    public boolean isAtOrBelow( Path other ) {
+        CheckArg.isNotNull(other, "other");
+        if (this == other) return true;
+        if (other.isRoot()) return true;
+        if (other.size() > this.size()) return false;
+        Iterator<Segment> thisIter = iterator();
+        Iterator<Segment> thatIter = other.iterator();
+        while (thisIter.hasNext() && thatIter.hasNext()) {
+            if (!thisIter.next().equals(thatIter.next())) return false;
+        }
+        if (thatIter.hasNext()) return false; // The other still has segments, but this doesn't
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isAtOrAbove(org.jboss.dna.graph.property.Path)
+     */
+    public boolean isAtOrAbove( Path other ) {
+        CheckArg.isNotNull(other, "other");
+        if (this == other) return true;
+        if (this.size() > other.size()) return false;
+        Iterator<Segment> thisIter = iterator();
+        Iterator<Segment> thatIter = other.iterator();
+        while (thisIter.hasNext() && thatIter.hasNext()) {
+            if (!thisIter.next().equals(thatIter.next())) return false;
+        }
+        if (thisIter.hasNext()) return false; // This still has segments, but other doesn't
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isDecendantOf( Path ancestor ) {
+        CheckArg.isNotNull(ancestor, "ancestor");
+        return ancestor.isAncestorOf(this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isSameAs( Path other ) {
+        return other != null && this.compareTo(other) == 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<Segment> iterator() {
+        return getSegmentsList().iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path relativeTo( Path startingPath ) {
+        CheckArg.isNotNull(startingPath, "to");
+        if (!this.isAbsolute()) {
+            String msg = GraphI18n.pathIsNotAbsolute.text(this);
+            throw new InvalidPathException(msg);
+        }
+        if (!startingPath.isAbsolute()) {
+            String msg = GraphI18n.pathIsNotAbsolute.text(startingPath);
+            throw new InvalidPathException(msg);
+        }
+
+        // Count the number of segments up to the common ancestor (relative path is what remains) ...
+        int lengthOfCommonAncestor = 0;
+        Iterator<Segment> thisIter = this.getNormalizedPath().iterator();
+        Iterator<Segment> toIter = startingPath.getNormalizedPath().iterator();
+        while (thisIter.hasNext() && toIter.hasNext()) {
+            Segment thisSeg = thisIter.next();
+            Segment toSeg = toIter.next();
+            if (thisSeg.equals(toSeg)) {
+                ++lengthOfCommonAncestor;
+            } else {
+                break;
+            }
+        }
+        // Create the relative path, starting with parent references to the common ancestor ...
+        int numberOfParentReferences = startingPath.size() - lengthOfCommonAncestor;
+        List<Segment> relativeSegments = new ArrayList<Segment>();
+        for (int i = 0; i != numberOfParentReferences; ++i) {
+            relativeSegments.add(Path.PARENT_SEGMENT);
+        }
+        // Add the segments of this path from the common ancestor ...
+        for (int i = lengthOfCommonAncestor; i < this.size(); ++i) {
+            relativeSegments.add(getSegment(i));
+        }
+        if (relativeSegments.isEmpty()) {
+            relativeSegments.add(Path.SELF_SEGMENT);
+        }
+        return new BasicPath(relativeSegments, false);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path resolve( Path relativePath ) {
+        CheckArg.isNotNull(relativePath, "relative path");
+        if (!this.isAbsolute()) {
+            String msg = GraphI18n.pathIsNotAbsolute.text(this);
+            throw new InvalidPathException(msg);
+        }
+        if (relativePath.isAbsolute()) {
+            String msg = GraphI18n.pathIsNotRelative.text(relativePath);
+            throw new InvalidPathException(msg);
+        }
+        // If the relative path is the self or parent reference ...
+        relativePath = relativePath.getNormalizedPath();
+        if (relativePath.size() == 1) {
+            Segment onlySegment = relativePath.getSegment(0);
+            if (onlySegment.isSelfReference()) return this;
+            if (onlySegment.isParentReference()) return this.getParent();
+        }
+        List<Segment> segments = new ArrayList<Segment>(this.size() + relativePath.size());
+        for (Segment segment : this) {
+            segments.add(segment);
+        }
+        for (Segment segment : relativePath) {
+            segments.add(segment);
+        }
+        return new BasicPath(segments, true).getNormalizedPath();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path resolveAgainst( Path absolutePath ) {
+        CheckArg.isNotNull(absolutePath, "absolute path");
+        return absolutePath.resolve(this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path subpath( int beginIndex ) {
+        return subpath(beginIndex, size());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path subpath( int beginIndex,
+                         int endIndex ) {
+        CheckArg.isNonNegative(beginIndex, "beginIndex");
+        CheckArg.isNonNegative(endIndex, "endIndex");
+        int size = size();
+        if (beginIndex == 0) {
+            if (endIndex == 0) return RootPath.INSTANCE;
+            if (endIndex == size) return this;
+        }
+        if (beginIndex >= size) {
+            throw new IndexOutOfBoundsException(
+                                                GraphI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToSize.text(beginIndex,
+                                                                                                                       size));
+        }
+        if (beginIndex > endIndex) {
+            throw new IndexOutOfBoundsException(
+                                                GraphI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex.text(beginIndex,
+                                                                                                                              endIndex));
+        }
+        // This reuses the same list, so it's pretty efficient ...
+        return new BasicPath(createSegmentsSubList(beginIndex, endIndex), this.isAbsolute());
+    }
+
+    protected List<Segment> createSegmentsSubList( int validBeginIndex,
+                                                   int validEndIndex ) {
+        return this.getSegmentsList().subList(validBeginIndex, validEndIndex);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        if (hc == 0) {
+            int hashCode = 1;
+            for (Segment segment : this) {
+                hashCode = 31 * hashCode + segment.hashCode();
+            }
+            hc = hashCode;
+        }
+        return hc;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof Path) {
+            Path that = (Path)obj;
+            if (this.size() != that.size()) return false;
+            if (this.hashCode() != that.hashCode()) return false;
+            Iterator<Segment> thisIter = this.iterator();
+            Iterator<Segment> thatIter = that.iterator();
+            while (thisIter.hasNext()) {
+                Segment thisSegment = thisIter.next();
+                Segment thatSegment = thatIter.next();
+                if (!thisSegment.equals(thatSegment)) return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( Path that ) {
+        if (this == that) return 0;
+        Iterator<Segment> thisIter = getSegmentsList().iterator();
+        Iterator<Segment> thatIter = that.iterator();
+        while (thisIter.hasNext() && thatIter.hasNext()) {
+            Segment thisSegment = thisIter.next();
+            Segment thatSegment = thatIter.next();
+            int diff = thisSegment.compareTo(thatSegment);
+            if (diff != 0) return diff;
+        }
+        if (thisIter.hasNext()) return 1;
+        if (thatIter.hasNext()) return -1;
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return getString(Path.URL_ENCODER);
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactories.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractValueFactories.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactories.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,132 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.Iterator;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.ValueFactory;
-
-/**
- * Abstract implementation of {@link ValueFactories} that implements all the methods other than the <code>get*Factory()</code>
- * methods. Subclasses can simply implement these methods and inherit the {@link #iterator()}, {@link #getValueFactory(Object)}
- * and {@link #getValueFactory(PropertyType)} method implementations.
- * 
- * @author Randall Hauch
- */
-public abstract class AbstractValueFactories implements ValueFactories {
-
-    /**
-     * <p>
-     * {@inheritDoc}
-     * </p>
-     * <p>
-     * This implementation always iterates over the instances return by the <code>get*Factory()</code> methods.
-     * </p>
-     */
-    public Iterator<ValueFactory<?>> iterator() {
-        return new ValueFactoryIterator();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<?> getValueFactory( PropertyType type ) {
-        CheckArg.isNotNull(type, "type");
-        switch (type) {
-            case BINARY:
-                return getBinaryFactory();
-            case BOOLEAN:
-                return getBooleanFactory();
-            case DATE:
-                return getDateFactory();
-            case DECIMAL:
-                return getDecimalFactory();
-            case DOUBLE:
-                return getDoubleFactory();
-            case LONG:
-                return getLongFactory();
-            case NAME:
-                return getNameFactory();
-            case PATH:
-                return getPathFactory();
-            case REFERENCE:
-                return getReferenceFactory();
-            case STRING:
-                return getStringFactory();
-            case URI:
-                return getUriFactory();
-            case UUID:
-                return getUuidFactory();
-            case OBJECT:
-                return getObjectFactory();
-        }
-        return getObjectFactory();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<?> getValueFactory( Object prototype ) {
-        CheckArg.isNotNull(prototype, "prototype");
-        PropertyType inferredType = PropertyType.discoverType(prototype);
-        assert inferredType != null;
-        return getValueFactory(inferredType);
-    }
-
-    protected class ValueFactoryIterator implements Iterator<ValueFactory<?>> {
-        private final Iterator<PropertyType> propertyTypeIter = PropertyType.iterator();
-
-        protected ValueFactoryIterator() {
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see java.util.Iterator#hasNext()
-         */
-        public boolean hasNext() {
-            return propertyTypeIter.hasNext();
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see java.util.Iterator#next()
-         */
-        public ValueFactory<?> next() {
-            PropertyType nextType = propertyTypeIter.next();
-            return getValueFactory(nextType);
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see java.util.Iterator#remove()
-         */
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactories.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractValueFactories.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactories.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactories.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.Iterator;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.ValueFactory;
+
+/**
+ * Abstract implementation of {@link ValueFactories} that implements all the methods other than the <code>get*Factory()</code>
+ * methods. Subclasses can simply implement these methods and inherit the {@link #iterator()}, {@link #getValueFactory(Object)}
+ * and {@link #getValueFactory(PropertyType)} method implementations.
+ * 
+ * @author Randall Hauch
+ */
+public abstract class AbstractValueFactories implements ValueFactories {
+
+    /**
+     * <p>
+     * {@inheritDoc}
+     * </p>
+     * <p>
+     * This implementation always iterates over the instances return by the <code>get*Factory()</code> methods.
+     * </p>
+     */
+    public Iterator<ValueFactory<?>> iterator() {
+        return new ValueFactoryIterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<?> getValueFactory( PropertyType type ) {
+        CheckArg.isNotNull(type, "type");
+        switch (type) {
+            case BINARY:
+                return getBinaryFactory();
+            case BOOLEAN:
+                return getBooleanFactory();
+            case DATE:
+                return getDateFactory();
+            case DECIMAL:
+                return getDecimalFactory();
+            case DOUBLE:
+                return getDoubleFactory();
+            case LONG:
+                return getLongFactory();
+            case NAME:
+                return getNameFactory();
+            case PATH:
+                return getPathFactory();
+            case REFERENCE:
+                return getReferenceFactory();
+            case STRING:
+                return getStringFactory();
+            case URI:
+                return getUriFactory();
+            case UUID:
+                return getUuidFactory();
+            case OBJECT:
+                return getObjectFactory();
+        }
+        return getObjectFactory();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<?> getValueFactory( Object prototype ) {
+        CheckArg.isNotNull(prototype, "prototype");
+        PropertyType inferredType = PropertyType.discoverType(prototype);
+        assert inferredType != null;
+        return getValueFactory(inferredType);
+    }
+
+    protected class ValueFactoryIterator implements Iterator<ValueFactory<?>> {
+        private final Iterator<PropertyType> propertyTypeIter = PropertyType.iterator();
+
+        protected ValueFactoryIterator() {
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.util.Iterator#hasNext()
+         */
+        public boolean hasNext() {
+            return propertyTypeIter.hasNext();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.util.Iterator#next()
+         */
+        public ValueFactory<?> next() {
+            PropertyType nextType = propertyTypeIter.next();
+            return getValueFactory(nextType);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.util.Iterator#remove()
+         */
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,445 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * Abstract {@link ValueFactory}.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- * @param <T> the property type
- */
- at Immutable
-public abstract class AbstractValueFactory<T> implements ValueFactory<T> {
-
-    private final TextDecoder decoder;
-    private final PropertyType propertyType;
-    private final ValueFactory<String> stringValueFactory;
-
-    protected AbstractValueFactory( PropertyType type,
-                                    TextDecoder decoder,
-                                    ValueFactory<String> stringValueFactory ) {
-        CheckArg.isNotNull(type, "type");
-        this.propertyType = type;
-        this.decoder = decoder != null ? decoder : DEFAULT_DECODER;
-        this.stringValueFactory = stringValueFactory;
-    }
-
-    /**
-     * @return stringValueFactory
-     */
-    protected ValueFactory<String> getStringValueFactory() {
-        return this.stringValueFactory;
-    }
-
-    /**
-     * Get the text decoder.
-     * 
-     * @return the decoder
-     */
-    public TextDecoder getDecoder() {
-        return this.decoder;
-    }
-
-    /**
-     * Utility method to obtain either the supplied decoder (if not null) or this factory's {@link #getDecoder() decoder}.
-     * 
-     * @param decoder the decoder, which may be null if this factory's {@link #getDecoder() is to be used}
-     * @return the decoder; never null
-     */
-    protected TextDecoder getDecoder( TextDecoder decoder ) {
-        return decoder != null ? decoder : this.getDecoder();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public PropertyType getPropertyType() {
-        return propertyType;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T create( Object value ) {
-        if (value == null) return null;
-        if (value instanceof String) return create((String)value);
-        if (value instanceof Integer) return create(((Integer)value).intValue());
-        if (value instanceof Long) return create(((Long)value).longValue());
-        if (value instanceof Double) return create(((Double)value).doubleValue());
-        if (value instanceof Float) return create(((Float)value).floatValue());
-        if (value instanceof Boolean) return create(((Boolean)value).booleanValue());
-        if (value instanceof BigDecimal) return create((BigDecimal)value);
-        if (value instanceof Calendar) return create((Calendar)value);
-        if (value instanceof Date) return create((Date)value);
-        if (value instanceof Name) return create((Name)value);
-        if (value instanceof Path) return create((Path)value);
-        if (value instanceof Reference) return create((Reference)value);
-        if (value instanceof URI) return create((URI)value);
-        if (value instanceof Binary) return create((Binary)value);
-        if (value instanceof byte[]) return create((byte[])value);
-        if (value instanceof InputStream) return create((InputStream)value, 0);
-        if (value instanceof Reader) return create((Reader)value, 0);
-        return create(value.toString());
-    }
-
-    protected abstract T[] createEmptyArray( int length );
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( BigDecimal[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( boolean[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( byte[][] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( Calendar[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( Date[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime[])
-     */
-    public T[] create( DateTime[] values ) throws ValueFormatException {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( double[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( float[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( int[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( long[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( Name[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( Object[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( Path[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( Reference[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( String[] values,
-                       TextDecoder decoder ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i], decoder);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( String[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public T[] create( URI[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID[])
-     */
-    public T[] create( UUID[] values ) {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary[])
-     */
-    public T[] create( Binary[] values ) throws ValueFormatException, IoException {
-        if (values == null) return null;
-        final int length = values.length;
-        T[] result = createEmptyArray(length);
-        for (int i = 0; i != length; ++i) {
-            result[i] = create(values[i]);
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.Iterator)
-     */
-    public Iterator<T> create( Iterator<?> values ) throws ValueFormatException, IoException {
-        return new ConvertingIterator<T>(values, this);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.lang.Iterable)
-     */
-    public Iterable<T> create( final Iterable<?> valueIterable ) throws ValueFormatException, IoException {
-        return new Iterable<T>() {
-
-            public Iterator<T> iterator() {
-                return create(valueIterable.iterator());
-            }
-        };
-    }
-
-    protected static class ConvertingIterator<ValueType> implements Iterator<ValueType> {
-        private final Iterator<?> delegate;
-        private final ValueFactory<ValueType> factory;
-
-        protected ConvertingIterator( Iterator<?> delegate,
-                                      ValueFactory<ValueType> factory ) {
-            assert delegate != null;
-            assert factory != null;
-            this.delegate = delegate;
-            this.factory = factory;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see java.util.Iterator#hasNext()
-         */
-        public boolean hasNext() {
-            return this.delegate.hasNext();
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see java.util.Iterator#next()
-         */
-        public ValueType next() {
-            return factory.create(this.delegate.next());
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see java.util.Iterator#remove()
-         */
-        public void remove() {
-            this.delegate.remove();
-        }
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,445 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * Abstract {@link ValueFactory}.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ * @param <T> the property type
+ */
+ at Immutable
+public abstract class AbstractValueFactory<T> implements ValueFactory<T> {
+
+    private final TextDecoder decoder;
+    private final PropertyType propertyType;
+    private final ValueFactory<String> stringValueFactory;
+
+    protected AbstractValueFactory( PropertyType type,
+                                    TextDecoder decoder,
+                                    ValueFactory<String> stringValueFactory ) {
+        CheckArg.isNotNull(type, "type");
+        this.propertyType = type;
+        this.decoder = decoder != null ? decoder : DEFAULT_DECODER;
+        this.stringValueFactory = stringValueFactory;
+    }
+
+    /**
+     * @return stringValueFactory
+     */
+    protected ValueFactory<String> getStringValueFactory() {
+        return this.stringValueFactory;
+    }
+
+    /**
+     * Get the text decoder.
+     * 
+     * @return the decoder
+     */
+    public TextDecoder getDecoder() {
+        return this.decoder;
+    }
+
+    /**
+     * Utility method to obtain either the supplied decoder (if not null) or this factory's {@link #getDecoder() decoder}.
+     * 
+     * @param decoder the decoder, which may be null if this factory's {@link #getDecoder() is to be used}
+     * @return the decoder; never null
+     */
+    protected TextDecoder getDecoder( TextDecoder decoder ) {
+        return decoder != null ? decoder : this.getDecoder();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PropertyType getPropertyType() {
+        return propertyType;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T create( Object value ) {
+        if (value == null) return null;
+        if (value instanceof String) return create((String)value);
+        if (value instanceof Integer) return create(((Integer)value).intValue());
+        if (value instanceof Long) return create(((Long)value).longValue());
+        if (value instanceof Double) return create(((Double)value).doubleValue());
+        if (value instanceof Float) return create(((Float)value).floatValue());
+        if (value instanceof Boolean) return create(((Boolean)value).booleanValue());
+        if (value instanceof BigDecimal) return create((BigDecimal)value);
+        if (value instanceof Calendar) return create((Calendar)value);
+        if (value instanceof Date) return create((Date)value);
+        if (value instanceof Name) return create((Name)value);
+        if (value instanceof Path) return create((Path)value);
+        if (value instanceof Reference) return create((Reference)value);
+        if (value instanceof URI) return create((URI)value);
+        if (value instanceof Binary) return create((Binary)value);
+        if (value instanceof byte[]) return create((byte[])value);
+        if (value instanceof InputStream) return create((InputStream)value, 0);
+        if (value instanceof Reader) return create((Reader)value, 0);
+        return create(value.toString());
+    }
+
+    protected abstract T[] createEmptyArray( int length );
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( BigDecimal[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( boolean[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( byte[][] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( Calendar[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( Date[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime[])
+     */
+    public T[] create( DateTime[] values ) throws ValueFormatException {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( double[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( float[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( int[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( long[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( Name[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( Object[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( Path[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( Reference[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( String[] values,
+                       TextDecoder decoder ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i], decoder);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( String[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public T[] create( URI[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID[])
+     */
+    public T[] create( UUID[] values ) {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary[])
+     */
+    public T[] create( Binary[] values ) throws ValueFormatException, IoException {
+        if (values == null) return null;
+        final int length = values.length;
+        T[] result = createEmptyArray(length);
+        for (int i = 0; i != length; ++i) {
+            result[i] = create(values[i]);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.Iterator)
+     */
+    public Iterator<T> create( Iterator<?> values ) throws ValueFormatException, IoException {
+        return new ConvertingIterator<T>(values, this);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.lang.Iterable)
+     */
+    public Iterable<T> create( final Iterable<?> valueIterable ) throws ValueFormatException, IoException {
+        return new Iterable<T>() {
+
+            public Iterator<T> iterator() {
+                return create(valueIterable.iterator());
+            }
+        };
+    }
+
+    protected static class ConvertingIterator<ValueType> implements Iterator<ValueType> {
+        private final Iterator<?> delegate;
+        private final ValueFactory<ValueType> factory;
+
+        protected ConvertingIterator( Iterator<?> delegate,
+                                      ValueFactory<ValueType> factory ) {
+            assert delegate != null;
+            assert factory != null;
+            this.delegate = delegate;
+            this.factory = factory;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.util.Iterator#hasNext()
+         */
+        public boolean hasNext() {
+            return this.delegate.hasNext();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.util.Iterator#next()
+         */
+        public ValueType next() {
+            return factory.create(this.delegate.next());
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.util.Iterator#remove()
+         */
+        public void remove() {
+            this.delegate.remove();
+        }
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicEmptyProperty.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicEmptyProperty.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicEmptyProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,121 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.properties.Name;
-
-/**
- * An immutable version of a property that has no values. This is done for efficiency of the in-memory representation, since many
- * properties will have just a single value, while others will have multiple values.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class BasicEmptyProperty extends BasicProperty {
-
-    private static final Iterator<Object> SHARED_ITERATOR = new EmptyIterator<Object>();
-
-    /**
-     * Create a property with no values.
-     * 
-     * @param name the property name
-     */
-    public BasicEmptyProperty( Name name ) {
-        super(name);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isEmpty() {
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isMultiple() {
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isSingle() {
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int size() {
-        return 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Property#getFirstValue()
-     */
-    public Object getFirstValue() {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<Object> iterator() {
-        return SHARED_ITERATOR;
-    }
-
-    protected static class EmptyIterator<T> implements Iterator<T> {
-
-        protected EmptyIterator() {
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean hasNext() {
-            return false;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public T next() {
-            throw new NoSuchElementException();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicEmptyProperty.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicEmptyProperty.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicEmptyProperty.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicEmptyProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,121 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.property.Name;
+
+/**
+ * An immutable version of a property that has no values. This is done for efficiency of the in-memory representation, since many
+ * properties will have just a single value, while others will have multiple values.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class BasicEmptyProperty extends BasicProperty {
+
+    private static final Iterator<Object> SHARED_ITERATOR = new EmptyIterator<Object>();
+
+    /**
+     * Create a property with no values.
+     * 
+     * @param name the property name
+     */
+    public BasicEmptyProperty( Name name ) {
+        super(name);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEmpty() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isMultiple() {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isSingle() {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int size() {
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Property#getFirstValue()
+     */
+    public Object getFirstValue() {
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<Object> iterator() {
+        return SHARED_ITERATOR;
+    }
+
+    protected static class EmptyIterator<T> implements Iterator<T> {
+
+        protected EmptyIterator() {
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean hasNext() {
+            return false;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public T next() {
+            throw new NoSuchElementException();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicMultiValueProperty.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicMultiValueProperty.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicMultiValueProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,148 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.Name;
-
-/**
- * An immutable version of a property that has 2 or more values. This is done for efficiency of the in-memory representation,
- * since many properties will have just a single value, while others will have multiple values.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class BasicMultiValueProperty extends BasicProperty {
-
-    private final List<Object> values;
-
-    /**
-     * Create a property with 2 or more values. Note that the supplied list may be modifiable, as this object does not expose any
-     * means for modifying the contents.
-     * 
-     * @param name the property name
-     * @param values the property values
-     * @throws IllegalArgumentException if the values is null or does not have at least 2 values
-     */
-    public BasicMultiValueProperty( Name name,
-                                    List<Object> values ) {
-        super(name);
-        CheckArg.isNotNull(values, "values");
-        CheckArg.hasSizeOfAtLeast(values, 2, "values");
-        this.values = values;
-    }
-
-    /**
-     * Create a property with 2 or more values.
-     * 
-     * @param name the property name
-     * @param values the property values
-     * @throws IllegalArgumentException if the values is null or does not have at least 2 values
-     */
-    public BasicMultiValueProperty( Name name,
-                                    Object... values ) {
-        super(name);
-        CheckArg.isNotNull(values, "values");
-        CheckArg.hasSizeOfAtLeast(values, 2, "values");
-        this.values = Arrays.asList(values);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isEmpty() {
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isMultiple() {
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isSingle() {
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int size() {
-        return values.size();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Property#getFirstValue()
-     */
-    public Object getFirstValue() {
-        return values.get(0);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<Object> iterator() {
-        return new ReadOnlyIterator(values.iterator());
-    }
-
-    protected class ReadOnlyIterator implements Iterator<Object> {
-
-        private final Iterator<Object> values;
-
-        protected ReadOnlyIterator( Iterator<Object> values ) {
-            assert values != null;
-            this.values = values;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean hasNext() {
-            return values.hasNext();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Object next() {
-            return values.next();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicMultiValueProperty.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicMultiValueProperty.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicMultiValueProperty.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicMultiValueProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,148 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.Name;
+
+/**
+ * An immutable version of a property that has 2 or more values. This is done for efficiency of the in-memory representation,
+ * since many properties will have just a single value, while others will have multiple values.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class BasicMultiValueProperty extends BasicProperty {
+
+    private final List<Object> values;
+
+    /**
+     * Create a property with 2 or more values. Note that the supplied list may be modifiable, as this object does not expose any
+     * means for modifying the contents.
+     * 
+     * @param name the property name
+     * @param values the property values
+     * @throws IllegalArgumentException if the values is null or does not have at least 2 values
+     */
+    public BasicMultiValueProperty( Name name,
+                                    List<Object> values ) {
+        super(name);
+        CheckArg.isNotNull(values, "values");
+        CheckArg.hasSizeOfAtLeast(values, 2, "values");
+        this.values = values;
+    }
+
+    /**
+     * Create a property with 2 or more values.
+     * 
+     * @param name the property name
+     * @param values the property values
+     * @throws IllegalArgumentException if the values is null or does not have at least 2 values
+     */
+    public BasicMultiValueProperty( Name name,
+                                    Object... values ) {
+        super(name);
+        CheckArg.isNotNull(values, "values");
+        CheckArg.hasSizeOfAtLeast(values, 2, "values");
+        this.values = Arrays.asList(values);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEmpty() {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isMultiple() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isSingle() {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int size() {
+        return values.size();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Property#getFirstValue()
+     */
+    public Object getFirstValue() {
+        return values.get(0);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<Object> iterator() {
+        return new ReadOnlyIterator(values.iterator());
+    }
+
+    protected class ReadOnlyIterator implements Iterator<Object> {
+
+        private final Iterator<Object> values;
+
+        protected ReadOnlyIterator( Iterator<Object> values ) {
+            assert values != null;
+            this.values = values;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean hasNext() {
+            return values.hasNext();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Object next() {
+            return values.next();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicName.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,194 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.HashCode;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-
-/**
- * A basic implementation of {@link Name}.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class BasicName implements Name {
-
-    private String trimNonEmptyStrings( String value ) {
-        if (value == null) return null;
-        String trimmed = value.trim();
-        return trimmed.length() == 0 ? value : trimmed;
-    }
-
-    /**
-     */
-    private static final long serialVersionUID = -1737537720336990144L;
-    private final String namespaceUri;
-    private final String localName;
-    private final int hc;
-
-    public BasicName( String namespaceUri,
-                      String localName ) {
-        CheckArg.isNotEmpty(localName, "localName");
-        this.namespaceUri = namespaceUri != null ? namespaceUri.trim().intern() : "";
-        this.localName = trimNonEmptyStrings(localName);
-        this.hc = HashCode.compute(this.namespaceUri, this.localName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getLocalName() {
-        return this.localName;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getNamespaceUri() {
-        return this.namespaceUri;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString() {
-        return getString(Path.DEFAULT_ENCODER);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( TextEncoder encoder ) {
-        if (this.getNamespaceUri().length() == 0) {
-            if (this.getLocalName().equals(Path.SELF)) return Path.SELF;
-            if (this.getLocalName().equals(Path.PARENT)) return Path.PARENT;
-        }
-        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
-        return "{" + encoder.encode(this.namespaceUri) + "}" + encoder.encode(this.localName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( NamespaceRegistry namespaceRegistry ) {
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        String prefix = namespaceRegistry.getPrefixForNamespaceUri(this.namespaceUri, true);
-        if (prefix != null && prefix.length() != 0) {
-            return prefix + ":" + this.localName;
-        }
-        return this.localName;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder ) {
-        // This is the most-often used method, so implement it directly
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        String prefix = namespaceRegistry.getPrefixForNamespaceUri(this.namespaceUri, true);
-        if (prefix != null && prefix.length() != 0) {
-            return encoder.encode(prefix) + ":" + encoder.encode(this.localName);
-        }
-        return this.localName;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Name#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
-     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder,
-                             TextEncoder delimiterEncoder ) {
-        if (namespaceRegistry == null) {
-            if (this.getNamespaceUri().length() == 0) {
-                if (this.getLocalName().equals(Path.SELF)) return Path.SELF;
-                if (this.getLocalName().equals(Path.PARENT)) return Path.PARENT;
-            }
-            if (encoder == null) encoder = Path.DEFAULT_ENCODER;
-            if (delimiterEncoder != null) {
-                return delimiterEncoder.encode("{") + encoder.encode(this.namespaceUri) + delimiterEncoder.encode("}")
-                       + encoder.encode(this.localName);
-            }
-            return "{" + encoder.encode(this.namespaceUri) + "}" + encoder.encode(this.localName);
-
-        }
-        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
-        String prefix = namespaceRegistry.getPrefixForNamespaceUri(this.namespaceUri, true);
-        if (prefix != null && prefix.length() != 0) {
-            String delim = delimiterEncoder != null ? delimiterEncoder.encode(":") : ":";
-            return encoder.encode(prefix) + delim + encoder.encode(this.localName);
-        }
-        return this.localName;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int compareTo( Name that ) {
-        if (that == this) return 0;
-        int diff = this.getLocalName().compareTo(that.getLocalName());
-        if (diff != 0) return diff;
-        diff = this.getNamespaceUri().compareTo(that.getNamespaceUri());
-        return diff;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return this.hc;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof Name) {
-            Name that = (Name)obj;
-            if (!this.getLocalName().equals(that.getLocalName())) return false;
-            if (!this.getNamespaceUri().equals(that.getNamespaceUri())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return "{" + this.namespaceUri + "}" + this.localName;
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicName.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,194 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * A basic implementation of {@link Name}.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class BasicName implements Name {
+
+    private String trimNonEmptyStrings( String value ) {
+        if (value == null) return null;
+        String trimmed = value.trim();
+        return trimmed.length() == 0 ? value : trimmed;
+    }
+
+    /**
+     */
+    private static final long serialVersionUID = -1737537720336990144L;
+    private final String namespaceUri;
+    private final String localName;
+    private final int hc;
+
+    public BasicName( String namespaceUri,
+                      String localName ) {
+        CheckArg.isNotEmpty(localName, "localName");
+        this.namespaceUri = namespaceUri != null ? namespaceUri.trim().intern() : "";
+        this.localName = trimNonEmptyStrings(localName);
+        this.hc = HashCode.compute(this.namespaceUri, this.localName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getLocalName() {
+        return this.localName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getNamespaceUri() {
+        return this.namespaceUri;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString() {
+        return getString(Path.DEFAULT_ENCODER);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( TextEncoder encoder ) {
+        if (this.getNamespaceUri().length() == 0) {
+            if (this.getLocalName().equals(Path.SELF)) return Path.SELF;
+            if (this.getLocalName().equals(Path.PARENT)) return Path.PARENT;
+        }
+        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
+        return "{" + encoder.encode(this.namespaceUri) + "}" + encoder.encode(this.localName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( NamespaceRegistry namespaceRegistry ) {
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        String prefix = namespaceRegistry.getPrefixForNamespaceUri(this.namespaceUri, true);
+        if (prefix != null && prefix.length() != 0) {
+            return prefix + ":" + this.localName;
+        }
+        return this.localName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder ) {
+        // This is the most-often used method, so implement it directly
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        String prefix = namespaceRegistry.getPrefixForNamespaceUri(this.namespaceUri, true);
+        if (prefix != null && prefix.length() != 0) {
+            return encoder.encode(prefix) + ":" + encoder.encode(this.localName);
+        }
+        return this.localName;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Name#getString(org.jboss.dna.graph.property.NamespaceRegistry,
+     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder,
+                             TextEncoder delimiterEncoder ) {
+        if (namespaceRegistry == null) {
+            if (this.getNamespaceUri().length() == 0) {
+                if (this.getLocalName().equals(Path.SELF)) return Path.SELF;
+                if (this.getLocalName().equals(Path.PARENT)) return Path.PARENT;
+            }
+            if (encoder == null) encoder = Path.DEFAULT_ENCODER;
+            if (delimiterEncoder != null) {
+                return delimiterEncoder.encode("{") + encoder.encode(this.namespaceUri) + delimiterEncoder.encode("}")
+                       + encoder.encode(this.localName);
+            }
+            return "{" + encoder.encode(this.namespaceUri) + "}" + encoder.encode(this.localName);
+
+        }
+        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
+        String prefix = namespaceRegistry.getPrefixForNamespaceUri(this.namespaceUri, true);
+        if (prefix != null && prefix.length() != 0) {
+            String delim = delimiterEncoder != null ? delimiterEncoder.encode(":") : ":";
+            return encoder.encode(prefix) + delim + encoder.encode(this.localName);
+        }
+        return this.localName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( Name that ) {
+        if (that == this) return 0;
+        int diff = this.getLocalName().compareTo(that.getLocalName());
+        if (diff != 0) return diff;
+        diff = this.getNamespaceUri().compareTo(that.getNamespaceUri());
+        return diff;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return this.hc;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof Name) {
+            Name that = (Name)obj;
+            if (!this.getLocalName().equals(that.getLocalName())) return false;
+            if (!this.getNamespaceUri().equals(that.getNamespaceUri())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return "{" + this.namespaceUri + "}" + this.localName;
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespace.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicNamespace.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespace.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,104 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.NamespaceRegistry.Namespace;
-
-/**
- * @author Randall Hauch
- */
- at Immutable
-public class BasicNamespace implements NamespaceRegistry.Namespace {
-    private final String prefix;
-    private final String namespaceUri;
-
-    /**
-     * Create a namespace instance.
-     * 
-     * @param prefix the namespace prefix; may not be null (this is not checked)
-     * @param namespaceUri the namespace URI; may not be null (this is not checked)
-     */
-    public BasicNamespace( String prefix,
-                           String namespaceUri ) {
-        assert prefix != null;
-        assert namespaceUri != null;
-        this.prefix = prefix;
-        this.namespaceUri = namespaceUri;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.NamespaceRegistry.Namespace#getNamespaceUri()
-     */
-    public String getNamespaceUri() {
-        return namespaceUri;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.NamespaceRegistry.Namespace#getPrefix()
-     */
-    public String getPrefix() {
-        return prefix;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return namespaceUri.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof Namespace) {
-            Namespace that = (Namespace)obj;
-            if (!this.namespaceUri.equals(that.getNamespaceUri())) return false;
-            // if (!this.prefix.equals(that.getPrefix())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return prefix + ":" + namespaceUri;
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespace.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicNamespace.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespace.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespace.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,104 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.NamespaceRegistry.Namespace;
+
+/**
+ * @author Randall Hauch
+ */
+ at Immutable
+public class BasicNamespace implements NamespaceRegistry.Namespace {
+    private final String prefix;
+    private final String namespaceUri;
+
+    /**
+     * Create a namespace instance.
+     * 
+     * @param prefix the namespace prefix; may not be null (this is not checked)
+     * @param namespaceUri the namespace URI; may not be null (this is not checked)
+     */
+    public BasicNamespace( String prefix,
+                           String namespaceUri ) {
+        assert prefix != null;
+        assert namespaceUri != null;
+        this.prefix = prefix;
+        this.namespaceUri = namespaceUri;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.NamespaceRegistry.Namespace#getNamespaceUri()
+     */
+    public String getNamespaceUri() {
+        return namespaceUri;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.NamespaceRegistry.Namespace#getPrefix()
+     */
+    public String getPrefix() {
+        return prefix;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return namespaceUri.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof Namespace) {
+            Namespace that = (Namespace)obj;
+            if (!this.namespaceUri.equals(that.getNamespaceUri())) return false;
+            // if (!this.prefix.equals(that.getPrefix())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return prefix + ":" + namespaceUri;
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistry.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicNamespaceRegistry.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistry.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,259 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.text.DecimalFormat;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import net.jcip.annotations.GuardedBy;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-
-/**
- * @author Randall Hauch
- */
- at ThreadSafe
-public class BasicNamespaceRegistry implements NamespaceRegistry {
-
-    public static final String DEFAULT_NAMESPACE_URI = "";
-    public static final String DEFAULT_PREFIX_TEMPLATE = "ns##000";
-    public static final String DEFAULT_PREFIX_NUMBER_FORMAT = "##000";
-
-    private final ReadWriteLock registryLock = new ReentrantReadWriteLock();
-    private final Map<String, String> namespacesByPrefix = new HashMap<String, String>();
-    private final Map<String, String> prefixesByNamespace = new HashMap<String, String>();
-    private String generatedPrefixTemplate = DEFAULT_PREFIX_TEMPLATE;
-    private int nextGeneratedPrefixNumber = 1;
-
-    /**
-     * 
-     */
-    public BasicNamespaceRegistry() {
-        this(DEFAULT_NAMESPACE_URI);
-    }
-
-    /**
-     * @param defaultNamespaceUri the namespace URI to use for the default prefix
-     */
-    public BasicNamespaceRegistry( final String defaultNamespaceUri ) {
-        register("", defaultNamespaceUri);
-    }
-
-    /**
-     * @return prefixTemplate
-     */
-    public String getGeneratedPrefixTemplate() {
-        Lock lock = this.registryLock.readLock();
-        try {
-            lock.lock();
-            return this.generatedPrefixTemplate;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * @param prefixTemplate Sets prefixTemplate to the specified value.
-     */
-    public void setGeneratedPrefixTemplate( String prefixTemplate ) {
-        if (prefixTemplate == null) prefixTemplate = DEFAULT_PREFIX_TEMPLATE;
-        Lock lock = this.registryLock.writeLock();
-        try {
-            lock.lock();
-            this.generatedPrefixTemplate = prefixTemplate;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getNamespaceForPrefix( String prefix ) {
-        CheckArg.isNotNull(prefix, "prefix");
-        Lock lock = this.registryLock.readLock();
-        try {
-            lock.lock();
-            return this.namespacesByPrefix.get(prefix);
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getPrefixForNamespaceUri( String namespaceUri,
-                                            boolean generateIfMissing ) {
-        CheckArg.isNotNull(namespaceUri, "namespaceUri");
-        String prefix = null;
-        Lock lock = this.registryLock.readLock();
-        try {
-            lock.lock();
-            prefix = this.prefixesByNamespace.get(namespaceUri);
-        } finally {
-            lock.unlock();
-        }
-        if (prefix == null && generateIfMissing) {
-            // Get a write lock ...
-            lock = this.registryLock.writeLock();
-            try {
-                lock.lock();
-                // Since we got a new lock, we need to check again ...
-                prefix = this.prefixesByNamespace.get(namespaceUri);
-                if (prefix == null) {
-                    // Now we can genereate a prefix and register it ...
-                    prefix = this.generatePrefix();
-                    this.register(prefix, namespaceUri);
-                }
-                return prefix;
-            } finally {
-                lock.unlock();
-            }
-        }
-        return prefix;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isRegisteredNamespaceUri( String namespaceUri ) {
-        CheckArg.isNotNull(namespaceUri, "namespaceUri");
-        Lock lock = this.registryLock.readLock();
-        try {
-            lock.lock();
-            return this.prefixesByNamespace.containsKey(namespaceUri);
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getDefaultNamespaceUri() {
-        Lock lock = this.registryLock.readLock();
-        try {
-            lock.lock();
-            return this.namespacesByPrefix.get("");
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String register( String prefix,
-                            String namespaceUri ) {
-        CheckArg.isNotNull(namespaceUri, "namespaceUri");
-        String previousNamespaceForPrefix = null;
-        namespaceUri = namespaceUri.trim();
-        Lock lock = this.registryLock.writeLock();
-        try {
-            lock.lock();
-            if (prefix == null) prefix = generatePrefix();
-            prefix = prefix.trim();
-            prefix = prefix.replaceFirst("^:+", "");
-            prefix = prefix.replaceFirst(":+$", "");
-            previousNamespaceForPrefix = this.namespacesByPrefix.put(prefix, namespaceUri);
-            String previousPrefix = this.prefixesByNamespace.put(namespaceUri, prefix);
-            if (previousPrefix != null && !previousPrefix.equals(prefix)) {
-                this.namespacesByPrefix.remove(previousPrefix);
-            }
-            if (previousNamespaceForPrefix != null && !previousNamespaceForPrefix.equals(namespaceUri)) {
-                this.prefixesByNamespace.remove(previousNamespaceForPrefix);
-            }
-        } finally {
-            lock.unlock();
-        }
-        return previousNamespaceForPrefix;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.NamespaceRegistry#unregister(java.lang.String)
-     */
-    public boolean unregister( String namespaceUri ) {
-        CheckArg.isNotNull(namespaceUri, "namespaceUri");
-        namespaceUri = namespaceUri.trim();
-        Lock lock = this.registryLock.writeLock();
-        try {
-            lock.lock();
-            String prefix = this.prefixesByNamespace.remove(namespaceUri);
-            if (prefix == null) return false;
-            this.namespacesByPrefix.remove(prefix);
-        } finally {
-            lock.unlock();
-        }
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Set<String> getRegisteredNamespaceUris() {
-        Set<String> result = new HashSet<String>();
-        Lock lock = this.registryLock.readLock();
-        try {
-            lock.lock();
-            result.addAll(this.prefixesByNamespace.keySet());
-        } finally {
-            lock.unlock();
-        }
-        return Collections.unmodifiableSet(result);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.NamespaceRegistry#getNamespaces()
-     */
-    public Set<Namespace> getNamespaces() {
-        Set<Namespace> result = new HashSet<Namespace>();
-        Lock lock = this.registryLock.readLock();
-        try {
-            lock.lock();
-            for (Map.Entry<String, String> entry : this.namespacesByPrefix.entrySet()) {
-                result.add(new BasicNamespace(entry.getKey(), entry.getValue()));
-            }
-        } finally {
-            lock.unlock();
-        }
-        return Collections.unmodifiableSet(result);
-    }
-
-    @GuardedBy( "registryLock" )
-    protected String generatePrefix() {
-        DecimalFormat formatter = new DecimalFormat(this.generatedPrefixTemplate);
-        return formatter.format(nextGeneratedPrefixNumber++);
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistry.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicNamespaceRegistry.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistry.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistry.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,259 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.text.DecimalFormat;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import net.jcip.annotations.GuardedBy;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+
+/**
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public class BasicNamespaceRegistry implements NamespaceRegistry {
+
+    public static final String DEFAULT_NAMESPACE_URI = "";
+    public static final String DEFAULT_PREFIX_TEMPLATE = "ns##000";
+    public static final String DEFAULT_PREFIX_NUMBER_FORMAT = "##000";
+
+    private final ReadWriteLock registryLock = new ReentrantReadWriteLock();
+    private final Map<String, String> namespacesByPrefix = new HashMap<String, String>();
+    private final Map<String, String> prefixesByNamespace = new HashMap<String, String>();
+    private String generatedPrefixTemplate = DEFAULT_PREFIX_TEMPLATE;
+    private int nextGeneratedPrefixNumber = 1;
+
+    /**
+     * 
+     */
+    public BasicNamespaceRegistry() {
+        this(DEFAULT_NAMESPACE_URI);
+    }
+
+    /**
+     * @param defaultNamespaceUri the namespace URI to use for the default prefix
+     */
+    public BasicNamespaceRegistry( final String defaultNamespaceUri ) {
+        register("", defaultNamespaceUri);
+    }
+
+    /**
+     * @return prefixTemplate
+     */
+    public String getGeneratedPrefixTemplate() {
+        Lock lock = this.registryLock.readLock();
+        try {
+            lock.lock();
+            return this.generatedPrefixTemplate;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * @param prefixTemplate Sets prefixTemplate to the specified value.
+     */
+    public void setGeneratedPrefixTemplate( String prefixTemplate ) {
+        if (prefixTemplate == null) prefixTemplate = DEFAULT_PREFIX_TEMPLATE;
+        Lock lock = this.registryLock.writeLock();
+        try {
+            lock.lock();
+            this.generatedPrefixTemplate = prefixTemplate;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getNamespaceForPrefix( String prefix ) {
+        CheckArg.isNotNull(prefix, "prefix");
+        Lock lock = this.registryLock.readLock();
+        try {
+            lock.lock();
+            return this.namespacesByPrefix.get(prefix);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getPrefixForNamespaceUri( String namespaceUri,
+                                            boolean generateIfMissing ) {
+        CheckArg.isNotNull(namespaceUri, "namespaceUri");
+        String prefix = null;
+        Lock lock = this.registryLock.readLock();
+        try {
+            lock.lock();
+            prefix = this.prefixesByNamespace.get(namespaceUri);
+        } finally {
+            lock.unlock();
+        }
+        if (prefix == null && generateIfMissing) {
+            // Get a write lock ...
+            lock = this.registryLock.writeLock();
+            try {
+                lock.lock();
+                // Since we got a new lock, we need to check again ...
+                prefix = this.prefixesByNamespace.get(namespaceUri);
+                if (prefix == null) {
+                    // Now we can genereate a prefix and register it ...
+                    prefix = this.generatePrefix();
+                    this.register(prefix, namespaceUri);
+                }
+                return prefix;
+            } finally {
+                lock.unlock();
+            }
+        }
+        return prefix;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isRegisteredNamespaceUri( String namespaceUri ) {
+        CheckArg.isNotNull(namespaceUri, "namespaceUri");
+        Lock lock = this.registryLock.readLock();
+        try {
+            lock.lock();
+            return this.prefixesByNamespace.containsKey(namespaceUri);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getDefaultNamespaceUri() {
+        Lock lock = this.registryLock.readLock();
+        try {
+            lock.lock();
+            return this.namespacesByPrefix.get("");
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String register( String prefix,
+                            String namespaceUri ) {
+        CheckArg.isNotNull(namespaceUri, "namespaceUri");
+        String previousNamespaceForPrefix = null;
+        namespaceUri = namespaceUri.trim();
+        Lock lock = this.registryLock.writeLock();
+        try {
+            lock.lock();
+            if (prefix == null) prefix = generatePrefix();
+            prefix = prefix.trim();
+            prefix = prefix.replaceFirst("^:+", "");
+            prefix = prefix.replaceFirst(":+$", "");
+            previousNamespaceForPrefix = this.namespacesByPrefix.put(prefix, namespaceUri);
+            String previousPrefix = this.prefixesByNamespace.put(namespaceUri, prefix);
+            if (previousPrefix != null && !previousPrefix.equals(prefix)) {
+                this.namespacesByPrefix.remove(previousPrefix);
+            }
+            if (previousNamespaceForPrefix != null && !previousNamespaceForPrefix.equals(namespaceUri)) {
+                this.prefixesByNamespace.remove(previousNamespaceForPrefix);
+            }
+        } finally {
+            lock.unlock();
+        }
+        return previousNamespaceForPrefix;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.NamespaceRegistry#unregister(java.lang.String)
+     */
+    public boolean unregister( String namespaceUri ) {
+        CheckArg.isNotNull(namespaceUri, "namespaceUri");
+        namespaceUri = namespaceUri.trim();
+        Lock lock = this.registryLock.writeLock();
+        try {
+            lock.lock();
+            String prefix = this.prefixesByNamespace.remove(namespaceUri);
+            if (prefix == null) return false;
+            this.namespacesByPrefix.remove(prefix);
+        } finally {
+            lock.unlock();
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Set<String> getRegisteredNamespaceUris() {
+        Set<String> result = new HashSet<String>();
+        Lock lock = this.registryLock.readLock();
+        try {
+            lock.lock();
+            result.addAll(this.prefixesByNamespace.keySet());
+        } finally {
+            lock.unlock();
+        }
+        return Collections.unmodifiableSet(result);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.NamespaceRegistry#getNamespaces()
+     */
+    public Set<Namespace> getNamespaces() {
+        Set<Namespace> result = new HashSet<Namespace>();
+        Lock lock = this.registryLock.readLock();
+        try {
+            lock.lock();
+            for (Map.Entry<String, String> entry : this.namespacesByPrefix.entrySet()) {
+                result.add(new BasicNamespace(entry.getKey(), entry.getValue()));
+            }
+        } finally {
+            lock.unlock();
+        }
+        return Collections.unmodifiableSet(result);
+    }
+
+    @GuardedBy( "registryLock" )
+    protected String generatePrefix() {
+        DecimalFormat formatter = new DecimalFormat(this.generatedPrefixTemplate);
+        return formatter.format(nextGeneratedPrefixNumber++);
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPath.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,121 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.Collections;
-import java.util.List;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.Inflector;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.Path;
-
-/**
- * A basic implementation of {@link Path}.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class BasicPath extends AbstractPath {
-
-    /**
-     * The initial serializable version. Version {@value}
-     */
-    private static final long serialVersionUID = 1L;
-
-    private static final List<Segment> EMPTY_SEGMENTS = Collections.emptyList();
-
-    public static final Path EMPTY_RELATIVE = new BasicPath(EMPTY_SEGMENTS, false);
-
-    public static final Path SELF_PATH = new BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
-
-    public static final Path PARENT_PATH = new BasicPath(Collections.singletonList(Path.PARENT_SEGMENT), false);
-
-    private final List<Segment> segments;
-    private final boolean absolute;
-    private final boolean normalized;
-
-    /**
-     * @param segments the segments
-     * @param absolute true if this path is absolute, or false otherwise
-     */
-    public BasicPath( List<Segment> segments,
-                      boolean absolute ) {
-        assert segments != null;
-        this.segments = Collections.unmodifiableList(segments);
-        this.absolute = absolute;
-        this.normalized = isNormalized(this.segments);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path getAncestor( int degree ) {
-        CheckArg.isNonNegative(degree, "degree");
-        if (degree == 0) return this;
-        int endIndex = this.segments.size() - degree;
-        if (endIndex == 0) return this.isAbsolute() ? RootPath.INSTANCE : null;
-        if (endIndex < 0) {
-            String msg = GraphI18n.pathAncestorDegreeIsInvalid.text(this.getString(), Inflector.getInstance().ordinalize(degree));
-            throw new InvalidPathException(msg);
-        }
-        return subpath(0, endIndex);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public List<Segment> getSegmentsList() {
-        return this.segments;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isAbsolute() {
-        return this.absolute;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isNormalized() {
-        return this.normalized;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isRoot() {
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int size() {
-        return this.segments.size();
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPath.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPath.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPath.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,121 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.Collections;
+import java.util.List;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.Inflector;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * A basic implementation of {@link Path}.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class BasicPath extends AbstractPath {
+
+    /**
+     * The initial serializable version. Version {@value}
+     */
+    private static final long serialVersionUID = 1L;
+
+    private static final List<Segment> EMPTY_SEGMENTS = Collections.emptyList();
+
+    public static final Path EMPTY_RELATIVE = new BasicPath(EMPTY_SEGMENTS, false);
+
+    public static final Path SELF_PATH = new BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
+
+    public static final Path PARENT_PATH = new BasicPath(Collections.singletonList(Path.PARENT_SEGMENT), false);
+
+    private final List<Segment> segments;
+    private final boolean absolute;
+    private final boolean normalized;
+
+    /**
+     * @param segments the segments
+     * @param absolute true if this path is absolute, or false otherwise
+     */
+    public BasicPath( List<Segment> segments,
+                      boolean absolute ) {
+        assert segments != null;
+        this.segments = Collections.unmodifiableList(segments);
+        this.absolute = absolute;
+        this.normalized = isNormalized(this.segments);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path getAncestor( int degree ) {
+        CheckArg.isNonNegative(degree, "degree");
+        if (degree == 0) return this;
+        int endIndex = this.segments.size() - degree;
+        if (endIndex == 0) return this.isAbsolute() ? RootPath.INSTANCE : null;
+        if (endIndex < 0) {
+            String msg = GraphI18n.pathAncestorDegreeIsInvalid.text(this.getString(), Inflector.getInstance().ordinalize(degree));
+            throw new InvalidPathException(msg);
+        }
+        return subpath(0, endIndex);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public List<Segment> getSegmentsList() {
+        return this.segments;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAbsolute() {
+        return this.absolute;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isNormalized() {
+        return this.normalized;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isRoot() {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int size() {
+        return this.segments.size();
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPathSegment.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPathSegment.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPathSegment.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,200 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-
-/**
- * A basic implementation of {@link Path.Segment}.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class BasicPathSegment implements Path.Segment {
-
-    /**
-     */
-    private static final long serialVersionUID = 4367349287846075157L;
-    private final Name name;
-    private final int index;
-
-    /**
-     * @param name the segment name
-     * @throws IllegalArgumentException if the name is null or if the index is invalid
-     */
-    public BasicPathSegment( Name name ) {
-        this(name, Path.NO_INDEX);
-    }
-
-    /**
-     * @param name the segment name
-     * @param index the segment index
-     * @throws IllegalArgumentException if the name is null or if the index is invalid
-     */
-    public BasicPathSegment( Name name,
-                             int index ) {
-        assert name != null;
-        assert index >= Path.NO_INDEX;
-        this.name = name;
-        this.index = (this.isSelfReference() || this.isParentReference()) ? Path.NO_INDEX : index;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getIndex() {
-        return this.index;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name getName() {
-        return this.name;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean hasIndex() {
-        return this.index != Path.NO_INDEX;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isParentReference() {
-        return this.name.getNamespaceUri().length() == 0 && this.name.getLocalName().equals(Path.PARENT);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isSelfReference() {
-        return this.name.getNamespaceUri().length() == 0 && this.name.getLocalName().equals(Path.SELF);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int compareTo( Path.Segment that ) {
-        if (this == that) return 0;
-        int diff = this.getName().compareTo(that.getName());
-        if (diff != 0) return diff;
-        return this.getIndex() - that.getIndex();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return this.name.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof Path.Segment) {
-            Path.Segment that = (Path.Segment)obj;
-            if (!this.getName().equals(that.getName())) return false;
-            return Math.abs(getIndex()) == Math.abs(that.getIndex());
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        if (this.hasIndex()) {
-            return this.getName().toString() + "[" + this.getIndex() + "]";
-        }
-        return this.getName().toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getUnencodedString() {
-        return getString(Path.NO_OP_ENCODER);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString() {
-        return getString(Path.DEFAULT_ENCODER);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( TextEncoder encoder ) {
-        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
-        String encodedName = this.getName().getString(encoder);
-        if (this.hasIndex()) {
-            return encodedName + "[" + this.getIndex() + "]";
-        }
-        return encodedName;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( NamespaceRegistry namespaceRegistry ) {
-        return getString(namespaceRegistry, Path.DEFAULT_ENCODER);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder ) {
-        return getString(namespaceRegistry, encoder, null);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path.Segment#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
-     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder,
-                             TextEncoder delimiterEncoder ) {
-        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
-        String encodedName = this.getName().getString(namespaceRegistry, encoder, delimiterEncoder);
-        if (this.hasIndex()) {
-            return encodedName + "[" + this.getIndex() + "]";
-        }
-        return encodedName;
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPathSegment.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPathSegment.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPathSegment.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPathSegment.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,200 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * A basic implementation of {@link Path.Segment}.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class BasicPathSegment implements Path.Segment {
+
+    /**
+     */
+    private static final long serialVersionUID = 4367349287846075157L;
+    private final Name name;
+    private final int index;
+
+    /**
+     * @param name the segment name
+     * @throws IllegalArgumentException if the name is null or if the index is invalid
+     */
+    public BasicPathSegment( Name name ) {
+        this(name, Path.NO_INDEX);
+    }
+
+    /**
+     * @param name the segment name
+     * @param index the segment index
+     * @throws IllegalArgumentException if the name is null or if the index is invalid
+     */
+    public BasicPathSegment( Name name,
+                             int index ) {
+        assert name != null;
+        assert index >= Path.NO_INDEX;
+        this.name = name;
+        this.index = (this.isSelfReference() || this.isParentReference()) ? Path.NO_INDEX : index;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getIndex() {
+        return this.index;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name getName() {
+        return this.name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasIndex() {
+        return this.index != Path.NO_INDEX;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isParentReference() {
+        return this.name.getNamespaceUri().length() == 0 && this.name.getLocalName().equals(Path.PARENT);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isSelfReference() {
+        return this.name.getNamespaceUri().length() == 0 && this.name.getLocalName().equals(Path.SELF);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( Path.Segment that ) {
+        if (this == that) return 0;
+        int diff = this.getName().compareTo(that.getName());
+        if (diff != 0) return diff;
+        return this.getIndex() - that.getIndex();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof Path.Segment) {
+            Path.Segment that = (Path.Segment)obj;
+            if (!this.getName().equals(that.getName())) return false;
+            return Math.abs(getIndex()) == Math.abs(that.getIndex());
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        if (this.hasIndex()) {
+            return this.getName().toString() + "[" + this.getIndex() + "]";
+        }
+        return this.getName().toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getUnencodedString() {
+        return getString(Path.NO_OP_ENCODER);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString() {
+        return getString(Path.DEFAULT_ENCODER);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( TextEncoder encoder ) {
+        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
+        String encodedName = this.getName().getString(encoder);
+        if (this.hasIndex()) {
+            return encodedName + "[" + this.getIndex() + "]";
+        }
+        return encodedName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( NamespaceRegistry namespaceRegistry ) {
+        return getString(namespaceRegistry, Path.DEFAULT_ENCODER);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder ) {
+        return getString(namespaceRegistry, encoder, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path.Segment#getString(org.jboss.dna.graph.property.NamespaceRegistry,
+     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder,
+                             TextEncoder delimiterEncoder ) {
+        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
+        String encodedName = this.getName().getString(namespaceRegistry, encoder, delimiterEncoder);
+        if (this.hasIndex()) {
+            return encodedName + "[" + this.getIndex() + "]";
+        }
+        return encodedName;
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicProperty.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicProperty.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,201 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.ValueComparators;
-
-/**
- * @author Randall Hauch
- */
- at Immutable
-public abstract class BasicProperty implements Property {
-
-    private final Name name;
-
-    /**
-     * @param name
-     */
-    public BasicProperty( Name name ) {
-        this.name = name;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name getName() {
-        return name;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<?> getValues() {
-        return iterator();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object[] getValuesAsArray() {
-        if (size() == 0) return null;
-        Object[] results = new Object[size()];
-        Iterator<?> iter = iterator();
-        int index = 0;
-        while (iter.hasNext()) {
-            Object value = iter.next();
-            results[index++] = value;
-        }
-        return results;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int compareTo( Property o ) {
-        return 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return name.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this == obj) return true;
-        if (obj instanceof Property) {
-            Property that = (Property)obj;
-            if (!this.getName().equals(that.getName())) return false;
-            if (this.size() != that.size()) return false;
-            Iterator<?> thisIter = iterator();
-            Iterator<?> thatIter = that.iterator();
-            while (thisIter.hasNext()) { // && thatIter.hasNext()
-                Object thisValue = thisIter.next();
-                Object thatValue = thatIter.next();
-                if (ValueComparators.OBJECT_COMPARATOR.compare(thisValue, thatValue) != 0) return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString() {
-        return getString(null, null, null);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( TextEncoder encoder ) {
-        return getString(null, encoder, null);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( NamespaceRegistry namespaceRegistry ) {
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        return getString(namespaceRegistry, null, null);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder ) {
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        return getString(namespaceRegistry, encoder, null);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
-     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
-     */
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder,
-                             TextEncoder delimiterEncoder ) {
-        StringBuilder sb = new StringBuilder();
-        sb.append(getName().getString(namespaceRegistry, encoder, delimiterEncoder));
-        sb.append(" = ");
-        if (isEmpty()) {
-            sb.append("null");
-        } else {
-            if (isMultiple()) sb.append("[");
-            boolean first = true;
-            for (Object value : this) {
-                if (first) first = false;
-                else sb.append(",");
-                if (value instanceof Path) {
-                    Path path = (Path)value;
-                    sb.append(path.getString(namespaceRegistry, encoder, delimiterEncoder));
-                } else if (value instanceof Name) {
-                    Name name = (Name)value;
-                    sb.append(name.getString(namespaceRegistry, encoder, delimiterEncoder));
-                } else {
-                    sb.append(value);
-                }
-            }
-            if (isMultiple()) sb.append("]");
-        }
-        return sb.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(getName());
-        sb.append(" = ");
-        if (isSingle()) {
-            sb.append(getValues().next());
-        } else if (isEmpty()) {
-            sb.append("null");
-        } else {
-            sb.append(Arrays.asList(getValuesAsArray()));
-        }
-        return sb.toString();
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicProperty.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicProperty.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicProperty.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,201 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.ValueComparators;
+
+/**
+ * @author Randall Hauch
+ */
+ at Immutable
+public abstract class BasicProperty implements Property {
+
+    private final Name name;
+
+    /**
+     * @param name
+     */
+    public BasicProperty( Name name ) {
+        this.name = name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name getName() {
+        return name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<?> getValues() {
+        return iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object[] getValuesAsArray() {
+        if (size() == 0) return null;
+        Object[] results = new Object[size()];
+        Iterator<?> iter = iterator();
+        int index = 0;
+        while (iter.hasNext()) {
+            Object value = iter.next();
+            results[index++] = value;
+        }
+        return results;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( Property o ) {
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this == obj) return true;
+        if (obj instanceof Property) {
+            Property that = (Property)obj;
+            if (!this.getName().equals(that.getName())) return false;
+            if (this.size() != that.size()) return false;
+            Iterator<?> thisIter = iterator();
+            Iterator<?> thatIter = that.iterator();
+            while (thisIter.hasNext()) { // && thatIter.hasNext()
+                Object thisValue = thisIter.next();
+                Object thatValue = thatIter.next();
+                if (ValueComparators.OBJECT_COMPARATOR.compare(thisValue, thatValue) != 0) return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString() {
+        return getString(null, null, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( TextEncoder encoder ) {
+        return getString(null, encoder, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( NamespaceRegistry namespaceRegistry ) {
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        return getString(namespaceRegistry, null, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder ) {
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        return getString(namespaceRegistry, encoder, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getString(org.jboss.dna.graph.property.NamespaceRegistry,
+     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
+     */
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder,
+                             TextEncoder delimiterEncoder ) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getName().getString(namespaceRegistry, encoder, delimiterEncoder));
+        sb.append(" = ");
+        if (isEmpty()) {
+            sb.append("null");
+        } else {
+            if (isMultiple()) sb.append("[");
+            boolean first = true;
+            for (Object value : this) {
+                if (first) first = false;
+                else sb.append(",");
+                if (value instanceof Path) {
+                    Path path = (Path)value;
+                    sb.append(path.getString(namespaceRegistry, encoder, delimiterEncoder));
+                } else if (value instanceof Name) {
+                    Name name = (Name)value;
+                    sb.append(name.getString(namespaceRegistry, encoder, delimiterEncoder));
+                } else {
+                    sb.append(value);
+                }
+            }
+            if (isMultiple()) sb.append("]");
+        }
+        return sb.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getName());
+        sb.append(" = ");
+        if (isSingle()) {
+            sb.append(getValues().next());
+        } else if (isEmpty()) {
+            sb.append("null");
+        } else {
+            sb.append(Arrays.asList(getValuesAsArray()));
+        }
+        return sb.toString();
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPropertyFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPropertyFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPropertyFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,165 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.ValueFactory;
-
-/**
- * @author Randall Hauch
- */
-public class BasicPropertyFactory implements PropertyFactory {
-
-    private final ValueFactories factories;
-
-    /**
-     * @param valueFactories the value factories
-     * @throws IllegalArgumentException if the reference to the value factories is null
-     */
-    public BasicPropertyFactory( ValueFactories valueFactories ) {
-        CheckArg.isNotNull(valueFactories, "value factories");
-        this.factories = valueFactories;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Property create( Name name,
-                            Iterable<?> values ) {
-        return create(name, PropertyType.OBJECT, values);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Property create( Name name,
-                            Iterator<?> values ) {
-        return create(name, PropertyType.OBJECT, values);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Property create( Name name,
-                            Object... values ) {
-        return create(name, PropertyType.OBJECT, values);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Property create( Name name,
-                            PropertyType desiredType,
-                            Object... values ) {
-        CheckArg.isNotNull(name, "name");
-        if (values == null || values.length == 0) {
-            return new BasicEmptyProperty(name);
-        }
-        final int len = values.length;
-        if (desiredType == null) desiredType = PropertyType.OBJECT;
-        final ValueFactory<?> factory = factories.getValueFactory(desiredType);
-        if (values.length == 1) {
-            Object value = values[0];
-            // Check whether the sole value was a collection ...
-            if (value instanceof Collection) {
-                // The single value is a collection, so create property with the collection's contents ...
-                return create(name, (Collection<?>)value);
-            }
-            value = factory.create(values[0]);
-            return new BasicSingleValueProperty(name, value);
-        }
-        List<Object> valueList = new ArrayList<Object>(len);
-        for (int i = 0; i != len; ++i) {
-            Object value = factory.create(values[i]);
-            valueList.add(value);
-        }
-        return new BasicMultiValueProperty(name, valueList);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @SuppressWarnings( "unchecked" )
-    public Property create( Name name,
-                            PropertyType desiredType,
-                            Iterable<?> values ) {
-        CheckArg.isNotNull(name, "name");
-        List<Object> valueList = null;
-        if (values instanceof Collection) {
-            Collection<Object> originalValues = (Collection<Object>)values;
-            if (originalValues.isEmpty()) {
-                return new BasicEmptyProperty(name);
-            }
-            valueList = new ArrayList<Object>(originalValues.size());
-        } else {
-            // We don't know the size
-            valueList = new ArrayList<Object>();
-        }
-        // Copy the values, ensuring that the values are the correct type ...
-        if (desiredType == null) desiredType = PropertyType.OBJECT;
-        final ValueFactory<?> factory = factories.getValueFactory(desiredType);
-        for (Object value : values) {
-            valueList.add(factory.create(value));
-        }
-        if (valueList.isEmpty()) { // may not have been a collection earlier
-            return new BasicEmptyProperty(name);
-        }
-        if (valueList.size() == 1) {
-            return new BasicSingleValueProperty(name, valueList.get(0));
-        }
-        return new BasicMultiValueProperty(name, valueList);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Property create( Name name,
-                            PropertyType desiredType,
-                            Iterator<?> values ) {
-        CheckArg.isNotNull(name, "name");
-        final List<Object> valueList = new ArrayList<Object>();
-        if (desiredType == null) desiredType = PropertyType.OBJECT;
-        final ValueFactory<?> factory = factories.getValueFactory(desiredType);
-        while (values.hasNext()) {
-            Object value = values.next();
-            value = factory.create(value);
-            valueList.add(value);
-        }
-        if (valueList.isEmpty()) {
-            return new BasicEmptyProperty(name);
-        }
-        if (valueList.size() == 1) {
-            return new BasicSingleValueProperty(name, valueList.get(0));
-        }
-        return new BasicMultiValueProperty(name, valueList);
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPropertyFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPropertyFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPropertyFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicPropertyFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,165 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.ValueFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicPropertyFactory implements PropertyFactory {
+
+    private final ValueFactories factories;
+
+    /**
+     * @param valueFactories the value factories
+     * @throws IllegalArgumentException if the reference to the value factories is null
+     */
+    public BasicPropertyFactory( ValueFactories valueFactories ) {
+        CheckArg.isNotNull(valueFactories, "value factories");
+        this.factories = valueFactories;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Property create( Name name,
+                            Iterable<?> values ) {
+        return create(name, PropertyType.OBJECT, values);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Property create( Name name,
+                            Iterator<?> values ) {
+        return create(name, PropertyType.OBJECT, values);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Property create( Name name,
+                            Object... values ) {
+        return create(name, PropertyType.OBJECT, values);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Property create( Name name,
+                            PropertyType desiredType,
+                            Object... values ) {
+        CheckArg.isNotNull(name, "name");
+        if (values == null || values.length == 0) {
+            return new BasicEmptyProperty(name);
+        }
+        final int len = values.length;
+        if (desiredType == null) desiredType = PropertyType.OBJECT;
+        final ValueFactory<?> factory = factories.getValueFactory(desiredType);
+        if (values.length == 1) {
+            Object value = values[0];
+            // Check whether the sole value was a collection ...
+            if (value instanceof Collection) {
+                // The single value is a collection, so create property with the collection's contents ...
+                return create(name, (Collection<?>)value);
+            }
+            value = factory.create(values[0]);
+            return new BasicSingleValueProperty(name, value);
+        }
+        List<Object> valueList = new ArrayList<Object>(len);
+        for (int i = 0; i != len; ++i) {
+            Object value = factory.create(values[i]);
+            valueList.add(value);
+        }
+        return new BasicMultiValueProperty(name, valueList);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings( "unchecked" )
+    public Property create( Name name,
+                            PropertyType desiredType,
+                            Iterable<?> values ) {
+        CheckArg.isNotNull(name, "name");
+        List<Object> valueList = null;
+        if (values instanceof Collection) {
+            Collection<Object> originalValues = (Collection<Object>)values;
+            if (originalValues.isEmpty()) {
+                return new BasicEmptyProperty(name);
+            }
+            valueList = new ArrayList<Object>(originalValues.size());
+        } else {
+            // We don't know the size
+            valueList = new ArrayList<Object>();
+        }
+        // Copy the values, ensuring that the values are the correct type ...
+        if (desiredType == null) desiredType = PropertyType.OBJECT;
+        final ValueFactory<?> factory = factories.getValueFactory(desiredType);
+        for (Object value : values) {
+            valueList.add(factory.create(value));
+        }
+        if (valueList.isEmpty()) { // may not have been a collection earlier
+            return new BasicEmptyProperty(name);
+        }
+        if (valueList.size() == 1) {
+            return new BasicSingleValueProperty(name, valueList.get(0));
+        }
+        return new BasicMultiValueProperty(name, valueList);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Property create( Name name,
+                            PropertyType desiredType,
+                            Iterator<?> values ) {
+        CheckArg.isNotNull(name, "name");
+        final List<Object> valueList = new ArrayList<Object>();
+        if (desiredType == null) desiredType = PropertyType.OBJECT;
+        final ValueFactory<?> factory = factories.getValueFactory(desiredType);
+        while (values.hasNext()) {
+            Object value = values.next();
+            value = factory.create(value);
+            valueList.add(value);
+        }
+        if (valueList.isEmpty()) {
+            return new BasicEmptyProperty(name);
+        }
+        if (valueList.size() == 1) {
+            return new BasicSingleValueProperty(name, valueList.get(0));
+        }
+        return new BasicMultiValueProperty(name, valueList);
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicSingleValueProperty.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicSingleValueProperty.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicSingleValueProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,130 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.properties.Name;
-
-/**
- * An immutable version of a property that has exactly 1 value. This is done for efficiency of the in-memory representation, since
- * many properties will have just a single value, while others will have multiple values.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class BasicSingleValueProperty extends BasicProperty {
-
-    protected final Object value;
-
-    /**
-     * Create a property with a single value
-     * 
-     * @param name the property name
-     * @param value the property value (which may be null)
-     */
-    public BasicSingleValueProperty( Name name,
-                                     Object value ) {
-        super(name);
-        this.value = value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isEmpty() {
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isMultiple() {
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isSingle() {
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int size() {
-        return 1;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Property#getFirstValue()
-     */
-    public Object getFirstValue() {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<Object> iterator() {
-        return new ValueIterator();
-    }
-
-    protected class ValueIterator implements Iterator<Object> {
-
-        private boolean done = false;
-
-        protected ValueIterator() {
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean hasNext() {
-            return !done;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Object next() {
-            if (!done) {
-                done = true;
-                return BasicSingleValueProperty.this.value;
-            }
-            throw new NoSuchElementException();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicSingleValueProperty.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicSingleValueProperty.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicSingleValueProperty.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicSingleValueProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,130 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.property.Name;
+
+/**
+ * An immutable version of a property that has exactly 1 value. This is done for efficiency of the in-memory representation, since
+ * many properties will have just a single value, while others will have multiple values.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class BasicSingleValueProperty extends BasicProperty {
+
+    protected final Object value;
+
+    /**
+     * Create a property with a single value
+     * 
+     * @param name the property name
+     * @param value the property value (which may be null)
+     */
+    public BasicSingleValueProperty( Name name,
+                                     Object value ) {
+        super(name);
+        this.value = value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEmpty() {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isMultiple() {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isSingle() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int size() {
+        return 1;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Property#getFirstValue()
+     */
+    public Object getFirstValue() {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<Object> iterator() {
+        return new ValueIterator();
+    }
+
+    protected class ValueIterator implements Iterator<Object> {
+
+        private boolean done = false;
+
+        protected ValueIterator() {
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean hasNext() {
+            return !done;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Object next() {
+            if (!done) {
+                done = true;
+                return BasicSingleValueProperty.this.value;
+            }
+            throw new NoSuchElementException();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BooleanValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BooleanValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BooleanValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,249 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#BOOLEAN} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class BooleanValueFactory extends AbstractValueFactory<Boolean> {
-
-    public BooleanValueFactory( TextDecoder decoder,
-                                ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.BOOLEAN, decoder, stringValueFactory);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( String value ) {
-        if (value == null) return null;
-        return Boolean.valueOf(value.trim());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( String value,
-                           TextDecoder decoder ) {
-        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
-        return create(getDecoder(decoder).decode(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( int value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Integer.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( long value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Long.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( boolean value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( float value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Float.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( double value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Double.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( BigDecimal value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        BigDecimal.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( Calendar value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Calendar.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( Date value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Date.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public Boolean create( DateTime value ) throws ValueFormatException {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  DateTime.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( Name value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Name.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( Path value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Path.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( Reference value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        Reference.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( URI value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  URI.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public Boolean create( UUID value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  UUID.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( byte[] value ) {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public Boolean create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( InputStream stream,
-                           long approximateLength ) throws IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Boolean create( Reader reader,
-                           long approximateLength ) throws IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Boolean[] createEmptyArray( int length ) {
-        return new Boolean[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BooleanValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BooleanValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BooleanValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BooleanValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,249 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#BOOLEAN} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class BooleanValueFactory extends AbstractValueFactory<Boolean> {
+
+    public BooleanValueFactory( TextDecoder decoder,
+                                ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.BOOLEAN, decoder, stringValueFactory);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( String value ) {
+        if (value == null) return null;
+        return Boolean.valueOf(value.trim());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( String value,
+                           TextDecoder decoder ) {
+        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
+        return create(getDecoder(decoder).decode(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( int value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Integer.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( long value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Long.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( boolean value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( float value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Float.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( double value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Double.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( BigDecimal value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        BigDecimal.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( Calendar value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Calendar.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( Date value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Date.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public Boolean create( DateTime value ) throws ValueFormatException {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  DateTime.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( Name value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Name.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( Path value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Path.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( Reference value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        Reference.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( URI value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  URI.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public Boolean create( UUID value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  UUID.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( byte[] value ) {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public Boolean create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( InputStream stream,
+                           long approximateLength ) throws IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean create( Reader reader,
+                           long approximateLength ) throws IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Boolean[] createEmptyArray( int length ) {
+        return new Boolean[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ChildPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/ChildPath.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ChildPath.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,261 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-import org.jboss.dna.common.collection.ImmutableAppendedList;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.Path;
-
-/**
- * Implementation of a {@link Path} that has the information for the last segment but that points to another Path for the parent
- * information.
- * 
- * @author Randall Hauch
- */
-public class ChildPath extends AbstractPath {
-
-    /**
-     * The serializable version. Version {@value}
-     */
-    private static final long serialVersionUID = 1L;
-
-    private final Path parent;
-    private final Path.Segment child;
-    private final int size;
-    private transient List<Segment> cachedSegmentList;
-
-    public ChildPath( Path parent,
-                      Path.Segment child ) {
-        assert parent != null;
-        assert child != null;
-        this.parent = parent;
-        this.child = child;
-        this.size = this.parent.size() + 1;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getAncestor(int)
-     */
-    public Path getAncestor( int degree ) {
-        CheckArg.isNonNegative(degree, "degree");
-        if (degree == 0) return this;
-        if (degree == 1) return parent;
-        return parent.getAncestor(degree - 1);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getLastSegment()
-     */
-    @Override
-    public Segment getLastSegment() {
-        return child;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getParent()
-     */
-    @Override
-    public Path getParent() {
-        return parent;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getSegment(int)
-     */
-    @Override
-    public Segment getSegment( int index ) {
-        if (index == (size - 1)) return child;
-        return parent.getSegment(index - 1);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getSegmentsList()
-     */
-    public List<Segment> getSegmentsList() {
-        if (cachedSegmentList == null) {
-            // No need to synchronize, since this is idempotent and thus the list will be as well
-            List<Segment> segments = null;
-            if (parent.isRoot()) {
-                segments = Collections.singletonList(child); // already immutable
-            } else if (size < 4) {
-                segments = new ArrayList<Segment>(size);
-                for (Segment segment : parent) {
-                    segments.add(segment);
-                }
-                segments.add(child);
-                segments = Collections.unmodifiableList(segments);
-            } else {
-                segments = new ImmutableAppendedList<Segment>(parent.getSegmentsList(), child);
-            }
-            cachedSegmentList = segments;
-        }
-        return cachedSegmentList;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#hasSameAncestor(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public boolean hasSameAncestor( Path that ) {
-        CheckArg.isNotNull(that, "that");
-        if (parent.equals(that.getParent())) return true;
-        return super.hasSameAncestor(that);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isAbsolute()
-     */
-    public boolean isAbsolute() {
-        return parent.isAbsolute();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isAtOrBelow(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public boolean isAtOrBelow( Path other ) {
-        if (this == other || parent == other) return true;
-        return super.isAtOrBelow(other);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isDecendantOf(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public boolean isDecendantOf( Path ancestor ) {
-        if (parent == ancestor) return true; // same instance
-        return parent.isAtOrBelow(ancestor);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isNormalized()
-     */
-    public boolean isNormalized() {
-        if (child.isParentReference() || child.isSelfReference()) return false;
-        return parent.isNormalized();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isRoot()
-     */
-    public boolean isRoot() {
-        if (child.isParentReference()) return parent.isRoot();
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#iterator()
-     */
-    @Override
-    @SuppressWarnings( "synthetic-access" )
-    public Iterator<Segment> iterator() {
-        if (parent.isRoot()) {
-            return new Iterator<Segment>() {
-                boolean finished = false;
-
-                public boolean hasNext() {
-                    return !finished;
-                }
-
-                public Segment next() {
-                    if (finished) throw new NoSuchElementException();
-                    finished = true;
-                    return ChildPath.this.child;
-                }
-
-                public void remove() {
-                    throw new UnsupportedOperationException();
-                }
-            };
-        }
-        final Iterator<Segment> parentIterator = parent.iterator();
-        return new Iterator<Segment>() {
-            boolean finished = false;
-
-            public boolean hasNext() {
-                return parentIterator.hasNext() || !finished;
-            }
-
-            public Segment next() {
-                if (parentIterator.hasNext()) return parentIterator.next();
-                if (finished) throw new NoSuchElementException();
-                finished = true;
-                return ChildPath.this.child;
-            }
-
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#size()
-     */
-    public int size() {
-        return size;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#subpath(int, int)
-     */
-    @Override
-    public Path subpath( int beginIndex,
-                         int endIndex ) {
-        if (beginIndex == 0 && endIndex == (size - 1)) return parent;
-        return super.subpath(beginIndex, endIndex);
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ChildPath.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/ChildPath.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ChildPath.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ChildPath.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,261 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import org.jboss.dna.common.collection.ImmutableAppendedList;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * Implementation of a {@link Path} that has the information for the last segment but that points to another Path for the parent
+ * information.
+ * 
+ * @author Randall Hauch
+ */
+public class ChildPath extends AbstractPath {
+
+    /**
+     * The serializable version. Version {@value}
+     */
+    private static final long serialVersionUID = 1L;
+
+    private final Path parent;
+    private final Path.Segment child;
+    private final int size;
+    private transient List<Segment> cachedSegmentList;
+
+    public ChildPath( Path parent,
+                      Path.Segment child ) {
+        assert parent != null;
+        assert child != null;
+        this.parent = parent;
+        this.child = child;
+        this.size = this.parent.size() + 1;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getAncestor(int)
+     */
+    public Path getAncestor( int degree ) {
+        CheckArg.isNonNegative(degree, "degree");
+        if (degree == 0) return this;
+        if (degree == 1) return parent;
+        return parent.getAncestor(degree - 1);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getLastSegment()
+     */
+    @Override
+    public Segment getLastSegment() {
+        return child;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getParent()
+     */
+    @Override
+    public Path getParent() {
+        return parent;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getSegment(int)
+     */
+    @Override
+    public Segment getSegment( int index ) {
+        if (index == (size - 1)) return child;
+        return parent.getSegment(index - 1);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getSegmentsList()
+     */
+    public List<Segment> getSegmentsList() {
+        if (cachedSegmentList == null) {
+            // No need to synchronize, since this is idempotent and thus the list will be as well
+            List<Segment> segments = null;
+            if (parent.isRoot()) {
+                segments = Collections.singletonList(child); // already immutable
+            } else if (size < 4) {
+                segments = new ArrayList<Segment>(size);
+                for (Segment segment : parent) {
+                    segments.add(segment);
+                }
+                segments.add(child);
+                segments = Collections.unmodifiableList(segments);
+            } else {
+                segments = new ImmutableAppendedList<Segment>(parent.getSegmentsList(), child);
+            }
+            cachedSegmentList = segments;
+        }
+        return cachedSegmentList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#hasSameAncestor(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public boolean hasSameAncestor( Path that ) {
+        CheckArg.isNotNull(that, "that");
+        if (parent.equals(that.getParent())) return true;
+        return super.hasSameAncestor(that);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isAbsolute()
+     */
+    public boolean isAbsolute() {
+        return parent.isAbsolute();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isAtOrBelow(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public boolean isAtOrBelow( Path other ) {
+        if (this == other || parent == other) return true;
+        return super.isAtOrBelow(other);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isDecendantOf(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public boolean isDecendantOf( Path ancestor ) {
+        if (parent == ancestor) return true; // same instance
+        return parent.isAtOrBelow(ancestor);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isNormalized()
+     */
+    public boolean isNormalized() {
+        if (child.isParentReference() || child.isSelfReference()) return false;
+        return parent.isNormalized();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isRoot()
+     */
+    public boolean isRoot() {
+        if (child.isParentReference()) return parent.isRoot();
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#iterator()
+     */
+    @Override
+    @SuppressWarnings( "synthetic-access" )
+    public Iterator<Segment> iterator() {
+        if (parent.isRoot()) {
+            return new Iterator<Segment>() {
+                boolean finished = false;
+
+                public boolean hasNext() {
+                    return !finished;
+                }
+
+                public Segment next() {
+                    if (finished) throw new NoSuchElementException();
+                    finished = true;
+                    return ChildPath.this.child;
+                }
+
+                public void remove() {
+                    throw new UnsupportedOperationException();
+                }
+            };
+        }
+        final Iterator<Segment> parentIterator = parent.iterator();
+        return new Iterator<Segment>() {
+            boolean finished = false;
+
+            public boolean hasNext() {
+                return parentIterator.hasNext() || !finished;
+            }
+
+            public Segment next() {
+                if (parentIterator.hasNext()) return parentIterator.next();
+                if (finished) throw new NoSuchElementException();
+                finished = true;
+                return ChildPath.this.child;
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#size()
+     */
+    public int size() {
+        return size;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#subpath(int, int)
+     */
+    @Override
+    public Path subpath( int beginIndex,
+                         int endIndex ) {
+        if (beginIndex == 0 && endIndex == (size - 1)) return parent;
+        return super.subpath(beginIndex, endIndex);
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DecimalValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/DecimalValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DecimalValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,244 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#DECIMAL} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class DecimalValueFactory extends AbstractValueFactory<BigDecimal> {
-
-    public DecimalValueFactory( TextDecoder decoder,
-                                ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.DECIMAL, decoder, stringValueFactory);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( String value ) {
-        if (value == null) return null;
-        try {
-            return new BigDecimal(value.trim());
-        } catch (NumberFormatException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                            BigDecimal.class.getSimpleName(),
-                                                                            value), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( String value,
-                              TextDecoder decoder ) {
-        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
-        return create(getDecoder(decoder).decode(value.trim()));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( int value ) {
-        return BigDecimal.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( long value ) {
-        return BigDecimal.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( boolean value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Boolean.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( float value ) {
-        return BigDecimal.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( double value ) {
-        return BigDecimal.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( BigDecimal value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( Calendar value ) {
-        if (value == null) return null;
-        return create(value.getTimeInMillis());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( Date value ) {
-        if (value == null) return null;
-        return create(value.getTime());
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public BigDecimal create( DateTime value ) throws ValueFormatException {
-        if (value == null) return null;
-        return create(value.getMilliseconds());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( Name value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Name.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( Path value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Path.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( Reference value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        Reference.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( URI value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  URI.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public BigDecimal create( UUID value ) throws IoException {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  UUID.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( byte[] value ) {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public BigDecimal create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( InputStream stream,
-                              long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BigDecimal create( Reader reader,
-                              long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected BigDecimal[] createEmptyArray( int length ) {
-        return new BigDecimal[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DecimalValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/DecimalValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DecimalValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DecimalValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,244 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#DECIMAL} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class DecimalValueFactory extends AbstractValueFactory<BigDecimal> {
+
+    public DecimalValueFactory( TextDecoder decoder,
+                                ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.DECIMAL, decoder, stringValueFactory);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( String value ) {
+        if (value == null) return null;
+        try {
+            return new BigDecimal(value.trim());
+        } catch (NumberFormatException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                            BigDecimal.class.getSimpleName(),
+                                                                            value), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( String value,
+                              TextDecoder decoder ) {
+        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
+        return create(getDecoder(decoder).decode(value.trim()));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( int value ) {
+        return BigDecimal.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( long value ) {
+        return BigDecimal.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( boolean value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Boolean.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( float value ) {
+        return BigDecimal.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( double value ) {
+        return BigDecimal.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( BigDecimal value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( Calendar value ) {
+        if (value == null) return null;
+        return create(value.getTimeInMillis());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( Date value ) {
+        if (value == null) return null;
+        return create(value.getTime());
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public BigDecimal create( DateTime value ) throws ValueFormatException {
+        if (value == null) return null;
+        return create(value.getMilliseconds());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( Name value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Name.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( Path value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Path.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( Reference value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        Reference.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( URI value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  URI.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public BigDecimal create( UUID value ) throws IoException {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  UUID.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( byte[] value ) {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public BigDecimal create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( InputStream stream,
+                              long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BigDecimal create( Reader reader,
+                              long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected BigDecimal[] createEmptyArray( int length ) {
+        return new BigDecimal[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DelegatingValueFactories.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/DelegatingValueFactories.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DelegatingValueFactories.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,99 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.math.BigDecimal;
-import java.net.URI;
-import org.jboss.dna.graph.properties.BinaryFactory;
-import org.jboss.dna.graph.properties.DateTimeFactory;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.UuidFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.ValueFactory;
-
-/**
- * @author Randall Hauch
- */
-public class DelegatingValueFactories extends AbstractValueFactories {
-
-    private final ValueFactories delegate;
-
-    protected DelegatingValueFactories( ValueFactories delegate ) {
-        assert delegate != null;
-        this.delegate = delegate;
-    }
-
-    public BinaryFactory getBinaryFactory() {
-        return delegate.getBinaryFactory();
-    }
-
-    public ValueFactory<Boolean> getBooleanFactory() {
-        return delegate.getBooleanFactory();
-    }
-
-    public DateTimeFactory getDateFactory() {
-        return delegate.getDateFactory();
-    }
-
-    public ValueFactory<BigDecimal> getDecimalFactory() {
-        return delegate.getDecimalFactory();
-    }
-
-    public ValueFactory<Double> getDoubleFactory() {
-        return delegate.getDoubleFactory();
-    }
-
-    public ValueFactory<Long> getLongFactory() {
-        return delegate.getLongFactory();
-    }
-
-    public NameFactory getNameFactory() {
-        return delegate.getNameFactory();
-    }
-
-    public ValueFactory<Object> getObjectFactory() {
-        return delegate.getObjectFactory();
-    }
-
-    public PathFactory getPathFactory() {
-        return delegate.getPathFactory();
-    }
-
-    public ValueFactory<Reference> getReferenceFactory() {
-        return delegate.getReferenceFactory();
-    }
-
-    public ValueFactory<String> getStringFactory() {
-        return delegate.getStringFactory();
-    }
-
-    public ValueFactory<URI> getUriFactory() {
-        return delegate.getUriFactory();
-    }
-
-    public UuidFactory getUuidFactory() {
-        return delegate.getUuidFactory();
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DelegatingValueFactories.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/DelegatingValueFactories.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DelegatingValueFactories.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DelegatingValueFactories.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,99 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.math.BigDecimal;
+import java.net.URI;
+import org.jboss.dna.graph.property.BinaryFactory;
+import org.jboss.dna.graph.property.DateTimeFactory;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.UuidFactory;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.ValueFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public class DelegatingValueFactories extends AbstractValueFactories {
+
+    private final ValueFactories delegate;
+
+    protected DelegatingValueFactories( ValueFactories delegate ) {
+        assert delegate != null;
+        this.delegate = delegate;
+    }
+
+    public BinaryFactory getBinaryFactory() {
+        return delegate.getBinaryFactory();
+    }
+
+    public ValueFactory<Boolean> getBooleanFactory() {
+        return delegate.getBooleanFactory();
+    }
+
+    public DateTimeFactory getDateFactory() {
+        return delegate.getDateFactory();
+    }
+
+    public ValueFactory<BigDecimal> getDecimalFactory() {
+        return delegate.getDecimalFactory();
+    }
+
+    public ValueFactory<Double> getDoubleFactory() {
+        return delegate.getDoubleFactory();
+    }
+
+    public ValueFactory<Long> getLongFactory() {
+        return delegate.getLongFactory();
+    }
+
+    public NameFactory getNameFactory() {
+        return delegate.getNameFactory();
+    }
+
+    public ValueFactory<Object> getObjectFactory() {
+        return delegate.getObjectFactory();
+    }
+
+    public PathFactory getPathFactory() {
+        return delegate.getPathFactory();
+    }
+
+    public ValueFactory<Reference> getReferenceFactory() {
+        return delegate.getReferenceFactory();
+    }
+
+    public ValueFactory<String> getStringFactory() {
+        return delegate.getStringFactory();
+    }
+
+    public ValueFactory<URI> getUriFactory() {
+        return delegate.getUriFactory();
+    }
+
+    public UuidFactory getUuidFactory() {
+        return delegate.getUuidFactory();
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DoubleValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/DoubleValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DoubleValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,252 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#DOUBLE} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class DoubleValueFactory extends AbstractValueFactory<Double> {
-
-    public DoubleValueFactory( TextDecoder decoder,
-                               ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.DOUBLE, decoder, stringValueFactory);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( String value ) {
-        if (value == null) return null;
-        try {
-            return Double.valueOf(value.trim());
-        } catch (NumberFormatException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                            Double.class.getSimpleName(),
-                                                                            value), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( String value,
-                          TextDecoder decoder ) {
-        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
-        return create(getDecoder(decoder).decode(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( int value ) {
-        return Double.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( long value ) {
-        return new Double(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( boolean value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Double.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( float value ) {
-        return Double.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( double value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( BigDecimal value ) {
-        if (value == null) return null;
-        double result = value.doubleValue();
-        if (result == Double.NEGATIVE_INFINITY || result == Double.POSITIVE_INFINITY) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(BigDecimal.class.getSimpleName(),
-                                                                            Double.class.getSimpleName(),
-                                                                            value));
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( Calendar value ) {
-        if (value == null) return null;
-        return create(value.getTimeInMillis());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( Date value ) {
-        if (value == null) return null;
-        return create(value.getTime());
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public Double create( DateTime value ) throws ValueFormatException {
-        if (value == null) return null;
-        return create(value.getMilliseconds());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( Name value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Name.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( Path value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Path.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( Reference value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        Reference.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( URI value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  URI.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public Double create( UUID value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  UUID.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( byte[] value ) {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public Double create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( InputStream stream,
-                          long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Double create( Reader reader,
-                          long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Double[] createEmptyArray( int length ) {
-        return new Double[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DoubleValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/DoubleValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DoubleValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/DoubleValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,252 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#DOUBLE} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class DoubleValueFactory extends AbstractValueFactory<Double> {
+
+    public DoubleValueFactory( TextDecoder decoder,
+                               ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.DOUBLE, decoder, stringValueFactory);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( String value ) {
+        if (value == null) return null;
+        try {
+            return Double.valueOf(value.trim());
+        } catch (NumberFormatException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                            Double.class.getSimpleName(),
+                                                                            value), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( String value,
+                          TextDecoder decoder ) {
+        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
+        return create(getDecoder(decoder).decode(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( int value ) {
+        return Double.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( long value ) {
+        return new Double(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( boolean value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Double.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( float value ) {
+        return Double.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( double value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( BigDecimal value ) {
+        if (value == null) return null;
+        double result = value.doubleValue();
+        if (result == Double.NEGATIVE_INFINITY || result == Double.POSITIVE_INFINITY) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(BigDecimal.class.getSimpleName(),
+                                                                            Double.class.getSimpleName(),
+                                                                            value));
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( Calendar value ) {
+        if (value == null) return null;
+        return create(value.getTimeInMillis());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( Date value ) {
+        if (value == null) return null;
+        return create(value.getTime());
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public Double create( DateTime value ) throws ValueFormatException {
+        if (value == null) return null;
+        return create(value.getMilliseconds());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( Name value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Name.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( Path value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Path.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( Reference value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        Reference.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( URI value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  URI.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public Double create( UUID value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  UUID.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( byte[] value ) {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public Double create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( InputStream stream,
+                          long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Double create( Reader reader,
+                          long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Double[] createEmptyArray( int length ) {
+        return new Double[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/InMemoryBinary.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,98 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.Binary;
-
-/**
- * An implementation of {@link Binary} that keeps the binary data in-memory.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class InMemoryBinary extends AbstractBinary {
-
-    /**
-     * Version {@value} .
-     */
-    private static final long serialVersionUID = 2L;
-
-    private final byte[] bytes;
-    private byte[] sha1hash;
-
-    public InMemoryBinary( byte[] bytes ) {
-        CheckArg.isNotNull(bytes, "bytes");
-        this.bytes = bytes;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public long getSize() {
-        return this.bytes.length;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Binary#getHash()
-     */
-    public byte[] getHash() {
-        if (sha1hash == null) {
-            // Idempotent, so doesn't matter if we recompute in concurrent threads ...
-            sha1hash = computeHash(bytes);
-        }
-        return sha1hash;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public byte[] getBytes() {
-        return this.bytes;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public InputStream getStream() {
-        return new ByteArrayInputStream(this.bytes);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void acquire() {
-        // do nothing
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void release() {
-        // do nothing
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/InMemoryBinary.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,98 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.Binary;
+
+/**
+ * An implementation of {@link Binary} that keeps the binary data in-memory.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class InMemoryBinary extends AbstractBinary {
+
+    /**
+     * Version {@value} .
+     */
+    private static final long serialVersionUID = 2L;
+
+    private final byte[] bytes;
+    private byte[] sha1hash;
+
+    public InMemoryBinary( byte[] bytes ) {
+        CheckArg.isNotNull(bytes, "bytes");
+        this.bytes = bytes;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getSize() {
+        return this.bytes.length;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Binary#getHash()
+     */
+    public byte[] getHash() {
+        if (sha1hash == null) {
+            // Idempotent, so doesn't matter if we recompute in concurrent threads ...
+            sha1hash = computeHash(bytes);
+        }
+        return sha1hash;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte[] getBytes() {
+        return this.bytes;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public InputStream getStream() {
+        return new ByteArrayInputStream(this.bytes);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void acquire() {
+        // do nothing
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void release() {
+        // do nothing
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/InMemoryBinaryValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,53 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.ValueFactory;
-
-/**
- * The {@link ValueFactory} for in-memory {@link PropertyType#BINARY} values.
- * <p>
- * This factory does not {@link #find(byte[]) reuse} any instances.
- * </p>
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class InMemoryBinaryValueFactory extends AbstractBinaryValueFactory {
-
-    public InMemoryBinaryValueFactory( TextDecoder decoder,
-                                       ValueFactory<String> stringValueFactory ) {
-        super(decoder, stringValueFactory);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Binary create( byte[] value ) {
-        return new InMemoryBinary(value);
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/InMemoryBinaryValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.ValueFactory;
+
+/**
+ * The {@link ValueFactory} for in-memory {@link PropertyType#BINARY} values.
+ * <p>
+ * This factory does not {@link #find(byte[]) reuse} any instances.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class InMemoryBinaryValueFactory extends AbstractBinaryValueFactory {
+
+    public InMemoryBinaryValueFactory( TextDecoder decoder,
+                                       ValueFactory<String> stringValueFactory ) {
+        super(decoder, stringValueFactory);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Binary create( byte[] value ) {
+        return new InMemoryBinary(value);
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTime.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/JodaDateTime.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTime.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,567 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.concurrent.TimeUnit;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.CheckArg;
-import org.joda.time.Chronology;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-
-/**
- * Implementation of DateTime based upon the Joda-Time library.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class JodaDateTime implements org.jboss.dna.graph.properties.DateTime {
-
-    /**
-     */
-    private static final long serialVersionUID = -730188225988292422L;
-
-    private static final int MILLIS_IN_HOUR = 1000 * 60 * 60;
-
-    private final DateTime instance;
-
-    public JodaDateTime() {
-        this.instance = new DateTime();
-    }
-
-    public JodaDateTime( String iso8601 ) {
-        this.instance = new DateTime(iso8601);
-    }
-
-    public JodaDateTime( String iso8601,
-                         String timeZoneId ) {
-        this.instance = new DateTime(iso8601, DateTimeZone.forID(timeZoneId));
-    }
-
-    public JodaDateTime( long milliseconds ) {
-        this.instance = new DateTime(milliseconds);
-    }
-
-    public JodaDateTime( long milliseconds,
-                         Chronology chronology ) {
-        this.instance = new DateTime(milliseconds, chronology);
-    }
-
-    public JodaDateTime( long milliseconds,
-                         String timeZoneId ) {
-        this.instance = new DateTime(milliseconds, DateTimeZone.forID(timeZoneId));
-    }
-
-    public JodaDateTime( DateTimeZone dateTimeZone ) {
-        this.instance = new DateTime(dateTimeZone);
-    }
-
-    public JodaDateTime( int year,
-                         int monthOfYear,
-                         int dayOfMonth,
-                         int hourOfDay,
-                         int minuteOfHour,
-                         int secondOfMinute,
-                         int millisecondsOfSecond ) {
-        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisecondsOfSecond);
-    }
-
-    public JodaDateTime( int year,
-                         int monthOfYear,
-                         int dayOfMonth,
-                         int hourOfDay,
-                         int minuteOfHour,
-                         int secondOfMinute,
-                         int millisecondsOfSecond,
-                         Chronology chronology ) {
-        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
-                                     millisecondsOfSecond, chronology);
-    }
-
-    public JodaDateTime( int year,
-                         int monthOfYear,
-                         int dayOfMonth,
-                         int hourOfDay,
-                         int minuteOfHour,
-                         int secondOfMinute,
-                         int millisecondsOfSecond,
-                         DateTimeZone dateTimeZone ) {
-        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
-                                     millisecondsOfSecond, dateTimeZone);
-    }
-
-    public JodaDateTime( int year,
-                         int monthOfYear,
-                         int dayOfMonth,
-                         int hourOfDay,
-                         int minuteOfHour,
-                         int secondOfMinute,
-                         int millisecondsOfSecond,
-                         int timeZoneOffsetHours ) {
-        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
-                                     millisecondsOfSecond, DateTimeZone.forOffsetHours(timeZoneOffsetHours));
-    }
-
-    public JodaDateTime( int year,
-                         int monthOfYear,
-                         int dayOfMonth,
-                         int hourOfDay,
-                         int minuteOfHour,
-                         int secondOfMinute,
-                         int millisecondsOfSecond,
-                         String timeZoneId ) {
-        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
-                                     millisecondsOfSecond, DateTimeZone.forID(timeZoneId));
-    }
-
-    public JodaDateTime( java.util.Date jdkDate ) {
-        this.instance = new DateTime(jdkDate);
-    }
-
-    public JodaDateTime( java.util.Calendar jdkCalendar ) {
-        this.instance = new DateTime(jdkCalendar);
-    }
-
-    public JodaDateTime( DateTime dateTime ) {
-        this.instance = dateTime; // it's immutable, so just hold onto the supplied instance
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getCenturyOfEra() {
-        return this.instance.getCenturyOfEra();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getDayOfMonth() {
-        return this.instance.getDayOfMonth();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getDayOfWeek() {
-        return this.instance.getDayOfWeek();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getDayOfYear() {
-        return this.instance.getDayOfYear();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getEra() {
-        return this.instance.getEra();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getHourOfDay() {
-        return this.instance.getHourOfDay();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getMillisOfSecond() {
-        return this.instance.getMillisOfSecond();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public long getMilliseconds() {
-        return this.instance.getMillis();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getMinuteOfHour() {
-        return this.instance.getMinuteOfHour();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getMonthOfYear() {
-        return this.instance.getMonthOfYear();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getSecondOfMinute() {
-        return this.instance.getSecondOfMinute();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString() {
-        return this.instance.toString(org.joda.time.format.ISODateTimeFormat.dateTime());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getWeekOfWeekyear() {
-        return this.instance.getWeekOfWeekyear();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getWeekyear() {
-        return this.instance.getWeekyear();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getYear() {
-        return this.instance.getYear();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getYearOfCentury() {
-        return this.instance.getYearOfCentury();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getYearOfEra() {
-        return this.instance.getYearOfEra();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getTimeZoneOffsetHours() {
-        // return this.instance.getZone().toTimeZone().getRawOffset() / MILLIS_IN_HOUR;
-        return this.instance.getZone().getOffset(this.instance.getMillis()) / MILLIS_IN_HOUR;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getTimeZoneId() {
-        return this.instance.getZone().getID();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Calendar toCalendar() {
-        return toCalendar(null);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Calendar toCalendar( Locale locale ) {
-        return this.instance.toCalendar(locale);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Date toDate() {
-        return this.instance.toDate();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public GregorianCalendar toGregorianCalendar() {
-        return this.instance.toGregorianCalendar();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int compareTo( org.jboss.dna.graph.properties.DateTime that ) {
-        if (that instanceof JodaDateTime) {
-            return this.instance.compareTo(((JodaDateTime)that).instance);
-        }
-        long diff = this.toUtcTimeZone().getMilliseconds() - that.toUtcTimeZone().getMilliseconds();
-        return (int)diff;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return this.instance.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof JodaDateTime) {
-            JodaDateTime that = (JodaDateTime)obj;
-            return this.instance.equals(that.instance);
-        }
-        if (obj instanceof DateTime) {
-            return this.instance.equals(obj);
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return getString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public org.jboss.dna.graph.properties.DateTime toUtcTimeZone() {
-        DateTime jodaTime = this.instance.withZone(DateTimeZone.forID("UTC"));
-        return new JodaDateTime(jodaTime);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public org.jboss.dna.graph.properties.DateTime toTimeZone( String timeZoneId ) {
-        CheckArg.isNotNull(timeZoneId, "time zone identifier");
-        DateTime jodaTime = this.instance.withZone(DateTimeZone.forID(timeZoneId));
-        return new JodaDateTime(jodaTime);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#isBefore(org.jboss.dna.graph.properties.DateTime)
-     */
-    public boolean isBefore( org.jboss.dna.graph.properties.DateTime other ) {
-        return this.compareTo(other) < 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#isSameAs(org.jboss.dna.graph.properties.DateTime)
-     */
-    public boolean isSameAs( org.jboss.dna.graph.properties.DateTime other ) {
-        return this.compareTo(other) == 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#isAfter(org.jboss.dna.graph.properties.DateTime)
-     */
-    public boolean isAfter( org.jboss.dna.graph.properties.DateTime other ) {
-        return this.compareTo(other) > 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#minus(long, java.util.concurrent.TimeUnit)
-     */
-    public org.jboss.dna.graph.properties.DateTime minus( long timeAmount,
-                                                          TimeUnit unit ) {
-        CheckArg.isNotNull(unit, "unit");
-        return new JodaDateTime(this.instance.minus(TimeUnit.MILLISECONDS.convert(timeAmount, unit)));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#minusDays(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime minusDays( int days ) {
-        return new JodaDateTime(this.instance.minusDays(days));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#minusHours(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime minusHours( int hours ) {
-        return new JodaDateTime(this.instance.minusHours(hours));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#minusMillis(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime minusMillis( int milliseconds ) {
-        return new JodaDateTime(this.instance.minusMillis(milliseconds));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#minusMinutes(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime minusMinutes( int minutes ) {
-        return new JodaDateTime(this.instance.minusMinutes(minutes));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#minusMonths(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime minusMonths( int months ) {
-        return new JodaDateTime(this.instance.minusMonths(months));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#minusSeconds(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime minusSeconds( int seconds ) {
-        return new JodaDateTime(this.instance.minusSeconds(seconds));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#minusWeeks(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime minusWeeks( int weeks ) {
-        return new JodaDateTime(this.instance.minusWeeks(weeks));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#minusYears(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime minusYears( int years ) {
-        return new JodaDateTime(this.instance.minusYears(years));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#plus(long, java.util.concurrent.TimeUnit)
-     */
-    public org.jboss.dna.graph.properties.DateTime plus( long timeAmount,
-                                                         TimeUnit unit ) {
-        CheckArg.isNotNull(unit, "unit");
-        return new JodaDateTime(this.instance.plus(TimeUnit.MILLISECONDS.convert(timeAmount, unit)));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#plusDays(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime plusDays( int days ) {
-        return new JodaDateTime(this.instance.plusDays(days));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#plusHours(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime plusHours( int hours ) {
-        return new JodaDateTime(this.instance.plusHours(hours));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#plusMillis(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime plusMillis( int milliseconds ) {
-        return new JodaDateTime(this.instance.plusMillis(milliseconds));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#plusMinutes(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime plusMinutes( int minutes ) {
-        return new JodaDateTime(this.instance.plusMinutes(minutes));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#plusMonths(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime plusMonths( int months ) {
-        return new JodaDateTime(this.instance.plusMonths(months));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#plusSeconds(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime plusSeconds( int seconds ) {
-        return new JodaDateTime(this.instance.plusSeconds(seconds));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#plusWeeks(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime plusWeeks( int weeks ) {
-        return new JodaDateTime(this.instance.plusWeeks(weeks));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTime#plusYears(int)
-     */
-    public org.jboss.dna.graph.properties.DateTime plusYears( int years ) {
-        return new JodaDateTime(this.instance.plusYears(years));
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTime.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/JodaDateTime.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTime.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTime.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,567 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.joda.time.Chronology;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+/**
+ * Implementation of DateTime based upon the Joda-Time library.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class JodaDateTime implements org.jboss.dna.graph.property.DateTime {
+
+    /**
+     */
+    private static final long serialVersionUID = -730188225988292422L;
+
+    private static final int MILLIS_IN_HOUR = 1000 * 60 * 60;
+
+    private final DateTime instance;
+
+    public JodaDateTime() {
+        this.instance = new DateTime();
+    }
+
+    public JodaDateTime( String iso8601 ) {
+        this.instance = new DateTime(iso8601);
+    }
+
+    public JodaDateTime( String iso8601,
+                         String timeZoneId ) {
+        this.instance = new DateTime(iso8601, DateTimeZone.forID(timeZoneId));
+    }
+
+    public JodaDateTime( long milliseconds ) {
+        this.instance = new DateTime(milliseconds);
+    }
+
+    public JodaDateTime( long milliseconds,
+                         Chronology chronology ) {
+        this.instance = new DateTime(milliseconds, chronology);
+    }
+
+    public JodaDateTime( long milliseconds,
+                         String timeZoneId ) {
+        this.instance = new DateTime(milliseconds, DateTimeZone.forID(timeZoneId));
+    }
+
+    public JodaDateTime( DateTimeZone dateTimeZone ) {
+        this.instance = new DateTime(dateTimeZone);
+    }
+
+    public JodaDateTime( int year,
+                         int monthOfYear,
+                         int dayOfMonth,
+                         int hourOfDay,
+                         int minuteOfHour,
+                         int secondOfMinute,
+                         int millisecondsOfSecond ) {
+        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisecondsOfSecond);
+    }
+
+    public JodaDateTime( int year,
+                         int monthOfYear,
+                         int dayOfMonth,
+                         int hourOfDay,
+                         int minuteOfHour,
+                         int secondOfMinute,
+                         int millisecondsOfSecond,
+                         Chronology chronology ) {
+        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
+                                     millisecondsOfSecond, chronology);
+    }
+
+    public JodaDateTime( int year,
+                         int monthOfYear,
+                         int dayOfMonth,
+                         int hourOfDay,
+                         int minuteOfHour,
+                         int secondOfMinute,
+                         int millisecondsOfSecond,
+                         DateTimeZone dateTimeZone ) {
+        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
+                                     millisecondsOfSecond, dateTimeZone);
+    }
+
+    public JodaDateTime( int year,
+                         int monthOfYear,
+                         int dayOfMonth,
+                         int hourOfDay,
+                         int minuteOfHour,
+                         int secondOfMinute,
+                         int millisecondsOfSecond,
+                         int timeZoneOffsetHours ) {
+        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
+                                     millisecondsOfSecond, DateTimeZone.forOffsetHours(timeZoneOffsetHours));
+    }
+
+    public JodaDateTime( int year,
+                         int monthOfYear,
+                         int dayOfMonth,
+                         int hourOfDay,
+                         int minuteOfHour,
+                         int secondOfMinute,
+                         int millisecondsOfSecond,
+                         String timeZoneId ) {
+        this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
+                                     millisecondsOfSecond, DateTimeZone.forID(timeZoneId));
+    }
+
+    public JodaDateTime( java.util.Date jdkDate ) {
+        this.instance = new DateTime(jdkDate);
+    }
+
+    public JodaDateTime( java.util.Calendar jdkCalendar ) {
+        this.instance = new DateTime(jdkCalendar);
+    }
+
+    public JodaDateTime( DateTime dateTime ) {
+        this.instance = dateTime; // it's immutable, so just hold onto the supplied instance
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getCenturyOfEra() {
+        return this.instance.getCenturyOfEra();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getDayOfMonth() {
+        return this.instance.getDayOfMonth();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getDayOfWeek() {
+        return this.instance.getDayOfWeek();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getDayOfYear() {
+        return this.instance.getDayOfYear();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getEra() {
+        return this.instance.getEra();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getHourOfDay() {
+        return this.instance.getHourOfDay();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getMillisOfSecond() {
+        return this.instance.getMillisOfSecond();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getMilliseconds() {
+        return this.instance.getMillis();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getMinuteOfHour() {
+        return this.instance.getMinuteOfHour();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getMonthOfYear() {
+        return this.instance.getMonthOfYear();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getSecondOfMinute() {
+        return this.instance.getSecondOfMinute();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString() {
+        return this.instance.toString(org.joda.time.format.ISODateTimeFormat.dateTime());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getWeekOfWeekyear() {
+        return this.instance.getWeekOfWeekyear();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getWeekyear() {
+        return this.instance.getWeekyear();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getYear() {
+        return this.instance.getYear();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getYearOfCentury() {
+        return this.instance.getYearOfCentury();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getYearOfEra() {
+        return this.instance.getYearOfEra();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getTimeZoneOffsetHours() {
+        // return this.instance.getZone().toTimeZone().getRawOffset() / MILLIS_IN_HOUR;
+        return this.instance.getZone().getOffset(this.instance.getMillis()) / MILLIS_IN_HOUR;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getTimeZoneId() {
+        return this.instance.getZone().getID();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar toCalendar() {
+        return toCalendar(null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar toCalendar( Locale locale ) {
+        return this.instance.toCalendar(locale);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Date toDate() {
+        return this.instance.toDate();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public GregorianCalendar toGregorianCalendar() {
+        return this.instance.toGregorianCalendar();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( org.jboss.dna.graph.property.DateTime that ) {
+        if (that instanceof JodaDateTime) {
+            return this.instance.compareTo(((JodaDateTime)that).instance);
+        }
+        long diff = this.toUtcTimeZone().getMilliseconds() - that.toUtcTimeZone().getMilliseconds();
+        return (int)diff;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return this.instance.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof JodaDateTime) {
+            JodaDateTime that = (JodaDateTime)obj;
+            return this.instance.equals(that.instance);
+        }
+        if (obj instanceof DateTime) {
+            return this.instance.equals(obj);
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return getString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.jboss.dna.graph.property.DateTime toUtcTimeZone() {
+        DateTime jodaTime = this.instance.withZone(DateTimeZone.forID("UTC"));
+        return new JodaDateTime(jodaTime);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.jboss.dna.graph.property.DateTime toTimeZone( String timeZoneId ) {
+        CheckArg.isNotNull(timeZoneId, "time zone identifier");
+        DateTime jodaTime = this.instance.withZone(DateTimeZone.forID(timeZoneId));
+        return new JodaDateTime(jodaTime);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#isBefore(org.jboss.dna.graph.property.DateTime)
+     */
+    public boolean isBefore( org.jboss.dna.graph.property.DateTime other ) {
+        return this.compareTo(other) < 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#isSameAs(org.jboss.dna.graph.property.DateTime)
+     */
+    public boolean isSameAs( org.jboss.dna.graph.property.DateTime other ) {
+        return this.compareTo(other) == 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#isAfter(org.jboss.dna.graph.property.DateTime)
+     */
+    public boolean isAfter( org.jboss.dna.graph.property.DateTime other ) {
+        return this.compareTo(other) > 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#minus(long, java.util.concurrent.TimeUnit)
+     */
+    public org.jboss.dna.graph.property.DateTime minus( long timeAmount,
+                                                          TimeUnit unit ) {
+        CheckArg.isNotNull(unit, "unit");
+        return new JodaDateTime(this.instance.minus(TimeUnit.MILLISECONDS.convert(timeAmount, unit)));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#minusDays(int)
+     */
+    public org.jboss.dna.graph.property.DateTime minusDays( int days ) {
+        return new JodaDateTime(this.instance.minusDays(days));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#minusHours(int)
+     */
+    public org.jboss.dna.graph.property.DateTime minusHours( int hours ) {
+        return new JodaDateTime(this.instance.minusHours(hours));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#minusMillis(int)
+     */
+    public org.jboss.dna.graph.property.DateTime minusMillis( int milliseconds ) {
+        return new JodaDateTime(this.instance.minusMillis(milliseconds));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#minusMinutes(int)
+     */
+    public org.jboss.dna.graph.property.DateTime minusMinutes( int minutes ) {
+        return new JodaDateTime(this.instance.minusMinutes(minutes));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#minusMonths(int)
+     */
+    public org.jboss.dna.graph.property.DateTime minusMonths( int months ) {
+        return new JodaDateTime(this.instance.minusMonths(months));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#minusSeconds(int)
+     */
+    public org.jboss.dna.graph.property.DateTime minusSeconds( int seconds ) {
+        return new JodaDateTime(this.instance.minusSeconds(seconds));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#minusWeeks(int)
+     */
+    public org.jboss.dna.graph.property.DateTime minusWeeks( int weeks ) {
+        return new JodaDateTime(this.instance.minusWeeks(weeks));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#minusYears(int)
+     */
+    public org.jboss.dna.graph.property.DateTime minusYears( int years ) {
+        return new JodaDateTime(this.instance.minusYears(years));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#plus(long, java.util.concurrent.TimeUnit)
+     */
+    public org.jboss.dna.graph.property.DateTime plus( long timeAmount,
+                                                         TimeUnit unit ) {
+        CheckArg.isNotNull(unit, "unit");
+        return new JodaDateTime(this.instance.plus(TimeUnit.MILLISECONDS.convert(timeAmount, unit)));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#plusDays(int)
+     */
+    public org.jboss.dna.graph.property.DateTime plusDays( int days ) {
+        return new JodaDateTime(this.instance.plusDays(days));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#plusHours(int)
+     */
+    public org.jboss.dna.graph.property.DateTime plusHours( int hours ) {
+        return new JodaDateTime(this.instance.plusHours(hours));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#plusMillis(int)
+     */
+    public org.jboss.dna.graph.property.DateTime plusMillis( int milliseconds ) {
+        return new JodaDateTime(this.instance.plusMillis(milliseconds));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#plusMinutes(int)
+     */
+    public org.jboss.dna.graph.property.DateTime plusMinutes( int minutes ) {
+        return new JodaDateTime(this.instance.plusMinutes(minutes));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#plusMonths(int)
+     */
+    public org.jboss.dna.graph.property.DateTime plusMonths( int months ) {
+        return new JodaDateTime(this.instance.plusMonths(months));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#plusSeconds(int)
+     */
+    public org.jboss.dna.graph.property.DateTime plusSeconds( int seconds ) {
+        return new JodaDateTime(this.instance.plusSeconds(seconds));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#plusWeeks(int)
+     */
+    public org.jboss.dna.graph.property.DateTime plusWeeks( int weeks ) {
+        return new JodaDateTime(this.instance.plusWeeks(weeks));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTime#plusYears(int)
+     */
+    public org.jboss.dna.graph.property.DateTime plusYears( int years ) {
+        return new JodaDateTime(this.instance.plusYears(years));
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/JodaDateTimeValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,317 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.DateTimeFactory;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.joda.time.DateTimeZone;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#DATE} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class JodaDateTimeValueFactory extends AbstractValueFactory<DateTime> implements DateTimeFactory {
-
-    public JodaDateTimeValueFactory( TextDecoder decoder,
-                                     ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.DATE, decoder, stringValueFactory);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( String value ) {
-        if (value == null) return null;
-        try {
-            return new JodaDateTime(value.trim());
-        } catch (IllegalArgumentException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                            DateTime.class.getSimpleName(),
-                                                                            value), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( String value,
-                            TextDecoder decoder ) {
-        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
-        return create(getDecoder(decoder).decode(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( int value ) {
-        return create((long)value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( long value ) {
-        return new JodaDateTime(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( boolean value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Date.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( float value ) {
-        return create((long)value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( double value ) {
-        return create((long)value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( BigDecimal value ) {
-        if (value == null) return null;
-        return create(value.longValue());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( Calendar value ) {
-        if (value == null) return null;
-        return new JodaDateTime(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( Date value ) {
-        if (value == null) return null;
-        return new JodaDateTime(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public DateTime create( DateTime value ) throws ValueFormatException {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( Name value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Name.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( Path value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Path.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( Reference value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        Reference.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( URI value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  URI.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public DateTime create( UUID value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  UUID.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( byte[] value ) {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public DateTime create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( InputStream stream,
-                            long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( Reader reader,
-                            long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create() {
-        return new JodaDateTime();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTimeFactory#createUtc()
-     */
-    public DateTime createUtc() {
-        return new JodaDateTime(DateTimeZone.UTC);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( int year,
-                            int monthOfYear,
-                            int dayOfMonth,
-                            int hourOfDay,
-                            int minuteOfHour,
-                            int secondOfMinute,
-                            int millisecondsOfSecond ) {
-        return new JodaDateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisecondsOfSecond);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( int year,
-                            int monthOfYear,
-                            int dayOfMonth,
-                            int hourOfDay,
-                            int minuteOfHour,
-                            int secondOfMinute,
-                            int millisecondsOfSecond,
-                            int timeZoneOffsetHours ) {
-        return new JodaDateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisecondsOfSecond,
-                                timeZoneOffsetHours);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTime create( int year,
-                            int monthOfYear,
-                            int dayOfMonth,
-                            int hourOfDay,
-                            int minuteOfHour,
-                            int secondOfMinute,
-                            int millisecondsOfSecond,
-                            String timeZoneId ) {
-        return new JodaDateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisecondsOfSecond,
-                                timeZoneId);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.DateTimeFactory#create(org.jboss.dna.graph.properties.DateTime, long)
-     */
-    public DateTime create( DateTime original,
-                            long offsetInMillis ) {
-        assert original != null;
-        if (offsetInMillis == 0l) return original;
-        long newMillis = original.getMilliseconds() + offsetInMillis;
-        return new JodaDateTime(newMillis, original.getTimeZoneId());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected DateTime[] createEmptyArray( int length ) {
-        return new DateTime[length];
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/JodaDateTimeValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,317 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.DateTimeFactory;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.joda.time.DateTimeZone;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#DATE} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class JodaDateTimeValueFactory extends AbstractValueFactory<DateTime> implements DateTimeFactory {
+
+    public JodaDateTimeValueFactory( TextDecoder decoder,
+                                     ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.DATE, decoder, stringValueFactory);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( String value ) {
+        if (value == null) return null;
+        try {
+            return new JodaDateTime(value.trim());
+        } catch (IllegalArgumentException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                            DateTime.class.getSimpleName(),
+                                                                            value), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( String value,
+                            TextDecoder decoder ) {
+        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
+        return create(getDecoder(decoder).decode(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( int value ) {
+        return create((long)value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( long value ) {
+        return new JodaDateTime(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( boolean value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Date.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( float value ) {
+        return create((long)value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( double value ) {
+        return create((long)value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( BigDecimal value ) {
+        if (value == null) return null;
+        return create(value.longValue());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( Calendar value ) {
+        if (value == null) return null;
+        return new JodaDateTime(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( Date value ) {
+        if (value == null) return null;
+        return new JodaDateTime(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public DateTime create( DateTime value ) throws ValueFormatException {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( Name value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Name.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( Path value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Path.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( Reference value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        Reference.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( URI value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  URI.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public DateTime create( UUID value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  UUID.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( byte[] value ) {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public DateTime create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( InputStream stream,
+                            long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( Reader reader,
+                            long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create() {
+        return new JodaDateTime();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTimeFactory#createUtc()
+     */
+    public DateTime createUtc() {
+        return new JodaDateTime(DateTimeZone.UTC);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( int year,
+                            int monthOfYear,
+                            int dayOfMonth,
+                            int hourOfDay,
+                            int minuteOfHour,
+                            int secondOfMinute,
+                            int millisecondsOfSecond ) {
+        return new JodaDateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisecondsOfSecond);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( int year,
+                            int monthOfYear,
+                            int dayOfMonth,
+                            int hourOfDay,
+                            int minuteOfHour,
+                            int secondOfMinute,
+                            int millisecondsOfSecond,
+                            int timeZoneOffsetHours ) {
+        return new JodaDateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisecondsOfSecond,
+                                timeZoneOffsetHours);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTime create( int year,
+                            int monthOfYear,
+                            int dayOfMonth,
+                            int hourOfDay,
+                            int minuteOfHour,
+                            int secondOfMinute,
+                            int millisecondsOfSecond,
+                            String timeZoneId ) {
+        return new JodaDateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisecondsOfSecond,
+                                timeZoneId);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.DateTimeFactory#create(org.jboss.dna.graph.property.DateTime, long)
+     */
+    public DateTime create( DateTime original,
+                            long offsetInMillis ) {
+        assert original != null;
+        if (offsetInMillis == 0l) return original;
+        long newMillis = original.getMilliseconds() + offsetInMillis;
+        return new JodaDateTime(newMillis, original.getTimeZoneId());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected DateTime[] createEmptyArray( int length ) {
+        return new DateTime[length];
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistry.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/LocalNamespaceRegistry.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistry.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,176 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-
-/**
- * @author Randall Hauch
- */
- at ThreadSafe
-public class LocalNamespaceRegistry extends BasicNamespaceRegistry {
-
-    private final NamespaceRegistry delegate;
-
-    /**
-     * @param delegate the namespace registry that this registry should delegate to if not found locally
-     */
-    public LocalNamespaceRegistry( NamespaceRegistry delegate ) {
-        super();
-        CheckArg.isNotNull(delegate, "delegate");
-        this.delegate = delegate;
-        unregister(DEFAULT_NAMESPACE_URI);
-    }
-
-    /**
-     * @param delegate the namespace registry that this registry should delegate to if not found locally
-     * @param defaultNamespaceUri the namespace URI to use for the default prefix
-     */
-    public LocalNamespaceRegistry( NamespaceRegistry delegate,
-                                   final String defaultNamespaceUri ) {
-        super();
-        CheckArg.isNotNull(delegate, "delegate");
-        this.delegate = delegate;
-        register("", defaultNamespaceUri);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getDefaultNamespaceUri()
-     */
-    @Override
-    public String getDefaultNamespaceUri() {
-        String result = super.getDefaultNamespaceUri();
-        if (result == null) result = this.delegate.getDefaultNamespaceUri();
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getNamespaceForPrefix(java.lang.String)
-     */
-    @Override
-    public String getNamespaceForPrefix( String prefix ) {
-        String result = super.getNamespaceForPrefix(prefix);
-        if (result == null) result = this.delegate.getNamespaceForPrefix(prefix);
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getNamespaces()
-     */
-    @Override
-    public Set<Namespace> getNamespaces() {
-        Set<Namespace> delegateNamespaces = this.delegate.getNamespaces();
-        Set<Namespace> localNamespaces = super.getNamespaces();
-
-        // Load the local namespaces first ...
-        Set<Namespace> namespaces = new HashSet<Namespace>(localNamespaces);
-
-        // Now build a map of the local prefixes so we can check for prefixes
-        Map<String, Namespace> localNamespacesByPrefix = new HashMap<String, Namespace>();
-        for (Namespace ns : localNamespaces)
-            localNamespacesByPrefix.put(ns.getPrefix(), ns);
-
-        // Now iterate over the local namespaces, removing any existing namespace with the same prefix
-        for (Namespace ns : delegateNamespaces) {
-            if (localNamespacesByPrefix.get(ns.getPrefix()) != null) continue;
-            // Try to add the delegate namespace, which won't work if a local with the same URI was already added...
-            namespaces.add(ns);
-        }
-        return Collections.unmodifiableSet(namespaces);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getPrefixForNamespaceUri(java.lang.String, boolean)
-     */
-    @Override
-    public String getPrefixForNamespaceUri( String namespaceUri,
-                                            boolean generateIfMissing ) {
-        String result = super.getPrefixForNamespaceUri(namespaceUri, false);
-        if (result == null) result = this.delegate.getPrefixForNamespaceUri(namespaceUri, false);
-        if (result == null && generateIfMissing) result = super.getPrefixForNamespaceUri(namespaceUri, true);
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getRegisteredNamespaceUris()
-     */
-    @Override
-    public Set<String> getRegisteredNamespaceUris() {
-        Set<String> uris = new HashSet<String>(this.delegate.getRegisteredNamespaceUris());
-        uris.addAll(super.getRegisteredNamespaceUris());
-        return Collections.unmodifiableSet(uris);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#isRegisteredNamespaceUri(java.lang.String)
-     */
-    @Override
-    public boolean isRegisteredNamespaceUri( String namespaceUri ) {
-        return super.isRegisteredNamespaceUri(namespaceUri) || this.delegate.isRegisteredNamespaceUri(namespaceUri);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#register(java.lang.String, java.lang.String)
-     */
-    @Override
-    public String register( String prefix,
-                            String namespaceUri ) {
-        // Just register the namespace locally ...
-        String previous = super.register(prefix, namespaceUri);
-        // But check whether there is a "previous" from the delegate ...
-        if (previous == null && delegate != null) previous = delegate.getPrefixForNamespaceUri(namespaceUri, false);
-        return previous;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#unregister(java.lang.String)
-     */
-    @Override
-    public boolean unregister( String namespaceUri ) {
-        // Unregister locally ...
-        return super.unregister(namespaceUri);
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistry.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/LocalNamespaceRegistry.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistry.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistry.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,176 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+
+/**
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public class LocalNamespaceRegistry extends BasicNamespaceRegistry {
+
+    private final NamespaceRegistry delegate;
+
+    /**
+     * @param delegate the namespace registry that this registry should delegate to if not found locally
+     */
+    public LocalNamespaceRegistry( NamespaceRegistry delegate ) {
+        super();
+        CheckArg.isNotNull(delegate, "delegate");
+        this.delegate = delegate;
+        unregister(DEFAULT_NAMESPACE_URI);
+    }
+
+    /**
+     * @param delegate the namespace registry that this registry should delegate to if not found locally
+     * @param defaultNamespaceUri the namespace URI to use for the default prefix
+     */
+    public LocalNamespaceRegistry( NamespaceRegistry delegate,
+                                   final String defaultNamespaceUri ) {
+        super();
+        CheckArg.isNotNull(delegate, "delegate");
+        this.delegate = delegate;
+        register("", defaultNamespaceUri);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.BasicNamespaceRegistry#getDefaultNamespaceUri()
+     */
+    @Override
+    public String getDefaultNamespaceUri() {
+        String result = super.getDefaultNamespaceUri();
+        if (result == null) result = this.delegate.getDefaultNamespaceUri();
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.BasicNamespaceRegistry#getNamespaceForPrefix(java.lang.String)
+     */
+    @Override
+    public String getNamespaceForPrefix( String prefix ) {
+        String result = super.getNamespaceForPrefix(prefix);
+        if (result == null) result = this.delegate.getNamespaceForPrefix(prefix);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.BasicNamespaceRegistry#getNamespaces()
+     */
+    @Override
+    public Set<Namespace> getNamespaces() {
+        Set<Namespace> delegateNamespaces = this.delegate.getNamespaces();
+        Set<Namespace> localNamespaces = super.getNamespaces();
+
+        // Load the local namespaces first ...
+        Set<Namespace> namespaces = new HashSet<Namespace>(localNamespaces);
+
+        // Now build a map of the local prefixes so we can check for prefixes
+        Map<String, Namespace> localNamespacesByPrefix = new HashMap<String, Namespace>();
+        for (Namespace ns : localNamespaces)
+            localNamespacesByPrefix.put(ns.getPrefix(), ns);
+
+        // Now iterate over the local namespaces, removing any existing namespace with the same prefix
+        for (Namespace ns : delegateNamespaces) {
+            if (localNamespacesByPrefix.get(ns.getPrefix()) != null) continue;
+            // Try to add the delegate namespace, which won't work if a local with the same URI was already added...
+            namespaces.add(ns);
+        }
+        return Collections.unmodifiableSet(namespaces);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.BasicNamespaceRegistry#getPrefixForNamespaceUri(java.lang.String, boolean)
+     */
+    @Override
+    public String getPrefixForNamespaceUri( String namespaceUri,
+                                            boolean generateIfMissing ) {
+        String result = super.getPrefixForNamespaceUri(namespaceUri, false);
+        if (result == null) result = this.delegate.getPrefixForNamespaceUri(namespaceUri, false);
+        if (result == null && generateIfMissing) result = super.getPrefixForNamespaceUri(namespaceUri, true);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.BasicNamespaceRegistry#getRegisteredNamespaceUris()
+     */
+    @Override
+    public Set<String> getRegisteredNamespaceUris() {
+        Set<String> uris = new HashSet<String>(this.delegate.getRegisteredNamespaceUris());
+        uris.addAll(super.getRegisteredNamespaceUris());
+        return Collections.unmodifiableSet(uris);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.BasicNamespaceRegistry#isRegisteredNamespaceUri(java.lang.String)
+     */
+    @Override
+    public boolean isRegisteredNamespaceUri( String namespaceUri ) {
+        return super.isRegisteredNamespaceUri(namespaceUri) || this.delegate.isRegisteredNamespaceUri(namespaceUri);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.BasicNamespaceRegistry#register(java.lang.String, java.lang.String)
+     */
+    @Override
+    public String register( String prefix,
+                            String namespaceUri ) {
+        // Just register the namespace locally ...
+        String previous = super.register(prefix, namespaceUri);
+        // But check whether there is a "previous" from the delegate ...
+        if (previous == null && delegate != null) previous = delegate.getPrefixForNamespaceUri(namespaceUri, false);
+        return previous;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.BasicNamespaceRegistry#unregister(java.lang.String)
+     */
+    @Override
+    public boolean unregister( String namespaceUri ) {
+        // Unregister locally ...
+        return super.unregister(namespaceUri);
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LongValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/LongValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LongValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,245 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#LONG} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class LongValueFactory extends AbstractValueFactory<Long> {
-
-    public LongValueFactory( TextDecoder decoder,
-                             ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.LONG, decoder, stringValueFactory);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( String value ) {
-        if (value == null) return null;
-        try {
-            return Long.valueOf(value.trim());
-        } catch (NumberFormatException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                            Long.class.getSimpleName(),
-                                                                            value), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( String value,
-                        TextDecoder decoder ) {
-        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
-        return create(getDecoder(decoder).decode(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( int value ) {
-        return Long.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( long value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( boolean value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Long.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( float value ) {
-        return (long)value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( double value ) {
-        return (long)value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( BigDecimal value ) {
-        if (value == null) return null;
-        return value.longValue();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( Calendar value ) {
-        if (value == null) return null;
-        return value.getTimeInMillis();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( Date value ) {
-        if (value == null) return null;
-        return value.getTime();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public Long create( DateTime value ) throws ValueFormatException {
-        if (value == null) return null;
-        return value.getMilliseconds();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( Name value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Name.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( Path value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Path.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( Reference value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        Reference.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( URI value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  URI.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public Long create( UUID value ) throws IoException {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  UUID.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( byte[] value ) {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public Long create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( InputStream stream,
-                        long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Long create( Reader reader,
-                        long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Long[] createEmptyArray( int length ) {
-        return new Long[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LongValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/LongValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LongValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/LongValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,245 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#LONG} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class LongValueFactory extends AbstractValueFactory<Long> {
+
+    public LongValueFactory( TextDecoder decoder,
+                             ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.LONG, decoder, stringValueFactory);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( String value ) {
+        if (value == null) return null;
+        try {
+            return Long.valueOf(value.trim());
+        } catch (NumberFormatException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                            Long.class.getSimpleName(),
+                                                                            value), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( String value,
+                        TextDecoder decoder ) {
+        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
+        return create(getDecoder(decoder).decode(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( int value ) {
+        return Long.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( long value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( boolean value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Long.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( float value ) {
+        return (long)value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( double value ) {
+        return (long)value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( BigDecimal value ) {
+        if (value == null) return null;
+        return value.longValue();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( Calendar value ) {
+        if (value == null) return null;
+        return value.getTimeInMillis();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( Date value ) {
+        if (value == null) return null;
+        return value.getTime();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public Long create( DateTime value ) throws ValueFormatException {
+        if (value == null) return null;
+        return value.getMilliseconds();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( Name value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Name.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( Path value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Path.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( Reference value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        Reference.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( URI value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  URI.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public Long create( UUID value ) throws IoException {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  UUID.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( byte[] value ) {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public Long create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( InputStream stream,
+                        long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Long create( Reader reader,
+                        long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Long[] createEmptyArray( int length ) {
+        return new Long[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/NameValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,357 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.NamespaceException;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#NAME} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class NameValueFactory extends AbstractValueFactory<Name> implements NameFactory {
-
-    // Non-escaped pattern: (\{([^}]*)\})?(.*)
-    protected static final String FULLY_QUALFIED_NAME_PATTERN_STRING = "\\{([^}]*)\\}(.*)";
-    protected static final Pattern FULLY_QUALIFIED_NAME_PATTERN = Pattern.compile(FULLY_QUALFIED_NAME_PATTERN_STRING);
-
-    // Original pattern: (([^:/]*):)?(.*)
-    private static final String PREFIXED_NAME_PATTERN_STRING = "(([^:/]*):)?(.*)";
-    private static final Pattern PREFIXED_NAME_PATTERN = Pattern.compile(PREFIXED_NAME_PATTERN_STRING);
-
-    private final NamespaceRegistry namespaceRegistry;
-
-    public NameValueFactory( NamespaceRegistry namespaceRegistry,
-                             TextDecoder decoder,
-                             ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.NAME, decoder, stringValueFactory);
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        this.namespaceRegistry = namespaceRegistry;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( String value ) {
-        return create(value, getDecoder());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( String value,
-                        TextDecoder decoder ) {
-        if (value == null) return null;
-        if (decoder == null) decoder = getDecoder();
-        try {
-            if (value.length() == 0) {
-                return new BasicName("", "");
-            }
-            if (value.charAt(0) != '{') {
-                // First, see whether the value fits the prefixed name pattern ...
-                Matcher matcher = PREFIXED_NAME_PATTERN.matcher(value);
-                if (matcher.matches()) {
-                    String prefix = matcher.group(2);
-                    String localName = matcher.group(3);
-                    // Decode the parts ...
-                    prefix = prefix == null ? "" : decoder.decode(prefix);
-                    localName = decoder.decode(localName);
-                    // Look for a namespace match ...
-                    String namespaceUri = this.namespaceRegistry.getNamespaceForPrefix(prefix);
-                    // Fail if no namespace is found ...
-                    if (namespaceUri == null) {
-                        throw new NamespaceException(GraphI18n.noNamespaceRegisteredForPrefix.text(prefix));
-                    }
-                    return new BasicName(namespaceUri, localName);
-                }
-            }
-            // If it doesn't fit the prefixed pattern, then try the internal pattern
-            Matcher matcher = FULLY_QUALIFIED_NAME_PATTERN.matcher(value);
-            if (matcher.matches()) {
-                String namespaceUri = matcher.group(1);
-                String localName = matcher.group(2);
-                // Decode the parts ...
-                namespaceUri = decoder.decode(namespaceUri);
-                localName = decoder.decode(localName);
-                return new BasicName(namespaceUri, localName);
-            }
-        } catch (NamespaceException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                              Name.class.getSimpleName(),
-                                                                              value), err);
-        }
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                                                    Name.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( String namespaceUri,
-                        String localName ) {
-        return create(namespaceUri, localName, getDecoder());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( String namespaceUri,
-                        String localName,
-                        TextDecoder decoder ) {
-        CheckArg.isNotEmpty(localName, "localName");
-        if (decoder == null) decoder = getDecoder();
-        namespaceUri = namespaceUri != null ? decoder.decode(namespaceUri.trim()) : null;
-        localName = decoder.decode(localName.trim());
-        return new BasicName(namespaceUri, localName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( int value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          Integer.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( long value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    Long.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( boolean value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          Boolean.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( float value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    Float.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( double value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    Double.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( BigDecimal value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          BigDecimal.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( Calendar value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          Calendar.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( Date value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    Date.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public Name create( DateTime value ) throws ValueFormatException {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          DateTime.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( Name value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( Path value ) {
-        if (value == null) return null;
-        if (!value.isAbsolute() && value.size() == 1) {
-            // A relative name of length 1 is converted to a name
-            return value.getSegment(0).getName();
-        }
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(Path.class.getSimpleName(),
-                                                                                                    Name.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( Reference value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          Reference.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( URI value ) {
-        if (value == null) return null;
-        String asciiString = value.toASCIIString();
-        // Remove any leading "./" ...
-        if (asciiString.startsWith("./") && asciiString.length() > 2) {
-            asciiString = asciiString.substring(2);
-        }
-        if (asciiString.indexOf('/') == -1) {
-            return create(asciiString);
-        }
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(URI.class.getSimpleName(),
-                                                                                                    Path.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public Name create( UUID value ) throws IoException {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    UUID.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( byte[] value ) {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public Name create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( InputStream stream,
-                        long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Name create( Reader reader,
-                        long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * <p>
-     * {@inheritDoc}
-     * </p>
-     * 
-     * @see org.jboss.dna.graph.properties.NameFactory#getNamespaceRegistry()
-     */
-    public NamespaceRegistry getNamespaceRegistry() {
-        return namespaceRegistry;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Name[] createEmptyArray( int length ) {
-        return new Name[length];
-    }
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/NameValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,357 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.NamespaceException;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#NAME} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class NameValueFactory extends AbstractValueFactory<Name> implements NameFactory {
+
+    // Non-escaped pattern: (\{([^}]*)\})?(.*)
+    protected static final String FULLY_QUALFIED_NAME_PATTERN_STRING = "\\{([^}]*)\\}(.*)";
+    protected static final Pattern FULLY_QUALIFIED_NAME_PATTERN = Pattern.compile(FULLY_QUALFIED_NAME_PATTERN_STRING);
+
+    // Original pattern: (([^:/]*):)?(.*)
+    private static final String PREFIXED_NAME_PATTERN_STRING = "(([^:/]*):)?(.*)";
+    private static final Pattern PREFIXED_NAME_PATTERN = Pattern.compile(PREFIXED_NAME_PATTERN_STRING);
+
+    private final NamespaceRegistry namespaceRegistry;
+
+    public NameValueFactory( NamespaceRegistry namespaceRegistry,
+                             TextDecoder decoder,
+                             ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.NAME, decoder, stringValueFactory);
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        this.namespaceRegistry = namespaceRegistry;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( String value ) {
+        return create(value, getDecoder());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( String value,
+                        TextDecoder decoder ) {
+        if (value == null) return null;
+        if (decoder == null) decoder = getDecoder();
+        try {
+            if (value.length() == 0) {
+                return new BasicName("", "");
+            }
+            if (value.charAt(0) != '{') {
+                // First, see whether the value fits the prefixed name pattern ...
+                Matcher matcher = PREFIXED_NAME_PATTERN.matcher(value);
+                if (matcher.matches()) {
+                    String prefix = matcher.group(2);
+                    String localName = matcher.group(3);
+                    // Decode the parts ...
+                    prefix = prefix == null ? "" : decoder.decode(prefix);
+                    localName = decoder.decode(localName);
+                    // Look for a namespace match ...
+                    String namespaceUri = this.namespaceRegistry.getNamespaceForPrefix(prefix);
+                    // Fail if no namespace is found ...
+                    if (namespaceUri == null) {
+                        throw new NamespaceException(GraphI18n.noNamespaceRegisteredForPrefix.text(prefix));
+                    }
+                    return new BasicName(namespaceUri, localName);
+                }
+            }
+            // If it doesn't fit the prefixed pattern, then try the internal pattern
+            Matcher matcher = FULLY_QUALIFIED_NAME_PATTERN.matcher(value);
+            if (matcher.matches()) {
+                String namespaceUri = matcher.group(1);
+                String localName = matcher.group(2);
+                // Decode the parts ...
+                namespaceUri = decoder.decode(namespaceUri);
+                localName = decoder.decode(localName);
+                return new BasicName(namespaceUri, localName);
+            }
+        } catch (NamespaceException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                              Name.class.getSimpleName(),
+                                                                              value), err);
+        }
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                                                    Name.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( String namespaceUri,
+                        String localName ) {
+        return create(namespaceUri, localName, getDecoder());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( String namespaceUri,
+                        String localName,
+                        TextDecoder decoder ) {
+        CheckArg.isNotEmpty(localName, "localName");
+        if (decoder == null) decoder = getDecoder();
+        namespaceUri = namespaceUri != null ? decoder.decode(namespaceUri.trim()) : null;
+        localName = decoder.decode(localName.trim());
+        return new BasicName(namespaceUri, localName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( int value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          Integer.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( long value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    Long.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( boolean value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          Boolean.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( float value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    Float.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( double value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    Double.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( BigDecimal value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          BigDecimal.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( Calendar value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          Calendar.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( Date value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    Date.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public Name create( DateTime value ) throws ValueFormatException {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          DateTime.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( Name value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( Path value ) {
+        if (value == null) return null;
+        if (!value.isAbsolute() && value.size() == 1) {
+            // A relative name of length 1 is converted to a name
+            return value.getSegment(0).getName();
+        }
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(Path.class.getSimpleName(),
+                                                                                                    Name.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( Reference value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          Reference.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( URI value ) {
+        if (value == null) return null;
+        String asciiString = value.toASCIIString();
+        // Remove any leading "./" ...
+        if (asciiString.startsWith("./") && asciiString.length() > 2) {
+            asciiString = asciiString.substring(2);
+        }
+        if (asciiString.indexOf('/') == -1) {
+            return create(asciiString);
+        }
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(URI.class.getSimpleName(),
+                                                                                                    Path.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public Name create( UUID value ) throws IoException {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    UUID.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( byte[] value ) {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public Name create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( InputStream stream,
+                        long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( Reader reader,
+                        long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * <p>
+     * {@inheritDoc}
+     * </p>
+     * 
+     * @see org.jboss.dna.graph.property.NameFactory#getNamespaceRegistry()
+     */
+    public NamespaceRegistry getNamespaceRegistry() {
+        return namespaceRegistry;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Name[] createEmptyArray( int length ) {
+        return new Name[length];
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ObjectValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/ObjectValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ObjectValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,247 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#OBJECT} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class ObjectValueFactory extends AbstractValueFactory<Object> {
-
-    private final ValueFactory<Binary> binaryValueFactory;
-
-    public ObjectValueFactory( TextDecoder decoder,
-                               ValueFactory<String> stringValueFactory,
-                               ValueFactory<Binary> binaryValueFactory ) {
-        super(PropertyType.OBJECT, decoder, stringValueFactory);
-        CheckArg.isNotNull(binaryValueFactory, "binaryValueFactory");
-        this.binaryValueFactory = binaryValueFactory;
-    }
-
-    /**
-     * @return binaryValueFactory
-     */
-    protected ValueFactory<Binary> getBinaryValueFactory() {
-        return this.binaryValueFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( String value ) {
-        return this.getStringValueFactory().create(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( String value,
-                          TextDecoder decoder ) {
-        return this.getStringValueFactory().create(value, decoder);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( int value ) {
-        return Integer.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( long value ) {
-        return Long.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( boolean value ) {
-        return Boolean.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( float value ) {
-        return Float.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( double value ) {
-        return Double.valueOf(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( BigDecimal value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( Calendar value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( Date value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public Object create( DateTime value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( Name value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( Path value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( Reference value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( URI value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public Object create( UUID value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.AbstractValueFactory#create(java.lang.Object)
-     */
-    @Override
-    public Object create( Object value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.AbstractValueFactory#create(java.lang.Object[])
-     */
-    @Override
-    public Object[] create( Object[] values ) {
-        return values;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( byte[] value ) {
-        return getBinaryValueFactory().create(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public Object create( Binary value ) throws ValueFormatException, IoException {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( InputStream stream,
-                          long approximateLength ) {
-        return getBinaryValueFactory().create(stream, approximateLength);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object create( Reader reader,
-                          long approximateLength ) {
-        return getBinaryValueFactory().create(reader, approximateLength);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Object[] createEmptyArray( int length ) {
-        return new Object[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ObjectValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/ObjectValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ObjectValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/ObjectValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,247 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#OBJECT} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class ObjectValueFactory extends AbstractValueFactory<Object> {
+
+    private final ValueFactory<Binary> binaryValueFactory;
+
+    public ObjectValueFactory( TextDecoder decoder,
+                               ValueFactory<String> stringValueFactory,
+                               ValueFactory<Binary> binaryValueFactory ) {
+        super(PropertyType.OBJECT, decoder, stringValueFactory);
+        CheckArg.isNotNull(binaryValueFactory, "binaryValueFactory");
+        this.binaryValueFactory = binaryValueFactory;
+    }
+
+    /**
+     * @return binaryValueFactory
+     */
+    protected ValueFactory<Binary> getBinaryValueFactory() {
+        return this.binaryValueFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( String value ) {
+        return this.getStringValueFactory().create(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( String value,
+                          TextDecoder decoder ) {
+        return this.getStringValueFactory().create(value, decoder);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( int value ) {
+        return Integer.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( long value ) {
+        return Long.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( boolean value ) {
+        return Boolean.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( float value ) {
+        return Float.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( double value ) {
+        return Double.valueOf(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( BigDecimal value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( Calendar value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( Date value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public Object create( DateTime value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( Name value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( Path value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( Reference value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( URI value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public Object create( UUID value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.AbstractValueFactory#create(java.lang.Object)
+     */
+    @Override
+    public Object create( Object value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.AbstractValueFactory#create(java.lang.Object[])
+     */
+    @Override
+    public Object[] create( Object[] values ) {
+        return values;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( byte[] value ) {
+        return getBinaryValueFactory().create(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public Object create( Binary value ) throws ValueFormatException, IoException {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( InputStream stream,
+                          long approximateLength ) {
+        return getBinaryValueFactory().create(stream, approximateLength);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object create( Reader reader,
+                          long approximateLength ) {
+        return getBinaryValueFactory().create(reader, approximateLength);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Object[] createEmptyArray( int length ) {
+        return new Object[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/PathValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/PathValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,688 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.UUID;
-import java.util.regex.Pattern;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.Path.Segment;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#NAME} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class PathValueFactory extends AbstractValueFactory<Path> implements PathFactory {
-
-    /**
-     * Regular expression used to identify the different segments in a path, using the standard '/' delimiter. The expression is
-     * simply:
-     * 
-     * <pre>
-     * /
-     * </pre>
-     */
-    protected static final Pattern DELIMITER_PATTERN = Pattern.compile("/");
-
-    /**
-     * Regular expression used to identify the different parts of a segment. The expression is
-     * 
-     * <pre>
-     * ([&circ;*:/\[\]|]+)(:([&circ;*:/\[\]|]+))?(\[(\d+)])?
-     * </pre>
-     * 
-     * where the first part is accessed with group 1, the second part is accessed with group 3, and the index is accessed with
-     * group 5.
-     */
-    protected static final Pattern SEGMENT_PATTERN = Pattern.compile("([^:/]+)(:([^/\\[\\]]+))?(\\[(\\d+)])?");
-
-    private final ValueFactory<Name> nameValueFactory;
-
-    public PathValueFactory( TextDecoder decoder,
-                             ValueFactory<String> stringValueFactory,
-                             ValueFactory<Name> nameValueFactory ) {
-        super(PropertyType.PATH, decoder, stringValueFactory);
-        CheckArg.isNotNull(nameValueFactory, "nameValueFactory");
-        this.nameValueFactory = nameValueFactory;
-    }
-
-    /**
-     * @return nameValueFactory
-     */
-    protected ValueFactory<Name> getNameValueFactory() {
-        return this.nameValueFactory;
-    }
-
-    /**
-     * <p>
-     * {@inheritDoc}
-     * </p>
-     * 
-     * @see org.jboss.dna.graph.properties.PathFactory#createRootPath()
-     */
-    public Path createRootPath() {
-        return RootPath.INSTANCE;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( String value ) {
-        return create(value, getDecoder());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( final String value,
-                        TextDecoder decoder ) {
-        if (value == null) return null;
-        String trimmedValue = value.trim();
-        int length = trimmedValue.length();
-        boolean absolute = false;
-        if (length == 0) {
-            return BasicPath.EMPTY_RELATIVE;
-        }
-        if (Path.DELIMITER_STR.equals(trimmedValue)) return RootPath.INSTANCE;
-        if (Path.SELF.equals(trimmedValue)) return BasicPath.SELF_PATH;
-        if (Path.PARENT.equals(trimmedValue)) return BasicPath.PARENT_PATH;
-
-        // Remove the leading delimiter ...
-        if (trimmedValue.charAt(0) == Path.DELIMITER) {
-            trimmedValue = length > 1 ? trimmedValue.substring(1) : "";
-            --length;
-            absolute = true;
-        }
-        // remove the trailing delimiter ...
-        if (length > 0 && trimmedValue.charAt(length - 1) == Path.DELIMITER) {
-            trimmedValue = length > 1 ? trimmedValue.substring(0, length - 1) : "";
-            length = trimmedValue.length();
-        }
-        if (length == 0) {
-            return RootPath.INSTANCE;
-        }
-
-        // Parse the path into its segments ...
-        List<Segment> segments = new ArrayList<Segment>();
-        String[] pathSegments = DELIMITER_PATTERN.split(trimmedValue);
-        if (pathSegments.length == 0) {
-            throw new ValueFormatException(value, getPropertyType(), GraphI18n.validPathMayNotContainEmptySegment.text(value));
-        }
-        if (decoder == null) decoder = getDecoder();
-        assert pathSegments.length != 0;
-        assert decoder != null;
-        for (String segment : pathSegments) {
-            assert segment != null;
-            segment = segment.trim();
-            if (segment.length() == 0) {
-                throw new ValueFormatException(value, getPropertyType(), GraphI18n.validPathMayNotContainEmptySegment.text(value));
-            }
-            // Create the name and add a segment with it ...
-            segments.add(createSegment(segment, decoder));
-        }
-
-        if (absolute && segments.size() == 1) {
-            // Special case of a single-segment name ...
-            return new ChildPath(RootPath.INSTANCE, segments.get(0));
-        }
-        // Create a path constructed from the supplied segments ...
-        return new BasicPath(segments, absolute);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( int value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          Integer.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( long value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    Long.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( boolean value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          Boolean.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( float value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    Float.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( double value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    Double.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( BigDecimal value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          BigDecimal.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( Calendar value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          Calendar.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( Date value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    Date.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public Path create( DateTime value ) throws ValueFormatException {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          DateTime.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( Name value ) {
-        if (value == null) return null;
-        try {
-            return new ChildPath(RootPath.INSTANCE, new BasicPathSegment(value));
-        } catch (IllegalArgumentException e) {
-            throw new ValueFormatException(value, getPropertyType(), e);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( Path value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path createAbsolutePath( Name... segmentNames ) {
-        if (segmentNames == null || segmentNames.length == 0) return RootPath.INSTANCE;
-        List<Segment> segments = new ArrayList<Segment>(segmentNames.length);
-        for (Name segmentName : segmentNames) {
-            if (segmentName == null) {
-                CheckArg.containsNoNulls(segmentNames, "segment names");
-            }
-            segments.add(new BasicPathSegment(segmentName));
-        }
-        if (segments.size() == 1) {
-            // Special case of a single-segment name ...
-            return new ChildPath(RootPath.INSTANCE, segments.get(0));
-        }
-        return new BasicPath(segments, true);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path createAbsolutePath( Segment... segments ) {
-        if (segments == null || segments.length == 0) return RootPath.INSTANCE;
-        List<Segment> segmentsList = new ArrayList<Segment>(segments.length);
-        for (Segment segment : segments) {
-            if (segment == null) {
-                CheckArg.containsNoNulls(segments, "segments");
-            }
-            segmentsList.add(segment);
-        }
-        if (segmentsList.size() == 1) {
-            // Special case of a single-segment name ...
-            return new ChildPath(RootPath.INSTANCE, segmentsList.get(0));
-        }
-        return new BasicPath(segmentsList, true);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.PathFactory#createAbsolutePath(java.lang.Iterable)
-     */
-    public Path createAbsolutePath( Iterable<Segment> segments ) {
-        List<Segment> segmentsList = new LinkedList<Segment>();
-        for (Segment segment : segments) {
-            if (segment == null) {
-                CheckArg.containsNoNulls(segments, "segments");
-            }
-            segmentsList.add(segment);
-        }
-        if (segmentsList.isEmpty()) return RootPath.INSTANCE;
-        if (segmentsList.size() == 1) {
-            // Special case of a single-segment name ...
-            return new ChildPath(RootPath.INSTANCE, segmentsList.get(0));
-        }
-        return new BasicPath(segmentsList, true);
-    }
-
-    /**
-     * <p>
-     * {@inheritDoc}
-     * </p>
-     * 
-     * @see org.jboss.dna.graph.properties.PathFactory#createRelativePath()
-     */
-    public Path createRelativePath() {
-        return BasicPath.EMPTY_RELATIVE;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path createRelativePath( Name... segmentNames ) {
-        if (segmentNames == null || segmentNames.length == 0) return BasicPath.EMPTY_RELATIVE;
-        List<Segment> segments = new ArrayList<Segment>(segmentNames.length);
-        for (Name segmentName : segmentNames) {
-            if (segmentName == null) {
-                CheckArg.containsNoNulls(segmentNames, "segment names");
-            }
-            segments.add(new BasicPathSegment(segmentName));
-        }
-        return new BasicPath(segments, false);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path createRelativePath( Segment... segments ) {
-        if (segments == null || segments.length == 0) return BasicPath.EMPTY_RELATIVE;
-        List<Segment> segmentsList = new ArrayList<Segment>(segments.length);
-        for (Segment segment : segments) {
-            if (segment == null) {
-                CheckArg.containsNoNulls(segments, "segments");
-            }
-            segmentsList.add(segment);
-        }
-        return new BasicPath(segmentsList, false);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.PathFactory#createRelativePath(java.lang.Iterable)
-     */
-    public Path createRelativePath( Iterable<Segment> segments ) {
-        List<Segment> segmentsList = new LinkedList<Segment>();
-        for (Segment segment : segments) {
-            if (segment == null) {
-                CheckArg.containsNoNulls(segments, "segments");
-            }
-            segmentsList.add(segment);
-        }
-        if (segmentsList.isEmpty()) return BasicPath.EMPTY_RELATIVE;
-        return new BasicPath(segmentsList, false);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.PathFactory#create(org.jboss.dna.graph.properties.Path,
-     *      org.jboss.dna.graph.properties.Path)
-     */
-    public Path create( Path parentPath,
-                        Path childPath ) {
-        CheckArg.isNotNull(parentPath, "parent path");
-        CheckArg.isNotNull(childPath, "child path");
-        if (childPath.size() == 0) return parentPath;
-        if (parentPath.size() == 0) {
-            // Just need to return the child path, but it must be absolute if the parent is ...
-            if (childPath.isAbsolute() == parentPath.isAbsolute()) return childPath;
-            // They aren't the same absoluteness, so create a new one ...
-            return new BasicPath(childPath.getSegmentsList(), parentPath.isAbsolute());
-        }
-        List<Segment> segments = new ArrayList<Segment>(parentPath.size() + childPath.size());
-        for (Segment seg : parentPath) {
-            segments.add(seg);
-        }
-        for (Segment seg : childPath) {
-            segments.add(seg);
-        }
-        return new BasicPath(segments, parentPath.isAbsolute());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( Path parentPath,
-                        Name segmentName,
-                        int index ) {
-        CheckArg.isNotNull(parentPath, "parent path");
-        CheckArg.isNotNull(segmentName, "segment name");
-        return new ChildPath(parentPath, new BasicPathSegment(segmentName, index));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( Path parentPath,
-                        Name... segmentNames ) {
-        CheckArg.isNotNull(parentPath, "parent path");
-        if (segmentNames == null || segmentNames.length == 0) return parentPath;
-        if (segmentNames.length == 1 && segmentNames[0] != null) {
-            return new ChildPath(parentPath, new BasicPathSegment(segmentNames[0]));
-        }
-
-        List<Segment> segments = new ArrayList<Segment>(parentPath.size() + 1);
-        segments.addAll(parentPath.getSegmentsList());
-        for (Name segmentName : segmentNames) {
-            if (segmentName == null) {
-                CheckArg.containsNoNulls(segmentNames, "segment names");
-            }
-            segments.add(new BasicPathSegment(segmentName));
-        }
-        return new BasicPath(segments, parentPath.isAbsolute());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( Path parentPath,
-                        Segment... segments ) {
-        CheckArg.isNotNull(parentPath, "parent path");
-        if (segments == null || segments.length == 0) return RootPath.INSTANCE;
-        if (segments.length == 1 && segments[0] != null) {
-            return new ChildPath(parentPath, segments[0]);
-        }
-
-        List<Segment> segmentsList = new ArrayList<Segment>(parentPath.size() + 1);
-        segmentsList.addAll(parentPath.getSegmentsList());
-        for (Segment segment : segments) {
-            if (segment == null) {
-                CheckArg.containsNoNulls(segments, "segments");
-            }
-            segmentsList.add(segment);
-        }
-        return new BasicPath(segmentsList, parentPath.isAbsolute());
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.PathFactory#create(org.jboss.dna.graph.properties.Path, java.lang.Iterable)
-     */
-    public Path create( Path parentPath,
-                        Iterable<Segment> segments ) {
-        CheckArg.isNotNull(parentPath, "parent path");
-
-        List<Segment> segmentsList = new LinkedList<Segment>();
-        segmentsList.addAll(parentPath.getSegmentsList());
-        for (Segment segment : segments) {
-            if (segment == null) {
-                CheckArg.containsNoNulls(segments, "segments");
-            }
-            segmentsList.add(segment);
-        }
-        if (segmentsList.isEmpty()) return RootPath.INSTANCE;
-        if (segmentsList.size() == 0) return new ChildPath(parentPath, segmentsList.get(0));
-        return new BasicPath(segmentsList, parentPath.isAbsolute());
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.PathFactory#create(org.jboss.dna.graph.properties.Path, java.lang.String)
-     */
-    public Path create( Path parentPath,
-                        String subpath ) {
-        CheckArg.isNotNull(parentPath, "parentPath");
-        CheckArg.isNotNull(subpath, "subpath");
-        subpath = subpath.trim();
-        boolean singleChild = subpath.indexOf(Path.DELIMITER) == -1;
-        if (!singleChild && subpath.startsWith("./")) {
-            if (subpath.length() == 2) return parentPath; // self reference
-            // Remove the leading parent reference and try again to see if single child ...
-            subpath = subpath.substring(2);
-            singleChild = subpath.indexOf(Path.DELIMITER) == -1;
-        }
-        if (singleChild) {
-            try {
-                Path.Segment childSegment = createSegment(subpath);
-                return new ChildPath(parentPath, childSegment);
-            } catch (IllegalArgumentException t) {
-                // Catch and eat, letting the slower implementation catch anything ...
-            }
-        }
-        // It is a subpath with more than one segment, so create a relative path for the subpath ...
-        Path relativeSubpath = create(subpath);
-        return create(parentPath, relativeSubpath);
-
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Segment createSegment( Name segmentName ) {
-        CheckArg.isNotNull(segmentName, "segment name");
-        if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
-        if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
-        return new BasicPathSegment(segmentName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Segment createSegment( Name segmentName,
-                                  int index ) {
-        CheckArg.isNotNull(segmentName, "segment name");
-        if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
-        if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
-        return new BasicPathSegment(segmentName, index);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.PathFactory#createSegment(java.lang.String)
-     */
-    public Segment createSegment( String segmentName ) {
-        return createSegment(segmentName, getDecoder());
-    }
-
-    /**
-     * <p>
-     * {@inheritDoc}
-     * </p>
-     * 
-     * @see org.jboss.dna.graph.properties.PathFactory#createSegment(java.lang.String, org.jboss.dna.common.text.TextDecoder)
-     */
-    public Segment createSegment( String segmentName,
-                                  TextDecoder decoder ) {
-        CheckArg.isNotNull(segmentName, "segment name");
-        if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
-        if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
-        int startBracketNdx = segmentName.indexOf('[');
-        if (startBracketNdx < 0) {
-            return new BasicPathSegment(this.nameValueFactory.create(segmentName, decoder));
-        }
-        int endBracketNdx = segmentName.indexOf(']', startBracketNdx);
-        if (endBracketNdx < 0) {
-            throw new IllegalArgumentException(GraphI18n.missingEndBracketInSegmentName.text(segmentName));
-        }
-        String ndx = segmentName.substring(startBracketNdx + 1, endBracketNdx);
-        try {
-            return new BasicPathSegment(this.nameValueFactory.create(segmentName.substring(0, startBracketNdx), decoder),
-                                        Integer.parseInt(ndx));
-        } catch (NumberFormatException err) {
-            throw new ValueFormatException(segmentName, getPropertyType(), GraphI18n.invalidIndexInSegmentName.text(ndx,
-                                                                                                                    segmentName));
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Segment createSegment( String segmentName,
-                                  int index ) {
-        CheckArg.isNotNull(segmentName, "segment name");
-        if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
-        if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
-        return new BasicPathSegment(this.nameValueFactory.create(segmentName), index);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( Reference value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                          Reference.class.getSimpleName(),
-                                                                          value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( URI value ) {
-        if (value == null) return null;
-        String asciiString = value.toASCIIString();
-        // Remove any leading "./" ...
-        if (asciiString.startsWith("./") && asciiString.length() > 2) {
-            asciiString = asciiString.substring(2);
-        }
-        if (asciiString.indexOf('/') == -1) {
-            return create(asciiString);
-        }
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(URI.class.getSimpleName(),
-                                                                                                    Path.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public Path create( UUID value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                    UUID.class.getSimpleName(),
-                                                                                                    value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( byte[] value ) {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public Path create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( InputStream stream,
-                        long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Path create( Reader reader,
-                        long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Path[] createEmptyArray( int length ) {
-        return new Path[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/PathValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/PathValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/PathValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,688 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+import java.util.regex.Pattern;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.Path.Segment;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#NAME} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class PathValueFactory extends AbstractValueFactory<Path> implements PathFactory {
+
+    /**
+     * Regular expression used to identify the different segments in a path, using the standard '/' delimiter. The expression is
+     * simply:
+     * 
+     * <pre>
+     * /
+     * </pre>
+     */
+    protected static final Pattern DELIMITER_PATTERN = Pattern.compile("/");
+
+    /**
+     * Regular expression used to identify the different parts of a segment. The expression is
+     * 
+     * <pre>
+     * ([&circ;*:/\[\]|]+)(:([&circ;*:/\[\]|]+))?(\[(\d+)])?
+     * </pre>
+     * 
+     * where the first part is accessed with group 1, the second part is accessed with group 3, and the index is accessed with
+     * group 5.
+     */
+    protected static final Pattern SEGMENT_PATTERN = Pattern.compile("([^:/]+)(:([^/\\[\\]]+))?(\\[(\\d+)])?");
+
+    private final ValueFactory<Name> nameValueFactory;
+
+    public PathValueFactory( TextDecoder decoder,
+                             ValueFactory<String> stringValueFactory,
+                             ValueFactory<Name> nameValueFactory ) {
+        super(PropertyType.PATH, decoder, stringValueFactory);
+        CheckArg.isNotNull(nameValueFactory, "nameValueFactory");
+        this.nameValueFactory = nameValueFactory;
+    }
+
+    /**
+     * @return nameValueFactory
+     */
+    protected ValueFactory<Name> getNameValueFactory() {
+        return this.nameValueFactory;
+    }
+
+    /**
+     * <p>
+     * {@inheritDoc}
+     * </p>
+     * 
+     * @see org.jboss.dna.graph.property.PathFactory#createRootPath()
+     */
+    public Path createRootPath() {
+        return RootPath.INSTANCE;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( String value ) {
+        return create(value, getDecoder());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( final String value,
+                        TextDecoder decoder ) {
+        if (value == null) return null;
+        String trimmedValue = value.trim();
+        int length = trimmedValue.length();
+        boolean absolute = false;
+        if (length == 0) {
+            return BasicPath.EMPTY_RELATIVE;
+        }
+        if (Path.DELIMITER_STR.equals(trimmedValue)) return RootPath.INSTANCE;
+        if (Path.SELF.equals(trimmedValue)) return BasicPath.SELF_PATH;
+        if (Path.PARENT.equals(trimmedValue)) return BasicPath.PARENT_PATH;
+
+        // Remove the leading delimiter ...
+        if (trimmedValue.charAt(0) == Path.DELIMITER) {
+            trimmedValue = length > 1 ? trimmedValue.substring(1) : "";
+            --length;
+            absolute = true;
+        }
+        // remove the trailing delimiter ...
+        if (length > 0 && trimmedValue.charAt(length - 1) == Path.DELIMITER) {
+            trimmedValue = length > 1 ? trimmedValue.substring(0, length - 1) : "";
+            length = trimmedValue.length();
+        }
+        if (length == 0) {
+            return RootPath.INSTANCE;
+        }
+
+        // Parse the path into its segments ...
+        List<Segment> segments = new ArrayList<Segment>();
+        String[] pathSegments = DELIMITER_PATTERN.split(trimmedValue);
+        if (pathSegments.length == 0) {
+            throw new ValueFormatException(value, getPropertyType(), GraphI18n.validPathMayNotContainEmptySegment.text(value));
+        }
+        if (decoder == null) decoder = getDecoder();
+        assert pathSegments.length != 0;
+        assert decoder != null;
+        for (String segment : pathSegments) {
+            assert segment != null;
+            segment = segment.trim();
+            if (segment.length() == 0) {
+                throw new ValueFormatException(value, getPropertyType(), GraphI18n.validPathMayNotContainEmptySegment.text(value));
+            }
+            // Create the name and add a segment with it ...
+            segments.add(createSegment(segment, decoder));
+        }
+
+        if (absolute && segments.size() == 1) {
+            // Special case of a single-segment name ...
+            return new ChildPath(RootPath.INSTANCE, segments.get(0));
+        }
+        // Create a path constructed from the supplied segments ...
+        return new BasicPath(segments, absolute);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( int value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          Integer.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( long value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    Long.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( boolean value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          Boolean.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( float value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    Float.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( double value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    Double.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( BigDecimal value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          BigDecimal.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Calendar value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          Calendar.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Date value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    Date.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public Path create( DateTime value ) throws ValueFormatException {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          DateTime.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Name value ) {
+        if (value == null) return null;
+        try {
+            return new ChildPath(RootPath.INSTANCE, new BasicPathSegment(value));
+        } catch (IllegalArgumentException e) {
+            throw new ValueFormatException(value, getPropertyType(), e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Path value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path createAbsolutePath( Name... segmentNames ) {
+        if (segmentNames == null || segmentNames.length == 0) return RootPath.INSTANCE;
+        List<Segment> segments = new ArrayList<Segment>(segmentNames.length);
+        for (Name segmentName : segmentNames) {
+            if (segmentName == null) {
+                CheckArg.containsNoNulls(segmentNames, "segment names");
+            }
+            segments.add(new BasicPathSegment(segmentName));
+        }
+        if (segments.size() == 1) {
+            // Special case of a single-segment name ...
+            return new ChildPath(RootPath.INSTANCE, segments.get(0));
+        }
+        return new BasicPath(segments, true);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path createAbsolutePath( Segment... segments ) {
+        if (segments == null || segments.length == 0) return RootPath.INSTANCE;
+        List<Segment> segmentsList = new ArrayList<Segment>(segments.length);
+        for (Segment segment : segments) {
+            if (segment == null) {
+                CheckArg.containsNoNulls(segments, "segments");
+            }
+            segmentsList.add(segment);
+        }
+        if (segmentsList.size() == 1) {
+            // Special case of a single-segment name ...
+            return new ChildPath(RootPath.INSTANCE, segmentsList.get(0));
+        }
+        return new BasicPath(segmentsList, true);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.PathFactory#createAbsolutePath(java.lang.Iterable)
+     */
+    public Path createAbsolutePath( Iterable<Segment> segments ) {
+        List<Segment> segmentsList = new LinkedList<Segment>();
+        for (Segment segment : segments) {
+            if (segment == null) {
+                CheckArg.containsNoNulls(segments, "segments");
+            }
+            segmentsList.add(segment);
+        }
+        if (segmentsList.isEmpty()) return RootPath.INSTANCE;
+        if (segmentsList.size() == 1) {
+            // Special case of a single-segment name ...
+            return new ChildPath(RootPath.INSTANCE, segmentsList.get(0));
+        }
+        return new BasicPath(segmentsList, true);
+    }
+
+    /**
+     * <p>
+     * {@inheritDoc}
+     * </p>
+     * 
+     * @see org.jboss.dna.graph.property.PathFactory#createRelativePath()
+     */
+    public Path createRelativePath() {
+        return BasicPath.EMPTY_RELATIVE;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path createRelativePath( Name... segmentNames ) {
+        if (segmentNames == null || segmentNames.length == 0) return BasicPath.EMPTY_RELATIVE;
+        List<Segment> segments = new ArrayList<Segment>(segmentNames.length);
+        for (Name segmentName : segmentNames) {
+            if (segmentName == null) {
+                CheckArg.containsNoNulls(segmentNames, "segment names");
+            }
+            segments.add(new BasicPathSegment(segmentName));
+        }
+        return new BasicPath(segments, false);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path createRelativePath( Segment... segments ) {
+        if (segments == null || segments.length == 0) return BasicPath.EMPTY_RELATIVE;
+        List<Segment> segmentsList = new ArrayList<Segment>(segments.length);
+        for (Segment segment : segments) {
+            if (segment == null) {
+                CheckArg.containsNoNulls(segments, "segments");
+            }
+            segmentsList.add(segment);
+        }
+        return new BasicPath(segmentsList, false);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.PathFactory#createRelativePath(java.lang.Iterable)
+     */
+    public Path createRelativePath( Iterable<Segment> segments ) {
+        List<Segment> segmentsList = new LinkedList<Segment>();
+        for (Segment segment : segments) {
+            if (segment == null) {
+                CheckArg.containsNoNulls(segments, "segments");
+            }
+            segmentsList.add(segment);
+        }
+        if (segmentsList.isEmpty()) return BasicPath.EMPTY_RELATIVE;
+        return new BasicPath(segmentsList, false);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.PathFactory#create(org.jboss.dna.graph.property.Path,
+     *      org.jboss.dna.graph.property.Path)
+     */
+    public Path create( Path parentPath,
+                        Path childPath ) {
+        CheckArg.isNotNull(parentPath, "parent path");
+        CheckArg.isNotNull(childPath, "child path");
+        if (childPath.size() == 0) return parentPath;
+        if (parentPath.size() == 0) {
+            // Just need to return the child path, but it must be absolute if the parent is ...
+            if (childPath.isAbsolute() == parentPath.isAbsolute()) return childPath;
+            // They aren't the same absoluteness, so create a new one ...
+            return new BasicPath(childPath.getSegmentsList(), parentPath.isAbsolute());
+        }
+        List<Segment> segments = new ArrayList<Segment>(parentPath.size() + childPath.size());
+        for (Segment seg : parentPath) {
+            segments.add(seg);
+        }
+        for (Segment seg : childPath) {
+            segments.add(seg);
+        }
+        return new BasicPath(segments, parentPath.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Path parentPath,
+                        Name segmentName,
+                        int index ) {
+        CheckArg.isNotNull(parentPath, "parent path");
+        CheckArg.isNotNull(segmentName, "segment name");
+        return new ChildPath(parentPath, new BasicPathSegment(segmentName, index));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Path parentPath,
+                        Name... segmentNames ) {
+        CheckArg.isNotNull(parentPath, "parent path");
+        if (segmentNames == null || segmentNames.length == 0) return parentPath;
+        if (segmentNames.length == 1 && segmentNames[0] != null) {
+            return new ChildPath(parentPath, new BasicPathSegment(segmentNames[0]));
+        }
+
+        List<Segment> segments = new ArrayList<Segment>(parentPath.size() + 1);
+        segments.addAll(parentPath.getSegmentsList());
+        for (Name segmentName : segmentNames) {
+            if (segmentName == null) {
+                CheckArg.containsNoNulls(segmentNames, "segment names");
+            }
+            segments.add(new BasicPathSegment(segmentName));
+        }
+        return new BasicPath(segments, parentPath.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Path parentPath,
+                        Segment... segments ) {
+        CheckArg.isNotNull(parentPath, "parent path");
+        if (segments == null || segments.length == 0) return RootPath.INSTANCE;
+        if (segments.length == 1 && segments[0] != null) {
+            return new ChildPath(parentPath, segments[0]);
+        }
+
+        List<Segment> segmentsList = new ArrayList<Segment>(parentPath.size() + 1);
+        segmentsList.addAll(parentPath.getSegmentsList());
+        for (Segment segment : segments) {
+            if (segment == null) {
+                CheckArg.containsNoNulls(segments, "segments");
+            }
+            segmentsList.add(segment);
+        }
+        return new BasicPath(segmentsList, parentPath.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.PathFactory#create(org.jboss.dna.graph.property.Path, java.lang.Iterable)
+     */
+    public Path create( Path parentPath,
+                        Iterable<Segment> segments ) {
+        CheckArg.isNotNull(parentPath, "parent path");
+
+        List<Segment> segmentsList = new LinkedList<Segment>();
+        segmentsList.addAll(parentPath.getSegmentsList());
+        for (Segment segment : segments) {
+            if (segment == null) {
+                CheckArg.containsNoNulls(segments, "segments");
+            }
+            segmentsList.add(segment);
+        }
+        if (segmentsList.isEmpty()) return RootPath.INSTANCE;
+        if (segmentsList.size() == 0) return new ChildPath(parentPath, segmentsList.get(0));
+        return new BasicPath(segmentsList, parentPath.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.PathFactory#create(org.jboss.dna.graph.property.Path, java.lang.String)
+     */
+    public Path create( Path parentPath,
+                        String subpath ) {
+        CheckArg.isNotNull(parentPath, "parentPath");
+        CheckArg.isNotNull(subpath, "subpath");
+        subpath = subpath.trim();
+        boolean singleChild = subpath.indexOf(Path.DELIMITER) == -1;
+        if (!singleChild && subpath.startsWith("./")) {
+            if (subpath.length() == 2) return parentPath; // self reference
+            // Remove the leading parent reference and try again to see if single child ...
+            subpath = subpath.substring(2);
+            singleChild = subpath.indexOf(Path.DELIMITER) == -1;
+        }
+        if (singleChild) {
+            try {
+                Path.Segment childSegment = createSegment(subpath);
+                return new ChildPath(parentPath, childSegment);
+            } catch (IllegalArgumentException t) {
+                // Catch and eat, letting the slower implementation catch anything ...
+            }
+        }
+        // It is a subpath with more than one segment, so create a relative path for the subpath ...
+        Path relativeSubpath = create(subpath);
+        return create(parentPath, relativeSubpath);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Segment createSegment( Name segmentName ) {
+        CheckArg.isNotNull(segmentName, "segment name");
+        if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
+        if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
+        return new BasicPathSegment(segmentName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Segment createSegment( Name segmentName,
+                                  int index ) {
+        CheckArg.isNotNull(segmentName, "segment name");
+        if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
+        if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
+        return new BasicPathSegment(segmentName, index);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.PathFactory#createSegment(java.lang.String)
+     */
+    public Segment createSegment( String segmentName ) {
+        return createSegment(segmentName, getDecoder());
+    }
+
+    /**
+     * <p>
+     * {@inheritDoc}
+     * </p>
+     * 
+     * @see org.jboss.dna.graph.property.PathFactory#createSegment(java.lang.String, org.jboss.dna.common.text.TextDecoder)
+     */
+    public Segment createSegment( String segmentName,
+                                  TextDecoder decoder ) {
+        CheckArg.isNotNull(segmentName, "segment name");
+        if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
+        if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
+        int startBracketNdx = segmentName.indexOf('[');
+        if (startBracketNdx < 0) {
+            return new BasicPathSegment(this.nameValueFactory.create(segmentName, decoder));
+        }
+        int endBracketNdx = segmentName.indexOf(']', startBracketNdx);
+        if (endBracketNdx < 0) {
+            throw new IllegalArgumentException(GraphI18n.missingEndBracketInSegmentName.text(segmentName));
+        }
+        String ndx = segmentName.substring(startBracketNdx + 1, endBracketNdx);
+        try {
+            return new BasicPathSegment(this.nameValueFactory.create(segmentName.substring(0, startBracketNdx), decoder),
+                                        Integer.parseInt(ndx));
+        } catch (NumberFormatException err) {
+            throw new ValueFormatException(segmentName, getPropertyType(), GraphI18n.invalidIndexInSegmentName.text(ndx,
+                                                                                                                    segmentName));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Segment createSegment( String segmentName,
+                                  int index ) {
+        CheckArg.isNotNull(segmentName, "segment name");
+        if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
+        if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
+        return new BasicPathSegment(this.nameValueFactory.create(segmentName), index);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Reference value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                          Reference.class.getSimpleName(),
+                                                                          value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( URI value ) {
+        if (value == null) return null;
+        String asciiString = value.toASCIIString();
+        // Remove any leading "./" ...
+        if (asciiString.startsWith("./") && asciiString.length() > 2) {
+            asciiString = asciiString.substring(2);
+        }
+        if (asciiString.indexOf('/') == -1) {
+            return create(asciiString);
+        }
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(URI.class.getSimpleName(),
+                                                                                                    Path.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public Path create( UUID value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                    UUID.class.getSimpleName(),
+                                                                                                    value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( byte[] value ) {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public Path create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( InputStream stream,
+                        long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Reader reader,
+                        long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Path[] createEmptyArray( int length ) {
+        return new Path[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/RootPath.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,393 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.Inflector;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-
-/**
- * Optimized implementation of {@link Path} that serves as the root path.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class RootPath extends AbstractPath {
-
-    /**
-     * The serializable version. Version {@value}
-     */
-    private static final long serialVersionUID = 1L;
-
-    public static final Path INSTANCE = new RootPath();
-
-    private static final Path.Segment[] EMPTY_SEGMENT_ARRAY = new Path.Segment[] {};
-    private static final List<Path.Segment> EMPTY_SEGMENT_LIST = Collections.emptyList();
-
-    private RootPath() {
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getAncestor(int)
-     */
-    public Path getAncestor( int degree ) {
-        CheckArg.isNonNegative(degree, "degree");
-        if (degree == 0) {
-            return this;
-        }
-        String msg = GraphI18n.pathAncestorDegreeIsInvalid.text(this.getString(), Inflector.getInstance().ordinalize(degree));
-        throw new InvalidPathException(msg);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getCanonicalPath()
-     */
-    @Override
-    public Path getCanonicalPath() {
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getCommonAncestor(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public Path getCommonAncestor( Path that ) {
-        CheckArg.isNotNull(that, "that");
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getLastSegment()
-     */
-    @Override
-    public Segment getLastSegment() {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getNormalizedPath()
-     */
-    @Override
-    public Path getNormalizedPath() {
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.basic.AbstractPath#resolve(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public Path resolve( Path relativePath ) {
-        CheckArg.isNotNull(relativePath, "relative path");
-        if (relativePath.isAbsolute()) {
-            String msg = GraphI18n.pathIsNotRelative.text(relativePath);
-            throw new InvalidPathException(msg);
-        }
-        // Make an absolute path out of the supplied relative path ...
-        return new BasicPath(relativePath.getSegmentsList(), true).getNormalizedPath();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getParent()
-     */
-    @Override
-    public Path getParent() {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getSegment(int)
-     */
-    @Override
-    public Segment getSegment( int index ) {
-        CheckArg.isNonNegative(index, "index");
-        EMPTY_SEGMENT_LIST.get(index); // throws IndexOutOfBoundsException
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getSegmentsArray()
-     */
-    @Override
-    public Segment[] getSegmentsArray() {
-        // Can return the same array every time, since it's empty ...
-        return EMPTY_SEGMENT_ARRAY;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getSegmentsList()
-     */
-    public List<Segment> getSegmentsList() {
-        return EMPTY_SEGMENT_LIST;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getString()
-     */
-    @Override
-    public String getString() {
-        return Path.DELIMITER_STR;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.common.text.TextEncoder)
-     */
-    @Override
-    public String getString( TextEncoder encoder ) {
-        return Path.DELIMITER_STR;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry)
-     */
-    @Override
-    public String getString( NamespaceRegistry namespaceRegistry ) {
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        return Path.DELIMITER_STR;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
-     *      org.jboss.dna.common.text.TextEncoder)
-     */
-    @Override
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder ) {
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        return Path.DELIMITER_STR;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
-     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
-     */
-    @Override
-    public String getString( NamespaceRegistry namespaceRegistry,
-                             TextEncoder encoder,
-                             TextEncoder delimiterEncoder ) {
-        return (delimiterEncoder == null) ? DELIMITER_STR : delimiterEncoder.encode(DELIMITER_STR);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#hasSameAncestor(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public boolean hasSameAncestor( Path that ) {
-        CheckArg.isNotNull(that, "that");
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isAbsolute()
-     */
-    public boolean isAbsolute() {
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isAncestorOf(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public boolean isAncestorOf( Path decendant ) {
-        CheckArg.isNotNull(decendant, "decendant");
-        return !decendant.isRoot();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isAtOrAbove(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public boolean isAtOrAbove( Path other ) {
-        CheckArg.isNotNull(other, "other");
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isAtOrBelow(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public boolean isAtOrBelow( Path other ) {
-        CheckArg.isNotNull(other, "other");
-        return other.isRoot();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isDecendantOf(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public boolean isDecendantOf( Path ancestor ) {
-        CheckArg.isNotNull(ancestor, "ancestor");
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isNormalized()
-     */
-    public boolean isNormalized() {
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isRoot()
-     */
-    public boolean isRoot() {
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#isSameAs(org.jboss.dna.graph.properties.Path)
-     */
-    @Override
-    public boolean isSameAs( Path other ) {
-        CheckArg.isNotNull(other, "other");
-        return other.isRoot();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#iterator()
-     */
-    @Override
-    public Iterator<Segment> iterator() {
-        return EMPTY_SEGMENT_LIST.iterator();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#size()
-     */
-    public int size() {
-        return 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#subpath(int)
-     */
-    @Override
-    public Path subpath( int beginIndex ) {
-        CheckArg.isNonNegative(beginIndex, "beginIndex");
-        if (beginIndex == 0) return this;
-        EMPTY_SEGMENT_LIST.get(1); // throws IndexOutOfBoundsException
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.Path#subpath(int, int)
-     */
-    @Override
-    public Path subpath( int beginIndex,
-                         int endIndex ) {
-        CheckArg.isNonNegative(beginIndex, "beginIndex");
-        CheckArg.isNonNegative(endIndex, "endIndex");
-        if (endIndex >= 1) {
-            EMPTY_SEGMENT_LIST.get(endIndex); // throws IndexOutOfBoundsException
-        }
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Comparable#compareTo(java.lang.Object)
-     */
-    @Override
-    public int compareTo( Path other ) {
-        return other.isRoot() ? 0 : -1;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof Path) {
-            Path that = (Path)obj;
-            return that.isRoot();
-        }
-        return false;
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/RootPath.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,393 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.Inflector;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * Optimized implementation of {@link Path} that serves as the root path.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class RootPath extends AbstractPath {
+
+    /**
+     * The serializable version. Version {@value}
+     */
+    private static final long serialVersionUID = 1L;
+
+    public static final Path INSTANCE = new RootPath();
+
+    private static final Path.Segment[] EMPTY_SEGMENT_ARRAY = new Path.Segment[] {};
+    private static final List<Path.Segment> EMPTY_SEGMENT_LIST = Collections.emptyList();
+
+    private RootPath() {
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getAncestor(int)
+     */
+    public Path getAncestor( int degree ) {
+        CheckArg.isNonNegative(degree, "degree");
+        if (degree == 0) {
+            return this;
+        }
+        String msg = GraphI18n.pathAncestorDegreeIsInvalid.text(this.getString(), Inflector.getInstance().ordinalize(degree));
+        throw new InvalidPathException(msg);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getCanonicalPath()
+     */
+    @Override
+    public Path getCanonicalPath() {
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getCommonAncestor(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public Path getCommonAncestor( Path that ) {
+        CheckArg.isNotNull(that, "that");
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getLastSegment()
+     */
+    @Override
+    public Segment getLastSegment() {
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getNormalizedPath()
+     */
+    @Override
+    public Path getNormalizedPath() {
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.AbstractPath#resolve(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public Path resolve( Path relativePath ) {
+        CheckArg.isNotNull(relativePath, "relative path");
+        if (relativePath.isAbsolute()) {
+            String msg = GraphI18n.pathIsNotRelative.text(relativePath);
+            throw new InvalidPathException(msg);
+        }
+        // Make an absolute path out of the supplied relative path ...
+        return new BasicPath(relativePath.getSegmentsList(), true).getNormalizedPath();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getParent()
+     */
+    @Override
+    public Path getParent() {
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getSegment(int)
+     */
+    @Override
+    public Segment getSegment( int index ) {
+        CheckArg.isNonNegative(index, "index");
+        EMPTY_SEGMENT_LIST.get(index); // throws IndexOutOfBoundsException
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getSegmentsArray()
+     */
+    @Override
+    public Segment[] getSegmentsArray() {
+        // Can return the same array every time, since it's empty ...
+        return EMPTY_SEGMENT_ARRAY;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getSegmentsList()
+     */
+    public List<Segment> getSegmentsList() {
+        return EMPTY_SEGMENT_LIST;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getString()
+     */
+    @Override
+    public String getString() {
+        return Path.DELIMITER_STR;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getString(org.jboss.dna.common.text.TextEncoder)
+     */
+    @Override
+    public String getString( TextEncoder encoder ) {
+        return Path.DELIMITER_STR;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getString(org.jboss.dna.graph.property.NamespaceRegistry)
+     */
+    @Override
+    public String getString( NamespaceRegistry namespaceRegistry ) {
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        return Path.DELIMITER_STR;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getString(org.jboss.dna.graph.property.NamespaceRegistry,
+     *      org.jboss.dna.common.text.TextEncoder)
+     */
+    @Override
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder ) {
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        return Path.DELIMITER_STR;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#getString(org.jboss.dna.graph.property.NamespaceRegistry,
+     *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
+     */
+    @Override
+    public String getString( NamespaceRegistry namespaceRegistry,
+                             TextEncoder encoder,
+                             TextEncoder delimiterEncoder ) {
+        return (delimiterEncoder == null) ? DELIMITER_STR : delimiterEncoder.encode(DELIMITER_STR);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#hasSameAncestor(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public boolean hasSameAncestor( Path that ) {
+        CheckArg.isNotNull(that, "that");
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isAbsolute()
+     */
+    public boolean isAbsolute() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isAncestorOf(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public boolean isAncestorOf( Path decendant ) {
+        CheckArg.isNotNull(decendant, "decendant");
+        return !decendant.isRoot();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isAtOrAbove(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public boolean isAtOrAbove( Path other ) {
+        CheckArg.isNotNull(other, "other");
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isAtOrBelow(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public boolean isAtOrBelow( Path other ) {
+        CheckArg.isNotNull(other, "other");
+        return other.isRoot();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isDecendantOf(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public boolean isDecendantOf( Path ancestor ) {
+        CheckArg.isNotNull(ancestor, "ancestor");
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isNormalized()
+     */
+    public boolean isNormalized() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isRoot()
+     */
+    public boolean isRoot() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#isSameAs(org.jboss.dna.graph.property.Path)
+     */
+    @Override
+    public boolean isSameAs( Path other ) {
+        CheckArg.isNotNull(other, "other");
+        return other.isRoot();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#iterator()
+     */
+    @Override
+    public Iterator<Segment> iterator() {
+        return EMPTY_SEGMENT_LIST.iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#size()
+     */
+    public int size() {
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#subpath(int)
+     */
+    @Override
+    public Path subpath( int beginIndex ) {
+        CheckArg.isNonNegative(beginIndex, "beginIndex");
+        if (beginIndex == 0) return this;
+        EMPTY_SEGMENT_LIST.get(1); // throws IndexOutOfBoundsException
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#subpath(int, int)
+     */
+    @Override
+    public Path subpath( int beginIndex,
+                         int endIndex ) {
+        CheckArg.isNonNegative(beginIndex, "beginIndex");
+        CheckArg.isNonNegative(endIndex, "endIndex");
+        if (endIndex >= 1) {
+            EMPTY_SEGMENT_LIST.get(endIndex); // throws IndexOutOfBoundsException
+        }
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Comparable#compareTo(java.lang.Object)
+     */
+    @Override
+    public int compareTo( Path other ) {
+        return other.isRoot() ? 0 : -1;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof Path) {
+            Path that = (Path)obj;
+            return that.isRoot();
+        }
+        return false;
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StandardValueFactories.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/StandardValueFactories.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StandardValueFactories.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,243 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.BinaryFactory;
-import org.jboss.dna.graph.properties.DateTimeFactory;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.UuidFactory;
-import org.jboss.dna.graph.properties.ValueFactory;
-
-/**
- * The standard set of {@link ValueFactory value factories}.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class StandardValueFactories extends AbstractValueFactories {
-
-    // This class is implemented with separate members for each factory so that the typical usage is optimized.
-    private final ValueFactory<String> stringFactory;
-    private final BinaryFactory binaryFactory;
-    private final ValueFactory<Boolean> booleanFactory;
-    private final DateTimeFactory dateFactory;
-    private final ValueFactory<BigDecimal> decimalFactory;
-    private final ValueFactory<Double> doubleFactory;
-    private final ValueFactory<Long> longFactory;
-    private final NameFactory nameFactory;
-    private final PathFactory pathFactory;
-    private final ValueFactory<Reference> referenceFactory;
-    private final ValueFactory<URI> uriFactory;
-    private final UuidFactory uuidFactory;
-    private final ValueFactory<Object> objectFactory;
-
-    private final NamespaceRegistry namespaceRegistry;
-    private final TextDecoder decoder;
-    private final TextEncoder encoder;
-
-    /**
-     * Create a standard set of value factories, using the {@link ValueFactory#DEFAULT_DECODER default decoder}.
-     * 
-     * @param namespaceRegistry the namespace registry
-     * @throws IllegalArgumentException if the namespace registry is null
-     */
-    public StandardValueFactories( NamespaceRegistry namespaceRegistry ) {
-        this(namespaceRegistry, null, null);
-    }
-
-    /**
-     * Create a standard set of value factories, using the supplied encoder/decoder.
-     * 
-     * @param namespaceRegistry the namespace registry
-     * @param decoder the decoder that should be used; if null, the {@link ValueFactory#DEFAULT_DECODER default decoder} is used.
-     * @param encoder the encoder that should be used; if null, the {@link ValueFactory#DEFAULT_ENCODER default encoder} is used.
-     * @param extraFactories any extra factories that should be used; any factory will override the standard factories based upon
-     *        the {@link ValueFactory#getPropertyType() factory's property type}.
-     * @throws IllegalArgumentException if the namespace registry is null
-     */
-    public StandardValueFactories( NamespaceRegistry namespaceRegistry,
-                                   TextDecoder decoder,
-                                   TextEncoder encoder,
-                                   ValueFactory<?>... extraFactories ) {
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        this.namespaceRegistry = namespaceRegistry;
-        this.decoder = decoder != null ? decoder : ValueFactory.DEFAULT_DECODER;
-        this.encoder = encoder != null ? encoder : ValueFactory.DEFAULT_ENCODER;
-        Map<PropertyType, ValueFactory<?>> factories = new HashMap<PropertyType, ValueFactory<?>>();
-
-        // Put the extra factories into the map first ...
-        for (ValueFactory<?> factory : extraFactories) {
-            if (factory == null) continue;
-            factories.put(factory.getPropertyType(), factory);
-        }
-
-        // Now assign the members, using the factories in the map or (if null) the supplied default ...
-        this.stringFactory = getFactory(factories, new StringValueFactory(this.decoder, this.encoder));
-        this.binaryFactory = (BinaryFactory)getFactory(factories,
-                                                       new InMemoryBinaryValueFactory(this.decoder, this.stringFactory));
-        this.booleanFactory = getFactory(factories, new BooleanValueFactory(this.decoder, this.stringFactory));
-        this.dateFactory = (DateTimeFactory)getFactory(factories, new JodaDateTimeValueFactory(this.decoder, this.stringFactory));
-        this.decimalFactory = getFactory(factories, new DecimalValueFactory(this.decoder, this.stringFactory));
-        this.doubleFactory = getFactory(factories, new DoubleValueFactory(this.decoder, this.stringFactory));
-        this.longFactory = getFactory(factories, new LongValueFactory(this.decoder, this.stringFactory));
-        this.nameFactory = (NameFactory)getFactory(factories, new NameValueFactory(this.namespaceRegistry, this.decoder,
-                                                                                   this.stringFactory));
-        this.pathFactory = (PathFactory)getFactory(factories, new PathValueFactory(this.decoder, this.stringFactory,
-                                                                                   this.nameFactory));
-        this.referenceFactory = getFactory(factories, new UuidReferenceValueFactory(this.decoder, this.stringFactory));
-        this.uuidFactory = (UuidFactory)getFactory(factories, new UuidValueFactory(this.decoder, this.stringFactory));
-        this.uriFactory = getFactory(factories, new UriValueFactory(this.namespaceRegistry, this.decoder, this.stringFactory));
-        this.objectFactory = getFactory(factories, new ObjectValueFactory(this.decoder, this.stringFactory, this.binaryFactory));
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private static <T> ValueFactory<T> getFactory( Map<PropertyType, ValueFactory<?>> factories,
-                                                   ValueFactory<T> defaultFactory ) {
-        PropertyType type = defaultFactory.getPropertyType();
-        ValueFactory<?> factory = factories.get(type);
-        if (factory == null) {
-            factory = defaultFactory;
-            factories.put(type, factory);
-        }
-        return (ValueFactory<T>)factory;
-    }
-
-    /**
-     * @return decoder
-     */
-    public TextDecoder getTextDecoder() {
-        return this.decoder;
-    }
-
-    /**
-     * @return namespaceRegistry
-     */
-    public NamespaceRegistry getNamespaceRegistry() {
-        return this.namespaceRegistry;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public BinaryFactory getBinaryFactory() {
-        return this.binaryFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<Boolean> getBooleanFactory() {
-        return this.booleanFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public DateTimeFactory getDateFactory() {
-        return this.dateFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<BigDecimal> getDecimalFactory() {
-        return this.decimalFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<Double> getDoubleFactory() {
-        return this.doubleFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<Long> getLongFactory() {
-        return this.longFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public NameFactory getNameFactory() {
-        return this.nameFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public PathFactory getPathFactory() {
-        return this.pathFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<Reference> getReferenceFactory() {
-        return this.referenceFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<String> getStringFactory() {
-        return this.stringFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<URI> getUriFactory() {
-        return this.uriFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactories#getUuidFactory()
-     */
-    public UuidFactory getUuidFactory() {
-        return this.uuidFactory;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactory<Object> getObjectFactory() {
-        return this.objectFactory;
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StandardValueFactories.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/StandardValueFactories.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StandardValueFactories.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StandardValueFactories.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,243 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.BinaryFactory;
+import org.jboss.dna.graph.property.DateTimeFactory;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.UuidFactory;
+import org.jboss.dna.graph.property.ValueFactory;
+
+/**
+ * The standard set of {@link ValueFactory value factories}.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class StandardValueFactories extends AbstractValueFactories {
+
+    // This class is implemented with separate members for each factory so that the typical usage is optimized.
+    private final ValueFactory<String> stringFactory;
+    private final BinaryFactory binaryFactory;
+    private final ValueFactory<Boolean> booleanFactory;
+    private final DateTimeFactory dateFactory;
+    private final ValueFactory<BigDecimal> decimalFactory;
+    private final ValueFactory<Double> doubleFactory;
+    private final ValueFactory<Long> longFactory;
+    private final NameFactory nameFactory;
+    private final PathFactory pathFactory;
+    private final ValueFactory<Reference> referenceFactory;
+    private final ValueFactory<URI> uriFactory;
+    private final UuidFactory uuidFactory;
+    private final ValueFactory<Object> objectFactory;
+
+    private final NamespaceRegistry namespaceRegistry;
+    private final TextDecoder decoder;
+    private final TextEncoder encoder;
+
+    /**
+     * Create a standard set of value factories, using the {@link ValueFactory#DEFAULT_DECODER default decoder}.
+     * 
+     * @param namespaceRegistry the namespace registry
+     * @throws IllegalArgumentException if the namespace registry is null
+     */
+    public StandardValueFactories( NamespaceRegistry namespaceRegistry ) {
+        this(namespaceRegistry, null, null);
+    }
+
+    /**
+     * Create a standard set of value factories, using the supplied encoder/decoder.
+     * 
+     * @param namespaceRegistry the namespace registry
+     * @param decoder the decoder that should be used; if null, the {@link ValueFactory#DEFAULT_DECODER default decoder} is used.
+     * @param encoder the encoder that should be used; if null, the {@link ValueFactory#DEFAULT_ENCODER default encoder} is used.
+     * @param extraFactories any extra factories that should be used; any factory will override the standard factories based upon
+     *        the {@link ValueFactory#getPropertyType() factory's property type}.
+     * @throws IllegalArgumentException if the namespace registry is null
+     */
+    public StandardValueFactories( NamespaceRegistry namespaceRegistry,
+                                   TextDecoder decoder,
+                                   TextEncoder encoder,
+                                   ValueFactory<?>... extraFactories ) {
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        this.namespaceRegistry = namespaceRegistry;
+        this.decoder = decoder != null ? decoder : ValueFactory.DEFAULT_DECODER;
+        this.encoder = encoder != null ? encoder : ValueFactory.DEFAULT_ENCODER;
+        Map<PropertyType, ValueFactory<?>> factories = new HashMap<PropertyType, ValueFactory<?>>();
+
+        // Put the extra factories into the map first ...
+        for (ValueFactory<?> factory : extraFactories) {
+            if (factory == null) continue;
+            factories.put(factory.getPropertyType(), factory);
+        }
+
+        // Now assign the members, using the factories in the map or (if null) the supplied default ...
+        this.stringFactory = getFactory(factories, new StringValueFactory(this.decoder, this.encoder));
+        this.binaryFactory = (BinaryFactory)getFactory(factories,
+                                                       new InMemoryBinaryValueFactory(this.decoder, this.stringFactory));
+        this.booleanFactory = getFactory(factories, new BooleanValueFactory(this.decoder, this.stringFactory));
+        this.dateFactory = (DateTimeFactory)getFactory(factories, new JodaDateTimeValueFactory(this.decoder, this.stringFactory));
+        this.decimalFactory = getFactory(factories, new DecimalValueFactory(this.decoder, this.stringFactory));
+        this.doubleFactory = getFactory(factories, new DoubleValueFactory(this.decoder, this.stringFactory));
+        this.longFactory = getFactory(factories, new LongValueFactory(this.decoder, this.stringFactory));
+        this.nameFactory = (NameFactory)getFactory(factories, new NameValueFactory(this.namespaceRegistry, this.decoder,
+                                                                                   this.stringFactory));
+        this.pathFactory = (PathFactory)getFactory(factories, new PathValueFactory(this.decoder, this.stringFactory,
+                                                                                   this.nameFactory));
+        this.referenceFactory = getFactory(factories, new UuidReferenceValueFactory(this.decoder, this.stringFactory));
+        this.uuidFactory = (UuidFactory)getFactory(factories, new UuidValueFactory(this.decoder, this.stringFactory));
+        this.uriFactory = getFactory(factories, new UriValueFactory(this.namespaceRegistry, this.decoder, this.stringFactory));
+        this.objectFactory = getFactory(factories, new ObjectValueFactory(this.decoder, this.stringFactory, this.binaryFactory));
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private static <T> ValueFactory<T> getFactory( Map<PropertyType, ValueFactory<?>> factories,
+                                                   ValueFactory<T> defaultFactory ) {
+        PropertyType type = defaultFactory.getPropertyType();
+        ValueFactory<?> factory = factories.get(type);
+        if (factory == null) {
+            factory = defaultFactory;
+            factories.put(type, factory);
+        }
+        return (ValueFactory<T>)factory;
+    }
+
+    /**
+     * @return decoder
+     */
+    public TextDecoder getTextDecoder() {
+        return this.decoder;
+    }
+
+    /**
+     * @return namespaceRegistry
+     */
+    public NamespaceRegistry getNamespaceRegistry() {
+        return this.namespaceRegistry;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public BinaryFactory getBinaryFactory() {
+        return this.binaryFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<Boolean> getBooleanFactory() {
+        return this.booleanFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DateTimeFactory getDateFactory() {
+        return this.dateFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<BigDecimal> getDecimalFactory() {
+        return this.decimalFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<Double> getDoubleFactory() {
+        return this.doubleFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<Long> getLongFactory() {
+        return this.longFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public NameFactory getNameFactory() {
+        return this.nameFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PathFactory getPathFactory() {
+        return this.pathFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<Reference> getReferenceFactory() {
+        return this.referenceFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<String> getStringFactory() {
+        return this.stringFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<URI> getUriFactory() {
+        return this.uriFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactories#getUuidFactory()
+     */
+    public UuidFactory getUuidFactory() {
+        return this.uuidFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<Object> getObjectFactory() {
+        return this.objectFactory;
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StringValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/StringValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StringValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,293 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.IoUtil;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#STRING} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class StringValueFactory extends AbstractValueFactory<String> {
-
-    private final TextEncoder encoder;
-
-    public StringValueFactory( TextDecoder decoder,
-                               TextEncoder encoder ) {
-        super(PropertyType.STRING, decoder, null);
-        CheckArg.isNotNull(encoder, "encoder");
-        this.encoder = encoder;
-    }
-
-    /**
-     * @return encoder
-     */
-    public TextEncoder getEncoder() {
-        return this.encoder;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected ValueFactory<String> getStringValueFactory() {
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( String value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( String value,
-                          TextDecoder decoder ) {
-        if (value == null) return value;
-        if (decoder == null) decoder = getDecoder();
-        return decoder.decode(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( int value ) {
-        return Integer.toString(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( long value ) {
-        return Long.toString(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( boolean value ) {
-        return Boolean.toString(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( float value ) {
-        return Float.toString(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( double value ) {
-        return Double.toString(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( BigDecimal value ) {
-        if (value == null) return null;
-        return value.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( Calendar value ) {
-        if (value == null) return null;
-        return new JodaDateTime(value).getString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( Date value ) {
-        if (value == null) return null;
-        return new JodaDateTime(value).getString();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public String create( DateTime value ) throws ValueFormatException {
-        if (value == null) return null;
-        return value.getString(); // ISO representation
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( Name value ) {
-        if (value == null) return null;
-        return value.getString(getEncoder());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( Path value ) {
-        if (value == null) return null;
-        return value.getString(getEncoder());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( Reference value ) {
-        if (value == null) return null;
-        return value.getString(getEncoder());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( URI value ) {
-        if (value == null) return null;
-        return value.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public String create( UUID value ) throws IoException {
-        if (value == null) return null;
-        return value.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( byte[] value ) {
-        if (value == null) return null;
-        try {
-            return new String(value, "UTF-8");
-        } catch (UnsupportedEncodingException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(byte[].class.getSimpleName(),
-                                                                            String.class.getSimpleName(),
-                                                                            value), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public String create( Binary value ) throws ValueFormatException, IoException {
-        if (value == null) return null;
-        try {
-            value.acquire();
-            InputStream stream = value.getStream();
-            try {
-                return create(stream, value.getSize());
-            } finally {
-                try {
-                    stream.close();
-                } catch (IOException e) {
-                    Logger.getLogger(getClass()).debug(e, "Error closing the stream while converting from Binary to String");
-                }
-            }
-        } finally {
-            value.release();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( InputStream stream,
-                          long approximateLength ) throws IoException {
-        if (stream == null) return null;
-        byte[] value = null;
-        try {
-            value = IoUtil.readBytes(stream);
-            return new String(value, "UTF-8");
-        } catch (UnsupportedEncodingException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(InputStream.class.getSimpleName(),
-                                                                            String.class.getSimpleName(),
-                                                                            value), err);
-        } catch (IOException err) {
-            throw new IoException(
-                                  GraphI18n.errorConvertingIo.text(InputStream.class.getSimpleName(), String.class.getSimpleName()),
-                                  err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String create( Reader reader,
-                          long approximateLength ) throws IoException {
-        if (reader == null) return null;
-        try {
-            return IoUtil.read(reader);
-        } catch (IOException err) {
-            throw new IoException(GraphI18n.errorConvertingIo.text(Reader.class.getSimpleName(), String.class.getSimpleName()), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected String[] createEmptyArray( int length ) {
-        return new String[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StringValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/StringValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StringValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/StringValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,293 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.IoUtil;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#STRING} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class StringValueFactory extends AbstractValueFactory<String> {
+
+    private final TextEncoder encoder;
+
+    public StringValueFactory( TextDecoder decoder,
+                               TextEncoder encoder ) {
+        super(PropertyType.STRING, decoder, null);
+        CheckArg.isNotNull(encoder, "encoder");
+        this.encoder = encoder;
+    }
+
+    /**
+     * @return encoder
+     */
+    public TextEncoder getEncoder() {
+        return this.encoder;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected ValueFactory<String> getStringValueFactory() {
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( String value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( String value,
+                          TextDecoder decoder ) {
+        if (value == null) return value;
+        if (decoder == null) decoder = getDecoder();
+        return decoder.decode(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( int value ) {
+        return Integer.toString(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( long value ) {
+        return Long.toString(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( boolean value ) {
+        return Boolean.toString(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( float value ) {
+        return Float.toString(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( double value ) {
+        return Double.toString(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( BigDecimal value ) {
+        if (value == null) return null;
+        return value.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( Calendar value ) {
+        if (value == null) return null;
+        return new JodaDateTime(value).getString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( Date value ) {
+        if (value == null) return null;
+        return new JodaDateTime(value).getString();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public String create( DateTime value ) throws ValueFormatException {
+        if (value == null) return null;
+        return value.getString(); // ISO representation
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( Name value ) {
+        if (value == null) return null;
+        return value.getString(getEncoder());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( Path value ) {
+        if (value == null) return null;
+        return value.getString(getEncoder());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( Reference value ) {
+        if (value == null) return null;
+        return value.getString(getEncoder());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( URI value ) {
+        if (value == null) return null;
+        return value.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public String create( UUID value ) throws IoException {
+        if (value == null) return null;
+        return value.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( byte[] value ) {
+        if (value == null) return null;
+        try {
+            return new String(value, "UTF-8");
+        } catch (UnsupportedEncodingException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(byte[].class.getSimpleName(),
+                                                                            String.class.getSimpleName(),
+                                                                            value), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public String create( Binary value ) throws ValueFormatException, IoException {
+        if (value == null) return null;
+        try {
+            value.acquire();
+            InputStream stream = value.getStream();
+            try {
+                return create(stream, value.getSize());
+            } finally {
+                try {
+                    stream.close();
+                } catch (IOException e) {
+                    Logger.getLogger(getClass()).debug(e, "Error closing the stream while converting from Binary to String");
+                }
+            }
+        } finally {
+            value.release();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( InputStream stream,
+                          long approximateLength ) throws IoException {
+        if (stream == null) return null;
+        byte[] value = null;
+        try {
+            value = IoUtil.readBytes(stream);
+            return new String(value, "UTF-8");
+        } catch (UnsupportedEncodingException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(InputStream.class.getSimpleName(),
+                                                                            String.class.getSimpleName(),
+                                                                            value), err);
+        } catch (IOException err) {
+            throw new IoException(
+                                  GraphI18n.errorConvertingIo.text(InputStream.class.getSimpleName(), String.class.getSimpleName()),
+                                  err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String create( Reader reader,
+                          long approximateLength ) throws IoException {
+        if (reader == null) return null;
+        try {
+            return IoUtil.read(reader);
+        } catch (IOException err) {
+            throw new IoException(GraphI18n.errorConvertingIo.text(Reader.class.getSimpleName(), String.class.getSimpleName()), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected String[] createEmptyArray( int length ) {
+        return new String[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UriValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/UriValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UriValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,265 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#URI} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class UriValueFactory extends AbstractValueFactory<URI> {
-
-    private final NamespaceRegistry namespaceRegistry;
-
-    public UriValueFactory( NamespaceRegistry namespaceRegistry,
-                            TextDecoder decoder,
-                            ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.URI, decoder, stringValueFactory);
-        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
-        this.namespaceRegistry = namespaceRegistry;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( String value ) {
-        if (value == null) return null;
-        try {
-            return new URI(value);
-        } catch (URISyntaxException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                            URI.class.getSimpleName(),
-                                                                            value), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( String value,
-                       TextDecoder decoder ) {
-        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
-        return create(getDecoder(decoder).decode(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( int value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Integer.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( long value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Long.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( boolean value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Boolean.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( float value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Float.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( double value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Double.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( BigDecimal value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        BigDecimal.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( Calendar value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Calendar.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( Date value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Date.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public URI create( DateTime value ) throws ValueFormatException {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  DateTime.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( Name value ) {
-        if (value == null) return null;
-        return create("./" + value.getString(this.namespaceRegistry));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( Path value ) {
-        if (value == null) return null;
-        if (value.isAbsolute()) {
-            return create("/" + value.getString(this.namespaceRegistry));
-        }
-        return create("./" + value.getString(this.namespaceRegistry));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( Reference value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        Reference.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public URI create( UUID value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  UUID.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( URI value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( byte[] value ) {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public URI create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( InputStream stream,
-                       long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URI create( Reader reader,
-                       long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected URI[] createEmptyArray( int length ) {
-        return new URI[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UriValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/UriValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UriValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UriValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,265 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#URI} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class UriValueFactory extends AbstractValueFactory<URI> {
+
+    private final NamespaceRegistry namespaceRegistry;
+
+    public UriValueFactory( NamespaceRegistry namespaceRegistry,
+                            TextDecoder decoder,
+                            ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.URI, decoder, stringValueFactory);
+        CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+        this.namespaceRegistry = namespaceRegistry;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( String value ) {
+        if (value == null) return null;
+        try {
+            return new URI(value);
+        } catch (URISyntaxException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                            URI.class.getSimpleName(),
+                                                                            value), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( String value,
+                       TextDecoder decoder ) {
+        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
+        return create(getDecoder(decoder).decode(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( int value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Integer.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( long value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Long.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( boolean value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Boolean.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( float value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Float.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( double value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Double.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( BigDecimal value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        BigDecimal.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( Calendar value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Calendar.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( Date value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Date.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public URI create( DateTime value ) throws ValueFormatException {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  DateTime.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( Name value ) {
+        if (value == null) return null;
+        return create("./" + value.getString(this.namespaceRegistry));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( Path value ) {
+        if (value == null) return null;
+        if (value.isAbsolute()) {
+            return create("/" + value.getString(this.namespaceRegistry));
+        }
+        return create("./" + value.getString(this.namespaceRegistry));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( Reference value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        Reference.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public URI create( UUID value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  UUID.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( URI value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( byte[] value ) {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public URI create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( InputStream stream,
+                       long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URI create( Reader reader,
+                       long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected URI[] createEmptyArray( int length ) {
+        return new URI[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReference.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/UuidReference.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReference.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,101 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Reference;
-
-/**
- * @author Randall Hauch
- */
- at Immutable
-public class UuidReference implements Reference {
-
-    /**
-     */
-    private static final long serialVersionUID = 2299467578161645109L;
-    private UUID uuid;
-
-    public UuidReference( UUID uuid ) {
-        this.uuid = uuid;
-    }
-
-    /**
-     * @return uuid
-     */
-    public UUID getUuid() {
-        return this.uuid;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString() {
-        return this.uuid.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getString( TextEncoder encoder ) {
-        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
-        return encoder.encode(getString());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int compareTo( Reference that ) {
-        if (this == that) return 0;
-        if (that instanceof UuidReference) {
-            return this.uuid.compareTo(((UuidReference)that).getUuid());
-        }
-        return this.getString().compareTo(that.getString());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof UuidReference) {
-            return this.uuid.equals(((UuidReference)obj).getUuid());
-        }
-        if (obj instanceof Reference) {
-            return this.getString().equals(((Reference)obj).getString());
-        }
-        return super.equals(obj);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return this.uuid.toString();
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReference.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/UuidReference.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReference.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReference.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,101 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Reference;
+
+/**
+ * @author Randall Hauch
+ */
+ at Immutable
+public class UuidReference implements Reference {
+
+    /**
+     */
+    private static final long serialVersionUID = 2299467578161645109L;
+    private UUID uuid;
+
+    public UuidReference( UUID uuid ) {
+        this.uuid = uuid;
+    }
+
+    /**
+     * @return uuid
+     */
+    public UUID getUuid() {
+        return this.uuid;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString() {
+        return this.uuid.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( TextEncoder encoder ) {
+        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
+        return encoder.encode(getString());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( Reference that ) {
+        if (this == that) return 0;
+        if (that instanceof UuidReference) {
+            return this.uuid.compareTo(((UuidReference)that).getUuid());
+        }
+        return this.getString().compareTo(that.getString());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof UuidReference) {
+            return this.uuid.equals(((UuidReference)obj).getUuid());
+        }
+        if (obj instanceof Reference) {
+            return this.getString().equals(((Reference)obj).getString());
+        }
+        return super.equals(obj);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return this.uuid.toString();
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReferenceValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/UuidReferenceValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReferenceValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,255 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#REFERENCE} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class UuidReferenceValueFactory extends AbstractValueFactory<Reference> {
-
-    public UuidReferenceValueFactory( TextDecoder decoder,
-                                      ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.REFERENCE, decoder, stringValueFactory);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( String value ) {
-        if (value == null) return null;
-        try {
-            UUID uuid = UUID.fromString(value);
-            return new UuidReference(uuid);
-        } catch (IllegalArgumentException err) {
-            throw new ValueFormatException(value, getPropertyType(),
-                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                            Reference.class.getSimpleName(),
-                                                                            value), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( String value,
-                             TextDecoder decoder ) {
-        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
-        return create(getDecoder(decoder).decode(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( int value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Integer.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( long value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Long.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( boolean value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Boolean.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( float value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Float.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( double value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Double.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( BigDecimal value ) {
-        throw new ValueFormatException(value, getPropertyType(),
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        BigDecimal.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( Calendar value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Calendar.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( Date value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Date.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public Reference create( DateTime value ) throws ValueFormatException {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  DateTime.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( Name value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Name.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( Path value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Path.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( Reference value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public Reference create( UUID value ) {
-        if (value == null) return null;
-        return new UuidReference(value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( URI value ) {
-        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Date.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( byte[] value ) {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public Reference create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( InputStream stream,
-                             long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference create( Reader reader,
-                             long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Reference[] createEmptyArray( int length ) {
-        return new Reference[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReferenceValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/UuidReferenceValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReferenceValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidReferenceValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,255 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#REFERENCE} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class UuidReferenceValueFactory extends AbstractValueFactory<Reference> {
+
+    public UuidReferenceValueFactory( TextDecoder decoder,
+                                      ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.REFERENCE, decoder, stringValueFactory);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( String value ) {
+        if (value == null) return null;
+        try {
+            UUID uuid = UUID.fromString(value);
+            return new UuidReference(uuid);
+        } catch (IllegalArgumentException err) {
+            throw new ValueFormatException(value, getPropertyType(),
+                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                            Reference.class.getSimpleName(),
+                                                                            value), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( String value,
+                             TextDecoder decoder ) {
+        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
+        return create(getDecoder(decoder).decode(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( int value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Integer.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( long value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Long.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( boolean value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Boolean.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( float value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Float.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( double value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Double.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( BigDecimal value ) {
+        throw new ValueFormatException(value, getPropertyType(),
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        BigDecimal.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( Calendar value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Calendar.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( Date value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Date.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public Reference create( DateTime value ) throws ValueFormatException {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  DateTime.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( Name value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Name.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( Path value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Path.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( Reference value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public Reference create( UUID value ) {
+        if (value == null) return null;
+        return new UuidReference(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( URI value ) {
+        throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Date.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( byte[] value ) {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public Reference create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( InputStream stream,
+                             long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference create( Reader reader,
+                             long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Reference[] createEmptyArray( int length ) {
+        return new Reference[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/UuidValueFactory.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,271 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.UuidFactory;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-
-/**
- * The standard {@link ValueFactory} for {@link PropertyType#URI} values.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at Immutable
-public class UuidValueFactory extends AbstractValueFactory<UUID> implements UuidFactory {
-
-    public UuidValueFactory( TextDecoder decoder,
-                             ValueFactory<String> stringValueFactory ) {
-        super(PropertyType.UUID, decoder, stringValueFactory);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.UuidFactory#create()
-     */
-    public UUID create() {
-        return UUID.randomUUID();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( String value ) {
-        if (value == null) return null;
-        value = value.trim();
-        try {
-            return UUID.fromString(value);
-        } catch (IllegalArgumentException err) {
-            throw new ValueFormatException(value, PropertyType.UUID,
-                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
-                                                                            URI.class.getSimpleName(),
-                                                                            value), err);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( String value,
-                        TextDecoder decoder ) {
-        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
-        return create(getDecoder(decoder).decode(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( int value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Integer.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( long value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Long.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( boolean value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Boolean.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( float value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Float.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( double value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Double.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( BigDecimal value ) {
-        throw new ValueFormatException(value, PropertyType.UUID,
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        BigDecimal.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( Calendar value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Calendar.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( Date value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Date.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
-     */
-    public UUID create( DateTime value ) throws ValueFormatException {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  DateTime.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( Name value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Name.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( Path value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  Path.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( Reference value ) {
-        if (value instanceof UuidReference) {
-            UuidReference ref = (UuidReference)value;
-            return ref.getUuid();
-        }
-        throw new ValueFormatException(value, PropertyType.UUID,
-                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                        Reference.class.getSimpleName(),
-                                                                        value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( URI value ) {
-        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-                                                                                                  URI.class.getSimpleName(),
-                                                                                                  value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(java.util.UUID)
-     */
-    public UUID create( UUID value ) {
-        return value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( byte[] value ) {
-        // First attempt to create a string from the value, then a long from the string ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.Binary)
-     */
-    public UUID create( Binary value ) throws ValueFormatException, IoException {
-        // First create a string and then create the boolean from the string value ...
-        return create(getStringValueFactory().create(value));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( InputStream stream,
-                        long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(stream, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UUID create( Reader reader,
-                        long approximateLength ) throws IoException {
-        // First attempt to create a string from the value, then a double from the string ...
-        return create(getStringValueFactory().create(reader, approximateLength));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected UUID[] createEmptyArray( int length ) {
-        return new UUID[length];
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidValueFactory.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/UuidValueFactory.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidValueFactory.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/UuidValueFactory.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,271 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.UuidFactory;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+
+/**
+ * The standard {@link ValueFactory} for {@link PropertyType#URI} values.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at Immutable
+public class UuidValueFactory extends AbstractValueFactory<UUID> implements UuidFactory {
+
+    public UuidValueFactory( TextDecoder decoder,
+                             ValueFactory<String> stringValueFactory ) {
+        super(PropertyType.UUID, decoder, stringValueFactory);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.UuidFactory#create()
+     */
+    public UUID create() {
+        return UUID.randomUUID();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( String value ) {
+        if (value == null) return null;
+        value = value.trim();
+        try {
+            return UUID.fromString(value);
+        } catch (IllegalArgumentException err) {
+            throw new ValueFormatException(value, PropertyType.UUID,
+                                           GraphI18n.errorConvertingType.text(String.class.getSimpleName(),
+                                                                            URI.class.getSimpleName(),
+                                                                            value), err);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( String value,
+                        TextDecoder decoder ) {
+        // this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
+        return create(getDecoder(decoder).decode(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( int value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Integer.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( long value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Long.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( boolean value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Boolean.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( float value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Float.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( double value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Double.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( BigDecimal value ) {
+        throw new ValueFormatException(value, PropertyType.UUID,
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        BigDecimal.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( Calendar value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Calendar.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( Date value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Date.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
+     */
+    public UUID create( DateTime value ) throws ValueFormatException {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  DateTime.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( Name value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Name.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( Path value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  Path.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( Reference value ) {
+        if (value instanceof UuidReference) {
+            UuidReference ref = (UuidReference)value;
+            return ref.getUuid();
+        }
+        throw new ValueFormatException(value, PropertyType.UUID,
+                                       GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                        Reference.class.getSimpleName(),
+                                                                        value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( URI value ) {
+        throw new ValueFormatException(value, PropertyType.UUID, GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+                                                                                                  URI.class.getSimpleName(),
+                                                                                                  value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
+     */
+    public UUID create( UUID value ) {
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( byte[] value ) {
+        // First attempt to create a string from the value, then a long from the string ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
+     */
+    public UUID create( Binary value ) throws ValueFormatException, IoException {
+        // First create a string and then create the boolean from the string value ...
+        return create(getStringValueFactory().create(value));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( InputStream stream,
+                        long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(stream, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UUID create( Reader reader,
+                        long approximateLength ) throws IoException {
+        // First attempt to create a string from the value, then a double from the string ...
+        return create(getStringValueFactory().create(reader, approximateLength));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected UUID[] createEmptyArray( int length ) {
+        return new UUID[length];
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/package-info.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/package-info.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,7 +0,0 @@
-/**
- * A set of basic implementations of the various interfaces defined in {@link org.jboss.dna.graph.properties}.
- * These implementations are all very good defaults, and in most cases can be used as is.
- */
-
-package org.jboss.dna.graph.properties.basic;
-

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/package-info.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/package-info.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/package-info.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,7 @@
+/**
+ * A set of basic implementations of the various interfaces defined in {@link org.jboss.dna.graph.property}.
+ * These implementations are all very good defaults, and in most cases can be used as is.
+ */
+
+package org.jboss.dna.graph.property.basic;
+

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/package-info.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/package-info.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/package-info.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,158 @@
+/**
+ * Nodes in a graph contain properties, and this package defines the interfaces, classes and exceptions for
+ * representing and working with properties and their values.
+ * <p>
+ * A <i>property</i> consists of a <i>name</i> and a set of <i>values</i>.  A property name is represented
+ * by {@link Name}, and is defined as a {@link Name#getLocalName() local name} in a {@link Name#getNamespaceUri() namespace}.
+ * Property values can be of any type, although there are specific interfaces for the known types:
+ * <ul>
+ *  <li>{@link PropertyType#STRING String} - A value represented with instances of the standard {@link String} class.</li>
+ *  <li>{@link PropertyType#BINARY Binary} - A value represented with instances of the {@link Binary} interface.</li>
+ *  <li>{@link PropertyType#LONG Long} - A value represented with instances of the standard {@link Long} class.</li>
+ *  <li>{@link PropertyType#DOUBLE Double} - A value represented with instances of the standard {@link Double} class.</li>
+ *  <li>{@link PropertyType#DECIMAL Decimal} - A value represented with instances of the standard {@link java.math.BigDecimal} class.</li>
+ *  <li>{@link PropertyType#DATE Date} - A value represented with instances of the {@link DateTime} interface.
+ *  This interface hides the mishmash of Java date representations, and is designed to follow the anticipated
+ *  <code>ZonedDateTime</code> that is part of JSR-310.</li>
+ *  <li>{@link PropertyType#BOOLEAN Boolean} - A value represented with instances of the standard {@link Boolean} class.</li>
+ *  <li>{@link PropertyType#NAME Name} - A value represented with instances of the {@link Name} interface.</li>
+ *  <li>{@link PropertyType#PATH Path} - A value represented with instances of the {@link Path} interface.</li>
+ *  <li>{@link PropertyType#UUID UUID} - A value represented with instances of the standard {@link java.util.UUID} class.</li>
+ *  <li>{@link PropertyType#REFERENCE Reference} - A value represented with instances of the {@link Reference} interface.</li>
+ *  <li>{@link PropertyType#URI URI} - A value represented with instances of the standard {@link java.net.URI} class.</li>
+ *  <li>{@link PropertyType#OBJECT Object} - A value represented with instances of any class, although the class
+ *  should in all practicality implement {@link java.io.Serializable}.</li>
+ * </ul>
+ * </p>
+ * 
+ * <h3>Creating and converting property values</h3>
+ * <p>
+ * The design of properties and their values was centered around one key principle: when using a property value,
+ * you often don't care what type the property value actually is, but instead care about converting it to a
+ * property type that you know how to work with.  For example, you may be working with a property that represents
+ * a date, and you want to work with the value as a {@link DateTime} object, regardless of whether the values
+ * are actually String, {@link DateTime}, {@link Binary}, or even {@link java.util.Calendar} or {@link java.util.Date}
+ * instances.  You know its should be a date, so you want to get a value that behaves as a date.
+ * </p>
+ * <p>
+ * This notion of working with a <i>desired type</i> implies the ability to convert from one value type to another.
+ * And in fact, creating values is really just converting from "other" types into a known type.
+ * So, we can use the <i>factory</i> design pattern to have a single concept of a component that creates property values
+ * from a variety of types.  But by using generics, we can use a single {@link ValueFactory factory} interface
+ * that has the same methods for creating value objects, but make the return type specific to the type we want to create.
+ * </p>
+ * <p>
+ * The {@link ValueFactory} interface is defined as follows:
+ * <pre>
+ *   public interface ValueFactory&lt;T> {
+ *       T create( String value ) throws ValueFormatException;
+ *       T create( int value ) throws ValueFormatException;
+ *       T create( long value ) throws ValueFormatException;
+ *       T create( double value ) throws ValueFormatException;
+ *       ...
+ *       T create( java.util.Date value ) throws ValueFormatException;
+ *       T create( java.util.Calendar value ) throws ValueFormatException;
+ *       T create( DateTime value ) throws ValueFormatException;
+ *       ...
+ *       T create( java.util.UUID value ) throws ValueFormatException;
+ *       T create( java.net.URI value ) throws ValueFormatException;
+ *       T create( Reference value ) throws ValueFormatException;
+ *       T create( Name value ) throws ValueFormatException;
+ *       T create( Path value ) throws ValueFormatException;
+ *       ...
+ *       T create( InputStream value, long approximateLength ) throws ValueFormatException;
+ *       T create( Reader value, long approximateLength ) throws ValueFormatException;
+ *       T create( Binary value ) throws ValueFormatException;
+ *       ...
+ *       T[] create( String[] value ) throws ValueFormatException;
+ *       T[] create( int[] value ) throws ValueFormatException;
+ *       T[] create( long[] value ) throws ValueFormatException;
+ *       T[] create( double[] value ) throws ValueFormatException;
+ *       ...
+ *   }
+ * </pre>
+ * Notice that all the methods are called <code>create</code>, and most take a single parameter whose type is
+ * one of the known types, a primitive, or a number of "other" types frequently encountered.  (The <code>create(...)</code>
+ * methods that take an {@link java.io.InputStream} or {@link java.io.Reader} have a second parameter that specifies
+ * the length of the data.)  Finally, note that almost all of the <code>create</code> methods have a form that each 
+ * take an array of values and return an array of <code>T</code>.
+ * </p>
+ * <p>
+ * These methods also all throw a {@link ValueFormatException}, in case the supplied
+ * parameter cannot be converted to the desired type.  In many cases, there is a conversion (e.g., from the String "123"
+ * to an integer), but there certainly are cases where no conversion is allowed (e.g., the String "a123" cannot be converted
+ * to an integer, and a {@link Name} cannot be converted to a <code>boolean</code>).  All types can be converted
+ * to a string, and all factories support converting that string back to its original form.
+ * </p>
+ * <p>
+ * The factory for creating {@link DateTime} objects would then be an implementation of <code>ValueFactory&lt;DateTime></code>,
+ * a factory for creating {@link Binary} objects would be an implementation of <code>ValueFactory&lt;Binary</code>,
+ * and so on.  In some cases, we'd like to add additional forms of <code>create(...)</code> for specific values, and
+ * we can do this by extending a typed {@link ValueFactory}.  For example, the {@link DateTimeFactory} adds
+ * more methods for creating {@link DateTime} objects for the current time, current time in UTC, from another time
+ * and an offset, and from individual field values:
+ * <pre>
+ *   public interface DateTimeFactory extends ValueFactories&lt;DateTime> {
+ *       DateTime create();
+ *       DateTime createUtc();
+ *       DateTime create( DateTime original, long offsetInMillis );
+ *       DateTime create( int year, int monthOfYear, int dayOfMonth,
+ *                        int hourOfDay, int minuteOfHour, int secondOfMinute, int millisecondsOfSecond );
+ *       DateTime create( int year, int monthOfYear, int dayOfMonth,
+ *                        int hourOfDay, int minuteOfHour, int secondOfMinute, int millisecondsOfSecond,
+ *                        int timeZoneOffsetHours );
+ *       DateTime create( int year, int monthOfYear, int dayOfMonth,
+ *                        int hourOfDay, int minuteOfHour, int secondOfMinute, int millisecondsOfSecond,
+ *                        String timeZoneId );
+ *   }
+ * </pre>
+ * There are specialized factory interfaces for several other types, including {@link PathFactory}, {@link NameFactory},
+ * and {@link UuidFactory}.
+ * </p>
+ * <p>
+ * The {@link ValueFactories} interface collects all the factories into a single spot:
+ * <pre>
+ *   public interface ValueFactories&lt;T> {
+ *       ValueFactory&lt;String> getStringFactory();
+ *       ValueFactory&lt;Binary> getBinaryFactory();
+ *       ValueFactory&lt;Long> getLongFactory();
+ *       ValueFactory&lt;Double> getDoubleFactory();
+ *       ValueFactory&lt;BigDecimal> getDecimalFactory();
+ *       DateTimeFactory getDateFactory();
+ *       ValueFactory&lt;Boolean> getBooleanFactory();
+ *       NameFactory getNameFactory();
+ *       ValueFactory&lt;Reference> getReferenceFactory();
+ *       PathFactory getPathFactory();
+ *       ValueFactory&lt;URI> getUriFactory();
+ *       UuidFactory getUuidFactory();
+ *       ValueFactory&lt;Object> getObjectFactory();
+ *       
+ *       ValueFactory&lt;?> getValueFactory( PropertyType type );
+ *       ValueFactory&lt;?> getValueFactory( Object prototype );
+ *   }
+ * </pre>
+ * This allows us to programmatically get the correct factory for a type known at compile time, but also 
+ * to obtain the correct factory given a prototype object or the enumeration literal representing
+ * the desired type.  Thus, the following code compiles:
+ * <pre>
+ *    ValueFactories factories = ...
+ *    DateTime now = factories.getDateFactory.create();
+ *    String stringValue = factories.getStringFactory().create(now);
+ * </pre>
+ * A {@link ValueFactories} is provided as part of the {@link org.jboss.dna.graph.ExecutionContext}.  In this way,
+ * the environment may use a different implementation of one or more factories.
+ * </p>
+ * 
+ * <h3>Comparing property values</h3>
+ * <p>
+ * Because we have a mixture of standard Java types and custom interfaces for property values, we need
+ * a set of {@link java.util.Comparator} implementations that allow us to compare property values.
+ * The {@link ValueComparators} class defines a number of singleton comparators that can be used.
+ * Plus, the {@link PropertyType} enumeration has the ability to {@link PropertyType#getComparator() get the comparator}
+ * for the specific type (e.g., <code>PropertyType.BINARY.getComparator()</code>).
+ * </p>
+ * 
+ */
+
+package org.jboss.dna.graph.property;
+


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/package-info.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CacheableRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CacheableRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CacheableRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CacheableRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,75 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.graph.cache.CachePolicy;
+import org.jboss.dna.graph.cache.Cacheable;
+import org.jboss.dna.graph.property.DateTime;
+
+/**
+ * A request that contains results that may be cached.
+ * 
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public abstract class CacheableRequest extends Request implements Cacheable {
+
+    private static final long serialVersionUID = 1L;
+
+    private CachePolicy policy;
+    private DateTime timeLoaded;
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.cache.Cacheable#getCachePolicy()
+     */
+    public CachePolicy getCachePolicy() {
+        return policy;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.cache.Cacheable#getTimeLoaded()
+     */
+    public DateTime getTimeLoaded() {
+        return timeLoaded;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.cache.Cacheable#setCachePolicy(org.jboss.dna.graph.cache.CachePolicy)
+     */
+    public void setCachePolicy( CachePolicy cachePolicy ) {
+        policy = cachePolicy;
+    }
+
+    /**
+     * @param timeLoaded Sets timeLoaded to the specified value.
+     */
+    public void setTimeLoaded( DateTime timeLoaded ) {
+        this.timeLoaded = timeLoaded;
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CacheableRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CompositeRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CompositeRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CompositeRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CompositeRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,271 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.jboss.dna.common.util.CheckArg;
+
+/**
+ * A request that wraps multiple other requests, allowing multiple requests to be treated as a single request.
+ * <p>
+ * Note that {@link #isCancelled()} and {@link #cancel()} apply to all requests contained by the composite request. In other
+ * words, cancelling this request immediately marks all contained requests as cancelled. However, cancelling any request in the
+ * request has the effect of cancelling all other requests in the composite, including the composite. (This is implemented by
+ * having all {@link Request} objects in the composite share the same cancelled flag object.)
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+public class CompositeRequest extends Request implements Iterable<Request> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Return a request that either wraps multiple requests, or the single request if only one is supplied.
+     * 
+     * @param requests the requests to wrap
+     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request
+     * @throws IllegalArgumentException if there requests are null, empty, or contains only nulls
+     */
+    public static Request with( Request... requests ) {
+        CheckArg.isNotEmpty(requests, "requests");
+        if (requests.length == 1) {
+            CheckArg.isNotNull(requests[0], "requests[0]");
+            return requests[0];
+        }
+        boolean readOnly = true;
+        List<Request> list = new ArrayList<Request>(requests.length);
+        for (Request request : requests) {
+            if (request == null) continue;
+            if (request instanceof CompositeRequest) {
+                CompositeRequest composite = (CompositeRequest)request;
+                list.addAll(composite.getRequests());
+                if (!composite.isReadOnly()) readOnly = false;
+            } else {
+                list.add(request);
+                if (!request.isReadOnly()) readOnly = false;
+            }
+        }
+        CheckArg.isNotEmpty(list, "requests");
+        return new CompositeRequest(list, readOnly);
+    }
+
+    /**
+     * Return a request that either wraps multiple requests, or the single request if only one is supplied.
+     * 
+     * @param requests the requests to wrap
+     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request
+     * @throws IllegalArgumentException if there requests are null, empty, or contains only nulls
+     */
+    public static Request with( Iterator<? extends Request> requests ) {
+        CheckArg.isNotNull(requests, "requests");
+        boolean readOnly = true;
+        List<Request> list = new LinkedList<Request>();
+        while (requests.hasNext()) {
+            Request request = requests.next();
+            if (request == null) continue;
+            if (request instanceof CompositeRequest) {
+                CompositeRequest composite = (CompositeRequest)request;
+                list.addAll(composite.getRequests());
+                if (!composite.isReadOnly()) readOnly = false;
+            } else {
+                list.add(request);
+                if (!request.isReadOnly()) readOnly = false;
+            }
+        }
+        if (list.size() == 1) {
+            return list.get(0);
+        }
+        CheckArg.isNotEmpty(list, "requests");
+        return new CompositeRequest(list, readOnly);
+    }
+
+    /**
+     * Return a request that either wraps multiple requests, or the single request if only one is supplied.
+     * 
+     * @param requests the requests to wrap
+     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request
+     * @throws IllegalArgumentException if there requests are null or empty
+     */
+    public static Request with( List<? extends Request> requests ) {
+        CheckArg.isNotEmpty(requests, "requests");
+        if (requests.size() == 1) {
+            return requests.get(0);
+        }
+        boolean readOnly = true;
+        for (Request request : requests) {
+            if (request.isReadOnly()) continue;
+            readOnly = false;
+            break;
+        }
+        return new CompositeRequest(requests, readOnly);
+    }
+
+    /**
+     * Add requests to the supplied composite request.
+     * 
+     * @param composite the composite request to which the requests are to be added
+     * @param requests the requests to wrap
+     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request, or null if
+     *         there are no request
+     * @throws IllegalArgumentException if the composite request is null
+     */
+    public static CompositeRequest add( CompositeRequest composite,
+                                        Request... requests ) {
+        CheckArg.isNotNull(composite, "composite");
+        if (requests == null || requests.length == 0) return composite;
+        List<Request> list = new ArrayList<Request>(requests.length + composite.size());
+        boolean readOnly = composite.isReadOnly();
+        if (composite.size() != 0) list.addAll(composite.getRequests());
+        for (Request request : requests) {
+            if (request == null) continue;
+            if (request instanceof CompositeRequest) {
+                CompositeRequest compositeRequest = (CompositeRequest)request;
+                list.addAll(compositeRequest.getRequests());
+                if (!compositeRequest.isReadOnly()) readOnly = false;
+            } else {
+                list.add(request);
+                if (!request.isReadOnly()) readOnly = false;
+            }
+        }
+        return new CompositeRequest(list, readOnly);
+    }
+
+    /**
+     * Add requests to the supplied composite request.
+     * 
+     * @param composite the composite request to which the requests are to be added
+     * @param requests the requests to wrap
+     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request, or null if
+     *         there are no request
+     * @throws IllegalArgumentException if the composite request is null
+     */
+    public static CompositeRequest add( CompositeRequest composite,
+                                        Iterator<? extends Request> requests ) {
+        CheckArg.isNotNull(composite, "composite");
+        List<Request> list = new LinkedList<Request>();
+        boolean readOnly = composite.isReadOnly();
+        if (composite.size() != 0) list.addAll(composite.getRequests());
+        while (requests.hasNext()) {
+            Request request = requests.next();
+            if (request == null) continue;
+            if (request instanceof CompositeRequest) {
+                CompositeRequest compositeRequest = (CompositeRequest)request;
+                list.addAll(compositeRequest.getRequests());
+                if (!compositeRequest.isReadOnly()) readOnly = false;
+            } else {
+                list.add(request);
+                if (!request.isReadOnly()) readOnly = false;
+            }
+        }
+        return new CompositeRequest(list, readOnly);
+    }
+
+    private final List<Request> requests;
+    private final boolean readOnly;
+
+    /**
+     * Create a composite request from the supplied list of requests.
+     * 
+     * @param requests the modifiable list of requests; may not be null
+     * @param readOnly true if all of the requests are {@link Request#isReadOnly() read-only}
+     */
+    /*package*/CompositeRequest( List<? extends Request> requests,
+                                  boolean readOnly ) {
+        // Iterate through the requests and set the cancelled flag of each request to this object's flag ...
+        final AtomicBoolean flag = super.getCancelledFlag();
+        for (Request request : requests) {
+            request.setCancelledFlag(flag);
+        }
+        this.requests = Collections.unmodifiableList(requests);
+        this.readOnly = readOnly;
+    }
+
+    /**
+     * Return the unmodifiable requests contained in this composite request.
+     * 
+     * @return requests
+     */
+    public List<Request> getRequests() {
+        return requests;
+    }
+
+    /**
+     * Get the number of requests.
+     * 
+     * @return the number of requests
+     */
+    public int size() {
+        return requests.size();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<Request> iterator() {
+        return requests.iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return readOnly;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj instanceof CompositeRequest) {
+            CompositeRequest that = (CompositeRequest)obj;
+            if (this.size() != that.size()) return false;
+            Iterator<Request> thisIter = this.iterator();
+            Iterator<Request> thatIter = that.iterator();
+            while (thisIter.hasNext()) {
+                Request thisRequest = thisIter.next();
+                Request thatRequest = thatIter.next();
+                if (thisRequest == null) {
+                    if (thatRequest != null) return false;
+                } else {
+                    if (!thisRequest.equals(thatRequest)) return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CompositeRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CopyBranchRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,192 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.NodeConflictBehavior;
+
+/**
+ * Instruction that a branch be copied from one location into another.
+ * 
+ * @author Randall Hauch
+ */
+public class CopyBranchRequest extends Request {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR = NodeConflictBehavior.APPEND;
+
+    private final Location from;
+    private final Location into;
+    private final NodeConflictBehavior conflictBehavior;
+    private Location actualOldLocation;
+    private Location actualNewLocation;
+
+    /**
+     * Create a request to copy a branch to another.
+     * 
+     * @param from the location of the top node in the existing branch that is to be copied
+     * @param into the location of the existing node into which the copy should be placed
+     * @throws IllegalArgumentException if <code>from</code> or <code>into</code> are null
+     */
+    public CopyBranchRequest( Location from,
+                              Location into ) {
+        this(from, into, DEFAULT_CONFLICT_BEHAVIOR);
+    }
+
+    /**
+     * Create a request to copy a branch to another.
+     * 
+     * @param from the location of the top node in the existing branch that is to be copied
+     * @param into the location of the existing node into which the copy should be placed
+     * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code>
+     *        location
+     * @throws IllegalArgumentException if any of the parameters are null
+     */
+    public CopyBranchRequest( Location from,
+                              Location into,
+                              NodeConflictBehavior conflictBehavior ) {
+        CheckArg.isNotNull(from, "from");
+        CheckArg.isNotNull(into, "into");
+        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
+        this.from = from;
+        this.into = into;
+        this.conflictBehavior = conflictBehavior;
+    }
+
+    /**
+     * Get the location defining the top of the branch to be copied
+     * 
+     * @return the from location; never null
+     */
+    public Location from() {
+        return from;
+    }
+
+    /**
+     * Get the location defining the parent where the new copy is to be placed
+     * 
+     * @return the to location; never null
+     */
+    public Location into() {
+        return into;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return false;
+    }
+
+    /**
+     * Get the expected behavior when copying the branch and the {@link #into() destination} already has a node with the same
+     * name.
+     * 
+     * @return the behavior specification
+     */
+    public NodeConflictBehavior conflictBehavior() {
+        return conflictBehavior;
+    }
+
+    /**
+     * Sets the actual and complete location of the node being renamed and its new location. This method must be called when
+     * processing the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param oldLocation the actual location of the node before being renamed
+     * @param newLocation the actual location of the new copy of the node
+     * @throws IllegalArgumentException if the either location is null, if the old location does not represent the
+     *         {@link Location#isSame(Location) same location} as the {@link #from() from location}, if the new location does not
+     *         represent the {@link Location#isSame(Location) same location} as the {@link #into() into location}, or if the
+     *         either location does not have a path
+     */
+    public void setActualLocations( Location oldLocation,
+                                    Location newLocation ) {
+        if (!from.isSame(oldLocation)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(oldLocation, from));
+        }
+        CheckArg.isNotNull(newLocation, "newLocation");
+        assert oldLocation != null;
+        assert newLocation != null;
+        if (!oldLocation.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualOldLocationMustHavePath.text(oldLocation));
+        }
+        if (!newLocation.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualNewLocationMustHavePath.text(newLocation));
+        }
+        // The 'into' should be the parent of the 'newLocation' ...
+        if (into.hasPath() && !newLocation.getPath().getParent().equals(into.getPath())) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotChildOfInputLocation.text(newLocation, into));
+        }
+        this.actualNewLocation = newLocation;
+    }
+
+    /**
+     * Get the actual location of the node before being copied.
+     * 
+     * @return the actual location of the node before being moved, or null if the actual location was not set
+     */
+    public Location getActualLocationBefore() {
+        return actualOldLocation;
+    }
+
+    /**
+     * Get the actual location of the node after being copied.
+     * 
+     * @return the actual location of the node after being moved, or null if the actual location was not set
+     */
+    public Location getActualLocationAfter() {
+        return actualNewLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            CopyBranchRequest that = (CopyBranchRequest)obj;
+            if (!this.from().equals(that.from())) return false;
+            if (!this.into().equals(that.into())) return false;
+            if (!this.conflictBehavior().equals(that.conflictBehavior())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "copy branch " + from() + " into " + into();
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,316 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (under your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.NodeConflictBehavior;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to create the node under the specified location. This command will create the node and set the initial properties.
+ * 
+ * @author Randall Hauch
+ */
+public class CreateNodeRequest extends Request implements Iterable<Property> {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR = NodeConflictBehavior.APPEND;
+
+    private final Location under;
+    private final Name childName;
+    private final List<Property> properties;
+    private final NodeConflictBehavior conflictBehavior;
+    private Location actualLocation;
+
+    /**
+     * Create a request to create a node with the given properties under the supplied location.
+     * 
+     * @param parentLocation the location of the existing parent node, under which the new child should be created
+     * @param childName the name of the new child to create under the existing parent
+     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+     *        properties} for the new node
+     * @throws IllegalArgumentException if the location or the child name is null
+     */
+    public CreateNodeRequest( Location parentLocation,
+                              Name childName,
+                              Property... properties ) {
+        this(parentLocation, childName, DEFAULT_CONFLICT_BEHAVIOR, properties);
+    }
+
+    /**
+     * Create a request to create a node with the given properties under the supplied location.
+     * 
+     * @param parentLocation the location of the existing parent node, under which the new child should be created
+     * @param childName the name of the new child to create under the existing parent
+     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+     *        properties} for the new node
+     * @throws IllegalArgumentException if the location or the child name is null
+     */
+    public CreateNodeRequest( Location parentLocation,
+                              Name childName,
+                              Iterable<Property> properties ) {
+        this(parentLocation, childName, DEFAULT_CONFLICT_BEHAVIOR, properties);
+    }
+
+    /**
+     * Create a request to create a node with the given properties under the supplied location.
+     * 
+     * @param parentLocation the location of the existing parent node, under which the new child should be created
+     * @param childName the name of the new child to create under the existing parent
+     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+     *        properties} for the new node
+     * @throws IllegalArgumentException if the location or the child name is null
+     */
+    public CreateNodeRequest( Location parentLocation,
+                              Name childName,
+                              Iterator<Property> properties ) {
+        this(parentLocation, childName, DEFAULT_CONFLICT_BEHAVIOR, properties);
+    }
+
+    /**
+     * Create a request to create a node with the given properties under the supplied location.
+     * 
+     * @param parentLocation the location of the existing parent node, under which the new child should be created
+     * @param childName the name of the new child to create under the existing parent
+     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+     *        properties} for the new node
+     * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
+     *        location
+     * @throws IllegalArgumentException if the location, the child name, or the conflict behavior is null
+     */
+    public CreateNodeRequest( Location parentLocation,
+                              Name childName,
+                              NodeConflictBehavior conflictBehavior,
+                              Property... properties ) {
+        CheckArg.isNotNull(parentLocation, "parentLocation");
+        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
+        CheckArg.isNotNull(childName, "childName");
+        this.under = parentLocation;
+        this.childName = childName;
+        this.conflictBehavior = conflictBehavior;
+        int number = properties.length + (under.hasIdProperties() ? under.getIdProperties().size() : 0);
+        List<Property> props = new ArrayList<Property>(number);
+        for (Property property : properties) {
+            if (property != null) props.add(property);
+        }
+        this.properties = Collections.unmodifiableList(props);
+    }
+
+    /**
+     * Create a request to create a node with the given properties under the supplied location.
+     * 
+     * @param parentLocation the location of the existing parent node, under which the new child should be created
+     * @param childName the name of the new child to create under the existing parent
+     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+     *        properties} for the new node
+     * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
+     *        location
+     * @throws IllegalArgumentException if the location, the child name, or the conflict behavior is null
+     */
+    public CreateNodeRequest( Location parentLocation,
+                              Name childName,
+                              NodeConflictBehavior conflictBehavior,
+                              Iterable<Property> properties ) {
+        CheckArg.isNotNull(parentLocation, "parentLocation");
+        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
+        CheckArg.isNotNull(childName, "childName");
+        this.under = parentLocation;
+        this.childName = childName;
+        this.conflictBehavior = conflictBehavior;
+        List<Property> props = new LinkedList<Property>();
+        for (Property property : properties) {
+            if (property != null) props.add(property);
+        }
+        // Add in the location properties ...
+        if (under.hasIdProperties()) {
+            for (Property property : under.getIdProperties()) {
+                if (property != null) props.add(property);
+            }
+        }
+        this.properties = Collections.unmodifiableList(props);
+    }
+
+    /**
+     * Create a request to create a node with the given properties under the supplied location.
+     * 
+     * @param parentLocation the location of the existing parent node, under which the new child should be created
+     * @param childName the name of the new child to create under the existing parent
+     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+     *        properties} for the new node
+     * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
+     *        location
+     * @throws IllegalArgumentException if the location, the child name, or the conflict behavior is null
+     */
+    public CreateNodeRequest( Location parentLocation,
+                              Name childName,
+                              NodeConflictBehavior conflictBehavior,
+                              Iterator<Property> properties ) {
+        CheckArg.isNotNull(parentLocation, "parentLocation");
+        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
+        CheckArg.isNotNull(childName, "childName");
+        this.under = parentLocation;
+        this.childName = childName;
+        this.conflictBehavior = conflictBehavior;
+        List<Property> props = new LinkedList<Property>();
+        while (properties.hasNext()) {
+            Property property = properties.next();
+            if (property != null) props.add(property);
+        }
+        // Add in the location properties ...
+        if (under.hasIdProperties()) {
+            for (Property property : under.getIdProperties()) {
+                if (property != null) props.add(property);
+            }
+        }
+        this.properties = Collections.unmodifiableList(props);
+    }
+
+    /**
+     * Get the location defining the parent of the new node that is to be created.
+     * 
+     * @return the location of the parent node; never null
+     */
+    public Location under() {
+        return under;
+    }
+
+    /**
+     * Get the name for the new child.
+     * 
+     * @return the child's name; never null
+     */
+    public Name named() {
+        return childName;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<Property> iterator() {
+        return this.properties.iterator();
+    }
+
+    /**
+     * Get the properties for the node. If the node's {@link #under() location} has identification properties, the resulting
+     * properties will include the {@link Location#getIdProperties() identification properties}.
+     * 
+     * @return the collection of properties; never null
+     */
+    public Collection<Property> properties() {
+        return properties;
+    }
+
+    /**
+     * Get the expected behavior when copying the branch and the {@link #under() destination} already has a node with the same
+     * name.
+     * 
+     * @return the behavior specification
+     */
+    public NodeConflictBehavior conflictBehavior() {
+        return conflictBehavior;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return false;
+    }
+
+    /**
+     * Sets the actual and complete location of the node being created. This method must be called when processing the request,
+     * and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being created, or null if the {@link #under() current location} should be
+     *        used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #under() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        CheckArg.isNotNull(actual, "actual");
+        if (!under.isSame(actual, false)) { // not same if actual is null
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        assert actual.hasPath();
+        if (under.hasPath() && !under.getPath().equals(actual.getPath().getParent())) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, under));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node that was created.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            CreateNodeRequest that = (CreateNodeRequest)obj;
+            if (!this.under().equals(that.under())) return false;
+            if (!this.conflictBehavior().equals(that.conflictBehavior())) return false;
+            if (!this.properties().equals(that.properties())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        String parent = under() + "/";
+        if (under.hasPath() && under.getPath().isRoot()) parent = "/";
+        return "create node \"" + parent + childName + "\" with properties " + properties();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DeleteBranchRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/DeleteBranchRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DeleteBranchRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DeleteBranchRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,122 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+
+/**
+ * Instruction that a branch be deleted.
+ * 
+ * @author Randall Hauch
+ */
+public class DeleteBranchRequest extends Request {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Location at;
+    private Location actualLocation;
+
+    /**
+     * Create a request to delete a branch.
+     * 
+     * @param at the location of the top node in the existing branch that is to be deleted
+     * @throws IllegalArgumentException if the location is null
+     */
+    public DeleteBranchRequest( Location at ) {
+        CheckArg.isNotNull(at, "at");
+        this.at = at;
+    }
+
+    /**
+     * Get the location defining the top of the branch to be deleted
+     * 
+     * @return the location of the branch; never null
+     */
+    public Location at() {
+        return at;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return false;
+    }
+
+    /**
+     * Sets the actual and complete location of the node being deleted. This method must be called when processing the request,
+     * and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being deleted, or null if the {@link #at() current location} should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #at() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!at.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node that was deleted.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            DeleteBranchRequest that = (DeleteBranchRequest)obj;
+            if (!this.at().equals(that.at())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "delete branch " + at();
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DeleteBranchRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/InvalidRequestException.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/InvalidRequestException.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/InvalidRequestException.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/InvalidRequestException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+/**
+ * Specifies that the request was invalid and could not be completed.
+ * 
+ * @author Randall Hauch
+ */
+public class InvalidRequestException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 
+     */
+    public InvalidRequestException() {
+    }
+
+    /**
+     * @param message
+     */
+    public InvalidRequestException( String message ) {
+        super(message);
+
+    }
+
+    /**
+     * @param cause
+     */
+    public InvalidRequestException( Throwable cause ) {
+        super(cause);
+
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public InvalidRequestException( String message,
+                                    Throwable cause ) {
+        super(message, cause);
+
+    }
+
+}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/MoveBranchRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/MoveBranchRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/MoveBranchRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/MoveBranchRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,215 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.NodeConflictBehavior;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * Instruction that a branch be moved from one location into another.
+ * 
+ * @author Randall Hauch
+ */
+public class MoveBranchRequest extends Request {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR = NodeConflictBehavior.APPEND;
+
+    private final Location from;
+    private final Location into;
+    private final NodeConflictBehavior conflictBehavior;
+    private Location actualOldLocation;
+    private Location actualNewLocation;
+
+    /**
+     * Create a request to move a branch from one location into another.
+     * 
+     * @param from the location of the top node in the existing branch that is to be moved
+     * @param into the location of the existing node into which the branch should be moved
+     * @throws IllegalArgumentException if <code>from</code> or <code>into</code> are null
+     */
+    public MoveBranchRequest( Location from,
+                              Location into ) {
+        this(from, into, DEFAULT_CONFLICT_BEHAVIOR);
+    }
+
+    /**
+     * Create a request to move a branch from one location into another.
+     * 
+     * @param from the location of the top node in the existing branch that is to be moved
+     * @param into the location of the existing node into which the branch should be moved
+     * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code>
+     *        location
+     * @throws IllegalArgumentException if any of the parameters are null
+     */
+    public MoveBranchRequest( Location from,
+                              Location into,
+                              NodeConflictBehavior conflictBehavior ) {
+        CheckArg.isNotNull(from, "from");
+        CheckArg.isNotNull(into, "into");
+        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
+        this.from = from;
+        this.into = into;
+        this.conflictBehavior = conflictBehavior;
+    }
+
+    /**
+     * Get the location defining the top of the branch to be moved
+     * 
+     * @return the from location; never null
+     */
+    public Location from() {
+        return from;
+    }
+
+    /**
+     * Get the location defining the parent where the branch is to be placed
+     * 
+     * @return the to location; never null
+     */
+    public Location into() {
+        return into;
+    }
+
+    /**
+     * Get the expected behavior when copying the branch and the {@link #into() destination} already has a node with the same
+     * name.
+     * 
+     * @return the behavior specification
+     */
+    public NodeConflictBehavior conflictBehavior() {
+        return conflictBehavior;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return false;
+    }
+
+    /**
+     * Determine whether this move request can be determined to have no effect.
+     * <p>
+     * A move is known to have no effect when all of the following conditions are true:
+     * <ul>
+     * <li>the {@link #into() into} location has a {@link Location#hasPath() path} but no {@link Location#hasIdProperties()
+     * identification properties};</li>
+     * <li>the {@link #from() from} location has a {@link Location#getPath() path}; and</li>
+     * <li>the {@link #from() from} location's {@link Path#getParent() parent} is the same as the {@link #into() into} location's
+     * path.</li>
+     * </ul>
+     * If all of these conditions are not true, this method returns false.
+     * </p>
+     * 
+     * @return true if this move request really doesn't change the parent of the node, or false if it cannot be determined
+     */
+    public boolean hasNoEffect() {
+        if (into.hasPath() && into.hasIdProperties() == false && from.hasPath()) {
+            return from.getPath().getParent().equals(into.getPath());
+        }
+        // Can't be determined for certain
+        return false;
+    }
+
+    /**
+     * Sets the actual and complete location of the node being renamed and its new location. This method must be called when
+     * processing the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param oldLocation the actual location of the node before being renamed
+     * @param newLocation the actual location of the node after being renamed
+     * @throws IllegalArgumentException if the either location is null, if the old location does not represent the
+     *         {@link Location#isSame(Location) same location} as the {@link #from() from location}, if the new location does not
+     *         represent the {@link Location#isSame(Location) same location} as the {@link #into() into location}, or if the
+     *         either location does not have a path
+     */
+    public void setActualLocations( Location oldLocation,
+                                    Location newLocation ) {
+        if (!from.isSame(oldLocation)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(oldLocation, from));
+        }
+        if (!into.isSame(newLocation, false)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(newLocation, into));
+        }
+        assert oldLocation != null;
+        assert newLocation != null;
+        if (!oldLocation.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualOldLocationMustHavePath.text(oldLocation));
+        }
+        if (!newLocation.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualNewLocationMustHavePath.text(newLocation));
+        }
+        this.actualNewLocation = newLocation;
+    }
+
+    /**
+     * Get the actual location of the node before being moved.
+     * 
+     * @return the actual location of the node before being moved, or null if the actual location was not set
+     */
+    public Location getActualLocationBefore() {
+        return actualOldLocation;
+    }
+
+    /**
+     * Get the actual location of the node after being moved.
+     * 
+     * @return the actual location of the node after being moved, or null if the actual location was not set
+     */
+    public Location getActualLocationAfter() {
+        return actualNewLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            MoveBranchRequest that = (MoveBranchRequest)obj;
+            if (!this.from().equals(that.from())) return false;
+            if (!this.into().equals(that.into())) return false;
+            if (!this.conflictBehavior().equals(that.conflictBehavior())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "move branch " + from() + " into " + into();
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/MoveBranchRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllChildrenRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllChildrenRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllChildrenRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllChildrenRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,197 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to read all of the children of a node at a specific location.
+ * 
+ * @author Randall Hauch
+ */
+public class ReadAllChildrenRequest extends CacheableRequest implements Iterable<Location> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Location of;
+    private final List<Location> children = new LinkedList<Location>();
+    private Location actualOf;
+
+    /**
+     * Create a request to read the children of a node at the supplied location.
+     * 
+     * @param of the location of the node whose children are to be read
+     * @throws IllegalArgumentException if the location is null
+     */
+    public ReadAllChildrenRequest( Location of ) {
+        CheckArg.isNotNull(of, "of");
+        this.of = of;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return true;
+    }
+
+    /**
+     * Get the location defining the node whose children are to be read.
+     * 
+     * @return the location of the parent node; never null
+     */
+    public Location of() {
+        return of;
+    }
+
+    /**
+     * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
+     * represented by a location.
+     * 
+     * @return the children that were read; never null
+     */
+    public List<Location> getChildren() {
+        return children;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<Location> iterator() {
+        return children.iterator();
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param child the location of the child that was read
+     * @throws IllegalArgumentException if the location is null
+     * @see #addChild(Path, Property)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Location child ) {
+        CheckArg.isNotNull(child, "child");
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param firstIdProperty the first identification property of the child that was just read
+     * @param remainingIdProperties the remaining identification properties of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property)
+     */
+    public void addChild( Path pathToChild,
+                          Property firstIdProperty,
+                          Property... remainingIdProperties ) {
+        Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification property. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param idProperty the identification property of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Path pathToChild,
+                          Property idProperty ) {
+        Location child = new Location(pathToChild, idProperty);
+        this.children.add(child);
+    }
+
+    /**
+     * Sets the actual and complete location of the node whose children have been read. This method must be called when processing
+     * the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being read, or null if the {@link #of() current location} should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #of() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!this.of.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, of));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualOf = actual;
+    }
+
+    /**
+     * Get the actual location of the node whose children were read.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualOf;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            ReadAllChildrenRequest that = (ReadAllChildrenRequest)obj;
+            if (!this.of().equals(that.of())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "read children of " + of();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllChildrenRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllPropertiesRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllPropertiesRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllPropertiesRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,205 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to read the properties and the number of children of the node at the specifed location.
+ * 
+ * @author Randall Hauch
+ */
+public class ReadAllPropertiesRequest extends CacheableRequest implements Iterable<Property> {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final int UNKNOWN_NUMBER_OF_CHILDREN = -1;
+
+    private final Location at;
+    private final Map<Name, Property> properties = new HashMap<Name, Property>();
+    private int numberOfChildren = UNKNOWN_NUMBER_OF_CHILDREN;
+    private Location actualLocation;
+
+    /**
+     * Create a request to read the properties and number of children of a node at the supplied location.
+     * 
+     * @param at the location of the node to be read
+     * @throws IllegalArgumentException if the location is null
+     */
+    public ReadAllPropertiesRequest( Location at ) {
+        CheckArg.isNotNull(at, "at");
+        this.at = at;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return true;
+    }
+
+    /**
+     * Get the location defining the node that is to be read.
+     * 
+     * @return the location of the node; never null
+     */
+    public Location at() {
+        return at;
+    }
+
+    /**
+     * Get the properties that were read from the {@link RepositoryConnection}.
+     * 
+     * @return the properties, as a map of property name to property; never null
+     */
+    public Map<Name, Property> getPropertiesByName() {
+        return properties;
+    }
+
+    /**
+     * Get the properties that were read from the {@link RepositoryConnection}.
+     * 
+     * @return the collection of properties; never null
+     */
+    public Collection<Property> getProperties() {
+        return properties.values();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<Property> iterator() {
+        return getProperties().iterator();
+    }
+
+    /**
+     * Add a property that was read from the {@link RepositoryConnection}
+     * 
+     * @param property the property that was read
+     * @return the previous property that had the same name, or null if there was no previously-recorded property with the same
+     *         name
+     * @throws IllegalArgumentException if the property is null
+     */
+    public Property addProperty( Property property ) {
+        return this.properties.put(property.getName(), property);
+    }
+
+    /**
+     * Add a property that was read from the {@link RepositoryConnection}
+     * 
+     * @param properties the properties that were read
+     * @throws IllegalArgumentException if the property is null
+     */
+    public void addProperties( Property... properties ) {
+        for (Property property : properties) {
+            this.properties.put(property.getName(), property);
+        }
+    }
+
+    /**
+     * Get the number of children for this node.
+     * 
+     * @return the number of children, or {@link #UNKNOWN_NUMBER_OF_CHILDREN} if the number of children was not yet read
+     */
+    public int getNumberOfChildren() {
+        return numberOfChildren;
+    }
+
+    /**
+     * Set the number of children for this node
+     * 
+     * @param numberOfChildren the number of children
+     * @throws IllegalArgumentException if the number of childre is negative
+     */
+    public void setNumberOfChildren( int numberOfChildren ) {
+        CheckArg.isNonNegative(numberOfChildren, "numberOfChildren");
+        this.numberOfChildren = numberOfChildren;
+    }
+
+    /**
+     * Sets the actual and complete location of the node whose properties have been read. This method must be called when
+     * processing the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being read, or null if the {@link #at() current location} should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #at() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!at.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node whose properties were read.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            ReadAllPropertiesRequest that = (ReadAllPropertiesRequest)obj;
+            if (!this.at().equals(that.at())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "read properties of " + at();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadAllPropertiesRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,251 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.LinkedList;
+import java.util.List;
+import org.jboss.dna.common.text.Inflector;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to read a block of the children of a node, where the block is dictated by the {@link #startingAtIndex() starting
+ * index} and the {@link #count() maximum number of children} to include in the block. This command is useful when paging through
+ * a large number of children.
+ * 
+ * @see ReadNextBlockOfChildrenRequest
+ * @author Randall Hauch
+ */
+public class ReadBlockOfChildrenRequest extends CacheableRequest {
+
+    public static final int INDEX_NOT_USED = -1;
+
+    private static final long serialVersionUID = 1L;
+
+    private final Location of;
+    private final List<Location> children = new LinkedList<Location>();
+    private final int startingAtIndex;
+    private final int count;
+    private Location actualLocation;
+
+    /**
+     * Create a request to read a block of the children of a node at the supplied location. The block is defined by the starting
+     * index of the first child and the number of children to include. Note that this index is <i>not</i> the
+     * {@link Path.Segment#getIndex() same-name-sibiling index}, but rather is the index of the child as if the children were in
+     * an array.
+     * 
+     * @param of the location of the node whose children are to be read
+     * @param startingIndex the zero-based index of the first child to be included in the block
+     * @param count the maximum number of children that should be included in the block
+     * @throws IllegalArgumentException if the location is null, if <code>startingIndex</code> is negative, or if
+     *         <code>count</count> is less than 1.
+     */
+    public ReadBlockOfChildrenRequest( Location of,
+                                       int startingIndex,
+                                       int count ) {
+        CheckArg.isNotNull(of, "of");
+        CheckArg.isNonNegative(startingIndex, "startingIndex");
+        CheckArg.isPositive(count, "count");
+        this.of = of;
+        this.startingAtIndex = startingIndex;
+        this.count = count;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return true;
+    }
+
+    /**
+     * Get the location defining the node whose children are to be read.
+     * 
+     * @return the location of the parent node; never null
+     */
+    public Location of() {
+        return of;
+    }
+
+    /**
+     * Get the maximum number of children that may be returned in the block.
+     * 
+     * @return the block's maximum count
+     * @see #startingAtIndex()
+     * @see #endingBefore()
+     */
+    public int count() {
+        return this.count;
+    }
+
+    /**
+     * Get the starting index of the block, which is the index of the first child to include. This index corresponds to the index
+     * of all children in the list, not the {@link Path.Segment#getIndex() same-name-sibiling index}.
+     * 
+     * @return the (zero-based) child index at which this block starts; never negative and always less than
+     *         {@link #endingBefore()}
+     * @see #endingBefore()
+     * @see #count()
+     */
+    public int startingAtIndex() {
+        return this.startingAtIndex;
+    }
+
+    /**
+     * Get the index past the last child that is to be included in the block. This index corresponds to the index of all children
+     * in the list, not the {@link Path.Segment#getIndex() same-name-sibiling index}.
+     * 
+     * @return the index just past the last child included in the block; always positive and always greater than
+     *         {@link #startingAtIndex()}.
+     * @see #startingAtIndex()
+     * @see #count()
+     */
+    public int endingBefore() {
+        return this.startingAtIndex + this.count;
+    }
+
+    /**
+     * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
+     * represented by a location.
+     * 
+     * @return the children that were read; never null
+     */
+    public List<Location> getChildren() {
+        return children;
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param child the location of the child that was read
+     * @throws IllegalArgumentException if the location is null
+     * @see #addChild(Path, Property)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Location child ) {
+        CheckArg.isNotNull(child, "child");
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param firstIdProperty the first identification property of the child that was just read
+     * @param remainingIdProperties the remaining identification properties of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property)
+     */
+    public void addChild( Path pathToChild,
+                          Property firstIdProperty,
+                          Property... remainingIdProperties ) {
+        Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification property. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param idProperty the identification property of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Path pathToChild,
+                          Property idProperty ) {
+        Location child = new Location(pathToChild, idProperty);
+        this.children.add(child);
+    }
+
+    /**
+     * Sets the actual and complete location of the node whose children have been read. This method must be called when processing
+     * the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being read, or null if the {@link #of() current location} should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #of() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!of.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, of));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node whose children were read.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            ReadBlockOfChildrenRequest that = (ReadBlockOfChildrenRequest)obj;
+            if (!this.of().equals(that.of())) return false;
+            if (this.startingAtIndex() != that.startingAtIndex()) return false;
+            if (this.count() != that.count()) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        Inflector inflector = Inflector.getInstance();
+        if (count() == 1) {
+            return "read " + inflector.ordinalize(startingAtIndex()) + " thru " + inflector.ordinalize(endingBefore() - 1)
+                   + " children of " + of();
+        }
+        return "read " + inflector.ordinalize(startingAtIndex()) + " child of " + of();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBranchRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBranchRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBranchRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBranchRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,382 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to read the properties and children of the nodes in the branch at the supplied location. The children of the nodes
+ * at the bottom of the branch are not read.
+ * 
+ * @author Randall Hauch
+ */
+ at NotThreadSafe
+public class ReadBranchRequest extends CacheableRequest implements Iterable<Location> {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final int DEFAULT_MAXIMUM_DEPTH = 2;
+
+    private static class Node {
+        private final Location location;
+        private final Map<Name, Property> properties = new HashMap<Name, Property>();
+        private List<Location> children;
+
+        protected Node( Location location ) {
+            assert location != null;
+            this.location = location;
+        }
+
+        protected Location getLocation() {
+            return location;
+        }
+
+        protected Map<Name, Property> getProperties() {
+            return properties;
+        }
+
+        protected List<Location> getChildren() {
+            return children;
+        }
+
+        protected void setChildren( List<Location> children ) {
+            this.children = children;
+        }
+    }
+
+    private final Location at;
+    private final int maxDepth;
+    private final Map<Path, Node> nodes = new HashMap<Path, Node>();
+    private Location actualLocation;
+
+    /**
+     * Create a request to read the branch at the supplied location, to a maximum depth of 2.
+     * 
+     * @param at the location of the branch
+     * @throws IllegalArgumentException if the location is null
+     */
+    public ReadBranchRequest( Location at ) {
+        CheckArg.isNotNull(at, "at");
+        this.at = at;
+        this.maxDepth = DEFAULT_MAXIMUM_DEPTH;
+    }
+
+    /**
+     * Create a request to read the branch (of given depth) at the supplied location.
+     * 
+     * @param at the location of the branch
+     * @param maxDepth the maximum depth to read
+     * @throws IllegalArgumentException if the location is null or if the maximum depth is not positive
+     */
+    public ReadBranchRequest( Location at,
+                              int maxDepth ) {
+        CheckArg.isNotNull(at, "at");
+        CheckArg.isPositive(maxDepth, "maxDepth");
+        this.at = at;
+        this.maxDepth = maxDepth;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return true;
+    }
+
+    /**
+     * Get the location defining the top of the branch to be deleted
+     * 
+     * @return the location of the branch; never null
+     */
+    public Location at() {
+        return at;
+    }
+
+    /**
+     * Get the maximum depth of the branch that is to be read.
+     * 
+     * @return the maximum depth; always positive
+     */
+    public int maximumDepth() {
+        return maxDepth;
+    }
+
+    /**
+     * Return whether this branch contains the specified location.
+     * 
+     * @param location the location
+     * @return true if this branch includes the location, or false otherwise
+     */
+    public boolean includes( Location location ) {
+        if (location == null || !location.hasPath()) return false;
+        return this.nodes.containsKey(location.getPath());
+    }
+
+    /**
+     * Return whether this branch contains the specified path.
+     * 
+     * @param path the path
+     * @return true if this branch includes the path, or false otherwise
+     */
+    public boolean includes( Path path ) {
+        if (path == null) return false;
+        return this.nodes.containsKey(path);
+    }
+
+    /**
+     * Get the location for the supplied path.
+     * 
+     * @param path the path
+     * @return the location for the path, or null if the path is not known
+     */
+    public Location getLocationFor( Path path ) {
+        Node node = nodes.get(path);
+        return node != null ? node.getLocation() : null;
+    }
+
+    /**
+     * Add a node that was read from the {@link RepositoryConnection}. This method does not verify or check that the node is
+     * indeed on the branch and that it is at a level prescribed by the request.
+     * 
+     * @param node the location of the node that appears on this branch; must {@link Location#hasPath() have a path}
+     * @param properties the properties on the node
+     * @throws IllegalArgumentException if the node is null
+     */
+    public void setProperties( Location node,
+                               Property... properties ) {
+        CheckArg.isNotNull(node, "node");
+        assert node.hasPath();
+        Node nodeObj = nodes.get(node.getPath());
+        if (nodeObj == null) {
+            nodeObj = new Node(node);
+            nodes.put(node.getPath(), nodeObj);
+        }
+        Map<Name, Property> propertiesMap = nodeObj.getProperties();
+        for (Property property : properties) {
+            propertiesMap.put(property.getName(), property);
+        }
+    }
+
+    /**
+     * Add a node that was read from the {@link RepositoryConnection}. This method does not verify or check that the node is
+     * indeed on the branch and that it is at a level prescribed by the request.
+     * 
+     * @param node the location of the node that appears on this branch; must {@link Location#hasPath() have a path}
+     * @param properties the properties on the node
+     * @throws IllegalArgumentException if the node is null
+     */
+    public void setProperties( Location node,
+                               Iterable<Property> properties ) {
+        CheckArg.isNotNull(node, "node");
+        assert node.hasPath();
+        Node nodeObj = nodes.get(node.getPath());
+        if (nodeObj == null) {
+            nodeObj = new Node(node);
+            nodes.put(node.getPath(), nodeObj);
+        }
+        Map<Name, Property> propertiesMap = nodeObj.getProperties();
+        for (Property property : properties) {
+            propertiesMap.put(property.getName(), property);
+        }
+    }
+
+    /**
+     * Record the children for a parent node in the branch.
+     * 
+     * @param parent the location of the parent; must {@link Location#hasPath() have a path}
+     * @param children the location of each child, in the order they appear in the parent
+     */
+    public void setChildren( Location parent,
+                             Location... children ) {
+        CheckArg.isNotNull(parent, "parent");
+        CheckArg.isNotNull(children, "children");
+        assert parent.hasPath();
+        Node nodeObj = nodes.get(parent.getPath());
+        if (nodeObj == null) {
+            nodeObj = new Node(parent);
+            nodes.put(parent.getPath(), nodeObj);
+        }
+        nodeObj.setChildren(Arrays.asList(children));
+    }
+
+    /**
+     * Record the children for a parent node in the branch.
+     * 
+     * @param parent the location of the parent; must {@link Location#hasPath() have a path}
+     * @param children the location of each child, in the order they appear in the parent
+     */
+    public void setChildren( Location parent,
+                             List<Location> children ) {
+        CheckArg.isNotNull(parent, "parent");
+        CheckArg.isNotNull(children, "children");
+        assert parent.hasPath();
+        Node nodeObj = nodes.get(parent.getPath());
+        if (nodeObj == null) {
+            nodeObj = new Node(parent);
+            nodes.put(parent.getPath(), nodeObj);
+        }
+        nodeObj.setChildren(children);
+    }
+
+    // /**
+    // * Get the nodes that make up this branch. If this map is empty, the branch has not yet been read. The resulting map
+    // maintains
+    // * the order that the nodes were {@link #setProperties(Location, Property...) added}.
+    // *
+    // * @return the branch information
+    // * @see #iterator()
+    // */
+    // public Map<Path, Map<Name, Property>> getPropertiesByNode() {
+    // return nodeProperties;
+    // }
+
+    /**
+     * Get the nodes that make up this branch. If this map is empty, the branch has not yet been read. The resulting map maintains
+     * the order that the nodes were {@link #setProperties(Location, Property...) added}.
+     * 
+     * @param location the location of the node for which the properties are to be obtained
+     * @return the properties for the location, as a map keyed by the property name, or null if there is no such location
+     * @see #iterator()
+     */
+    public Map<Name, Property> getPropertiesFor( Location location ) {
+        if (location == null || !location.hasPath()) return null;
+        Node node = nodes.get(location.getPath());
+        return node != null ? node.getProperties() : null;
+    }
+
+    /**
+     * Get the children of the node at the supplied location.
+     * 
+     * @param parent the location of the parent
+     * @return the children, or null if there are no children (or if the parent has not been read)
+     */
+    public List<Location> getChildren( Location parent ) {
+        if (parent == null || !parent.hasPath()) return null;
+        Node node = nodes.get(parent.getPath());
+        return node != null ? node.getChildren() : null;
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * The resulting iterator accesses the {@link Location} objects in the branch, in pre-order traversal order.
+     * </p>
+     * 
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<Location> iterator() {
+        final LinkedList<Location> queue = new LinkedList<Location>();
+        if (getActualLocationOfNode() != null) {
+            Location actual = getActualLocationOfNode();
+            if (actual != null) queue.addFirst(getActualLocationOfNode());
+        }
+        return new Iterator<Location>() {
+            public boolean hasNext() {
+                return queue.peek() != null;
+            }
+
+            public Location next() {
+                // Add the children of the next node to the queue ...
+                Location next = queue.poll();
+                if (next == null) throw new NoSuchElementException();
+                List<Location> children = getChildren(next);
+                if (children != null && children.size() > 0) queue.addAll(0, children);
+                return next;
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    /**
+     * Sets the actual and complete location of the node being read. This method must be called when processing the request, and
+     * the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being read, or null if the {@link #at() current location} should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #at() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!at.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node that was read.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            ReadBranchRequest that = (ReadBranchRequest)obj;
+            if (!this.at().equals(that.at())) return false;
+            if (this.maximumDepth() != that.maximumDepth()) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "read branch " + at() + " to depth " + maximumDepth();
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadBranchRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNextBlockOfChildrenRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNextBlockOfChildrenRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNextBlockOfChildrenRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,217 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.LinkedList;
+import java.util.List;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to read a block of the children of a node, where the block is dictated by the {@link #startingAfter location of the
+ * child preceding the block} and the {@link #count() maximum number of children} to include in the block. This command is useful
+ * when paging through a large number of children, when the previous block of children was already retrieved and the next block is
+ * to be read.
+ * 
+ * @see ReadBlockOfChildrenRequest
+ * @author Randall Hauch
+ */
+public class ReadNextBlockOfChildrenRequest extends CacheableRequest {
+
+    public static final int INDEX_NOT_USED = -1;
+
+    private static final long serialVersionUID = 1L;
+
+    private final List<Location> children = new LinkedList<Location>();
+    private final Location startingAfter;
+    private final int count;
+    private Location actualStartingAfter;
+
+    /**
+     * Create a request to read those children of a node that are immediately after a supplied sibling node.
+     * 
+     * @param startingAfter the location of the previous sibling that was the last child of the previous block of children read
+     * @param count the maximum number of children that should be included in the block
+     * @throws IllegalArgumentException if the location is null, if <code>startingAfter</code> is null, or if
+     *         <code>count</count> is less than 1.
+     */
+    public ReadNextBlockOfChildrenRequest( Location startingAfter,
+                                           int count ) {
+        CheckArg.isNotNull(startingAfter, "startingAfter");
+        CheckArg.isPositive(count, "count");
+        this.startingAfter = startingAfter;
+        this.count = count;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return true;
+    }
+
+    /**
+     * Get the maximum number of children that may be returned in the block.
+     * 
+     * @return the block's maximum count
+     * @see #startingAfter()
+     */
+    public int count() {
+        return this.count;
+    }
+
+    /**
+     * Get the location of the child after which the block begins. This form may be easier to use when paging through blocks, as
+     * the last children retrieved with the previous block can be supplied with the next read request.
+     * 
+     * @return the location of the child that is immediately before the start of the block; index at which this block starts;
+     *         never negative
+     * @see #count()
+     */
+    public Location startingAfter() {
+        return this.startingAfter;
+    }
+
+    /**
+     * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
+     * represented by a location.
+     * 
+     * @return the children that were read; never null
+     */
+    public List<Location> getChildren() {
+        return children;
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param child the location of the child that was read
+     * @throws IllegalArgumentException if the location is null
+     * @see #addChild(Path, Property)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Location child ) {
+        CheckArg.isNotNull(child, "child");
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param firstIdProperty the first identification property of the child that was just read
+     * @param remainingIdProperties the remaining identification properties of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property)
+     */
+    public void addChild( Path pathToChild,
+                          Property firstIdProperty,
+                          Property... remainingIdProperties ) {
+        Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification property. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param idProperty the identification property of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Path pathToChild,
+                          Property idProperty ) {
+        Location child = new Location(pathToChild, idProperty);
+        this.children.add(child);
+    }
+
+    /**
+     * Sets the actual and complete location of the node whose children have been read. This method must be called when processing
+     * the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being read, or null if the {@link #startingAfter() starting after location}
+     *        should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #startingAfter() starting after location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfStartingAfterNode( Location actual ) {
+        if (!startingAfter.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, startingAfter));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualStartingAfter = actual;
+    }
+
+    /**
+     * Get the actual location of the {@link #startingAfter() starting after} sibling.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfStartingAfterNode() {
+        return actualStartingAfter;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            ReadNextBlockOfChildrenRequest that = (ReadNextBlockOfChildrenRequest)obj;
+            if (!this.startingAfter().equals(that.startingAfter())) return false;
+            if (this.count() != that.count()) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        if (count() == 1) {
+            return "read the next child after " + startingAfter();
+        }
+        return "read the next " + count() + " children after " + startingAfter();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNextBlockOfChildrenRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNodeRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNodeRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNodeRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNodeRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,244 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to read the properties and children of the node at the specifed location.
+ * 
+ * @author Randall Hauch
+ */
+public class ReadNodeRequest extends CacheableRequest implements Iterable<Location> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Location at;
+    private final Map<Name, Property> properties = new HashMap<Name, Property>();
+    private final List<Location> children = new LinkedList<Location>();
+    private Location actualLocation;
+
+    /**
+     * Create a request to read the properties and number of children of a node at the supplied location.
+     * 
+     * @param at the location of the node to be read
+     * @throws IllegalArgumentException if the location is null
+     */
+    public ReadNodeRequest( Location at ) {
+        CheckArg.isNotNull(at, "at");
+        this.at = at;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return true;
+    }
+
+    /**
+     * Get the location defining the node that is to be read.
+     * 
+     * @return the location of the node; never null
+     */
+    public Location at() {
+        return at;
+    }
+
+    /**
+     * Get the properties that were read from the {@link RepositoryConnection}.
+     * 
+     * @return the properties, as a map of property name to property; never null
+     */
+    public Map<Name, Property> getPropertiesByName() {
+        return properties;
+    }
+
+    /**
+     * Get the properties that were read from the {@link RepositoryConnection}.
+     * 
+     * @return the collection of properties; never null
+     */
+    public Collection<Property> getProperties() {
+        return properties.values();
+    }
+
+    /**
+     * Add a property that was read from the {@link RepositoryConnection}
+     * 
+     * @param property the property that was read
+     * @return the previous property that had the same name, or null if there was no previously-recorded property with the same
+     *         name
+     * @throws IllegalArgumentException if the property is null
+     */
+    public Property addProperty( Property property ) {
+        return this.properties.put(property.getName(), property);
+    }
+
+    /**
+     * Add a property that was read from the {@link RepositoryConnection}
+     * 
+     * @param properties the properties that were read
+     * @throws IllegalArgumentException if the property is null
+     */
+    public void addProperties( Property... properties ) {
+        for (Property property : properties) {
+            this.properties.put(property.getName(), property);
+        }
+    }
+
+    /**
+     * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
+     * represented by a location.
+     * 
+     * @return the children that were read; never null
+     */
+    public List<Location> getChildren() {
+        return children;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<Location> iterator() {
+        return children.iterator();
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param child the location of the child that was read
+     * @throws IllegalArgumentException if the location is null
+     * @see #addChild(Path, Property)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Location child ) {
+        CheckArg.isNotNull(child, "child");
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param firstIdProperty the first identification property of the child that was just read
+     * @param remainingIdProperties the remaining identification properties of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property)
+     */
+    public void addChild( Path pathToChild,
+                          Property firstIdProperty,
+                          Property... remainingIdProperties ) {
+        Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification property. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param idProperty the identification property of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Path pathToChild,
+                          Property idProperty ) {
+        Location child = new Location(pathToChild, idProperty);
+        this.children.add(child);
+    }
+
+    /**
+     * Sets the actual and complete location of the node whose children and properties have been read. This method must be called
+     * when processing the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being read, or null if the {@link #at() current location} should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #at() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!at.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node whose children and properties were read.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            ReadNodeRequest that = (ReadNodeRequest)obj;
+            if (!this.at().equals(that.at())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "read node at " + at();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadNodeRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadPropertyRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadPropertyRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadPropertyRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadPropertyRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,163 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to read a single property on the node at the specified location.
+ * 
+ * @author Randall Hauch
+ */
+public class ReadPropertyRequest extends CacheableRequest {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Location on;
+    private final Name propertyName;
+    private Property property;
+    private Location actualLocation;
+
+    /**
+     * Create a request to read the properties and number of children of a node at the supplied location.
+     * 
+     * @param on the location of the node to be read
+     * @param propertyName the name of the property to read
+     * @throws IllegalArgumentException if the location or property name are null
+     */
+    public ReadPropertyRequest( Location on,
+                                Name propertyName ) {
+        CheckArg.isNotNull(on, "on");
+        CheckArg.isNotNull(propertyName, "propertyName");
+        this.on = on;
+        this.propertyName = propertyName;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return true;
+    }
+
+    /**
+     * Get the location defining the node that is to be read.
+     * 
+     * @return the location of the node; never null
+     */
+    public Location on() {
+        return on;
+    }
+
+    /**
+     * Get the name of the property that is to be read
+     * 
+     * @return the property name; never null
+     */
+    public Name named() {
+        return propertyName;
+    }
+
+    /**
+     * Get the property that was read.
+     * 
+     * @return the property, or null if the property was not read or did not exist on the node
+     */
+    public Property getProperty() {
+        return property;
+    }
+
+    /**
+     * Set the property on the node as read from the {@link RepositoryConnection}
+     * 
+     * @param property the property that was read
+     * @throws IllegalArgumentException if the property's name does not match the {@link #named() name of the property} that was
+     *         to be read
+     */
+    public void setProperty( Property property ) {
+        if (property != null) CheckArg.isEquals(property.getName(), "property's name", named(), "property name");
+        this.property = property;
+    }
+
+    /**
+     * Sets the actual and complete location of the node whose property has been read. This method must be called when processing
+     * the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being read, or null if the {@link #on() current location} should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #on() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!on.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, on));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node whose property was read.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            ReadPropertyRequest that = (ReadPropertyRequest)obj;
+            if (!this.on().equals(that.on())) return false;
+            if (!this.named().equals(that.named())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "read " + named() + " property at " + on();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/ReadPropertyRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertiesRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RemovePropertiesRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertiesRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertiesRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,198 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Name;
+
+/**
+ * Instruction to remove properties from the node at the specified location.
+ * 
+ * @author Randall Hauch
+ */
+public class RemovePropertiesRequest extends Request implements Iterable<Name> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Location from;
+    private final Set<Name> propertyNames;
+    private Location actualLocation;
+
+    /**
+     * Create a request to remove the properties with the given names from the node at the supplied location.
+     * 
+     * @param from the location of the node to be read
+     * @param propertyNames the names of the properties to be removed from the node
+     * @throws IllegalArgumentException if the location is null or if there are no properties to remove
+     */
+    public RemovePropertiesRequest( Location from,
+                                    Name... propertyNames ) {
+        CheckArg.isNotNull(from, "from");
+        CheckArg.isNotEmpty(propertyNames, "propertyNames");
+        this.from = from;
+        Set<Name> names = new HashSet<Name>();
+        for (Name name : propertyNames) {
+            if (name != null) names.add(name);
+        }
+        this.propertyNames = Collections.unmodifiableSet(names);
+    }
+
+    /**
+     * Create a request to remove the properties with the given names from the node at the supplied location.
+     * 
+     * @param from the location of the node to be read
+     * @param propertyNames the names of the properties to be removed from the node
+     * @throws IllegalArgumentException if the location is null or if there are no properties to remove
+     */
+    public RemovePropertiesRequest( Location from,
+                                    Iterable<Name> propertyNames ) {
+        CheckArg.isNotNull(from, "from");
+        CheckArg.isNotNull(propertyNames, "propertyNames");
+        this.from = from;
+        Set<Name> names = new HashSet<Name>();
+        for (Name name : propertyNames) {
+            if (name != null) names.add(name);
+        }
+        this.propertyNames = Collections.unmodifiableSet(names);
+        CheckArg.isNotEmpty(this.propertyNames, "propertyNames");
+    }
+
+    /**
+     * Create a request to remove the properties with the given names from the node at the supplied location.
+     * 
+     * @param from the location of the node to be read
+     * @param propertyNames the names of the properties to be removed from the node
+     * @throws IllegalArgumentException if the location is null or if there are no properties to remove
+     */
+    public RemovePropertiesRequest( Location from,
+                                    Iterator<Name> propertyNames ) {
+        CheckArg.isNotNull(from, "from");
+        CheckArg.isNotNull(propertyNames, "propertyNames");
+        this.from = from;
+        Set<Name> names = new HashSet<Name>();
+        while (propertyNames.hasNext()) {
+            Name name = propertyNames.next();
+            if (name != null) names.add(name);
+        }
+        this.propertyNames = Collections.unmodifiableSet(names);
+        CheckArg.isNotEmpty(this.propertyNames, "propertyNames");
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return false;
+    }
+
+    /**
+     * Get the location defining the node from which the properties are to be removed.
+     * 
+     * @return the location of the node; never null
+     */
+    public Location from() {
+        return from;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<Name> iterator() {
+        return this.propertyNames.iterator();
+    }
+
+    /**
+     * Get the names of the properties that are to be removed from the node.
+     * 
+     * @return the collection of property names; never null and never empty
+     */
+    public Collection<Name> propertyNames() {
+        return propertyNames;
+    }
+
+    /**
+     * Sets the actual and complete location of the node whose properties were removed. This method must be called when processing
+     * the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being changed, or null if the {@link #from() current location} should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #from() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!from.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, from));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node whose properties were removed.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            RemovePropertiesRequest that = (RemovePropertiesRequest)obj;
+            if (!this.from().equals(that.from())) return false;
+            if (!this.propertyNames().equals(that.propertyNames())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "remove from " + from() + " properties named " + propertyNames();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertiesRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RenameNodeRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RenameNodeRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RenameNodeRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RenameNodeRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,171 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * Instruction to rename an existing node (but keep it under the same parent). The same-name-sibling index will be determined
+ * automatically, based upon it's current location within the list of children.
+ * 
+ * @author Randall Hauch
+ */
+public class RenameNodeRequest extends Request {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Location at;
+    private final Name newName;
+    private Location actualOldLocation;
+    private Location actualNewLocation;
+
+    /**
+     * Create a request to rename the node at the supplied location.
+     * 
+     * @param at the location of the node to be read
+     * @param newName the new name for the node
+     * @throws IllegalArgumentException if the location is null
+     */
+    public RenameNodeRequest( Location at,
+                              Name newName ) {
+        CheckArg.isNotNull(at, "at");
+        CheckArg.isNotNull(newName, "newName");
+        this.at = at;
+        this.newName = newName;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return false;
+    }
+
+    /**
+     * Get the location defining the node that is to be read.
+     * 
+     * @return the location of the node; never null
+     */
+    public Location at() {
+        return at;
+    }
+
+    /**
+     * Get the new name for the node.
+     * 
+     * @return the new name; never null
+     */
+    public Name toName() {
+        return newName;
+    }
+
+    /**
+     * Sets the actual and complete location of the node being renamed and its new location. This method must be called when
+     * processing the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param oldLocation the actual location of the node before being renamed
+     * @param newLocation the actual location of the node after being renamed
+     * @throws IllegalArgumentException if the either location is null or is missing its path, if the old location does not
+     *         represent the {@link Location#isSame(Location) same location} as the {@link #at() current location}, if the new
+     *         location does not have the same parent as the old location, or if the new location does not have the same
+     *         {@link Path.Segment#getName() name} on {@link Path#getLastSegment() last segment} as that {@link #toName()
+     *         specified on the request}
+     */
+    public void setActualLocations( Location oldLocation,
+                                    Location newLocation ) {
+        if (!at.isSame(oldLocation)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(oldLocation, at));
+        }
+        assert oldLocation != null;
+        if (newLocation == null) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(newLocation, at));
+        }
+        if (!oldLocation.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualOldLocationMustHavePath.text(oldLocation));
+        }
+        if (!newLocation.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualNewLocationMustHavePath.text(newLocation));
+        }
+        Path newPath = newLocation.getPath();
+        if (!newPath.getParent().equals(oldLocation.getPath().getParent())) {
+            String msg = GraphI18n.actualNewLocationMustHaveSameParentAsOldLocation.text(newLocation, oldLocation);
+            throw new IllegalArgumentException(msg);
+        }
+        if (!newPath.getLastSegment().getName().equals(toName())) {
+            String msg = GraphI18n.actualNewLocationMustHaveSameNameAsRequest.text(newLocation, toName());
+            throw new IllegalArgumentException(msg);
+        }
+        this.actualNewLocation = newLocation;
+    }
+
+    /**
+     * Get the actual location of the node before being renamed.
+     * 
+     * @return the actual location of the node before being renamed, or null if the actual location was not set
+     */
+    public Location getActualLocationBefore() {
+        return actualOldLocation;
+    }
+
+    /**
+     * Get the actual location of the node after being renamed.
+     * 
+     * @return the actual location of the node after being renamed, or null if the actual location was not set
+     */
+    public Location getActualLocationAfter() {
+        return actualNewLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            RenameNodeRequest that = (RenameNodeRequest)obj;
+            if (!this.at().equals(that.at())) return false;
+            if (!this.toName().equals(that.toName())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "rename node at " + at() + " to " + toName();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RenameNodeRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/Request.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Request.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/Request.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/Request.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,129 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.io.Serializable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+
+/**
+ * The abstract base class for all classes representing requests to be executed against a {@link RepositoryConnection}.
+ * 
+ * @author Randall Hauch
+ */
+public abstract class Request implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private Throwable error;
+    private AtomicBoolean cancelled;
+
+    protected Request() {
+        this.cancelled = new AtomicBoolean(false);
+    }
+
+    /**
+     * Set the error for this request.
+     * 
+     * @param error the error to be associated with this request, or null if this request is to have no error
+     */
+    public void setError( Throwable error ) {
+        this.error = error;
+    }
+
+    /**
+     * Return whether there is an error associated with this request
+     * 
+     * @return true if there is an error, or false otherwise
+     */
+    public boolean hasError() {
+        return this.error != null;
+    }
+
+    /**
+     * Get the error associated with this request, if there is such an error.
+     * 
+     * @return the error, or null if there is none
+     */
+    public Throwable getError() {
+        return error;
+    }
+
+    /**
+     * Check whether this request has been cancelled. Although it is a recommendation that the result of this method be followed
+     * wherever possible, it is not required to immediately stop processing the request if this method returns <code>true</code>.
+     * For example, if processing is almost complete, it may be appropriate to simply finish processing the request.
+     * <p>
+     * This method is safe to be called by different threads.
+     * </p>
+     * 
+     * @return true if this request has been cancelled, or false otherwise.
+     */
+    public boolean isCancelled() {
+        return cancelled.get();
+    }
+
+    /**
+     * Set the cancelled state of this request. All requests are initially marked as not cancelled. Note that this is designed so
+     * that the same {@link AtomicBoolean} instance can be passed to multiple requests, allowing a single flag to dictate the
+     * cancelled state of all of those requests.
+     * <p>
+     * So, by default, each request should already be set up to not be cancelled, so for most cases this method does not need to
+     * be called at all. This method should be called when this flag is to be shared among multiple requests, usually when the
+     * requests are being initialized or assembled.
+     * </p>
+     * 
+     * @param cancelled the new (potentially shared) cancelled state for the request; may not be null
+     */
+    /*package*/void setCancelledFlag( AtomicBoolean cancelled ) {
+        assert cancelled != null;
+        this.cancelled = cancelled;
+    }
+
+    /**
+     * Get this request's cancelled flag.
+     * 
+     * @return the cancelled flag
+     */
+    /*package*/AtomicBoolean getCancelledFlag() {
+        return cancelled;
+    }
+
+    /**
+     * Cancel this request. After this method is called, the {@link #isCancelled() cancellation flag} is set, and any current or
+     * future processing of the request may be affected by the cancellation. (Note however, that processors may choose to not
+     * respect this request.)
+     * <p>
+     * This method is safe to be called by different threads.
+     * </p>
+     */
+    public void cancel() {
+        this.cancelled.set(true);
+    }
+
+    /**
+     * Return whether this request only reads information.
+     * 
+     * @return true if this request reads information, or false if it requests that the repository content be changed in some way
+     */
+    public abstract boolean isReadOnly();
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/Request.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/UpdatePropertiesRequest.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/UpdatePropertiesRequest.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/UpdatePropertiesRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/UpdatePropertiesRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,249 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to update the properties on the node at the specified location. Any property with no values will be removed.
+ * 
+ * @author Randall Hauch
+ */
+public class UpdatePropertiesRequest extends Request implements Iterable<Property> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Location on;
+    private final List<Property> properties;
+    private Location actualLocation;
+
+    /**
+     * Create a request to update the properties on the node at the supplied location.
+     * 
+     * @param on the location of the node to be read
+     * @param properties the new properties on the node
+     * @throws IllegalArgumentException if the location is null or if there are no properties to update
+     */
+    public UpdatePropertiesRequest( Location on,
+                                    Property... properties ) {
+        CheckArg.isNotNull(on, "on");
+        CheckArg.isNotEmpty(properties, "properties");
+        this.on = on;
+        this.properties = Collections.unmodifiableList(Arrays.asList(properties));
+    }
+
+    /**
+     * Create a request to update the properties on the node at the supplied location.
+     * 
+     * @param on the location of the node to be read
+     * @param properties the new properties on the node
+     * @throws IllegalArgumentException if the location is null or if there are no properties to update
+     */
+    public UpdatePropertiesRequest( Location on,
+                                    Iterable<Property> properties ) {
+        CheckArg.isNotNull(on, "on");
+        CheckArg.isNotNull(properties, "properties");
+        this.on = on;
+        List<Property> props = new LinkedList<Property>();
+        for (Property property : properties) {
+            if (property != null) props.add(property);
+        }
+        this.properties = Collections.unmodifiableList(props);
+        CheckArg.isNotEmpty(this.properties, "properties");
+    }
+
+    /**
+     * Create a request to update the properties on the node at the supplied location.
+     * 
+     * @param on the location of the node to be read
+     * @param properties the new properties on the node
+     * @throws IllegalArgumentException if the location is null or if there are no properties to update
+     */
+    public UpdatePropertiesRequest( Location on,
+                                    Iterator<Property> properties ) {
+        CheckArg.isNotNull(on, "on");
+        CheckArg.isNotNull(properties, "properties");
+        this.on = on;
+        List<Property> props = new LinkedList<Property>();
+        while (properties.hasNext()) {
+            Property property = properties.next();
+            if (property != null) props.add(property);
+        }
+        this.properties = Collections.unmodifiableList(props);
+        CheckArg.isNotEmpty(this.properties, "properties");
+    }
+
+    /**
+     * Create a request to update the properties on the node at the supplied location.
+     * 
+     * @param on the location of the node to be read
+     * @param properties the new properties on the node
+     * @throws IllegalArgumentException if the location is null or if there are no properties to update
+     */
+    private UpdatePropertiesRequest( Location on,
+                                     List<Property> properties ) {
+        CheckArg.isNotNull(on, "on");
+        CheckArg.isNotNull(properties, "properties");
+        this.on = on;
+        this.properties = properties;
+        CheckArg.isNotEmpty(this.properties, "properties");
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return false;
+    }
+
+    /**
+     * Get the location defining the node that is to be updated.
+     * 
+     * @return the location of the node; never null
+     */
+    public Location on() {
+        return on;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<Property> iterator() {
+        return this.properties.iterator();
+    }
+
+    /**
+     * Get the properties for the node.
+     * 
+     * @return the collection of properties; never null and never empty
+     */
+    public Collection<Property> properties() {
+        return properties;
+    }
+
+    /**
+     * Sets the actual and complete location of the node being updated. This method must be called when processing the request,
+     * and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being updated, or null if the {@link #on() current location} should be used
+     * @throws IllegalArgumentException if the actual location does represent the {@link Location#isSame(Location) same location}
+     *         as the {@link #on() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!on.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, on));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node that was updated.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            UpdatePropertiesRequest that = (UpdatePropertiesRequest)obj;
+            if (!this.on().equals(that.on())) return false;
+            if (!this.properties().equals(that.properties())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "update properties on " + on() + " to " + properties();
+    }
+
+    /**
+     * Merge these updates with those in the supplied request, with the supplied changes overwriting any similar changes on this
+     * node.
+     * 
+     * @param other the other updates that are to be merged with these
+     * @return the merged request
+     */
+    public UpdatePropertiesRequest mergeWith( UpdatePropertiesRequest other ) {
+        if (other == null) return this;
+        if (other.properties().size() == 1) {
+            Property newProp = other.properties.get(0);
+            List<Property> newProps = new LinkedList<Property>();
+            for (Property prop : this.properties) {
+                if (!prop.getName().equals(newProp.getName())) {
+                    newProps.add(prop);
+                }
+            }
+            newProps.add(newProp);
+            return new UpdatePropertiesRequest(on, Collections.unmodifiableList(newProps));
+        }
+        Set<Name> otherNames = new HashSet<Name>();
+        for (Property prop : other.properties()) {
+            otherNames.add(prop.getName());
+        }
+        List<Property> newProps = new LinkedList<Property>();
+        for (Property prop : this.properties) {
+            if (!otherNames.contains(prop.getName())) {
+                newProps.add(prop);
+            }
+        }
+        newProps.addAll(other.properties);
+        return new UpdatePropertiesRequest(on, Collections.unmodifiableList(newProps));
+
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/UpdatePropertiesRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/package-info.java (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/package-info.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/package-info.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,139 @@
+/**
+ * Sometimes its useful to work with a graph using objects that represent individual 
+ * <a href="http://en.wikipedia.org/wiki/Command_pattern">commands</a> on the graph.  For example, "read node A"
+ * or "create a node named C under node /A/B" or "create a copy of the subgraph at /E/F/G and place it under /E/H/I".
+ * The command pattern has a number of benefits.  Since commands represent atomic activities, they map well to events
+ * and can be easily serialized (making them very useful for {@link org.jboss.dna.graph.connector.RepositoryConnection connectors}). 
+ * They provide an easy way to inherit or override functionality.  
+ * New kinds of commands can be added with minimal (sometimes no) impact.
+ * And existing commands can be changed to include new fields, making it possible to evolve a command
+ * while minimizing the changes.
+ * <p>
+ * This package defines standard commands, called "requests", that correspond to different kinds of actions against a JBoss DNA graph.
+ * Each kind of request is represented by a single concrete class, and all request classes extend from the
+ * {@link Request} abstract class.  Because a lot of inheritance among commands can cause interference and inheritance cross-talk,
+ * inheritance other than from {@link Request} is avoided as much possible.  (One exception to this is
+ * {@link CacheableRequest}, which extends {@link Request} and serves as the base class for the "read" requests
+ * that return results.)
+ * </p>
+ * <h3>Processing Requests</h3>
+ * <p>
+ * Request objects are sent to a {@link org.jboss.dna.graph.request.processor.RequestProcessor}, which is responsible
+ * for performing the request.  {@link org.jboss.dna.graph.connector.RepositoryConnection Repository connectors} usually
+ * implement their own <code>RequestProcessor</code>, which processes each submitted request by performing the
+ * requested work.
+ * </p>
+ * <p>
+ * Processor generally do not throw exceptions when processing requests (other than errors that signal problems
+ * with the processor itself, such as connectivity problems, that signals the interruption of not only this request
+ * but subsequent requests, too).  Instead, each request has an
+ * {@link Request#setError(Throwable) error} field that can be used to store the exception that was encountered 
+ * while processing the request.  This makes it possible to submit {@link CompositeRequest multiple requests}
+ * at once, and have any errors directly associated with the request.
+ * </p>
+ * <h3>What's in a Request?</h3>
+ * <p>
+ * In general, a single request contains two kinds of information: the information that makes up the request (called the "input"),
+ * and the information that is the result of the request (called the "result").  The input information contains everything
+ * a processor needs to know to successfully perform the request.  For example, if the properties of a node are to be
+ * read, then the input information must include the identifier or location of the  node.  If a node is to be moved,
+ * then the input information must include the original location of the node as well as the new location.
+ * Oh, the request's input information is immutable, ensuring that this part of the request doesn't change as it is passed
+ * around the system.
+ * </p>
+ * <p>
+ * A processor then fulfills the request by performing the requested work, and setting on the request any 
+ * requested "results".  For example, if the properties of a node are to be read, then the results include
+ * the set of {@link org.jboss.dna.graph.property.Property} objects.  If the children are to be read, then the
+ * results consist of the list of {@link org.jboss.dna.graph.Location} object for each child.
+ * </p>
+ * <h3>Locations</h3>
+ * <p>
+ * All requests operate on some portion of the graph, so it's imperative that there be an easy but flexible
+ * way to identify the location of that area, whether it's a node, subgraph, child reference, or node reference.
+ * Like other parts of the JBoss DNA Graph API, requests use {@link org.jboss.dna.graph.Location} (or multiple
+ * Location objects) as request inputs, and one Location object for each "reference" to a node that's in the output.
+ * </p>
+ * <p>
+ * A {@link org.jboss.dna.graph.Location} can be specified as a {@link org.jboss.dna.graph.property.Path} and/or
+ * as a set of identification properties.  Usually, Locations are created using just the path, since that's how
+ * nodes are identified most of the time.  However, identification properties usually consist of information that 
+ * uniquely (and quickly) identifies a node, so including identification properties in a Location may allow the 
+ * processor to easily or more efficiently find the node given by the location.
+ * </p>
+ * <p>
+ * Fortunately, requests often return Location objects that are <i>fully-defined</i>, meaning they have a Path 
+ * <i>and</i> identification properties.  For example, the children of a node will be returned as a list of (fully-defined)
+ * Location objects.  In fact, all requests have as part of their results an "actual" Location for each Location in the input,
+ * so even when you don't have a fully-defined Location as an input, the request (after processing) should contain
+ * a fully-defined Location for the input.
+ * </p>
+ * <p>
+ * Because of this, and because working with a graph usually consists of making one request, using the results of that
+ * request to create additional requests, and so on, you'll find that it's very easy to include fully-defined Location
+ * objects in your requests.  Well, except for the first request.
+ * </p>
+ * <h3>Kinds of Requests</h3>
+ * <p>
+ * There are really two very broad categories of {@link Request}s: requests that don't modify content and those that do.
+ * The requests that don't modify content are generally "read" requests that are requests to return information about
+ * some part of the graph, and these requests should really have not side-effects on the graph.  Since these requests
+ * contain results that are essentially snapshots in time of a portion of the graph content, these request types
+ * extend {@link CacheableRequest} and contain fields for referencing a {@link org.jboss.dna.graph.cache.CachePolicy}
+ * and a time that the results were loaded.
+ * </p>
+ * <p>
+ * Requests that do modify graph content are used to create, update, move and delete content in the graph.  These
+ * kinds of requests often have little or no results (the changes will be made to the graph unless an exception
+ * is set on the request during processing), and as such the requests do not have any fields related to caching.
+ * </p>
+ * <p>
+ * The supported requests currently include:
+ * <ul>
+ *   <li>{@link ReadNodeRequest} - A request to read the specified node and return all of that node's properties and the 
+ *   location of every child node.</li>
+ *   <li>{@link ReadAllChildrenRequest} - A request to read and return all of the children of the specified node.
+ *   Each child node is represented by a {@link org.jboss.dna.graph.Location} object.  This request is useful for
+ *   determining the structure of the graph without having to load all of the properties of each node.</li>
+ *   <li>{@link ReadAllPropertiesRequest} - A request to read and return all of the properties of the specified node.
+ *   This request is useful when all of the properties for a node are to be returned, but without any children
+ *   information (usually because the children will be read later or were already read).</li>
+ *   <li>{@link ReadBranchRequest} - A request to read a branch of the graph, returning the node (with its properties
+ *   and children) at the specified location as well as nodes (with their properties and children) below the specified node,
+ *   up to an optional maximum depth.  This request is useful for efficiently obtaining the nodes in a subgraph when
+ *   the structure is known ahead of time.  This request can sometimes be significantly more efficient that walking
+ *   the subgraph and submitting individual {@link ReadNodeRequest}s for each node in the subgraph.</li>
+ *   <li>{@link ReadPropertyRequest} - A request to read and return a single named property on a specified node.</li>
+ *   <li>{@link ReadBlockOfChildrenRequest} - A request to read the children of the specified node, returning only
+ *   the locations for a subset of the children. The subset of children is defined by the index of the first child
+ *   to be returned and the number of children to be returned.  This is often useful when the repository may have large numbers
+ *   of children and it is unlikely that client applications will need all of them. </li>
+ *   <li>{@link ReadNextBlockOfChildrenRequest} - A request to read the children of the specified node, returning
+ *   only the locations for a subset of the children.  Unlike {@link ReadBlockOfChildrenRequest}, this request
+ *   specifies the Location of the child that appears immediately before the first child to be returned.  This
+ *   request is useful in concurrent applications when one client is reading the children while another client
+ *   may be adding or removing children (thereby changing the indexes).  Since this request includes the Location of the 
+ *   last child previously read, the request is unaffected by changing indexes.</li>
+ *   <li>{@link CreateNodeRequest} - A request to create a new node under an existing parent node.  This request
+ *   may optionally include properties for the new node.</li>
+ *   <li>{@link CopyBranchRequest} - A request to copy an entire branch located under a specified node, and place
+ *   the copy of that branch under another (existing) node.</li>
+ *   <li>{@link MoveBranchRequest} - A request to move the specified node and all nodes below it into a new location
+ *   specified by the Location of the new parent node.</li>
+ *   <li>{@link RenameNodeRequest} - A request to rename an existing node.  This may adjust the indexes of sibling nodes
+ *   with the same names (as same-name-sibling nodes are identified with SNS indexes).</li>
+ *   <li>{@link UpdatePropertiesRequest} - A request to update one or more properties on a node.  Any property
+ *   with no values will be removed, while properties with one or more values will be set (replace any existing property
+ *   with the same name, if they exist). </li>
+ *   <li>{@link RemovePropertiesRequest} - A request to remove one or more properties on a node.  No error is reported
+ *   if the node does not contain a property that is to be removed.</li>
+ *   <li>{@link DeleteBranchRequest} - A request to delete a node and all nodes located below it.</li>
+ *   <li>{@link CompositeRequest} - A request that acts as a container for multiple other requests (of various kinds),
+ *   allowing you to batch together multiple for processing.  Use the one of the {@link CompositeRequest#with(Request...) CompositeRequest.with(...)}
+ *   methods to create a CompositeRequest from a series of other requests.</li>
+ * </ul>
+ * </p>
+ */
+
+package org.jboss.dna.graph.request;
+


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/package-info.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor)

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/LoggingRequestProcessor.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,274 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests.processor;
-
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.requests.CompositeRequest;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadBranchRequest;
-import org.jboss.dna.graph.requests.ReadNextBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
-import org.jboss.dna.graph.requests.ReadPropertyRequest;
-import org.jboss.dna.graph.requests.RemovePropertiesRequest;
-import org.jboss.dna.graph.requests.RenameNodeRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-
-/**
- * A {@link RequestProcessor} implementation that wraps another and that logs messages at the supplied level.
- * 
- * @author Randall Hauch
- */
-public class LoggingRequestProcessor extends RequestProcessor {
-
-    private final RequestProcessor delegate;
-    private final Logger logger;
-    private final Logger.Level level;
-
-    /**
-     * @param delegate the processor to which this processor delegates
-     * @param logger the logger that should be used
-     * @param level the level of the log messages; defaults to {@link Logger.Level#TRACE}
-     */
-    public LoggingRequestProcessor( RequestProcessor delegate,
-                                    Logger logger,
-                                    Logger.Level level ) {
-        super(delegate.getSourceName(), delegate.getExecutionContext());
-        CheckArg.isNotNull(logger, "logger");
-        this.delegate = delegate;
-        this.logger = logger;
-        this.level = level != null ? level : Logger.Level.TRACE;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CopyBranchRequest)
-     */
-    @Override
-    public void process( CopyBranchRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CreateNodeRequest)
-     */
-    @Override
-    public void process( CreateNodeRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.DeleteBranchRequest)
-     */
-    @Override
-    public void process( DeleteBranchRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.MoveBranchRequest)
-     */
-    @Override
-    public void process( MoveBranchRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllChildrenRequest)
-     */
-    @Override
-    public void process( ReadAllChildrenRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllPropertiesRequest)
-     */
-    @Override
-    public void process( ReadAllPropertiesRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.UpdatePropertiesRequest)
-     */
-    @Override
-    public void process( UpdatePropertiesRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CompositeRequest)
-     */
-    @Override
-    public void process( CompositeRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest)
-     */
-    @Override
-    public void process( ReadBlockOfChildrenRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadNextBlockOfChildrenRequest)
-     */
-    @Override
-    public void process( ReadNextBlockOfChildrenRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadBranchRequest)
-     */
-    @Override
-    public void process( ReadBranchRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadNodeRequest)
-     */
-    @Override
-    public void process( ReadNodeRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadPropertyRequest)
-     */
-    @Override
-    public void process( ReadPropertyRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.RemovePropertiesRequest)
-     */
-    @Override
-    public void process( RemovePropertiesRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.RenameNodeRequest)
-     */
-    @Override
-    public void process( RenameNodeRequest request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.Request)
-     */
-    @Override
-    public void process( Request request ) {
-        logger.log(level, GraphI18n.executingRequest, request);
-        delegate.process(request);
-        logger.log(level, GraphI18n.executedRequest, request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#close()
-     */
-    @Override
-    public void close() {
-        logger.log(level, GraphI18n.closingRequestProcessor);
-        delegate.close();
-        logger.log(level, GraphI18n.closingRequestProcessor);
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/LoggingRequestProcessor.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,274 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request.processor;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.request.CompositeRequest;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadBranchRequest;
+import org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+import org.jboss.dna.graph.request.ReadPropertyRequest;
+import org.jboss.dna.graph.request.RemovePropertiesRequest;
+import org.jboss.dna.graph.request.RenameNodeRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+
+/**
+ * A {@link RequestProcessor} implementation that wraps another and that logs messages at the supplied level.
+ * 
+ * @author Randall Hauch
+ */
+public class LoggingRequestProcessor extends RequestProcessor {
+
+    private final RequestProcessor delegate;
+    private final Logger logger;
+    private final Logger.Level level;
+
+    /**
+     * @param delegate the processor to which this processor delegates
+     * @param logger the logger that should be used
+     * @param level the level of the log messages; defaults to {@link Logger.Level#TRACE}
+     */
+    public LoggingRequestProcessor( RequestProcessor delegate,
+                                    Logger logger,
+                                    Logger.Level level ) {
+        super(delegate.getSourceName(), delegate.getExecutionContext());
+        CheckArg.isNotNull(logger, "logger");
+        this.delegate = delegate;
+        this.logger = logger;
+        this.level = level != null ? level : Logger.Level.TRACE;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CopyBranchRequest)
+     */
+    @Override
+    public void process( CopyBranchRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CreateNodeRequest)
+     */
+    @Override
+    public void process( CreateNodeRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.DeleteBranchRequest)
+     */
+    @Override
+    public void process( DeleteBranchRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.MoveBranchRequest)
+     */
+    @Override
+    public void process( MoveBranchRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
+     */
+    @Override
+    public void process( ReadAllChildrenRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllPropertiesRequest)
+     */
+    @Override
+    public void process( ReadAllPropertiesRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.UpdatePropertiesRequest)
+     */
+    @Override
+    public void process( UpdatePropertiesRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CompositeRequest)
+     */
+    @Override
+    public void process( CompositeRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadBlockOfChildrenRequest)
+     */
+    @Override
+    public void process( ReadBlockOfChildrenRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest)
+     */
+    @Override
+    public void process( ReadNextBlockOfChildrenRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadBranchRequest)
+     */
+    @Override
+    public void process( ReadBranchRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadNodeRequest)
+     */
+    @Override
+    public void process( ReadNodeRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadPropertyRequest)
+     */
+    @Override
+    public void process( ReadPropertyRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RemovePropertiesRequest)
+     */
+    @Override
+    public void process( RemovePropertiesRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RenameNodeRequest)
+     */
+    @Override
+    public void process( RenameNodeRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.Request)
+     */
+    @Override
+    public void process( Request request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#close()
+     */
+    @Override
+    public void close() {
+        logger.log(level, GraphI18n.closingRequestProcessor);
+        delegate.close();
+        logger.log(level, GraphI18n.closingRequestProcessor);
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/RequestProcessor.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,585 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests.processor;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.ReferentialIntegrityException;
-import org.jboss.dna.graph.properties.basic.BasicEmptyProperty;
-import org.jboss.dna.graph.requests.CacheableRequest;
-import org.jboss.dna.graph.requests.CompositeRequest;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadBranchRequest;
-import org.jboss.dna.graph.requests.ReadNextBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
-import org.jboss.dna.graph.requests.ReadPropertyRequest;
-import org.jboss.dna.graph.requests.RemovePropertiesRequest;
-import org.jboss.dna.graph.requests.RenameNodeRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-
-/**
- * A component that is used to process and execute {@link Request}s. This class is intended to be subclassed and methods
- * overwritten to define the behavior for executing the different kinds of requests. Abstract methods must be overridden, but
- * non-abstract methods all have meaningful default implementations.
- * 
- * @author Randall Hauch
- */
- at Immutable
-public abstract class RequestProcessor {
-
-    private final ExecutionContext context;
-    private final String sourceName;
-    private final DateTime nowInUtc;
-    private final CachePolicy defaultCachePolicy;
-
-    protected RequestProcessor( String sourceName,
-                                ExecutionContext context ) {
-        this(sourceName, context, null, null);
-    }
-
-    protected RequestProcessor( String sourceName,
-                                ExecutionContext context,
-                                DateTime now ) {
-        this(sourceName, context, now, null);
-    }
-
-    protected RequestProcessor( String sourceName,
-                                ExecutionContext context,
-                                DateTime now,
-                                CachePolicy defaultCachePolicy ) {
-        CheckArg.isNotEmpty(sourceName, "sourceName");
-        CheckArg.isNotNull(context, "context");
-        this.context = context;
-        this.sourceName = sourceName;
-        this.nowInUtc = now != null ? now : context.getValueFactories().getDateFactory().createUtc();
-        this.defaultCachePolicy = defaultCachePolicy;
-    }
-
-    /**
-     * Get the name of the source against which this processor is executing.
-     * 
-     * @return the repository source name; never null or empty
-     */
-    public String getSourceName() {
-        return sourceName;
-    }
-
-    /**
-     * The execution context that this process is operating within.
-     * 
-     * @return the execution context; never null
-     */
-    public ExecutionContext getExecutionContext() {
-        return this.context;
-    }
-
-    /**
-     * Get the 'current time' for this processor, which is usually a constant during its lifetime.
-     * 
-     * @return the current time in UTC; never null
-     */
-    protected DateTime getNowInUtc() {
-        return this.nowInUtc;
-    }
-
-    /**
-     * Set the supplied request to have the default cache policy and the {@link #getNowInUtc() current time in UTC}.
-     * 
-     * @param request the cacheable request
-     */
-    protected void setCacheableInfo( CacheableRequest request ) {
-        request.setCachePolicy(defaultCachePolicy);
-        request.setTimeLoaded(nowInUtc);
-    }
-
-    /**
-     * Set the supplied request to have the supplied cache policy and the {@link #getNowInUtc() current time in UTC}.
-     * 
-     * @param request the cacheable request
-     * @param cachePolicy the cache policy for the request; may be null if there is to be no cache policy
-     */
-    protected void setCacheableInfo( CacheableRequest request,
-                                     CachePolicy cachePolicy ) {
-        request.setCachePolicy(cachePolicy);
-        request.setTimeLoaded(nowInUtc);
-    }
-
-    /**
-     * Process a request by determining the type of request and delegating to the appropriate <code>process</code> method for that
-     * type.
-     * <p>
-     * This method does nothing if the request is null.
-     * </p>
-     * 
-     * @param request the general request
-     */
-    public void process( Request request ) {
-        if (request == null) return;
-        if (request.isCancelled()) return;
-        if (request instanceof CompositeRequest) {
-            process((CompositeRequest)request);
-        } else if (request instanceof CopyBranchRequest) {
-            process((CopyBranchRequest)request);
-        } else if (request instanceof CreateNodeRequest) {
-            process((CreateNodeRequest)request);
-        } else if (request instanceof DeleteBranchRequest) {
-            process((DeleteBranchRequest)request);
-        } else if (request instanceof MoveBranchRequest) {
-            process((MoveBranchRequest)request);
-        } else if (request instanceof ReadAllChildrenRequest) {
-            process((ReadAllChildrenRequest)request);
-        } else if (request instanceof ReadNextBlockOfChildrenRequest) {
-            process((ReadNextBlockOfChildrenRequest)request);
-        } else if (request instanceof ReadBlockOfChildrenRequest) {
-            process((ReadBlockOfChildrenRequest)request);
-        } else if (request instanceof ReadBranchRequest) {
-            process((ReadBranchRequest)request);
-        } else if (request instanceof ReadNodeRequest) {
-            process((ReadNodeRequest)request);
-        } else if (request instanceof ReadAllPropertiesRequest) {
-            process((ReadAllPropertiesRequest)request);
-        } else if (request instanceof ReadPropertyRequest) {
-            process((ReadPropertyRequest)request);
-        } else if (request instanceof RemovePropertiesRequest) {
-            process((RemovePropertiesRequest)request);
-        } else if (request instanceof RenameNodeRequest) {
-            process((RenameNodeRequest)request);
-        } else if (request instanceof UpdatePropertiesRequest) {
-            process((UpdatePropertiesRequest)request);
-        }
-    }
-
-    /**
-     * Process a request that is composed of multiple other (non-composite) requests. If any of the embedded requests
-     * {@link Request#hasError() has an error} after it is processed, the submitted request will be marked with an error.
-     * <p>
-     * This method does nothing if the request is null.
-     * </p>
-     * 
-     * @param request the composite request
-     */
-    public void process( CompositeRequest request ) {
-        if (request == null) return;
-        int numberOfErrors = 0;
-        Throwable firstError = null;
-        for (Request embedded : request) {
-            assert embedded != null;
-            if (embedded.isCancelled()) return;
-            process(embedded);
-            if (embedded.hasError()) {
-                if (numberOfErrors == 0) firstError = embedded.getError();
-                ++numberOfErrors;
-            }
-        }
-        if (firstError == null) return;
-        if (numberOfErrors == 1) {
-            request.setError(firstError);
-        } else {
-            String msg = GraphI18n.multipleErrorsWhileExecutingRequests.text(numberOfErrors, request.size());
-            request.setError(new RepositorySourceException(getSourceName(), msg));
-        }
-    }
-
-    /**
-     * Process a request to copy a branch into another location.
-     * <p>
-     * This method does nothing if the request is null.
-     * </p>
-     * 
-     * @param request the copy request
-     */
-    public abstract void process( CopyBranchRequest request );
-
-    /**
-     * Process a request to create a node at a specified location.
-     * <p>
-     * This method does nothing if the request is null.
-     * </p>
-     * 
-     * @param request the create request
-     */
-    public abstract void process( CreateNodeRequest request );
-
-    /**
-     * Process a request to delete a branch at a specified location.
-     * <p>
-     * This method does nothing if the request is null.
-     * </p>
-     * 
-     * @param request the delete request
-     * @throws ReferentialIntegrityException if the delete could not be performed because some references to deleted nodes would
-     *         have remained after the delete operation completed
-     */
-    public abstract void process( DeleteBranchRequest request );
-
-    /**
-     * Process a request to move a branch at a specified location into a different location.
-     * <p>
-     * This method does nothing if the request is null.
-     * </p>
-     * 
-     * @param request the move request
-     */
-    public abstract void process( MoveBranchRequest request );
-
-    /**
-     * Process a request to read all of the children of a node.
-     * <p>
-     * This method does nothing if the request is null.
-     * </p>
-     * 
-     * @param request the read request
-     */
-    public abstract void process( ReadAllChildrenRequest request );
-
-    /**
-     * Process a request to read a block of the children of a node. The block is defined by a
-     * {@link ReadBlockOfChildrenRequest#startingAtIndex() starting index} and a {@link ReadBlockOfChildrenRequest#count() maximum
-     * number of children to include in the block}.
-     * <p>
-     * This method does nothing if the request is null. The default implementation converts the command to a
-     * {@link ReadAllChildrenRequest}, and then finds the children within the block. Obviously for large numbers of children, this
-     * implementation may not be efficient and may need to be overridden.
-     * </p>
-     * 
-     * @param request the read request
-     */
-    public void process( ReadBlockOfChildrenRequest request ) {
-        if (request == null) return;
-        // Convert the request to a ReadAllChildrenRequest and execute it ...
-        ReadAllChildrenRequest readAll = new ReadAllChildrenRequest(request.of());
-        process(readAll);
-        if (readAll.hasError()) {
-            request.setError(readAll.getError());
-            return;
-        }
-        List<Location> allChildren = readAll.getChildren();
-
-        // If there aren't enough children for the block's range ...
-        if (allChildren.size() < request.startingAtIndex()) return;
-
-        // Now, find the children in the block ...
-        int endIndex = Math.min(request.endingBefore(), allChildren.size());
-        for (int i = request.startingAtIndex(); i != endIndex; ++i) {
-            request.addChild(allChildren.get(i));
-        }
-        // Set the actual location ...
-        request.setActualLocationOfNode(readAll.getActualLocationOfNode());
-        setCacheableInfo(request);
-    }
-
-    /**
-     * Process a request to read the next block of the children of a node, starting after a previously-retrieved child.
-     * <p>
-     * This method does nothing if the request is null. The default implementation converts the command to a
-     * {@link ReadAllChildrenRequest}, and then finds the children within the block. Obviously for large numbers of children, this
-     * implementation may not be efficient and may need to be overridden.
-     * </p>
-     * 
-     * @param request the read request
-     */
-    public void process( ReadNextBlockOfChildrenRequest request ) {
-        if (request == null) return;
-
-        // Get the parent path ...
-        Path path = request.startingAfter().getPath();
-        Location actualSiblingLocation = request.startingAfter();
-        Path parentPath = null;
-        if (path != null) parentPath = path.getParent();
-        if (parentPath == null) {
-            ReadAllPropertiesRequest readPropertiesOfSibling = new ReadAllPropertiesRequest(request.startingAfter());
-            process(readPropertiesOfSibling);
-            actualSiblingLocation = readPropertiesOfSibling.getActualLocationOfNode();
-            parentPath = actualSiblingLocation.getPath().getParent();
-        }
-        assert parentPath != null;
-
-        // Convert the request to a ReadAllChildrenRequest and execute it ...
-        ReadAllChildrenRequest readAll = new ReadAllChildrenRequest(new Location(parentPath));
-        process(readAll);
-        if (readAll.hasError()) {
-            request.setError(readAll.getError());
-            return;
-        }
-        List<Location> allChildren = readAll.getChildren();
-
-        // Iterate through the children, looking for the 'startingAfter' child ...
-        boolean found = false;
-        int count = 0;
-        for (Location child : allChildren) {
-            if (count > request.count()) break;
-            if (!found) {
-                // Set to true if we find the child we're looking for ...
-                found = child.equals(request.startingAfter());
-            } else {
-                // Add the child to the block ...
-                ++count;
-                request.addChild(child);
-            }
-        }
-
-        // Set the actual location ...
-        request.setActualLocationOfStartingAfterNode(actualSiblingLocation);
-        setCacheableInfo(request);
-    }
-
-    /**
-     * Process a request to read a branch or subgraph that's below a node at a specified location.
-     * <p>
-     * This method does nothing if the request is null. The default implementation processes the branch by submitting the
-     * equivalent requests to {@link ReadNodeRequest read the nodes} and the {@link ReadAllChildrenRequest children}. It starts by
-     * doing this for the top-level node, then proceeds for each of the children of that node, and so forth.
-     * </p>
-     * 
-     * @param request the request to read the branch
-     */
-    public void process( ReadBranchRequest request ) {
-        if (request == null) return;
-        // Create a queue for locations that need to be read ...
-        Queue<LocationWithDepth> locationsToRead = new LinkedList<LocationWithDepth>();
-        locationsToRead.add(new LocationWithDepth(request.at(), 1));
-
-        // Now read the locations ...
-        boolean first = true;
-        while (locationsToRead.peek() != null) {
-            if (request.isCancelled()) return;
-            LocationWithDepth read = locationsToRead.poll();
-
-            // Check the depth ...
-            if (read.depth > request.maximumDepth()) break;
-
-            // Read the properties ...
-            ReadNodeRequest readNode = new ReadNodeRequest(read.location);
-            process(readNode);
-            if (readNode.hasError()) {
-                request.setError(readNode.getError());
-                return;
-            }
-            Location actualLocation = readNode.getActualLocationOfNode();
-            if (first) {
-                // Set the actual location on the original request
-                request.setActualLocationOfNode(actualLocation);
-                first = false;
-            }
-
-            // Record in the request the children and properties that were read on this node ...
-            request.setChildren(actualLocation, readNode.getChildren());
-            request.setProperties(actualLocation, readNode.getProperties());
-
-            // Add each of the children to the list of locations that we need to read ...
-            for (Location child : readNode.getChildren()) {
-                locationsToRead.add(new LocationWithDepth(child, read.depth + 1));
-            }
-        }
-        setCacheableInfo(request);
-    }
-
-    /**
-     * Process a request to read the properties of a node at the supplied location.
-     * <p>
-     * This method does nothing if the request is null.
-     * </p>
-     * 
-     * @param request the read request
-     */
-    public abstract void process( ReadAllPropertiesRequest request );
-
-    /**
-     * Process a request to read the properties and children of a node at the supplied location.
-     * <p>
-     * This method does nothing if the request is null. Unless overridden, this method converts the single request into a
-     * {@link ReadAllChildrenRequest} and a {@link ReadAllPropertiesRequest}.
-     * </p>
-     * 
-     * @param request the read request
-     */
-    public void process( ReadNodeRequest request ) {
-        if (request == null) return;
-        // Read the properties ...
-        ReadAllPropertiesRequest readProperties = new ReadAllPropertiesRequest(request.at());
-        process(readProperties);
-        if (readProperties.hasError()) {
-            request.setError(readProperties.getError());
-            return;
-        }
-        // Set the actual location ...
-        request.setActualLocationOfNode(readProperties.getActualLocationOfNode());
-
-        // Read the children ...
-        ReadAllChildrenRequest readChildren = new ReadAllChildrenRequest(request.at());
-        process(readChildren);
-        if (readChildren.hasError()) {
-            request.setError(readChildren.getError());
-            return;
-        }
-        if (request.isCancelled()) return;
-        // Now, copy all of the results into the submitted request ...
-        for (Property property : readProperties) {
-            request.addProperty(property);
-        }
-        for (Location child : readChildren) {
-            request.addChild(child);
-        }
-        setCacheableInfo(request);
-    }
-
-    /**
-     * Process a request to read a single property of a node at the supplied location.
-     * <p>
-     * This method does nothing if the request is null. Unless overridden, this method converts the request that
-     * {@link ReadNodeRequest reads the node} and simply returns the one property.
-     * </p>
-     * 
-     * @param request the read request
-     */
-    public void process( ReadPropertyRequest request ) {
-        if (request == null) return;
-        ReadAllPropertiesRequest readNode = new ReadAllPropertiesRequest(request.on());
-        process(readNode);
-        if (readNode.hasError()) {
-            request.setError(readNode.getError());
-            return;
-        }
-        Property property = readNode.getPropertiesByName().get(request.named());
-        request.setProperty(property);
-        // Set the actual location ...
-        request.setActualLocationOfNode(readNode.getActualLocationOfNode());
-        setCacheableInfo(request);
-    }
-
-    /**
-     * Process a request to remove the specified properties from a node.
-     * <p>
-     * This method does nothing if the request is null. Unless overridden, this method converts this request into a
-     * {@link UpdatePropertiesRequest}.
-     * </p>
-     * 
-     * @param request the request to remove the properties with certain names
-     */
-    public void process( RemovePropertiesRequest request ) {
-        if (request == null) return;
-        Collection<Name> names = request.propertyNames();
-        if (names.isEmpty()) return;
-        List<Property> emptyProperties = new ArrayList<Property>(names.size());
-        for (Name propertyName : names) {
-            emptyProperties.add(new BasicEmptyProperty(propertyName));
-        }
-        UpdatePropertiesRequest update = new UpdatePropertiesRequest(request.from(), emptyProperties);
-        process(update);
-        if (update.hasError()) {
-            request.setError(update.getError());
-        }
-        // Set the actual location ...
-        request.setActualLocationOfNode(update.getActualLocationOfNode());
-    }
-
-    /**
-     * Process a request to remove the specified properties from a node.
-     * <p>
-     * This method does nothing if the request is null.
-     * </p>
-     * 
-     * @param request the remove request
-     */
-    public abstract void process( UpdatePropertiesRequest request );
-
-    /**
-     * Process a request to rename a node specified location into a different location.
-     * <p>
-     * This method does nothing if the request is null. Unless overridden, this method converts the rename into a
-     * {@link MoveBranchRequest move}. However, this only works if the <code>request</code> has a {@link Location#hasPath() path}
-     * for its {@link RenameNodeRequest#at() location}. (If not, this method throws an {@link UnsupportedOperationException} and
-     * must be overriddent.)
-     * </p>
-     * 
-     * @param request the rename request
-     */
-    public void process( RenameNodeRequest request ) {
-        if (request == null) return;
-        Location from = request.at();
-        if (!from.hasPath()) {
-            throw new UnsupportedOperationException();
-        }
-        Path newPath = getExecutionContext().getValueFactories().getPathFactory().create(from.getPath(), request.toName());
-        Location to = new Location(newPath);
-        MoveBranchRequest move = new MoveBranchRequest(from, to);
-        process(move);
-        // Set the actual locations ...
-        request.setActualLocations(move.getActualLocationBefore(), move.getActualLocationAfter());
-    }
-
-    /**
-     * Close this processor, allowing it to clean up any open resources.
-     */
-    public void close() {
-        // do nothing
-    }
-
-    /**
-     * A class that represents a location at a known depth
-     * 
-     * @author Randall Hauch
-     */
-    @Immutable
-    protected static class LocationWithDepth {
-        protected final Location location;
-        protected final int depth;
-
-        protected LocationWithDepth( Location location,
-                                     int depth ) {
-            this.location = location;
-            this.depth = depth;
-        }
-
-        @Override
-        public int hashCode() {
-            return location.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return location.toString() + " at depth " + depth;
-        }
-    }
-
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/RequestProcessor.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,585 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request.processor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.cache.CachePolicy;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.ReferentialIntegrityException;
+import org.jboss.dna.graph.property.basic.BasicEmptyProperty;
+import org.jboss.dna.graph.request.CacheableRequest;
+import org.jboss.dna.graph.request.CompositeRequest;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadBranchRequest;
+import org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+import org.jboss.dna.graph.request.ReadPropertyRequest;
+import org.jboss.dna.graph.request.RemovePropertiesRequest;
+import org.jboss.dna.graph.request.RenameNodeRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+
+/**
+ * A component that is used to process and execute {@link Request}s. This class is intended to be subclassed and methods
+ * overwritten to define the behavior for executing the different kinds of requests. Abstract methods must be overridden, but
+ * non-abstract methods all have meaningful default implementations.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public abstract class RequestProcessor {
+
+    private final ExecutionContext context;
+    private final String sourceName;
+    private final DateTime nowInUtc;
+    private final CachePolicy defaultCachePolicy;
+
+    protected RequestProcessor( String sourceName,
+                                ExecutionContext context ) {
+        this(sourceName, context, null, null);
+    }
+
+    protected RequestProcessor( String sourceName,
+                                ExecutionContext context,
+                                DateTime now ) {
+        this(sourceName, context, now, null);
+    }
+
+    protected RequestProcessor( String sourceName,
+                                ExecutionContext context,
+                                DateTime now,
+                                CachePolicy defaultCachePolicy ) {
+        CheckArg.isNotEmpty(sourceName, "sourceName");
+        CheckArg.isNotNull(context, "context");
+        this.context = context;
+        this.sourceName = sourceName;
+        this.nowInUtc = now != null ? now : context.getValueFactories().getDateFactory().createUtc();
+        this.defaultCachePolicy = defaultCachePolicy;
+    }
+
+    /**
+     * Get the name of the source against which this processor is executing.
+     * 
+     * @return the repository source name; never null or empty
+     */
+    public String getSourceName() {
+        return sourceName;
+    }
+
+    /**
+     * The execution context that this process is operating within.
+     * 
+     * @return the execution context; never null
+     */
+    public ExecutionContext getExecutionContext() {
+        return this.context;
+    }
+
+    /**
+     * Get the 'current time' for this processor, which is usually a constant during its lifetime.
+     * 
+     * @return the current time in UTC; never null
+     */
+    protected DateTime getNowInUtc() {
+        return this.nowInUtc;
+    }
+
+    /**
+     * Set the supplied request to have the default cache policy and the {@link #getNowInUtc() current time in UTC}.
+     * 
+     * @param request the cacheable request
+     */
+    protected void setCacheableInfo( CacheableRequest request ) {
+        request.setCachePolicy(defaultCachePolicy);
+        request.setTimeLoaded(nowInUtc);
+    }
+
+    /**
+     * Set the supplied request to have the supplied cache policy and the {@link #getNowInUtc() current time in UTC}.
+     * 
+     * @param request the cacheable request
+     * @param cachePolicy the cache policy for the request; may be null if there is to be no cache policy
+     */
+    protected void setCacheableInfo( CacheableRequest request,
+                                     CachePolicy cachePolicy ) {
+        request.setCachePolicy(cachePolicy);
+        request.setTimeLoaded(nowInUtc);
+    }
+
+    /**
+     * Process a request by determining the type of request and delegating to the appropriate <code>process</code> method for that
+     * type.
+     * <p>
+     * This method does nothing if the request is null.
+     * </p>
+     * 
+     * @param request the general request
+     */
+    public void process( Request request ) {
+        if (request == null) return;
+        if (request.isCancelled()) return;
+        if (request instanceof CompositeRequest) {
+            process((CompositeRequest)request);
+        } else if (request instanceof CopyBranchRequest) {
+            process((CopyBranchRequest)request);
+        } else if (request instanceof CreateNodeRequest) {
+            process((CreateNodeRequest)request);
+        } else if (request instanceof DeleteBranchRequest) {
+            process((DeleteBranchRequest)request);
+        } else if (request instanceof MoveBranchRequest) {
+            process((MoveBranchRequest)request);
+        } else if (request instanceof ReadAllChildrenRequest) {
+            process((ReadAllChildrenRequest)request);
+        } else if (request instanceof ReadNextBlockOfChildrenRequest) {
+            process((ReadNextBlockOfChildrenRequest)request);
+        } else if (request instanceof ReadBlockOfChildrenRequest) {
+            process((ReadBlockOfChildrenRequest)request);
+        } else if (request instanceof ReadBranchRequest) {
+            process((ReadBranchRequest)request);
+        } else if (request instanceof ReadNodeRequest) {
+            process((ReadNodeRequest)request);
+        } else if (request instanceof ReadAllPropertiesRequest) {
+            process((ReadAllPropertiesRequest)request);
+        } else if (request instanceof ReadPropertyRequest) {
+            process((ReadPropertyRequest)request);
+        } else if (request instanceof RemovePropertiesRequest) {
+            process((RemovePropertiesRequest)request);
+        } else if (request instanceof RenameNodeRequest) {
+            process((RenameNodeRequest)request);
+        } else if (request instanceof UpdatePropertiesRequest) {
+            process((UpdatePropertiesRequest)request);
+        }
+    }
+
+    /**
+     * Process a request that is composed of multiple other (non-composite) requests. If any of the embedded requests
+     * {@link Request#hasError() has an error} after it is processed, the submitted request will be marked with an error.
+     * <p>
+     * This method does nothing if the request is null.
+     * </p>
+     * 
+     * @param request the composite request
+     */
+    public void process( CompositeRequest request ) {
+        if (request == null) return;
+        int numberOfErrors = 0;
+        Throwable firstError = null;
+        for (Request embedded : request) {
+            assert embedded != null;
+            if (embedded.isCancelled()) return;
+            process(embedded);
+            if (embedded.hasError()) {
+                if (numberOfErrors == 0) firstError = embedded.getError();
+                ++numberOfErrors;
+            }
+        }
+        if (firstError == null) return;
+        if (numberOfErrors == 1) {
+            request.setError(firstError);
+        } else {
+            String msg = GraphI18n.multipleErrorsWhileExecutingRequests.text(numberOfErrors, request.size());
+            request.setError(new RepositorySourceException(getSourceName(), msg));
+        }
+    }
+
+    /**
+     * Process a request to copy a branch into another location.
+     * <p>
+     * This method does nothing if the request is null.
+     * </p>
+     * 
+     * @param request the copy request
+     */
+    public abstract void process( CopyBranchRequest request );
+
+    /**
+     * Process a request to create a node at a specified location.
+     * <p>
+     * This method does nothing if the request is null.
+     * </p>
+     * 
+     * @param request the create request
+     */
+    public abstract void process( CreateNodeRequest request );
+
+    /**
+     * Process a request to delete a branch at a specified location.
+     * <p>
+     * This method does nothing if the request is null.
+     * </p>
+     * 
+     * @param request the delete request
+     * @throws ReferentialIntegrityException if the delete could not be performed because some references to deleted nodes would
+     *         have remained after the delete operation completed
+     */
+    public abstract void process( DeleteBranchRequest request );
+
+    /**
+     * Process a request to move a branch at a specified location into a different location.
+     * <p>
+     * This method does nothing if the request is null.
+     * </p>
+     * 
+     * @param request the move request
+     */
+    public abstract void process( MoveBranchRequest request );
+
+    /**
+     * Process a request to read all of the children of a node.
+     * <p>
+     * This method does nothing if the request is null.
+     * </p>
+     * 
+     * @param request the read request
+     */
+    public abstract void process( ReadAllChildrenRequest request );
+
+    /**
+     * Process a request to read a block of the children of a node. The block is defined by a
+     * {@link ReadBlockOfChildrenRequest#startingAtIndex() starting index} and a {@link ReadBlockOfChildrenRequest#count() maximum
+     * number of children to include in the block}.
+     * <p>
+     * This method does nothing if the request is null. The default implementation converts the command to a
+     * {@link ReadAllChildrenRequest}, and then finds the children within the block. Obviously for large numbers of children, this
+     * implementation may not be efficient and may need to be overridden.
+     * </p>
+     * 
+     * @param request the read request
+     */
+    public void process( ReadBlockOfChildrenRequest request ) {
+        if (request == null) return;
+        // Convert the request to a ReadAllChildrenRequest and execute it ...
+        ReadAllChildrenRequest readAll = new ReadAllChildrenRequest(request.of());
+        process(readAll);
+        if (readAll.hasError()) {
+            request.setError(readAll.getError());
+            return;
+        }
+        List<Location> allChildren = readAll.getChildren();
+
+        // If there aren't enough children for the block's range ...
+        if (allChildren.size() < request.startingAtIndex()) return;
+
+        // Now, find the children in the block ...
+        int endIndex = Math.min(request.endingBefore(), allChildren.size());
+        for (int i = request.startingAtIndex(); i != endIndex; ++i) {
+            request.addChild(allChildren.get(i));
+        }
+        // Set the actual location ...
+        request.setActualLocationOfNode(readAll.getActualLocationOfNode());
+        setCacheableInfo(request);
+    }
+
+    /**
+     * Process a request to read the next block of the children of a node, starting after a previously-retrieved child.
+     * <p>
+     * This method does nothing if the request is null. The default implementation converts the command to a
+     * {@link ReadAllChildrenRequest}, and then finds the children within the block. Obviously for large numbers of children, this
+     * implementation may not be efficient and may need to be overridden.
+     * </p>
+     * 
+     * @param request the read request
+     */
+    public void process( ReadNextBlockOfChildrenRequest request ) {
+        if (request == null) return;
+
+        // Get the parent path ...
+        Path path = request.startingAfter().getPath();
+        Location actualSiblingLocation = request.startingAfter();
+        Path parentPath = null;
+        if (path != null) parentPath = path.getParent();
+        if (parentPath == null) {
+            ReadAllPropertiesRequest readPropertiesOfSibling = new ReadAllPropertiesRequest(request.startingAfter());
+            process(readPropertiesOfSibling);
+            actualSiblingLocation = readPropertiesOfSibling.getActualLocationOfNode();
+            parentPath = actualSiblingLocation.getPath().getParent();
+        }
+        assert parentPath != null;
+
+        // Convert the request to a ReadAllChildrenRequest and execute it ...
+        ReadAllChildrenRequest readAll = new ReadAllChildrenRequest(new Location(parentPath));
+        process(readAll);
+        if (readAll.hasError()) {
+            request.setError(readAll.getError());
+            return;
+        }
+        List<Location> allChildren = readAll.getChildren();
+
+        // Iterate through the children, looking for the 'startingAfter' child ...
+        boolean found = false;
+        int count = 0;
+        for (Location child : allChildren) {
+            if (count > request.count()) break;
+            if (!found) {
+                // Set to true if we find the child we're looking for ...
+                found = child.equals(request.startingAfter());
+            } else {
+                // Add the child to the block ...
+                ++count;
+                request.addChild(child);
+            }
+        }
+
+        // Set the actual location ...
+        request.setActualLocationOfStartingAfterNode(actualSiblingLocation);
+        setCacheableInfo(request);
+    }
+
+    /**
+     * Process a request to read a branch or subgraph that's below a node at a specified location.
+     * <p>
+     * This method does nothing if the request is null. The default implementation processes the branch by submitting the
+     * equivalent requests to {@link ReadNodeRequest read the nodes} and the {@link ReadAllChildrenRequest children}. It starts by
+     * doing this for the top-level node, then proceeds for each of the children of that node, and so forth.
+     * </p>
+     * 
+     * @param request the request to read the branch
+     */
+    public void process( ReadBranchRequest request ) {
+        if (request == null) return;
+        // Create a queue for locations that need to be read ...
+        Queue<LocationWithDepth> locationsToRead = new LinkedList<LocationWithDepth>();
+        locationsToRead.add(new LocationWithDepth(request.at(), 1));
+
+        // Now read the locations ...
+        boolean first = true;
+        while (locationsToRead.peek() != null) {
+            if (request.isCancelled()) return;
+            LocationWithDepth read = locationsToRead.poll();
+
+            // Check the depth ...
+            if (read.depth > request.maximumDepth()) break;
+
+            // Read the properties ...
+            ReadNodeRequest readNode = new ReadNodeRequest(read.location);
+            process(readNode);
+            if (readNode.hasError()) {
+                request.setError(readNode.getError());
+                return;
+            }
+            Location actualLocation = readNode.getActualLocationOfNode();
+            if (first) {
+                // Set the actual location on the original request
+                request.setActualLocationOfNode(actualLocation);
+                first = false;
+            }
+
+            // Record in the request the children and properties that were read on this node ...
+            request.setChildren(actualLocation, readNode.getChildren());
+            request.setProperties(actualLocation, readNode.getProperties());
+
+            // Add each of the children to the list of locations that we need to read ...
+            for (Location child : readNode.getChildren()) {
+                locationsToRead.add(new LocationWithDepth(child, read.depth + 1));
+            }
+        }
+        setCacheableInfo(request);
+    }
+
+    /**
+     * Process a request to read the properties of a node at the supplied location.
+     * <p>
+     * This method does nothing if the request is null.
+     * </p>
+     * 
+     * @param request the read request
+     */
+    public abstract void process( ReadAllPropertiesRequest request );
+
+    /**
+     * Process a request to read the properties and children of a node at the supplied location.
+     * <p>
+     * This method does nothing if the request is null. Unless overridden, this method converts the single request into a
+     * {@link ReadAllChildrenRequest} and a {@link ReadAllPropertiesRequest}.
+     * </p>
+     * 
+     * @param request the read request
+     */
+    public void process( ReadNodeRequest request ) {
+        if (request == null) return;
+        // Read the properties ...
+        ReadAllPropertiesRequest readProperties = new ReadAllPropertiesRequest(request.at());
+        process(readProperties);
+        if (readProperties.hasError()) {
+            request.setError(readProperties.getError());
+            return;
+        }
+        // Set the actual location ...
+        request.setActualLocationOfNode(readProperties.getActualLocationOfNode());
+
+        // Read the children ...
+        ReadAllChildrenRequest readChildren = new ReadAllChildrenRequest(request.at());
+        process(readChildren);
+        if (readChildren.hasError()) {
+            request.setError(readChildren.getError());
+            return;
+        }
+        if (request.isCancelled()) return;
+        // Now, copy all of the results into the submitted request ...
+        for (Property property : readProperties) {
+            request.addProperty(property);
+        }
+        for (Location child : readChildren) {
+            request.addChild(child);
+        }
+        setCacheableInfo(request);
+    }
+
+    /**
+     * Process a request to read a single property of a node at the supplied location.
+     * <p>
+     * This method does nothing if the request is null. Unless overridden, this method converts the request that
+     * {@link ReadNodeRequest reads the node} and simply returns the one property.
+     * </p>
+     * 
+     * @param request the read request
+     */
+    public void process( ReadPropertyRequest request ) {
+        if (request == null) return;
+        ReadAllPropertiesRequest readNode = new ReadAllPropertiesRequest(request.on());
+        process(readNode);
+        if (readNode.hasError()) {
+            request.setError(readNode.getError());
+            return;
+        }
+        Property property = readNode.getPropertiesByName().get(request.named());
+        request.setProperty(property);
+        // Set the actual location ...
+        request.setActualLocationOfNode(readNode.getActualLocationOfNode());
+        setCacheableInfo(request);
+    }
+
+    /**
+     * Process a request to remove the specified properties from a node.
+     * <p>
+     * This method does nothing if the request is null. Unless overridden, this method converts this request into a
+     * {@link UpdatePropertiesRequest}.
+     * </p>
+     * 
+     * @param request the request to remove the properties with certain names
+     */
+    public void process( RemovePropertiesRequest request ) {
+        if (request == null) return;
+        Collection<Name> names = request.propertyNames();
+        if (names.isEmpty()) return;
+        List<Property> emptyProperties = new ArrayList<Property>(names.size());
+        for (Name propertyName : names) {
+            emptyProperties.add(new BasicEmptyProperty(propertyName));
+        }
+        UpdatePropertiesRequest update = new UpdatePropertiesRequest(request.from(), emptyProperties);
+        process(update);
+        if (update.hasError()) {
+            request.setError(update.getError());
+        }
+        // Set the actual location ...
+        request.setActualLocationOfNode(update.getActualLocationOfNode());
+    }
+
+    /**
+     * Process a request to remove the specified properties from a node.
+     * <p>
+     * This method does nothing if the request is null.
+     * </p>
+     * 
+     * @param request the remove request
+     */
+    public abstract void process( UpdatePropertiesRequest request );
+
+    /**
+     * Process a request to rename a node specified location into a different location.
+     * <p>
+     * This method does nothing if the request is null. Unless overridden, this method converts the rename into a
+     * {@link MoveBranchRequest move}. However, this only works if the <code>request</code> has a {@link Location#hasPath() path}
+     * for its {@link RenameNodeRequest#at() location}. (If not, this method throws an {@link UnsupportedOperationException} and
+     * must be overriddent.)
+     * </p>
+     * 
+     * @param request the rename request
+     */
+    public void process( RenameNodeRequest request ) {
+        if (request == null) return;
+        Location from = request.at();
+        if (!from.hasPath()) {
+            throw new UnsupportedOperationException();
+        }
+        Path newPath = getExecutionContext().getValueFactories().getPathFactory().create(from.getPath(), request.toName());
+        Location to = new Location(newPath);
+        MoveBranchRequest move = new MoveBranchRequest(from, to);
+        process(move);
+        // Set the actual locations ...
+        request.setActualLocations(move.getActualLocationBefore(), move.getActualLocationAfter());
+    }
+
+    /**
+     * Close this processor, allowing it to clean up any open resources.
+     */
+    public void close() {
+        // do nothing
+    }
+
+    /**
+     * A class that represents a location at a known depth
+     * 
+     * @author Randall Hauch
+     */
+    @Immutable
+    protected static class LocationWithDepth {
+        protected final Location location;
+        protected final int depth;
+
+        protected LocationWithDepth( Location location,
+                                     int depth ) {
+            this.location = location;
+            this.depth = depth;
+        }
+
+        @Override
+        public int hashCode() {
+            return location.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return location.toString() + " at depth " + depth;
+        }
+    }
+
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/package-info.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/package-info.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,30 +0,0 @@
-/**
- * This portion of the JBoss DNA Graph API defines the {@link RequestProcessor processor} for {@link org.jboss.dna.graph.requests.Request requests}.
- * Simple enough, it defines methods that handle the processing of each kind of request
- * (for example, {@link RequestProcessor#process(org.jboss.dna.graph.requests.ReadNodeRequest)}).
- * Usually, an implementation will inherit default implementations for some of these methods, but will override
- * others (or provide implementations for the abstract methods).
- * <p>
- * The design of the processor is to have a separate <code>process(...)</code> methods that take as their only parameter
- * a particular kind of {@link org.jboss.dna.graph.requests.Request}.  Since the code to process each kind of request
- * is likely to be different, this helps to separate all the different processing code.
- * </p>
- * <p>The design also makes it possible to easily inherit or override <code>process(...)</code> implementations.
- * In fact, the {@link RequestProcessor} abstract class provides a number of default implementations that are
- * pretty good.  Sure, the default implementations may not the fastest, but it allows you to implement the minimum
- * number of methods and have a complete processor.  And should you find that the performance is not good enough
- * (which you'll verify by actually measuring performance, right?), then simply override the method in question
- * with an implementation that is more efficient.  In other words, start simple and add complexity only when needed.
- * </p>
- * <p>
- * This design has a great benefit, though: backward compability.  Let's imagine that you're using a particular release
- * of JBoss DNA, and have written a {@link org.jboss.dna.graph.connectors.RepositoryConnection connector} that uses
- * your own {@link RequestProcessor} subclass.  The next release of JBoss DNA might include additional request types
- * and provide default implementations for the corresponding <code>process(NewRequestType)</code> method, and your 
- * {@link RequestProcessor} subclass (written against an earlier release) will automatically work with the next release.
- * Plus, your connector will inherit the new functionality with zero effort on your part.
- * </p>
- */
-
-package org.jboss.dna.graph.requests.processor;
-

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/package-info.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/package-info.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/package-info.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,30 @@
+/**
+ * This portion of the JBoss DNA Graph API defines the {@link RequestProcessor processor} for {@link org.jboss.dna.graph.request.Request requests}.
+ * Simple enough, it defines methods that handle the processing of each kind of request
+ * (for example, {@link RequestProcessor#process(org.jboss.dna.graph.request.ReadNodeRequest)}).
+ * Usually, an implementation will inherit default implementations for some of these methods, but will override
+ * others (or provide implementations for the abstract methods).
+ * <p>
+ * The design of the processor is to have a separate <code>process(...)</code> methods that take as their only parameter
+ * a particular kind of {@link org.jboss.dna.graph.request.Request}.  Since the code to process each kind of request
+ * is likely to be different, this helps to separate all the different processing code.
+ * </p>
+ * <p>The design also makes it possible to easily inherit or override <code>process(...)</code> implementations.
+ * In fact, the {@link RequestProcessor} abstract class provides a number of default implementations that are
+ * pretty good.  Sure, the default implementations may not the fastest, but it allows you to implement the minimum
+ * number of methods and have a complete processor.  And should you find that the performance is not good enough
+ * (which you'll verify by actually measuring performance, right?), then simply override the method in question
+ * with an implementation that is more efficient.  In other words, start simple and add complexity only when needed.
+ * </p>
+ * <p>
+ * This design has a great benefit, though: backward compability.  Let's imagine that you're using a particular release
+ * of JBoss DNA, and have written a {@link org.jboss.dna.graph.connector.RepositoryConnection connector} that uses
+ * your own {@link RequestProcessor} subclass.  The next release of JBoss DNA might include additional request types
+ * and provide default implementations for the corresponding <code>process(NewRequestType)</code> method, and your 
+ * {@link RequestProcessor} subclass (written against an earlier release) will automatically work with the next release.
+ * Plus, your connector will inherit the new functionality with zero effort on your part.
+ * </p>
+ */
+
+package org.jboss.dna.graph.request.processor;
+

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CacheableRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CacheableRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CacheableRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,75 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.cache.Cacheable;
-import org.jboss.dna.graph.properties.DateTime;
-
-/**
- * A request that contains results that may be cached.
- * 
- * @author Randall Hauch
- */
- at ThreadSafe
-public abstract class CacheableRequest extends Request implements Cacheable {
-
-    private static final long serialVersionUID = 1L;
-
-    private CachePolicy policy;
-    private DateTime timeLoaded;
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.cache.Cacheable#getCachePolicy()
-     */
-    public CachePolicy getCachePolicy() {
-        return policy;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.cache.Cacheable#getTimeLoaded()
-     */
-    public DateTime getTimeLoaded() {
-        return timeLoaded;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.cache.Cacheable#setCachePolicy(org.jboss.dna.graph.cache.CachePolicy)
-     */
-    public void setCachePolicy( CachePolicy cachePolicy ) {
-        policy = cachePolicy;
-    }
-
-    /**
-     * @param timeLoaded Sets timeLoaded to the specified value.
-     */
-    public void setTimeLoaded( DateTime timeLoaded ) {
-        this.timeLoaded = timeLoaded;
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CompositeRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CompositeRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CompositeRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,271 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.jboss.dna.common.util.CheckArg;
-
-/**
- * A request that wraps multiple other requests, allowing multiple requests to be treated as a single request.
- * <p>
- * Note that {@link #isCancelled()} and {@link #cancel()} apply to all requests contained by the composite request. In other
- * words, cancelling this request immediately marks all contained requests as cancelled. However, cancelling any request in the
- * request has the effect of cancelling all other requests in the composite, including the composite. (This is implemented by
- * having all {@link Request} objects in the composite share the same cancelled flag object.)
- * </p>
- * 
- * @author Randall Hauch
- */
-public class CompositeRequest extends Request implements Iterable<Request> {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Return a request that either wraps multiple requests, or the single request if only one is supplied.
-     * 
-     * @param requests the requests to wrap
-     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request
-     * @throws IllegalArgumentException if there requests are null, empty, or contains only nulls
-     */
-    public static Request with( Request... requests ) {
-        CheckArg.isNotEmpty(requests, "requests");
-        if (requests.length == 1) {
-            CheckArg.isNotNull(requests[0], "requests[0]");
-            return requests[0];
-        }
-        boolean readOnly = true;
-        List<Request> list = new ArrayList<Request>(requests.length);
-        for (Request request : requests) {
-            if (request == null) continue;
-            if (request instanceof CompositeRequest) {
-                CompositeRequest composite = (CompositeRequest)request;
-                list.addAll(composite.getRequests());
-                if (!composite.isReadOnly()) readOnly = false;
-            } else {
-                list.add(request);
-                if (!request.isReadOnly()) readOnly = false;
-            }
-        }
-        CheckArg.isNotEmpty(list, "requests");
-        return new CompositeRequest(list, readOnly);
-    }
-
-    /**
-     * Return a request that either wraps multiple requests, or the single request if only one is supplied.
-     * 
-     * @param requests the requests to wrap
-     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request
-     * @throws IllegalArgumentException if there requests are null, empty, or contains only nulls
-     */
-    public static Request with( Iterator<? extends Request> requests ) {
-        CheckArg.isNotNull(requests, "requests");
-        boolean readOnly = true;
-        List<Request> list = new LinkedList<Request>();
-        while (requests.hasNext()) {
-            Request request = requests.next();
-            if (request == null) continue;
-            if (request instanceof CompositeRequest) {
-                CompositeRequest composite = (CompositeRequest)request;
-                list.addAll(composite.getRequests());
-                if (!composite.isReadOnly()) readOnly = false;
-            } else {
-                list.add(request);
-                if (!request.isReadOnly()) readOnly = false;
-            }
-        }
-        if (list.size() == 1) {
-            return list.get(0);
-        }
-        CheckArg.isNotEmpty(list, "requests");
-        return new CompositeRequest(list, readOnly);
-    }
-
-    /**
-     * Return a request that either wraps multiple requests, or the single request if only one is supplied.
-     * 
-     * @param requests the requests to wrap
-     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request
-     * @throws IllegalArgumentException if there requests are null or empty
-     */
-    public static Request with( List<? extends Request> requests ) {
-        CheckArg.isNotEmpty(requests, "requests");
-        if (requests.size() == 1) {
-            return requests.get(0);
-        }
-        boolean readOnly = true;
-        for (Request request : requests) {
-            if (request.isReadOnly()) continue;
-            readOnly = false;
-            break;
-        }
-        return new CompositeRequest(requests, readOnly);
-    }
-
-    /**
-     * Add requests to the supplied composite request.
-     * 
-     * @param composite the composite request to which the requests are to be added
-     * @param requests the requests to wrap
-     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request, or null if
-     *         there are no request
-     * @throws IllegalArgumentException if the composite request is null
-     */
-    public static CompositeRequest add( CompositeRequest composite,
-                                        Request... requests ) {
-        CheckArg.isNotNull(composite, "composite");
-        if (requests == null || requests.length == 0) return composite;
-        List<Request> list = new ArrayList<Request>(requests.length + composite.size());
-        boolean readOnly = composite.isReadOnly();
-        if (composite.size() != 0) list.addAll(composite.getRequests());
-        for (Request request : requests) {
-            if (request == null) continue;
-            if (request instanceof CompositeRequest) {
-                CompositeRequest compositeRequest = (CompositeRequest)request;
-                list.addAll(compositeRequest.getRequests());
-                if (!compositeRequest.isReadOnly()) readOnly = false;
-            } else {
-                list.add(request);
-                if (!request.isReadOnly()) readOnly = false;
-            }
-        }
-        return new CompositeRequest(list, readOnly);
-    }
-
-    /**
-     * Add requests to the supplied composite request.
-     * 
-     * @param composite the composite request to which the requests are to be added
-     * @param requests the requests to wrap
-     * @return the requests wrapped in a CompositeRequest, or if only one request is supplied that single request, or null if
-     *         there are no request
-     * @throws IllegalArgumentException if the composite request is null
-     */
-    public static CompositeRequest add( CompositeRequest composite,
-                                        Iterator<? extends Request> requests ) {
-        CheckArg.isNotNull(composite, "composite");
-        List<Request> list = new LinkedList<Request>();
-        boolean readOnly = composite.isReadOnly();
-        if (composite.size() != 0) list.addAll(composite.getRequests());
-        while (requests.hasNext()) {
-            Request request = requests.next();
-            if (request == null) continue;
-            if (request instanceof CompositeRequest) {
-                CompositeRequest compositeRequest = (CompositeRequest)request;
-                list.addAll(compositeRequest.getRequests());
-                if (!compositeRequest.isReadOnly()) readOnly = false;
-            } else {
-                list.add(request);
-                if (!request.isReadOnly()) readOnly = false;
-            }
-        }
-        return new CompositeRequest(list, readOnly);
-    }
-
-    private final List<Request> requests;
-    private final boolean readOnly;
-
-    /**
-     * Create a composite request from the supplied list of requests.
-     * 
-     * @param requests the modifiable list of requests; may not be null
-     * @param readOnly true if all of the requests are {@link Request#isReadOnly() read-only}
-     */
-    /*package*/CompositeRequest( List<? extends Request> requests,
-                                  boolean readOnly ) {
-        // Iterate through the requests and set the cancelled flag of each request to this object's flag ...
-        final AtomicBoolean flag = super.getCancelledFlag();
-        for (Request request : requests) {
-            request.setCancelledFlag(flag);
-        }
-        this.requests = Collections.unmodifiableList(requests);
-        this.readOnly = readOnly;
-    }
-
-    /**
-     * Return the unmodifiable requests contained in this composite request.
-     * 
-     * @return requests
-     */
-    public List<Request> getRequests() {
-        return requests;
-    }
-
-    /**
-     * Get the number of requests.
-     * 
-     * @return the number of requests
-     */
-    public int size() {
-        return requests.size();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Iterable#iterator()
-     */
-    public Iterator<Request> iterator() {
-        return requests.iterator();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return readOnly;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj instanceof CompositeRequest) {
-            CompositeRequest that = (CompositeRequest)obj;
-            if (this.size() != that.size()) return false;
-            Iterator<Request> thisIter = this.iterator();
-            Iterator<Request> thatIter = that.iterator();
-            while (thisIter.hasNext()) {
-                Request thisRequest = thisIter.next();
-                Request thatRequest = thatIter.next();
-                if (thisRequest == null) {
-                    if (thatRequest != null) return false;
-                } else {
-                    if (!thisRequest.equals(thatRequest)) return false;
-                }
-            }
-            return true;
-        }
-        return false;
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CopyBranchRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CopyBranchRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CopyBranchRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,192 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.NodeConflictBehavior;
-
-/**
- * Instruction that a branch be copied from one location into another.
- * 
- * @author Randall Hauch
- */
-public class CopyBranchRequest extends Request {
-
-    private static final long serialVersionUID = 1L;
-
-    public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR = NodeConflictBehavior.APPEND;
-
-    private final Location from;
-    private final Location into;
-    private final NodeConflictBehavior conflictBehavior;
-    private Location actualOldLocation;
-    private Location actualNewLocation;
-
-    /**
-     * Create a request to copy a branch to another.
-     * 
-     * @param from the location of the top node in the existing branch that is to be copied
-     * @param into the location of the existing node into which the copy should be placed
-     * @throws IllegalArgumentException if <code>from</code> or <code>into</code> are null
-     */
-    public CopyBranchRequest( Location from,
-                              Location into ) {
-        this(from, into, DEFAULT_CONFLICT_BEHAVIOR);
-    }
-
-    /**
-     * Create a request to copy a branch to another.
-     * 
-     * @param from the location of the top node in the existing branch that is to be copied
-     * @param into the location of the existing node into which the copy should be placed
-     * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code>
-     *        location
-     * @throws IllegalArgumentException if any of the parameters are null
-     */
-    public CopyBranchRequest( Location from,
-                              Location into,
-                              NodeConflictBehavior conflictBehavior ) {
-        CheckArg.isNotNull(from, "from");
-        CheckArg.isNotNull(into, "into");
-        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
-        this.from = from;
-        this.into = into;
-        this.conflictBehavior = conflictBehavior;
-    }
-
-    /**
-     * Get the location defining the top of the branch to be copied
-     * 
-     * @return the from location; never null
-     */
-    public Location from() {
-        return from;
-    }
-
-    /**
-     * Get the location defining the parent where the new copy is to be placed
-     * 
-     * @return the to location; never null
-     */
-    public Location into() {
-        return into;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return false;
-    }
-
-    /**
-     * Get the expected behavior when copying the branch and the {@link #into() destination} already has a node with the same
-     * name.
-     * 
-     * @return the behavior specification
-     */
-    public NodeConflictBehavior conflictBehavior() {
-        return conflictBehavior;
-    }
-
-    /**
-     * Sets the actual and complete location of the node being renamed and its new location. This method must be called when
-     * processing the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param oldLocation the actual location of the node before being renamed
-     * @param newLocation the actual location of the new copy of the node
-     * @throws IllegalArgumentException if the either location is null, if the old location does not represent the
-     *         {@link Location#isSame(Location) same location} as the {@link #from() from location}, if the new location does not
-     *         represent the {@link Location#isSame(Location) same location} as the {@link #into() into location}, or if the
-     *         either location does not have a path
-     */
-    public void setActualLocations( Location oldLocation,
-                                    Location newLocation ) {
-        if (!from.isSame(oldLocation)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(oldLocation, from));
-        }
-        CheckArg.isNotNull(newLocation, "newLocation");
-        assert oldLocation != null;
-        assert newLocation != null;
-        if (!oldLocation.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualOldLocationMustHavePath.text(oldLocation));
-        }
-        if (!newLocation.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualNewLocationMustHavePath.text(newLocation));
-        }
-        // The 'into' should be the parent of the 'newLocation' ...
-        if (into.hasPath() && !newLocation.getPath().getParent().equals(into.getPath())) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotChildOfInputLocation.text(newLocation, into));
-        }
-        this.actualNewLocation = newLocation;
-    }
-
-    /**
-     * Get the actual location of the node before being copied.
-     * 
-     * @return the actual location of the node before being moved, or null if the actual location was not set
-     */
-    public Location getActualLocationBefore() {
-        return actualOldLocation;
-    }
-
-    /**
-     * Get the actual location of the node after being copied.
-     * 
-     * @return the actual location of the node after being moved, or null if the actual location was not set
-     */
-    public Location getActualLocationAfter() {
-        return actualNewLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            CopyBranchRequest that = (CopyBranchRequest)obj;
-            if (!this.from().equals(that.from())) return false;
-            if (!this.into().equals(that.into())) return false;
-            if (!this.conflictBehavior().equals(that.conflictBehavior())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "copy branch " + from() + " into " + into();
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,316 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (under your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.NodeConflictBehavior;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * Instruction to create the node under the specified location. This command will create the node and set the initial properties.
- * 
- * @author Randall Hauch
- */
-public class CreateNodeRequest extends Request implements Iterable<Property> {
-
-    private static final long serialVersionUID = 1L;
-
-    public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR = NodeConflictBehavior.APPEND;
-
-    private final Location under;
-    private final Name childName;
-    private final List<Property> properties;
-    private final NodeConflictBehavior conflictBehavior;
-    private Location actualLocation;
-
-    /**
-     * Create a request to create a node with the given properties under the supplied location.
-     * 
-     * @param parentLocation the location of the existing parent node, under which the new child should be created
-     * @param childName the name of the new child to create under the existing parent
-     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
-     *        properties} for the new node
-     * @throws IllegalArgumentException if the location or the child name is null
-     */
-    public CreateNodeRequest( Location parentLocation,
-                              Name childName,
-                              Property... properties ) {
-        this(parentLocation, childName, DEFAULT_CONFLICT_BEHAVIOR, properties);
-    }
-
-    /**
-     * Create a request to create a node with the given properties under the supplied location.
-     * 
-     * @param parentLocation the location of the existing parent node, under which the new child should be created
-     * @param childName the name of the new child to create under the existing parent
-     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
-     *        properties} for the new node
-     * @throws IllegalArgumentException if the location or the child name is null
-     */
-    public CreateNodeRequest( Location parentLocation,
-                              Name childName,
-                              Iterable<Property> properties ) {
-        this(parentLocation, childName, DEFAULT_CONFLICT_BEHAVIOR, properties);
-    }
-
-    /**
-     * Create a request to create a node with the given properties under the supplied location.
-     * 
-     * @param parentLocation the location of the existing parent node, under which the new child should be created
-     * @param childName the name of the new child to create under the existing parent
-     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
-     *        properties} for the new node
-     * @throws IllegalArgumentException if the location or the child name is null
-     */
-    public CreateNodeRequest( Location parentLocation,
-                              Name childName,
-                              Iterator<Property> properties ) {
-        this(parentLocation, childName, DEFAULT_CONFLICT_BEHAVIOR, properties);
-    }
-
-    /**
-     * Create a request to create a node with the given properties under the supplied location.
-     * 
-     * @param parentLocation the location of the existing parent node, under which the new child should be created
-     * @param childName the name of the new child to create under the existing parent
-     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
-     *        properties} for the new node
-     * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
-     *        location
-     * @throws IllegalArgumentException if the location, the child name, or the conflict behavior is null
-     */
-    public CreateNodeRequest( Location parentLocation,
-                              Name childName,
-                              NodeConflictBehavior conflictBehavior,
-                              Property... properties ) {
-        CheckArg.isNotNull(parentLocation, "parentLocation");
-        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
-        CheckArg.isNotNull(childName, "childName");
-        this.under = parentLocation;
-        this.childName = childName;
-        this.conflictBehavior = conflictBehavior;
-        int number = properties.length + (under.hasIdProperties() ? under.getIdProperties().size() : 0);
-        List<Property> props = new ArrayList<Property>(number);
-        for (Property property : properties) {
-            if (property != null) props.add(property);
-        }
-        this.properties = Collections.unmodifiableList(props);
-    }
-
-    /**
-     * Create a request to create a node with the given properties under the supplied location.
-     * 
-     * @param parentLocation the location of the existing parent node, under which the new child should be created
-     * @param childName the name of the new child to create under the existing parent
-     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
-     *        properties} for the new node
-     * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
-     *        location
-     * @throws IllegalArgumentException if the location, the child name, or the conflict behavior is null
-     */
-    public CreateNodeRequest( Location parentLocation,
-                              Name childName,
-                              NodeConflictBehavior conflictBehavior,
-                              Iterable<Property> properties ) {
-        CheckArg.isNotNull(parentLocation, "parentLocation");
-        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
-        CheckArg.isNotNull(childName, "childName");
-        this.under = parentLocation;
-        this.childName = childName;
-        this.conflictBehavior = conflictBehavior;
-        List<Property> props = new LinkedList<Property>();
-        for (Property property : properties) {
-            if (property != null) props.add(property);
-        }
-        // Add in the location properties ...
-        if (under.hasIdProperties()) {
-            for (Property property : under.getIdProperties()) {
-                if (property != null) props.add(property);
-            }
-        }
-        this.properties = Collections.unmodifiableList(props);
-    }
-
-    /**
-     * Create a request to create a node with the given properties under the supplied location.
-     * 
-     * @param parentLocation the location of the existing parent node, under which the new child should be created
-     * @param childName the name of the new child to create under the existing parent
-     * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
-     *        properties} for the new node
-     * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
-     *        location
-     * @throws IllegalArgumentException if the location, the child name, or the conflict behavior is null
-     */
-    public CreateNodeRequest( Location parentLocation,
-                              Name childName,
-                              NodeConflictBehavior conflictBehavior,
-                              Iterator<Property> properties ) {
-        CheckArg.isNotNull(parentLocation, "parentLocation");
-        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
-        CheckArg.isNotNull(childName, "childName");
-        this.under = parentLocation;
-        this.childName = childName;
-        this.conflictBehavior = conflictBehavior;
-        List<Property> props = new LinkedList<Property>();
-        while (properties.hasNext()) {
-            Property property = properties.next();
-            if (property != null) props.add(property);
-        }
-        // Add in the location properties ...
-        if (under.hasIdProperties()) {
-            for (Property property : under.getIdProperties()) {
-                if (property != null) props.add(property);
-            }
-        }
-        this.properties = Collections.unmodifiableList(props);
-    }
-
-    /**
-     * Get the location defining the parent of the new node that is to be created.
-     * 
-     * @return the location of the parent node; never null
-     */
-    public Location under() {
-        return under;
-    }
-
-    /**
-     * Get the name for the new child.
-     * 
-     * @return the child's name; never null
-     */
-    public Name named() {
-        return childName;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Iterable#iterator()
-     */
-    public Iterator<Property> iterator() {
-        return this.properties.iterator();
-    }
-
-    /**
-     * Get the properties for the node. If the node's {@link #under() location} has identification properties, the resulting
-     * properties will include the {@link Location#getIdProperties() identification properties}.
-     * 
-     * @return the collection of properties; never null
-     */
-    public Collection<Property> properties() {
-        return properties;
-    }
-
-    /**
-     * Get the expected behavior when copying the branch and the {@link #under() destination} already has a node with the same
-     * name.
-     * 
-     * @return the behavior specification
-     */
-    public NodeConflictBehavior conflictBehavior() {
-        return conflictBehavior;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return false;
-    }
-
-    /**
-     * Sets the actual and complete location of the node being created. This method must be called when processing the request,
-     * and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being created, or null if the {@link #under() current location} should be
-     *        used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #under() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        CheckArg.isNotNull(actual, "actual");
-        if (!under.isSame(actual, false)) { // not same if actual is null
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        assert actual.hasPath();
-        if (under.hasPath() && !under.getPath().equals(actual.getPath().getParent())) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, under));
-        }
-        this.actualLocation = actual;
-    }
-
-    /**
-     * Get the actual location of the node that was created.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            CreateNodeRequest that = (CreateNodeRequest)obj;
-            if (!this.under().equals(that.under())) return false;
-            if (!this.conflictBehavior().equals(that.conflictBehavior())) return false;
-            if (!this.properties().equals(that.properties())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        String parent = under() + "/";
-        if (under.hasPath() && under.getPath().isRoot()) parent = "/";
-        return "create node \"" + parent + childName + "\" with properties " + properties();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/DeleteBranchRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/DeleteBranchRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/DeleteBranchRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,122 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-
-/**
- * Instruction that a branch be deleted.
- * 
- * @author Randall Hauch
- */
-public class DeleteBranchRequest extends Request {
-
-    private static final long serialVersionUID = 1L;
-
-    private final Location at;
-    private Location actualLocation;
-
-    /**
-     * Create a request to delete a branch.
-     * 
-     * @param at the location of the top node in the existing branch that is to be deleted
-     * @throws IllegalArgumentException if the location is null
-     */
-    public DeleteBranchRequest( Location at ) {
-        CheckArg.isNotNull(at, "at");
-        this.at = at;
-    }
-
-    /**
-     * Get the location defining the top of the branch to be deleted
-     * 
-     * @return the location of the branch; never null
-     */
-    public Location at() {
-        return at;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return false;
-    }
-
-    /**
-     * Sets the actual and complete location of the node being deleted. This method must be called when processing the request,
-     * and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being deleted, or null if the {@link #at() current location} should be used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #at() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        if (!at.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualLocation = actual;
-    }
-
-    /**
-     * Get the actual location of the node that was deleted.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            DeleteBranchRequest that = (DeleteBranchRequest)obj;
-            if (!this.at().equals(that.at())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "delete branch " + at();
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/InvalidRequestException.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/InvalidRequestException.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/InvalidRequestException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,67 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-/**
- * Specifies that the request was invalid and could not be completed.
- * 
- * @author Randall Hauch
- */
-public class InvalidRequestException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 
-     */
-    public InvalidRequestException() {
-    }
-
-    /**
-     * @param message
-     */
-    public InvalidRequestException( String message ) {
-        super(message);
-
-    }
-
-    /**
-     * @param cause
-     */
-    public InvalidRequestException( Throwable cause ) {
-        super(cause);
-
-    }
-
-    /**
-     * @param message
-     * @param cause
-     */
-    public InvalidRequestException( String message,
-                                    Throwable cause ) {
-        super(message, cause);
-
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/MoveBranchRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/MoveBranchRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/MoveBranchRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,215 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.NodeConflictBehavior;
-import org.jboss.dna.graph.properties.Path;
-
-/**
- * Instruction that a branch be moved from one location into another.
- * 
- * @author Randall Hauch
- */
-public class MoveBranchRequest extends Request {
-
-    private static final long serialVersionUID = 1L;
-
-    public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR = NodeConflictBehavior.APPEND;
-
-    private final Location from;
-    private final Location into;
-    private final NodeConflictBehavior conflictBehavior;
-    private Location actualOldLocation;
-    private Location actualNewLocation;
-
-    /**
-     * Create a request to move a branch from one location into another.
-     * 
-     * @param from the location of the top node in the existing branch that is to be moved
-     * @param into the location of the existing node into which the branch should be moved
-     * @throws IllegalArgumentException if <code>from</code> or <code>into</code> are null
-     */
-    public MoveBranchRequest( Location from,
-                              Location into ) {
-        this(from, into, DEFAULT_CONFLICT_BEHAVIOR);
-    }
-
-    /**
-     * Create a request to move a branch from one location into another.
-     * 
-     * @param from the location of the top node in the existing branch that is to be moved
-     * @param into the location of the existing node into which the branch should be moved
-     * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code>
-     *        location
-     * @throws IllegalArgumentException if any of the parameters are null
-     */
-    public MoveBranchRequest( Location from,
-                              Location into,
-                              NodeConflictBehavior conflictBehavior ) {
-        CheckArg.isNotNull(from, "from");
-        CheckArg.isNotNull(into, "into");
-        CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
-        this.from = from;
-        this.into = into;
-        this.conflictBehavior = conflictBehavior;
-    }
-
-    /**
-     * Get the location defining the top of the branch to be moved
-     * 
-     * @return the from location; never null
-     */
-    public Location from() {
-        return from;
-    }
-
-    /**
-     * Get the location defining the parent where the branch is to be placed
-     * 
-     * @return the to location; never null
-     */
-    public Location into() {
-        return into;
-    }
-
-    /**
-     * Get the expected behavior when copying the branch and the {@link #into() destination} already has a node with the same
-     * name.
-     * 
-     * @return the behavior specification
-     */
-    public NodeConflictBehavior conflictBehavior() {
-        return conflictBehavior;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return false;
-    }
-
-    /**
-     * Determine whether this move request can be determined to have no effect.
-     * <p>
-     * A move is known to have no effect when all of the following conditions are true:
-     * <ul>
-     * <li>the {@link #into() into} location has a {@link Location#hasPath() path} but no {@link Location#hasIdProperties()
-     * identification properties};</li>
-     * <li>the {@link #from() from} location has a {@link Location#getPath() path}; and</li>
-     * <li>the {@link #from() from} location's {@link Path#getParent() parent} is the same as the {@link #into() into} location's
-     * path.</li>
-     * </ul>
-     * If all of these conditions are not true, this method returns false.
-     * </p>
-     * 
-     * @return true if this move request really doesn't change the parent of the node, or false if it cannot be determined
-     */
-    public boolean hasNoEffect() {
-        if (into.hasPath() && into.hasIdProperties() == false && from.hasPath()) {
-            return from.getPath().getParent().equals(into.getPath());
-        }
-        // Can't be determined for certain
-        return false;
-    }
-
-    /**
-     * Sets the actual and complete location of the node being renamed and its new location. This method must be called when
-     * processing the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param oldLocation the actual location of the node before being renamed
-     * @param newLocation the actual location of the node after being renamed
-     * @throws IllegalArgumentException if the either location is null, if the old location does not represent the
-     *         {@link Location#isSame(Location) same location} as the {@link #from() from location}, if the new location does not
-     *         represent the {@link Location#isSame(Location) same location} as the {@link #into() into location}, or if the
-     *         either location does not have a path
-     */
-    public void setActualLocations( Location oldLocation,
-                                    Location newLocation ) {
-        if (!from.isSame(oldLocation)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(oldLocation, from));
-        }
-        if (!into.isSame(newLocation, false)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(newLocation, into));
-        }
-        assert oldLocation != null;
-        assert newLocation != null;
-        if (!oldLocation.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualOldLocationMustHavePath.text(oldLocation));
-        }
-        if (!newLocation.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualNewLocationMustHavePath.text(newLocation));
-        }
-        this.actualNewLocation = newLocation;
-    }
-
-    /**
-     * Get the actual location of the node before being moved.
-     * 
-     * @return the actual location of the node before being moved, or null if the actual location was not set
-     */
-    public Location getActualLocationBefore() {
-        return actualOldLocation;
-    }
-
-    /**
-     * Get the actual location of the node after being moved.
-     * 
-     * @return the actual location of the node after being moved, or null if the actual location was not set
-     */
-    public Location getActualLocationAfter() {
-        return actualNewLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            MoveBranchRequest that = (MoveBranchRequest)obj;
-            if (!this.from().equals(that.from())) return false;
-            if (!this.into().equals(that.into())) return false;
-            if (!this.conflictBehavior().equals(that.conflictBehavior())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "move branch " + from() + " into " + into();
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllChildrenRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllChildrenRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllChildrenRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,197 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * Instruction to read all of the children of a node at a specific location.
- * 
- * @author Randall Hauch
- */
-public class ReadAllChildrenRequest extends CacheableRequest implements Iterable<Location> {
-
-    private static final long serialVersionUID = 1L;
-
-    private final Location of;
-    private final List<Location> children = new LinkedList<Location>();
-    private Location actualOf;
-
-    /**
-     * Create a request to read the children of a node at the supplied location.
-     * 
-     * @param of the location of the node whose children are to be read
-     * @throws IllegalArgumentException if the location is null
-     */
-    public ReadAllChildrenRequest( Location of ) {
-        CheckArg.isNotNull(of, "of");
-        this.of = of;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return true;
-    }
-
-    /**
-     * Get the location defining the node whose children are to be read.
-     * 
-     * @return the location of the parent node; never null
-     */
-    public Location of() {
-        return of;
-    }
-
-    /**
-     * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
-     * represented by a location.
-     * 
-     * @return the children that were read; never null
-     */
-    public List<Location> getChildren() {
-        return children;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Iterable#iterator()
-     */
-    public Iterator<Location> iterator() {
-        return children.iterator();
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification properties. The children
-     * should be added in order.
-     * 
-     * @param child the location of the child that was read
-     * @throws IllegalArgumentException if the location is null
-     * @see #addChild(Path, Property)
-     * @see #addChild(Path, Property, Property...)
-     */
-    public void addChild( Location child ) {
-        CheckArg.isNotNull(child, "child");
-        this.children.add(child);
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification properties. The children
-     * should be added in order.
-     * 
-     * @param pathToChild the path of the child that was just read
-     * @param firstIdProperty the first identification property of the child that was just read
-     * @param remainingIdProperties the remaining identification properties of the child that was just read
-     * @throws IllegalArgumentException if the path or identification properties are null
-     * @see #addChild(Location)
-     * @see #addChild(Path, Property)
-     */
-    public void addChild( Path pathToChild,
-                          Property firstIdProperty,
-                          Property... remainingIdProperties ) {
-        Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
-        this.children.add(child);
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification property. The children
-     * should be added in order.
-     * 
-     * @param pathToChild the path of the child that was just read
-     * @param idProperty the identification property of the child that was just read
-     * @throws IllegalArgumentException if the path or identification properties are null
-     * @see #addChild(Location)
-     * @see #addChild(Path, Property, Property...)
-     */
-    public void addChild( Path pathToChild,
-                          Property idProperty ) {
-        Location child = new Location(pathToChild, idProperty);
-        this.children.add(child);
-    }
-
-    /**
-     * Sets the actual and complete location of the node whose children have been read. This method must be called when processing
-     * the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being read, or null if the {@link #of() current location} should be used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #of() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        if (!this.of.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, of));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualOf = actual;
-    }
-
-    /**
-     * Get the actual location of the node whose children were read.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualOf;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            ReadAllChildrenRequest that = (ReadAllChildrenRequest)obj;
-            if (!this.of().equals(that.of())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "read children of " + of();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,205 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * Instruction to read the properties and the number of children of the node at the specifed location.
- * 
- * @author Randall Hauch
- */
-public class ReadAllPropertiesRequest extends CacheableRequest implements Iterable<Property> {
-
-    private static final long serialVersionUID = 1L;
-
-    public static final int UNKNOWN_NUMBER_OF_CHILDREN = -1;
-
-    private final Location at;
-    private final Map<Name, Property> properties = new HashMap<Name, Property>();
-    private int numberOfChildren = UNKNOWN_NUMBER_OF_CHILDREN;
-    private Location actualLocation;
-
-    /**
-     * Create a request to read the properties and number of children of a node at the supplied location.
-     * 
-     * @param at the location of the node to be read
-     * @throws IllegalArgumentException if the location is null
-     */
-    public ReadAllPropertiesRequest( Location at ) {
-        CheckArg.isNotNull(at, "at");
-        this.at = at;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return true;
-    }
-
-    /**
-     * Get the location defining the node that is to be read.
-     * 
-     * @return the location of the node; never null
-     */
-    public Location at() {
-        return at;
-    }
-
-    /**
-     * Get the properties that were read from the {@link RepositoryConnection}.
-     * 
-     * @return the properties, as a map of property name to property; never null
-     */
-    public Map<Name, Property> getPropertiesByName() {
-        return properties;
-    }
-
-    /**
-     * Get the properties that were read from the {@link RepositoryConnection}.
-     * 
-     * @return the collection of properties; never null
-     */
-    public Collection<Property> getProperties() {
-        return properties.values();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Iterable#iterator()
-     */
-    public Iterator<Property> iterator() {
-        return getProperties().iterator();
-    }
-
-    /**
-     * Add a property that was read from the {@link RepositoryConnection}
-     * 
-     * @param property the property that was read
-     * @return the previous property that had the same name, or null if there was no previously-recorded property with the same
-     *         name
-     * @throws IllegalArgumentException if the property is null
-     */
-    public Property addProperty( Property property ) {
-        return this.properties.put(property.getName(), property);
-    }
-
-    /**
-     * Add a property that was read from the {@link RepositoryConnection}
-     * 
-     * @param properties the properties that were read
-     * @throws IllegalArgumentException if the property is null
-     */
-    public void addProperties( Property... properties ) {
-        for (Property property : properties) {
-            this.properties.put(property.getName(), property);
-        }
-    }
-
-    /**
-     * Get the number of children for this node.
-     * 
-     * @return the number of children, or {@link #UNKNOWN_NUMBER_OF_CHILDREN} if the number of children was not yet read
-     */
-    public int getNumberOfChildren() {
-        return numberOfChildren;
-    }
-
-    /**
-     * Set the number of children for this node
-     * 
-     * @param numberOfChildren the number of children
-     * @throws IllegalArgumentException if the number of childre is negative
-     */
-    public void setNumberOfChildren( int numberOfChildren ) {
-        CheckArg.isNonNegative(numberOfChildren, "numberOfChildren");
-        this.numberOfChildren = numberOfChildren;
-    }
-
-    /**
-     * Sets the actual and complete location of the node whose properties have been read. This method must be called when
-     * processing the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being read, or null if the {@link #at() current location} should be used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #at() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        if (!at.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualLocation = actual;
-    }
-
-    /**
-     * Get the actual location of the node whose properties were read.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            ReadAllPropertiesRequest that = (ReadAllPropertiesRequest)obj;
-            if (!this.at().equals(that.at())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "read properties of " + at();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,251 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.jboss.dna.common.text.Inflector;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * Instruction to read a block of the children of a node, where the block is dictated by the {@link #startingAtIndex() starting
- * index} and the {@link #count() maximum number of children} to include in the block. This command is useful when paging through
- * a large number of children.
- * 
- * @see ReadNextBlockOfChildrenRequest
- * @author Randall Hauch
- */
-public class ReadBlockOfChildrenRequest extends CacheableRequest {
-
-    public static final int INDEX_NOT_USED = -1;
-
-    private static final long serialVersionUID = 1L;
-
-    private final Location of;
-    private final List<Location> children = new LinkedList<Location>();
-    private final int startingAtIndex;
-    private final int count;
-    private Location actualLocation;
-
-    /**
-     * Create a request to read a block of the children of a node at the supplied location. The block is defined by the starting
-     * index of the first child and the number of children to include. Note that this index is <i>not</i> the
-     * {@link Path.Segment#getIndex() same-name-sibiling index}, but rather is the index of the child as if the children were in
-     * an array.
-     * 
-     * @param of the location of the node whose children are to be read
-     * @param startingIndex the zero-based index of the first child to be included in the block
-     * @param count the maximum number of children that should be included in the block
-     * @throws IllegalArgumentException if the location is null, if <code>startingIndex</code> is negative, or if
-     *         <code>count</count> is less than 1.
-     */
-    public ReadBlockOfChildrenRequest( Location of,
-                                       int startingIndex,
-                                       int count ) {
-        CheckArg.isNotNull(of, "of");
-        CheckArg.isNonNegative(startingIndex, "startingIndex");
-        CheckArg.isPositive(count, "count");
-        this.of = of;
-        this.startingAtIndex = startingIndex;
-        this.count = count;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return true;
-    }
-
-    /**
-     * Get the location defining the node whose children are to be read.
-     * 
-     * @return the location of the parent node; never null
-     */
-    public Location of() {
-        return of;
-    }
-
-    /**
-     * Get the maximum number of children that may be returned in the block.
-     * 
-     * @return the block's maximum count
-     * @see #startingAtIndex()
-     * @see #endingBefore()
-     */
-    public int count() {
-        return this.count;
-    }
-
-    /**
-     * Get the starting index of the block, which is the index of the first child to include. This index corresponds to the index
-     * of all children in the list, not the {@link Path.Segment#getIndex() same-name-sibiling index}.
-     * 
-     * @return the (zero-based) child index at which this block starts; never negative and always less than
-     *         {@link #endingBefore()}
-     * @see #endingBefore()
-     * @see #count()
-     */
-    public int startingAtIndex() {
-        return this.startingAtIndex;
-    }
-
-    /**
-     * Get the index past the last child that is to be included in the block. This index corresponds to the index of all children
-     * in the list, not the {@link Path.Segment#getIndex() same-name-sibiling index}.
-     * 
-     * @return the index just past the last child included in the block; always positive and always greater than
-     *         {@link #startingAtIndex()}.
-     * @see #startingAtIndex()
-     * @see #count()
-     */
-    public int endingBefore() {
-        return this.startingAtIndex + this.count;
-    }
-
-    /**
-     * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
-     * represented by a location.
-     * 
-     * @return the children that were read; never null
-     */
-    public List<Location> getChildren() {
-        return children;
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification properties. The children
-     * should be added in order.
-     * 
-     * @param child the location of the child that was read
-     * @throws IllegalArgumentException if the location is null
-     * @see #addChild(Path, Property)
-     * @see #addChild(Path, Property, Property...)
-     */
-    public void addChild( Location child ) {
-        CheckArg.isNotNull(child, "child");
-        this.children.add(child);
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification properties. The children
-     * should be added in order.
-     * 
-     * @param pathToChild the path of the child that was just read
-     * @param firstIdProperty the first identification property of the child that was just read
-     * @param remainingIdProperties the remaining identification properties of the child that was just read
-     * @throws IllegalArgumentException if the path or identification properties are null
-     * @see #addChild(Location)
-     * @see #addChild(Path, Property)
-     */
-    public void addChild( Path pathToChild,
-                          Property firstIdProperty,
-                          Property... remainingIdProperties ) {
-        Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
-        this.children.add(child);
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification property. The children
-     * should be added in order.
-     * 
-     * @param pathToChild the path of the child that was just read
-     * @param idProperty the identification property of the child that was just read
-     * @throws IllegalArgumentException if the path or identification properties are null
-     * @see #addChild(Location)
-     * @see #addChild(Path, Property, Property...)
-     */
-    public void addChild( Path pathToChild,
-                          Property idProperty ) {
-        Location child = new Location(pathToChild, idProperty);
-        this.children.add(child);
-    }
-
-    /**
-     * Sets the actual and complete location of the node whose children have been read. This method must be called when processing
-     * the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being read, or null if the {@link #of() current location} should be used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #of() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        if (!of.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, of));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualLocation = actual;
-    }
-
-    /**
-     * Get the actual location of the node whose children were read.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            ReadBlockOfChildrenRequest that = (ReadBlockOfChildrenRequest)obj;
-            if (!this.of().equals(that.of())) return false;
-            if (this.startingAtIndex() != that.startingAtIndex()) return false;
-            if (this.count() != that.count()) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        Inflector inflector = Inflector.getInstance();
-        if (count() == 1) {
-            return "read " + inflector.ordinalize(startingAtIndex()) + " thru " + inflector.ordinalize(endingBefore() - 1)
-                   + " children of " + of();
-        }
-        return "read " + inflector.ordinalize(startingAtIndex()) + " child of " + of();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBranchRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBranchRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBranchRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,382 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * Instruction to read the properties and children of the nodes in the branch at the supplied location. The children of the nodes
- * at the bottom of the branch are not read.
- * 
- * @author Randall Hauch
- */
- at NotThreadSafe
-public class ReadBranchRequest extends CacheableRequest implements Iterable<Location> {
-
-    private static final long serialVersionUID = 1L;
-
-    public static final int DEFAULT_MAXIMUM_DEPTH = 2;
-
-    private static class Node {
-        private final Location location;
-        private final Map<Name, Property> properties = new HashMap<Name, Property>();
-        private List<Location> children;
-
-        protected Node( Location location ) {
-            assert location != null;
-            this.location = location;
-        }
-
-        protected Location getLocation() {
-            return location;
-        }
-
-        protected Map<Name, Property> getProperties() {
-            return properties;
-        }
-
-        protected List<Location> getChildren() {
-            return children;
-        }
-
-        protected void setChildren( List<Location> children ) {
-            this.children = children;
-        }
-    }
-
-    private final Location at;
-    private final int maxDepth;
-    private final Map<Path, Node> nodes = new HashMap<Path, Node>();
-    private Location actualLocation;
-
-    /**
-     * Create a request to read the branch at the supplied location, to a maximum depth of 2.
-     * 
-     * @param at the location of the branch
-     * @throws IllegalArgumentException if the location is null
-     */
-    public ReadBranchRequest( Location at ) {
-        CheckArg.isNotNull(at, "at");
-        this.at = at;
-        this.maxDepth = DEFAULT_MAXIMUM_DEPTH;
-    }
-
-    /**
-     * Create a request to read the branch (of given depth) at the supplied location.
-     * 
-     * @param at the location of the branch
-     * @param maxDepth the maximum depth to read
-     * @throws IllegalArgumentException if the location is null or if the maximum depth is not positive
-     */
-    public ReadBranchRequest( Location at,
-                              int maxDepth ) {
-        CheckArg.isNotNull(at, "at");
-        CheckArg.isPositive(maxDepth, "maxDepth");
-        this.at = at;
-        this.maxDepth = maxDepth;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return true;
-    }
-
-    /**
-     * Get the location defining the top of the branch to be deleted
-     * 
-     * @return the location of the branch; never null
-     */
-    public Location at() {
-        return at;
-    }
-
-    /**
-     * Get the maximum depth of the branch that is to be read.
-     * 
-     * @return the maximum depth; always positive
-     */
-    public int maximumDepth() {
-        return maxDepth;
-    }
-
-    /**
-     * Return whether this branch contains the specified location.
-     * 
-     * @param location the location
-     * @return true if this branch includes the location, or false otherwise
-     */
-    public boolean includes( Location location ) {
-        if (location == null || !location.hasPath()) return false;
-        return this.nodes.containsKey(location.getPath());
-    }
-
-    /**
-     * Return whether this branch contains the specified path.
-     * 
-     * @param path the path
-     * @return true if this branch includes the path, or false otherwise
-     */
-    public boolean includes( Path path ) {
-        if (path == null) return false;
-        return this.nodes.containsKey(path);
-    }
-
-    /**
-     * Get the location for the supplied path.
-     * 
-     * @param path the path
-     * @return the location for the path, or null if the path is not known
-     */
-    public Location getLocationFor( Path path ) {
-        Node node = nodes.get(path);
-        return node != null ? node.getLocation() : null;
-    }
-
-    /**
-     * Add a node that was read from the {@link RepositoryConnection}. This method does not verify or check that the node is
-     * indeed on the branch and that it is at a level prescribed by the request.
-     * 
-     * @param node the location of the node that appears on this branch; must {@link Location#hasPath() have a path}
-     * @param properties the properties on the node
-     * @throws IllegalArgumentException if the node is null
-     */
-    public void setProperties( Location node,
-                               Property... properties ) {
-        CheckArg.isNotNull(node, "node");
-        assert node.hasPath();
-        Node nodeObj = nodes.get(node.getPath());
-        if (nodeObj == null) {
-            nodeObj = new Node(node);
-            nodes.put(node.getPath(), nodeObj);
-        }
-        Map<Name, Property> propertiesMap = nodeObj.getProperties();
-        for (Property property : properties) {
-            propertiesMap.put(property.getName(), property);
-        }
-    }
-
-    /**
-     * Add a node that was read from the {@link RepositoryConnection}. This method does not verify or check that the node is
-     * indeed on the branch and that it is at a level prescribed by the request.
-     * 
-     * @param node the location of the node that appears on this branch; must {@link Location#hasPath() have a path}
-     * @param properties the properties on the node
-     * @throws IllegalArgumentException if the node is null
-     */
-    public void setProperties( Location node,
-                               Iterable<Property> properties ) {
-        CheckArg.isNotNull(node, "node");
-        assert node.hasPath();
-        Node nodeObj = nodes.get(node.getPath());
-        if (nodeObj == null) {
-            nodeObj = new Node(node);
-            nodes.put(node.getPath(), nodeObj);
-        }
-        Map<Name, Property> propertiesMap = nodeObj.getProperties();
-        for (Property property : properties) {
-            propertiesMap.put(property.getName(), property);
-        }
-    }
-
-    /**
-     * Record the children for a parent node in the branch.
-     * 
-     * @param parent the location of the parent; must {@link Location#hasPath() have a path}
-     * @param children the location of each child, in the order they appear in the parent
-     */
-    public void setChildren( Location parent,
-                             Location... children ) {
-        CheckArg.isNotNull(parent, "parent");
-        CheckArg.isNotNull(children, "children");
-        assert parent.hasPath();
-        Node nodeObj = nodes.get(parent.getPath());
-        if (nodeObj == null) {
-            nodeObj = new Node(parent);
-            nodes.put(parent.getPath(), nodeObj);
-        }
-        nodeObj.setChildren(Arrays.asList(children));
-    }
-
-    /**
-     * Record the children for a parent node in the branch.
-     * 
-     * @param parent the location of the parent; must {@link Location#hasPath() have a path}
-     * @param children the location of each child, in the order they appear in the parent
-     */
-    public void setChildren( Location parent,
-                             List<Location> children ) {
-        CheckArg.isNotNull(parent, "parent");
-        CheckArg.isNotNull(children, "children");
-        assert parent.hasPath();
-        Node nodeObj = nodes.get(parent.getPath());
-        if (nodeObj == null) {
-            nodeObj = new Node(parent);
-            nodes.put(parent.getPath(), nodeObj);
-        }
-        nodeObj.setChildren(children);
-    }
-
-    // /**
-    // * Get the nodes that make up this branch. If this map is empty, the branch has not yet been read. The resulting map
-    // maintains
-    // * the order that the nodes were {@link #setProperties(Location, Property...) added}.
-    // *
-    // * @return the branch information
-    // * @see #iterator()
-    // */
-    // public Map<Path, Map<Name, Property>> getPropertiesByNode() {
-    // return nodeProperties;
-    // }
-
-    /**
-     * Get the nodes that make up this branch. If this map is empty, the branch has not yet been read. The resulting map maintains
-     * the order that the nodes were {@link #setProperties(Location, Property...) added}.
-     * 
-     * @param location the location of the node for which the properties are to be obtained
-     * @return the properties for the location, as a map keyed by the property name, or null if there is no such location
-     * @see #iterator()
-     */
-    public Map<Name, Property> getPropertiesFor( Location location ) {
-        if (location == null || !location.hasPath()) return null;
-        Node node = nodes.get(location.getPath());
-        return node != null ? node.getProperties() : null;
-    }
-
-    /**
-     * Get the children of the node at the supplied location.
-     * 
-     * @param parent the location of the parent
-     * @return the children, or null if there are no children (or if the parent has not been read)
-     */
-    public List<Location> getChildren( Location parent ) {
-        if (parent == null || !parent.hasPath()) return null;
-        Node node = nodes.get(parent.getPath());
-        return node != null ? node.getChildren() : null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * The resulting iterator accesses the {@link Location} objects in the branch, in pre-order traversal order.
-     * </p>
-     * 
-     * @see java.lang.Iterable#iterator()
-     */
-    public Iterator<Location> iterator() {
-        final LinkedList<Location> queue = new LinkedList<Location>();
-        if (getActualLocationOfNode() != null) {
-            Location actual = getActualLocationOfNode();
-            if (actual != null) queue.addFirst(getActualLocationOfNode());
-        }
-        return new Iterator<Location>() {
-            public boolean hasNext() {
-                return queue.peek() != null;
-            }
-
-            public Location next() {
-                // Add the children of the next node to the queue ...
-                Location next = queue.poll();
-                if (next == null) throw new NoSuchElementException();
-                List<Location> children = getChildren(next);
-                if (children != null && children.size() > 0) queue.addAll(0, children);
-                return next;
-            }
-
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
-    }
-
-    /**
-     * Sets the actual and complete location of the node being read. This method must be called when processing the request, and
-     * the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being read, or null if the {@link #at() current location} should be used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #at() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        if (!at.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualLocation = actual;
-    }
-
-    /**
-     * Get the actual location of the node that was read.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            ReadBranchRequest that = (ReadBranchRequest)obj;
-            if (!this.at().equals(that.at())) return false;
-            if (this.maximumDepth() != that.maximumDepth()) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "read branch " + at() + " to depth " + maximumDepth();
-    }
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,217 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * Instruction to read a block of the children of a node, where the block is dictated by the {@link #startingAfter location of the
- * child preceding the block} and the {@link #count() maximum number of children} to include in the block. This command is useful
- * when paging through a large number of children, when the previous block of children was already retrieved and the next block is
- * to be read.
- * 
- * @see ReadBlockOfChildrenRequest
- * @author Randall Hauch
- */
-public class ReadNextBlockOfChildrenRequest extends CacheableRequest {
-
-    public static final int INDEX_NOT_USED = -1;
-
-    private static final long serialVersionUID = 1L;
-
-    private final List<Location> children = new LinkedList<Location>();
-    private final Location startingAfter;
-    private final int count;
-    private Location actualStartingAfter;
-
-    /**
-     * Create a request to read those children of a node that are immediately after a supplied sibling node.
-     * 
-     * @param startingAfter the location of the previous sibling that was the last child of the previous block of children read
-     * @param count the maximum number of children that should be included in the block
-     * @throws IllegalArgumentException if the location is null, if <code>startingAfter</code> is null, or if
-     *         <code>count</count> is less than 1.
-     */
-    public ReadNextBlockOfChildrenRequest( Location startingAfter,
-                                           int count ) {
-        CheckArg.isNotNull(startingAfter, "startingAfter");
-        CheckArg.isPositive(count, "count");
-        this.startingAfter = startingAfter;
-        this.count = count;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return true;
-    }
-
-    /**
-     * Get the maximum number of children that may be returned in the block.
-     * 
-     * @return the block's maximum count
-     * @see #startingAfter()
-     */
-    public int count() {
-        return this.count;
-    }
-
-    /**
-     * Get the location of the child after which the block begins. This form may be easier to use when paging through blocks, as
-     * the last children retrieved with the previous block can be supplied with the next read request.
-     * 
-     * @return the location of the child that is immediately before the start of the block; index at which this block starts;
-     *         never negative
-     * @see #count()
-     */
-    public Location startingAfter() {
-        return this.startingAfter;
-    }
-
-    /**
-     * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
-     * represented by a location.
-     * 
-     * @return the children that were read; never null
-     */
-    public List<Location> getChildren() {
-        return children;
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification properties. The children
-     * should be added in order.
-     * 
-     * @param child the location of the child that was read
-     * @throws IllegalArgumentException if the location is null
-     * @see #addChild(Path, Property)
-     * @see #addChild(Path, Property, Property...)
-     */
-    public void addChild( Location child ) {
-        CheckArg.isNotNull(child, "child");
-        this.children.add(child);
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification properties. The children
-     * should be added in order.
-     * 
-     * @param pathToChild the path of the child that was just read
-     * @param firstIdProperty the first identification property of the child that was just read
-     * @param remainingIdProperties the remaining identification properties of the child that was just read
-     * @throws IllegalArgumentException if the path or identification properties are null
-     * @see #addChild(Location)
-     * @see #addChild(Path, Property)
-     */
-    public void addChild( Path pathToChild,
-                          Property firstIdProperty,
-                          Property... remainingIdProperties ) {
-        Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
-        this.children.add(child);
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification property. The children
-     * should be added in order.
-     * 
-     * @param pathToChild the path of the child that was just read
-     * @param idProperty the identification property of the child that was just read
-     * @throws IllegalArgumentException if the path or identification properties are null
-     * @see #addChild(Location)
-     * @see #addChild(Path, Property, Property...)
-     */
-    public void addChild( Path pathToChild,
-                          Property idProperty ) {
-        Location child = new Location(pathToChild, idProperty);
-        this.children.add(child);
-    }
-
-    /**
-     * Sets the actual and complete location of the node whose children have been read. This method must be called when processing
-     * the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being read, or null if the {@link #startingAfter() starting after location}
-     *        should be used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #startingAfter() starting after location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfStartingAfterNode( Location actual ) {
-        if (!startingAfter.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, startingAfter));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualStartingAfter = actual;
-    }
-
-    /**
-     * Get the actual location of the {@link #startingAfter() starting after} sibling.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfStartingAfterNode() {
-        return actualStartingAfter;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            ReadNextBlockOfChildrenRequest that = (ReadNextBlockOfChildrenRequest)obj;
-            if (!this.startingAfter().equals(that.startingAfter())) return false;
-            if (this.count() != that.count()) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        if (count() == 1) {
-            return "read the next child after " + startingAfter();
-        }
-        return "read the next " + count() + " children after " + startingAfter();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNodeRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNodeRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNodeRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,244 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * Instruction to read the properties and children of the node at the specifed location.
- * 
- * @author Randall Hauch
- */
-public class ReadNodeRequest extends CacheableRequest implements Iterable<Location> {
-
-    private static final long serialVersionUID = 1L;
-
-    private final Location at;
-    private final Map<Name, Property> properties = new HashMap<Name, Property>();
-    private final List<Location> children = new LinkedList<Location>();
-    private Location actualLocation;
-
-    /**
-     * Create a request to read the properties and number of children of a node at the supplied location.
-     * 
-     * @param at the location of the node to be read
-     * @throws IllegalArgumentException if the location is null
-     */
-    public ReadNodeRequest( Location at ) {
-        CheckArg.isNotNull(at, "at");
-        this.at = at;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return true;
-    }
-
-    /**
-     * Get the location defining the node that is to be read.
-     * 
-     * @return the location of the node; never null
-     */
-    public Location at() {
-        return at;
-    }
-
-    /**
-     * Get the properties that were read from the {@link RepositoryConnection}.
-     * 
-     * @return the properties, as a map of property name to property; never null
-     */
-    public Map<Name, Property> getPropertiesByName() {
-        return properties;
-    }
-
-    /**
-     * Get the properties that were read from the {@link RepositoryConnection}.
-     * 
-     * @return the collection of properties; never null
-     */
-    public Collection<Property> getProperties() {
-        return properties.values();
-    }
-
-    /**
-     * Add a property that was read from the {@link RepositoryConnection}
-     * 
-     * @param property the property that was read
-     * @return the previous property that had the same name, or null if there was no previously-recorded property with the same
-     *         name
-     * @throws IllegalArgumentException if the property is null
-     */
-    public Property addProperty( Property property ) {
-        return this.properties.put(property.getName(), property);
-    }
-
-    /**
-     * Add a property that was read from the {@link RepositoryConnection}
-     * 
-     * @param properties the properties that were read
-     * @throws IllegalArgumentException if the property is null
-     */
-    public void addProperties( Property... properties ) {
-        for (Property property : properties) {
-            this.properties.put(property.getName(), property);
-        }
-    }
-
-    /**
-     * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
-     * represented by a location.
-     * 
-     * @return the children that were read; never null
-     */
-    public List<Location> getChildren() {
-        return children;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Iterable#iterator()
-     */
-    public Iterator<Location> iterator() {
-        return children.iterator();
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification properties. The children
-     * should be added in order.
-     * 
-     * @param child the location of the child that was read
-     * @throws IllegalArgumentException if the location is null
-     * @see #addChild(Path, Property)
-     * @see #addChild(Path, Property, Property...)
-     */
-    public void addChild( Location child ) {
-        CheckArg.isNotNull(child, "child");
-        this.children.add(child);
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification properties. The children
-     * should be added in order.
-     * 
-     * @param pathToChild the path of the child that was just read
-     * @param firstIdProperty the first identification property of the child that was just read
-     * @param remainingIdProperties the remaining identification properties of the child that was just read
-     * @throws IllegalArgumentException if the path or identification properties are null
-     * @see #addChild(Location)
-     * @see #addChild(Path, Property)
-     */
-    public void addChild( Path pathToChild,
-                          Property firstIdProperty,
-                          Property... remainingIdProperties ) {
-        Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
-        this.children.add(child);
-    }
-
-    /**
-     * Add to the list of children that has been read the child with the given path and identification property. The children
-     * should be added in order.
-     * 
-     * @param pathToChild the path of the child that was just read
-     * @param idProperty the identification property of the child that was just read
-     * @throws IllegalArgumentException if the path or identification properties are null
-     * @see #addChild(Location)
-     * @see #addChild(Path, Property, Property...)
-     */
-    public void addChild( Path pathToChild,
-                          Property idProperty ) {
-        Location child = new Location(pathToChild, idProperty);
-        this.children.add(child);
-    }
-
-    /**
-     * Sets the actual and complete location of the node whose children and properties have been read. This method must be called
-     * when processing the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being read, or null if the {@link #at() current location} should be used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #at() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        if (!at.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualLocation = actual;
-    }
-
-    /**
-     * Get the actual location of the node whose children and properties were read.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            ReadNodeRequest that = (ReadNodeRequest)obj;
-            if (!this.at().equals(that.at())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "read node at " + at();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadPropertyRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadPropertyRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadPropertyRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,163 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * Instruction to read a single property on the node at the specified location.
- * 
- * @author Randall Hauch
- */
-public class ReadPropertyRequest extends CacheableRequest {
-
-    private static final long serialVersionUID = 1L;
-
-    private final Location on;
-    private final Name propertyName;
-    private Property property;
-    private Location actualLocation;
-
-    /**
-     * Create a request to read the properties and number of children of a node at the supplied location.
-     * 
-     * @param on the location of the node to be read
-     * @param propertyName the name of the property to read
-     * @throws IllegalArgumentException if the location or property name are null
-     */
-    public ReadPropertyRequest( Location on,
-                                Name propertyName ) {
-        CheckArg.isNotNull(on, "on");
-        CheckArg.isNotNull(propertyName, "propertyName");
-        this.on = on;
-        this.propertyName = propertyName;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return true;
-    }
-
-    /**
-     * Get the location defining the node that is to be read.
-     * 
-     * @return the location of the node; never null
-     */
-    public Location on() {
-        return on;
-    }
-
-    /**
-     * Get the name of the property that is to be read
-     * 
-     * @return the property name; never null
-     */
-    public Name named() {
-        return propertyName;
-    }
-
-    /**
-     * Get the property that was read.
-     * 
-     * @return the property, or null if the property was not read or did not exist on the node
-     */
-    public Property getProperty() {
-        return property;
-    }
-
-    /**
-     * Set the property on the node as read from the {@link RepositoryConnection}
-     * 
-     * @param property the property that was read
-     * @throws IllegalArgumentException if the property's name does not match the {@link #named() name of the property} that was
-     *         to be read
-     */
-    public void setProperty( Property property ) {
-        if (property != null) CheckArg.isEquals(property.getName(), "property's name", named(), "property name");
-        this.property = property;
-    }
-
-    /**
-     * Sets the actual and complete location of the node whose property has been read. This method must be called when processing
-     * the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being read, or null if the {@link #on() current location} should be used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #on() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        if (!on.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, on));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualLocation = actual;
-    }
-
-    /**
-     * Get the actual location of the node whose property was read.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            ReadPropertyRequest that = (ReadPropertyRequest)obj;
-            if (!this.on().equals(that.on())) return false;
-            if (!this.named().equals(that.named())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "read " + named() + " property at " + on();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RemovePropertiesRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RemovePropertiesRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RemovePropertiesRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,198 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-
-/**
- * Instruction to remove properties from the node at the specified location.
- * 
- * @author Randall Hauch
- */
-public class RemovePropertiesRequest extends Request implements Iterable<Name> {
-
-    private static final long serialVersionUID = 1L;
-
-    private final Location from;
-    private final Set<Name> propertyNames;
-    private Location actualLocation;
-
-    /**
-     * Create a request to remove the properties with the given names from the node at the supplied location.
-     * 
-     * @param from the location of the node to be read
-     * @param propertyNames the names of the properties to be removed from the node
-     * @throws IllegalArgumentException if the location is null or if there are no properties to remove
-     */
-    public RemovePropertiesRequest( Location from,
-                                    Name... propertyNames ) {
-        CheckArg.isNotNull(from, "from");
-        CheckArg.isNotEmpty(propertyNames, "propertyNames");
-        this.from = from;
-        Set<Name> names = new HashSet<Name>();
-        for (Name name : propertyNames) {
-            if (name != null) names.add(name);
-        }
-        this.propertyNames = Collections.unmodifiableSet(names);
-    }
-
-    /**
-     * Create a request to remove the properties with the given names from the node at the supplied location.
-     * 
-     * @param from the location of the node to be read
-     * @param propertyNames the names of the properties to be removed from the node
-     * @throws IllegalArgumentException if the location is null or if there are no properties to remove
-     */
-    public RemovePropertiesRequest( Location from,
-                                    Iterable<Name> propertyNames ) {
-        CheckArg.isNotNull(from, "from");
-        CheckArg.isNotNull(propertyNames, "propertyNames");
-        this.from = from;
-        Set<Name> names = new HashSet<Name>();
-        for (Name name : propertyNames) {
-            if (name != null) names.add(name);
-        }
-        this.propertyNames = Collections.unmodifiableSet(names);
-        CheckArg.isNotEmpty(this.propertyNames, "propertyNames");
-    }
-
-    /**
-     * Create a request to remove the properties with the given names from the node at the supplied location.
-     * 
-     * @param from the location of the node to be read
-     * @param propertyNames the names of the properties to be removed from the node
-     * @throws IllegalArgumentException if the location is null or if there are no properties to remove
-     */
-    public RemovePropertiesRequest( Location from,
-                                    Iterator<Name> propertyNames ) {
-        CheckArg.isNotNull(from, "from");
-        CheckArg.isNotNull(propertyNames, "propertyNames");
-        this.from = from;
-        Set<Name> names = new HashSet<Name>();
-        while (propertyNames.hasNext()) {
-            Name name = propertyNames.next();
-            if (name != null) names.add(name);
-        }
-        this.propertyNames = Collections.unmodifiableSet(names);
-        CheckArg.isNotEmpty(this.propertyNames, "propertyNames");
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return false;
-    }
-
-    /**
-     * Get the location defining the node from which the properties are to be removed.
-     * 
-     * @return the location of the node; never null
-     */
-    public Location from() {
-        return from;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Iterable#iterator()
-     */
-    public Iterator<Name> iterator() {
-        return this.propertyNames.iterator();
-    }
-
-    /**
-     * Get the names of the properties that are to be removed from the node.
-     * 
-     * @return the collection of property names; never null and never empty
-     */
-    public Collection<Name> propertyNames() {
-        return propertyNames;
-    }
-
-    /**
-     * Sets the actual and complete location of the node whose properties were removed. This method must be called when processing
-     * the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being changed, or null if the {@link #from() current location} should be used
-     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
-     *         location} as the {@link #from() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        if (!from.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, from));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualLocation = actual;
-    }
-
-    /**
-     * Get the actual location of the node whose properties were removed.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            RemovePropertiesRequest that = (RemovePropertiesRequest)obj;
-            if (!this.from().equals(that.from())) return false;
-            if (!this.propertyNames().equals(that.propertyNames())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "remove from " + from() + " properties named " + propertyNames();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RenameNodeRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RenameNodeRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RenameNodeRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,171 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-
-/**
- * Instruction to rename an existing node (but keep it under the same parent). The same-name-sibling index will be determined
- * automatically, based upon it's current location within the list of children.
- * 
- * @author Randall Hauch
- */
-public class RenameNodeRequest extends Request {
-
-    private static final long serialVersionUID = 1L;
-
-    private final Location at;
-    private final Name newName;
-    private Location actualOldLocation;
-    private Location actualNewLocation;
-
-    /**
-     * Create a request to rename the node at the supplied location.
-     * 
-     * @param at the location of the node to be read
-     * @param newName the new name for the node
-     * @throws IllegalArgumentException if the location is null
-     */
-    public RenameNodeRequest( Location at,
-                              Name newName ) {
-        CheckArg.isNotNull(at, "at");
-        CheckArg.isNotNull(newName, "newName");
-        this.at = at;
-        this.newName = newName;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return false;
-    }
-
-    /**
-     * Get the location defining the node that is to be read.
-     * 
-     * @return the location of the node; never null
-     */
-    public Location at() {
-        return at;
-    }
-
-    /**
-     * Get the new name for the node.
-     * 
-     * @return the new name; never null
-     */
-    public Name toName() {
-        return newName;
-    }
-
-    /**
-     * Sets the actual and complete location of the node being renamed and its new location. This method must be called when
-     * processing the request, and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param oldLocation the actual location of the node before being renamed
-     * @param newLocation the actual location of the node after being renamed
-     * @throws IllegalArgumentException if the either location is null or is missing its path, if the old location does not
-     *         represent the {@link Location#isSame(Location) same location} as the {@link #at() current location}, if the new
-     *         location does not have the same parent as the old location, or if the new location does not have the same
-     *         {@link Path.Segment#getName() name} on {@link Path#getLastSegment() last segment} as that {@link #toName()
-     *         specified on the request}
-     */
-    public void setActualLocations( Location oldLocation,
-                                    Location newLocation ) {
-        if (!at.isSame(oldLocation)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(oldLocation, at));
-        }
-        assert oldLocation != null;
-        if (newLocation == null) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(newLocation, at));
-        }
-        if (!oldLocation.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualOldLocationMustHavePath.text(oldLocation));
-        }
-        if (!newLocation.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualNewLocationMustHavePath.text(newLocation));
-        }
-        Path newPath = newLocation.getPath();
-        if (!newPath.getParent().equals(oldLocation.getPath().getParent())) {
-            String msg = GraphI18n.actualNewLocationMustHaveSameParentAsOldLocation.text(newLocation, oldLocation);
-            throw new IllegalArgumentException(msg);
-        }
-        if (!newPath.getLastSegment().getName().equals(toName())) {
-            String msg = GraphI18n.actualNewLocationMustHaveSameNameAsRequest.text(newLocation, toName());
-            throw new IllegalArgumentException(msg);
-        }
-        this.actualNewLocation = newLocation;
-    }
-
-    /**
-     * Get the actual location of the node before being renamed.
-     * 
-     * @return the actual location of the node before being renamed, or null if the actual location was not set
-     */
-    public Location getActualLocationBefore() {
-        return actualOldLocation;
-    }
-
-    /**
-     * Get the actual location of the node after being renamed.
-     * 
-     * @return the actual location of the node after being renamed, or null if the actual location was not set
-     */
-    public Location getActualLocationAfter() {
-        return actualNewLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            RenameNodeRequest that = (RenameNodeRequest)obj;
-            if (!this.at().equals(that.at())) return false;
-            if (!this.toName().equals(that.toName())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "rename node at " + at() + " to " + toName();
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Request.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Request.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Request.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,129 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.io.Serializable;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-
-/**
- * The abstract base class for all classes representing requests to be executed against a {@link RepositoryConnection}.
- * 
- * @author Randall Hauch
- */
-public abstract class Request implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    private Throwable error;
-    private AtomicBoolean cancelled;
-
-    protected Request() {
-        this.cancelled = new AtomicBoolean(false);
-    }
-
-    /**
-     * Set the error for this request.
-     * 
-     * @param error the error to be associated with this request, or null if this request is to have no error
-     */
-    public void setError( Throwable error ) {
-        this.error = error;
-    }
-
-    /**
-     * Return whether there is an error associated with this request
-     * 
-     * @return true if there is an error, or false otherwise
-     */
-    public boolean hasError() {
-        return this.error != null;
-    }
-
-    /**
-     * Get the error associated with this request, if there is such an error.
-     * 
-     * @return the error, or null if there is none
-     */
-    public Throwable getError() {
-        return error;
-    }
-
-    /**
-     * Check whether this request has been cancelled. Although it is a recommendation that the result of this method be followed
-     * wherever possible, it is not required to immediately stop processing the request if this method returns <code>true</code>.
-     * For example, if processing is almost complete, it may be appropriate to simply finish processing the request.
-     * <p>
-     * This method is safe to be called by different threads.
-     * </p>
-     * 
-     * @return true if this request has been cancelled, or false otherwise.
-     */
-    public boolean isCancelled() {
-        return cancelled.get();
-    }
-
-    /**
-     * Set the cancelled state of this request. All requests are initially marked as not cancelled. Note that this is designed so
-     * that the same {@link AtomicBoolean} instance can be passed to multiple requests, allowing a single flag to dictate the
-     * cancelled state of all of those requests.
-     * <p>
-     * So, by default, each request should already be set up to not be cancelled, so for most cases this method does not need to
-     * be called at all. This method should be called when this flag is to be shared among multiple requests, usually when the
-     * requests are being initialized or assembled.
-     * </p>
-     * 
-     * @param cancelled the new (potentially shared) cancelled state for the request; may not be null
-     */
-    /*package*/void setCancelledFlag( AtomicBoolean cancelled ) {
-        assert cancelled != null;
-        this.cancelled = cancelled;
-    }
-
-    /**
-     * Get this request's cancelled flag.
-     * 
-     * @return the cancelled flag
-     */
-    /*package*/AtomicBoolean getCancelledFlag() {
-        return cancelled;
-    }
-
-    /**
-     * Cancel this request. After this method is called, the {@link #isCancelled() cancellation flag} is set, and any current or
-     * future processing of the request may be affected by the cancellation. (Note however, that processors may choose to not
-     * respect this request.)
-     * <p>
-     * This method is safe to be called by different threads.
-     * </p>
-     */
-    public void cancel() {
-        this.cancelled.set(true);
-    }
-
-    /**
-     * Return whether this request only reads information.
-     * 
-     * @return true if this request reads information, or false if it requests that the repository content be changed in some way
-     */
-    public abstract boolean isReadOnly();
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/UpdatePropertiesRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/UpdatePropertiesRequest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/UpdatePropertiesRequest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,249 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * Instruction to update the properties on the node at the specified location. Any property with no values will be removed.
- * 
- * @author Randall Hauch
- */
-public class UpdatePropertiesRequest extends Request implements Iterable<Property> {
-
-    private static final long serialVersionUID = 1L;
-
-    private final Location on;
-    private final List<Property> properties;
-    private Location actualLocation;
-
-    /**
-     * Create a request to update the properties on the node at the supplied location.
-     * 
-     * @param on the location of the node to be read
-     * @param properties the new properties on the node
-     * @throws IllegalArgumentException if the location is null or if there are no properties to update
-     */
-    public UpdatePropertiesRequest( Location on,
-                                    Property... properties ) {
-        CheckArg.isNotNull(on, "on");
-        CheckArg.isNotEmpty(properties, "properties");
-        this.on = on;
-        this.properties = Collections.unmodifiableList(Arrays.asList(properties));
-    }
-
-    /**
-     * Create a request to update the properties on the node at the supplied location.
-     * 
-     * @param on the location of the node to be read
-     * @param properties the new properties on the node
-     * @throws IllegalArgumentException if the location is null or if there are no properties to update
-     */
-    public UpdatePropertiesRequest( Location on,
-                                    Iterable<Property> properties ) {
-        CheckArg.isNotNull(on, "on");
-        CheckArg.isNotNull(properties, "properties");
-        this.on = on;
-        List<Property> props = new LinkedList<Property>();
-        for (Property property : properties) {
-            if (property != null) props.add(property);
-        }
-        this.properties = Collections.unmodifiableList(props);
-        CheckArg.isNotEmpty(this.properties, "properties");
-    }
-
-    /**
-     * Create a request to update the properties on the node at the supplied location.
-     * 
-     * @param on the location of the node to be read
-     * @param properties the new properties on the node
-     * @throws IllegalArgumentException if the location is null or if there are no properties to update
-     */
-    public UpdatePropertiesRequest( Location on,
-                                    Iterator<Property> properties ) {
-        CheckArg.isNotNull(on, "on");
-        CheckArg.isNotNull(properties, "properties");
-        this.on = on;
-        List<Property> props = new LinkedList<Property>();
-        while (properties.hasNext()) {
-            Property property = properties.next();
-            if (property != null) props.add(property);
-        }
-        this.properties = Collections.unmodifiableList(props);
-        CheckArg.isNotEmpty(this.properties, "properties");
-    }
-
-    /**
-     * Create a request to update the properties on the node at the supplied location.
-     * 
-     * @param on the location of the node to be read
-     * @param properties the new properties on the node
-     * @throws IllegalArgumentException if the location is null or if there are no properties to update
-     */
-    private UpdatePropertiesRequest( Location on,
-                                     List<Property> properties ) {
-        CheckArg.isNotNull(on, "on");
-        CheckArg.isNotNull(properties, "properties");
-        this.on = on;
-        this.properties = properties;
-        CheckArg.isNotEmpty(this.properties, "properties");
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
-     */
-    @Override
-    public boolean isReadOnly() {
-        return false;
-    }
-
-    /**
-     * Get the location defining the node that is to be updated.
-     * 
-     * @return the location of the node; never null
-     */
-    public Location on() {
-        return on;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Iterable#iterator()
-     */
-    public Iterator<Property> iterator() {
-        return this.properties.iterator();
-    }
-
-    /**
-     * Get the properties for the node.
-     * 
-     * @return the collection of properties; never null and never empty
-     */
-    public Collection<Property> properties() {
-        return properties;
-    }
-
-    /**
-     * Sets the actual and complete location of the node being updated. This method must be called when processing the request,
-     * and the actual location must have a {@link Location#getPath() path}.
-     * 
-     * @param actual the actual location of the node being updated, or null if the {@link #on() current location} should be used
-     * @throws IllegalArgumentException if the actual location does represent the {@link Location#isSame(Location) same location}
-     *         as the {@link #on() current location}, or if the actual location does not have a path.
-     */
-    public void setActualLocationOfNode( Location actual ) {
-        if (!on.isSame(actual)) { // not same if actual is null
-            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, on));
-        }
-        assert actual != null;
-        if (!actual.hasPath()) {
-            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
-        }
-        this.actualLocation = actual;
-    }
-
-    /**
-     * Get the actual location of the node that was updated.
-     * 
-     * @return the actual location, or null if the actual location was not set
-     */
-    public Location getActualLocationOfNode() {
-        return actualLocation;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (this.getClass().isInstance(obj)) {
-            UpdatePropertiesRequest that = (UpdatePropertiesRequest)obj;
-            if (!this.on().equals(that.on())) return false;
-            if (!this.properties().equals(that.properties())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "update properties on " + on() + " to " + properties();
-    }
-
-    /**
-     * Merge these updates with those in the supplied request, with the supplied changes overwriting any similar changes on this
-     * node.
-     * 
-     * @param other the other updates that are to be merged with these
-     * @return the merged request
-     */
-    public UpdatePropertiesRequest mergeWith( UpdatePropertiesRequest other ) {
-        if (other == null) return this;
-        if (other.properties().size() == 1) {
-            Property newProp = other.properties.get(0);
-            List<Property> newProps = new LinkedList<Property>();
-            for (Property prop : this.properties) {
-                if (!prop.getName().equals(newProp.getName())) {
-                    newProps.add(prop);
-                }
-            }
-            newProps.add(newProp);
-            return new UpdatePropertiesRequest(on, Collections.unmodifiableList(newProps));
-        }
-        Set<Name> otherNames = new HashSet<Name>();
-        for (Property prop : other.properties()) {
-            otherNames.add(prop.getName());
-        }
-        List<Property> newProps = new LinkedList<Property>();
-        for (Property prop : this.properties) {
-            if (!otherNames.contains(prop.getName())) {
-                newProps.add(prop);
-            }
-        }
-        newProps.addAll(other.properties);
-        return new UpdatePropertiesRequest(on, Collections.unmodifiableList(newProps));
-
-    }
-
-}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/package-info.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/package-info.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,139 +0,0 @@
-/**
- * Sometimes its useful to work with a graph using objects that represent individual 
- * <a href="http://en.wikipedia.org/wiki/Command_pattern">commands</a> on the graph.  For example, "read node A"
- * or "create a node named C under node /A/B" or "create a copy of the subgraph at /E/F/G and place it under /E/H/I".
- * The command pattern has a number of benefits.  Since commands represent atomic activities, they map well to events
- * and can be easily serialized (making them very useful for {@link org.jboss.dna.graph.connectors.RepositoryConnection connectors}). 
- * They provide an easy way to inherit or override functionality.  
- * New kinds of commands can be added with minimal (sometimes no) impact.
- * And existing commands can be changed to include new fields, making it possible to evolve a command
- * while minimizing the changes.
- * <p>
- * This package defines standard commands, called "requests", that correspond to different kinds of actions against a JBoss DNA graph.
- * Each kind of request is represented by a single concrete class, and all request classes extend from the
- * {@link Request} abstract class.  Because a lot of inheritance among commands can cause interference and inheritance cross-talk,
- * inheritance other than from {@link Request} is avoided as much possible.  (One exception to this is
- * {@link CacheableRequest}, which extends {@link Request} and serves as the base class for the "read" requests
- * that return results.)
- * </p>
- * <h3>Processing Requests</h3>
- * <p>
- * Request objects are sent to a {@link org.jboss.dna.graph.requests.processor.RequestProcessor}, which is responsible
- * for performing the request.  {@link org.jboss.dna.graph.connectors.RepositoryConnection Repository connectors} usually
- * implement their own <code>RequestProcessor</code>, which processes each submitted request by performing the
- * requested work.
- * </p>
- * <p>
- * Processor generally do not throw exceptions when processing requests (other than errors that signal problems
- * with the processor itself, such as connectivity problems, that signals the interruption of not only this request
- * but subsequent requests, too).  Instead, each request has an
- * {@link Request#setError(Throwable) error} field that can be used to store the exception that was encountered 
- * while processing the request.  This makes it possible to submit {@link CompositeRequest multiple requests}
- * at once, and have any errors directly associated with the request.
- * </p>
- * <h3>What's in a Request?</h3>
- * <p>
- * In general, a single request contains two kinds of information: the information that makes up the request (called the "input"),
- * and the information that is the result of the request (called the "result").  The input information contains everything
- * a processor needs to know to successfully perform the request.  For example, if the properties of a node are to be
- * read, then the input information must include the identifier or location of the  node.  If a node is to be moved,
- * then the input information must include the original location of the node as well as the new location.
- * Oh, the request's input information is immutable, ensuring that this part of the request doesn't change as it is passed
- * around the system.
- * </p>
- * <p>
- * A processor then fulfills the request by performing the requested work, and setting on the request any 
- * requested "results".  For example, if the properties of a node are to be read, then the results include
- * the set of {@link org.jboss.dna.graph.properties.Property} objects.  If the children are to be read, then the
- * results consist of the list of {@link org.jboss.dna.graph.Location} object for each child.
- * </p>
- * <h3>Locations</h3>
- * <p>
- * All requests operate on some portion of the graph, so it's imperative that there be an easy but flexible
- * way to identify the location of that area, whether it's a node, subgraph, child reference, or node reference.
- * Like other parts of the JBoss DNA Graph API, requests use {@link org.jboss.dna.graph.Location} (or multiple
- * Location objects) as request inputs, and one Location object for each "reference" to a node that's in the output.
- * </p>
- * <p>
- * A {@link org.jboss.dna.graph.Location} can be specified as a {@link org.jboss.dna.graph.properties.Path} and/or
- * as a set of identification properties.  Usually, Locations are created using just the path, since that's how
- * nodes are identified most of the time.  However, identification properties usually consist of information that 
- * uniquely (and quickly) identifies a node, so including identification properties in a Location may allow the 
- * processor to easily or more efficiently find the node given by the location.
- * </p>
- * <p>
- * Fortunately, requests often return Location objects that are <i>fully-defined</i>, meaning they have a Path 
- * <i>and</i> identification properties.  For example, the children of a node will be returned as a list of (fully-defined)
- * Location objects.  In fact, all requests have as part of their results an "actual" Location for each Location in the input,
- * so even when you don't have a fully-defined Location as an input, the request (after processing) should contain
- * a fully-defined Location for the input.
- * </p>
- * <p>
- * Because of this, and because working with a graph usually consists of making one request, using the results of that
- * request to create additional requests, and so on, you'll find that it's very easy to include fully-defined Location
- * objects in your requests.  Well, except for the first request.
- * </p>
- * <h3>Kinds of Requests</h3>
- * <p>
- * There are really two very broad categories of {@link Request}s: requests that don't modify content and those that do.
- * The requests that don't modify content are generally "read" requests that are requests to return information about
- * some part of the graph, and these requests should really have not side-effects on the graph.  Since these requests
- * contain results that are essentially snapshots in time of a portion of the graph content, these request types
- * extend {@link CacheableRequest} and contain fields for referencing a {@link org.jboss.dna.graph.cache.CachePolicy}
- * and a time that the results were loaded.
- * </p>
- * <p>
- * Requests that do modify graph content are used to create, update, move and delete content in the graph.  These
- * kinds of requests often have little or no results (the changes will be made to the graph unless an exception
- * is set on the request during processing), and as such the requests do not have any fields related to caching.
- * </p>
- * <p>
- * The supported requests currently include:
- * <ul>
- *   <li>{@link ReadNodeRequest} - A request to read the specified node and return all of that node's properties and the 
- *   location of every child node.</li>
- *   <li>{@link ReadAllChildrenRequest} - A request to read and return all of the children of the specified node.
- *   Each child node is represented by a {@link org.jboss.dna.graph.Location} object.  This request is useful for
- *   determining the structure of the graph without having to load all of the properties of each node.</li>
- *   <li>{@link ReadAllPropertiesRequest} - A request to read and return all of the properties of the specified node.
- *   This request is useful when all of the properties for a node are to be returned, but without any children
- *   information (usually because the children will be read later or were already read).</li>
- *   <li>{@link ReadBranchRequest} - A request to read a branch of the graph, returning the node (with its properties
- *   and children) at the specified location as well as nodes (with their properties and children) below the specified node,
- *   up to an optional maximum depth.  This request is useful for efficiently obtaining the nodes in a subgraph when
- *   the structure is known ahead of time.  This request can sometimes be significantly more efficient that walking
- *   the subgraph and submitting individual {@link ReadNodeRequest}s for each node in the subgraph.</li>
- *   <li>{@link ReadPropertyRequest} - A request to read and return a single named property on a specified node.</li>
- *   <li>{@link ReadBlockOfChildrenRequest} - A request to read the children of the specified node, returning only
- *   the locations for a subset of the children. The subset of children is defined by the index of the first child
- *   to be returned and the number of children to be returned.  This is often useful when the repository may have large numbers
- *   of children and it is unlikely that client applications will need all of them. </li>
- *   <li>{@link ReadNextBlockOfChildrenRequest} - A request to read the children of the specified node, returning
- *   only the locations for a subset of the children.  Unlike {@link ReadBlockOfChildrenRequest}, this request
- *   specifies the Location of the child that appears immediately before the first child to be returned.  This
- *   request is useful in concurrent applications when one client is reading the children while another client
- *   may be adding or removing children (thereby changing the indexes).  Since this request includes the Location of the 
- *   last child previously read, the request is unaffected by changing indexes.</li>
- *   <li>{@link CreateNodeRequest} - A request to create a new node under an existing parent node.  This request
- *   may optionally include properties for the new node.</li>
- *   <li>{@link CopyBranchRequest} - A request to copy an entire branch located under a specified node, and place
- *   the copy of that branch under another (existing) node.</li>
- *   <li>{@link MoveBranchRequest} - A request to move the specified node and all nodes below it into a new location
- *   specified by the Location of the new parent node.</li>
- *   <li>{@link RenameNodeRequest} - A request to rename an existing node.  This may adjust the indexes of sibling nodes
- *   with the same names (as same-name-sibling nodes are identified with SNS indexes).</li>
- *   <li>{@link UpdatePropertiesRequest} - A request to update one or more properties on a node.  Any property
- *   with no values will be removed, while properties with one or more values will be set (replace any existing property
- *   with the same name, if they exist). </li>
- *   <li>{@link RemovePropertiesRequest} - A request to remove one or more properties on a node.  No error is reported
- *   if the node does not contain a property that is to be removed.</li>
- *   <li>{@link DeleteBranchRequest} - A request to delete a node and all nodes located below it.</li>
- *   <li>{@link CompositeRequest} - A request that acts as a container for multiple other requests (of various kinds),
- *   allowing you to batch together multiple for processing.  Use the one of the {@link CompositeRequest#with(Request...) CompositeRequest.with(...)}
- *   methods to create a CompositeRequest from a series of other requests.</li>
- * </ul>
- * </p>
- */
-
-package org.jboss.dna.graph.requests;
-

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer (from rev 705, trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers)

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerContext.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers/SequencerContext.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerContext.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,72 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.sequencers;
-
-import java.util.Set;
-import org.jboss.dna.common.collection.Problems;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * @author John Verhaeg
- */
-public interface SequencerContext extends ExecutionContext {
-
-    /**
-     * Return the path of the input node containing the content being sequenced.
-     * 
-     * @return input node's path.
-     */
-    Path getInputPath();
-
-    /**
-     * Return the set of properties from the input node containing the content being sequenced.
-     * 
-     * @return the input node's properties; never <code>null</code>.
-     */
-    Set<Property> getInputProperties();
-
-    /**
-     * Return the property with the supplied name from the input node containing the content being sequenced.
-     * 
-     * @param name
-     * @return the input node property, or <code>null</code> if none exists.
-     */
-    Property getInputProperty( Name name );
-
-    /**
-     * Return the MIME-type of the content being sequenced.
-     * 
-     * @return the MIME-type
-     */
-    String getMimeType();
-
-    /**
-     * Get an interface that can be used to record various problems, warnings, and errors that are not extreme enough to warrant
-     * throwing exceptions.
-     * 
-     * @return the interface for recording problems; never null
-     */
-    Problems getProblems();
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerContext.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers/SequencerContext.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerContext.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerContext.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,110 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.sequencer;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.common.collection.SimpleProblems;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * @author John Verhaeg
+ */
+public class SequencerContext extends ExecutionContext {
+
+    private final Path inputPath;
+    private final Map<Name, Property> inputPropertiesByName;
+    private final Set<Property> inputProperties;
+    private final Problems problems;
+    private final String mimeType;
+
+    public SequencerContext( ExecutionContext context,
+                             Path inputPath,
+                             Set<Property> inputProperties,
+                             String mimeType,
+                             Problems problems ) {
+        super(context);
+        this.inputPath = inputPath;
+        this.inputProperties = inputProperties != null ? new HashSet<Property>(inputProperties) : new HashSet<Property>();
+        this.mimeType = mimeType;
+        this.problems = problems != null ? problems : new SimpleProblems();
+        Map<Name, Property> inputPropertiesByName = new HashMap<Name, Property>();
+        for (Property property : this.inputProperties) {
+            inputPropertiesByName.put(property.getName(), property);
+        }
+        this.inputPropertiesByName = Collections.unmodifiableMap(inputPropertiesByName);
+    }
+
+    /**
+     * Return the path of the input node containing the content being sequenced.
+     * 
+     * @return input node's path.
+     */
+    public Path getInputPath() {
+        return inputPath;
+    }
+
+    /**
+     * Return the set of properties from the input node containing the content being sequenced.
+     * 
+     * @return the input node's properties; never <code>null</code>.
+     */
+    public Set<Property> getInputProperties() {
+        return inputProperties;
+    }
+
+    /**
+     * Return the property with the supplied name from the input node containing the content being sequenced.
+     * 
+     * @param name
+     * @return the input node property, or <code>null</code> if none exists.
+     */
+    public Property getInputProperty( Name name ) {
+        return inputPropertiesByName.get(name);
+    }
+
+    /**
+     * Return the MIME-type of the content being sequenced.
+     * 
+     * @return the MIME-type
+     */
+    public String getMimeType() {
+        return this.mimeType;
+    }
+
+    /**
+     * Get an interface that can be used to record various problems, warnings, and errors that are not extreme enough to warrant
+     * throwing exceptions.
+     * 
+     * @return the interface for recording problems; never null
+     */
+    public Problems getProblems() {
+        return this.problems;
+    }
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerOutput.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers/SequencerOutput.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerOutput.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,86 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.sequencers;
-
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-
-/**
- * Interface for sequencers to use to generate their output.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public interface SequencerOutput {
-
-    /**
-     * Set the supplied property on the supplied node.
-     * <p>
-     * The {@link SequencerContext#getValueFactories() value factories} should be used to create paths, names, and values. These
-     * factories can be used to create new values or convert values from one property type to another. (Note that each of the
-     * factories have methods that create values from all of the property types.)
-     * </p>
-     * <p>
-     * This method is provided as a convenience, but it identical to creating a {@link Path} and {@link Name} using the
-     * {@link SequencerContext#getValueFactories() factories} and calling {@link #setProperty(Path, Name, Object...)}.
-     * </p>
-     * 
-     * @param nodePath the path to the node containing the property; may not be null
-     * @param propertyName the name of the property to be set
-     * @param values the value(s) for the property; may be empty if any existing property is to be removed
-     */
-    void setProperty( String nodePath,
-                      String propertyName,
-                      Object... values );
-
-    /**
-     * Set the supplied reference on the supplied node.
-     * <p>
-     * This method is provided as a convenience, but it identical to creating a {@link Path} and {@link Name} using the
-     * {@link SequencerContext#getValueFactories() factories} and calling {@link #setProperty(Path, Name, Object...)}.
-     * </p>
-     * 
-     * @param nodePath the path to the node containing the property; may not be null
-     * @param propertyName the name of the property to be set
-     * @param paths the paths to the referenced property, which may be absolute paths or relative to the sequencer output node;
-     *        may be empty if any existing property is to be removed
-     */
-    void setReference( String nodePath,
-                       String propertyName,
-                       String... paths );
-
-    /**
-     * Set the supplied property on the supplied node.
-     * <p>
-     * The {@link SequencerContext#getValueFactories() value factories} should be used to create paths, names, and values. These
-     * factories can be used to create new values or convert values from one property type to another. (Note that each of the
-     * factories have methods that create values from all of the property types.)
-     * </p>
-     * 
-     * @param nodePath the path to the node containing the property; may not be null
-     * @param propertyName the name of the property to be set
-     * @param values the value(s) for the property; may be empty if any existing property is to be removed
-     */
-    void setProperty( Path nodePath,
-                      Name propertyName,
-                      Object... values );
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerOutput.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers/SequencerOutput.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerOutput.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/SequencerOutput.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,86 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.sequencer;
+
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * Interface for sequencers to use to generate their output.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public interface SequencerOutput {
+
+    /**
+     * Set the supplied property on the supplied node.
+     * <p>
+     * The {@link SequencerContext#getValueFactories() value factories} should be used to create paths, names, and values. These
+     * factories can be used to create new values or convert values from one property type to another. (Note that each of the
+     * factories have methods that create values from all of the property types.)
+     * </p>
+     * <p>
+     * This method is provided as a convenience, but it identical to creating a {@link Path} and {@link Name} using the
+     * {@link SequencerContext#getValueFactories() factories} and calling {@link #setProperty(Path, Name, Object...)}.
+     * </p>
+     * 
+     * @param nodePath the path to the node containing the property; may not be null
+     * @param propertyName the name of the property to be set
+     * @param values the value(s) for the property; may be empty if any existing property is to be removed
+     */
+    void setProperty( String nodePath,
+                      String propertyName,
+                      Object... values );
+
+    /**
+     * Set the supplied reference on the supplied node.
+     * <p>
+     * This method is provided as a convenience, but it identical to creating a {@link Path} and {@link Name} using the
+     * {@link SequencerContext#getValueFactories() factories} and calling {@link #setProperty(Path, Name, Object...)}.
+     * </p>
+     * 
+     * @param nodePath the path to the node containing the property; may not be null
+     * @param propertyName the name of the property to be set
+     * @param paths the paths to the referenced property, which may be absolute paths or relative to the sequencer output node;
+     *        may be empty if any existing property is to be removed
+     */
+    void setReference( String nodePath,
+                       String propertyName,
+                       String... paths );
+
+    /**
+     * Set the supplied property on the supplied node.
+     * <p>
+     * The {@link SequencerContext#getValueFactories() value factories} should be used to create paths, names, and values. These
+     * factories can be used to create new values or convert values from one property type to another. (Note that each of the
+     * factories have methods that create values from all of the property types.)
+     * </p>
+     * 
+     * @param nodePath the path to the node containing the property; may not be null
+     * @param propertyName the name of the property to be set
+     * @param values the value(s) for the property; may be empty if any existing property is to be removed
+     */
+    void setProperty( Path nodePath,
+                      Name propertyName,
+                      Object... values );
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/StreamSequencer.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers/StreamSequencer.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/StreamSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,54 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.sequencers;
-
-import java.io.InputStream;
-
-/**
- * The interface for a DNA sequencer that processes a property as a stream to extract information from the content and store in
- * the repository.
- * <p>
- * Implementations must provide a no-argument constructor.
- * </p>
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public interface StreamSequencer {
-
-    /**
-     * Sequence the data found in the supplied stream, placing the output information into the supplied map.
-     * <p>
-     * JBoss DNA's SequencingService determines the sequencers that should be executed by monitoring the changes to one or more
-     * workspaces that it is monitoring. Changes in those workspaces are aggregated and used to determine which sequencers should
-     * be called. If the sequencer implements this interface, then this method is called with the property that is to be sequenced
-     * along with the interface used to register the output. The framework takes care of all the rest.
-     * </p>
-     * 
-     * @param stream the stream with the data to be sequenced; never <code>null</code>
-     * @param output the output from the sequencing operation; never <code>null</code>
-     * @param context the context for the sequencing operation; never <code>null</code>
-     */
-    void sequence( InputStream stream,
-                   SequencerOutput output,
-                   SequencerContext context );
-}

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/StreamSequencer.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers/StreamSequencer.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/StreamSequencer.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/StreamSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.sequencer;
+
+import java.io.InputStream;
+
+/**
+ * The interface for a DNA sequencer that processes a property as a stream to extract information from the content and store in
+ * the repository.
+ * <p>
+ * Implementations must provide a no-argument constructor.
+ * </p>
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public interface StreamSequencer {
+
+    /**
+     * Sequence the data found in the supplied stream, placing the output information into the supplied map.
+     * <p>
+     * JBoss DNA's SequencingService determines the sequencers that should be executed by monitoring the changes to one or more
+     * workspaces that it is monitoring. Changes in those workspaces are aggregated and used to determine which sequencers should
+     * be called. If the sequencer implements this interface, then this method is called with the property that is to be sequenced
+     * along with the interface used to register the output. The framework takes care of all the rest.
+     * </p>
+     * 
+     * @param stream the stream with the data to be sequenced; never <code>null</code>
+     * @param output the output from the sequencing operation; never <code>null</code>
+     * @param context the context for the sequencing operation; never <code>null</code>
+     */
+    void sequence( InputStream stream,
+                   SequencerOutput output,
+                   SequencerContext context );
+}

Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/package-info.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers/package-info.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,14 +0,0 @@
-/**
- * A sequencer in JBoss DNA is a component that is able to process information (usually the content of a file,
- * or a property value on a node) and recreate that information as a graph of structured content.  This package
- * defines the interfaces for the sequencing system.
- * <h3>StreamSequencer</h3>
- * <p>The {@link StreamSequencer} interface is a special form of sequencer that processes information coming
- * through an {@link java.io.InputStream}. Implementations are responsible for processing the content and generating
- * structured content using the supplied {@link SequencerOutput} interface.  Additional details about the information
- * being sequenced is available in the supplied {@link SequencerContext}.
- * </p>
- */
-
-package org.jboss.dna.graph.sequencers;
-

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/package-info.java (from rev 706, trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencers/package-info.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/package-info.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/sequencer/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,14 @@
+/**
+ * A sequencer in JBoss DNA is a component that is able to process information (usually the content of a file,
+ * or a property value on a node) and recreate that information as a graph of structured content.  This package
+ * defines the interfaces for the sequencing system.
+ * <h3>StreamSequencer</h3>
+ * <p>The {@link StreamSequencer} interface is a special form of sequencer that processes information coming
+ * through an {@link java.io.InputStream}. Implementations are responsible for processing the content and generating
+ * structured content using the supplied {@link SequencerOutput} interface.  Additional details about the information
+ * being sequenced is available in the supplied {@link SequencerContext}.
+ * </p>
+ */
+
+package org.jboss.dna.graph.sequencer;
+

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -32,14 +32,14 @@
 import org.jboss.dna.common.text.XmlNameEncoder;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.basic.LocalNamespaceRegistry;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.basic.LocalNamespaceRegistry;
 import org.xml.sax.Attributes;
 import org.xml.sax.ext.DefaultHandler2;
 

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -35,16 +35,16 @@
 import java.util.regex.Pattern;
 import javax.transaction.xa.XAResource;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.requests.CompositeRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.Request;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CompositeRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.Request;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -42,29 +42,29 @@
 import java.util.concurrent.TimeUnit;
 import javax.transaction.xa.XAResource;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.requests.CompositeRequest;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadNextBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
-import org.jboss.dna.graph.requests.ReadPropertyRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CompositeRequest;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+import org.jboss.dna.graph.request.ReadPropertyRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentMatcher;

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithChildren.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithChildren.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithChildren.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -26,9 +26,9 @@
 import org.hamcrest.Description;
 import org.hamcrest.Factory;
 import org.hamcrest.Matcher;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.basic.BasicPathSegment;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.basic.BasicPathSegment;
 import org.junit.matchers.IsCollectionContaining;
 import org.junit.matchers.TypeSafeMatcher;
 

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithProperty.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithProperty.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -25,8 +25,8 @@
 import org.hamcrest.Factory;
 import org.hamcrest.Matcher;
 import org.jboss.dna.graph.Node;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
 import org.junit.matchers.IsCollectionContaining;
 import org.junit.matchers.TypeSafeMatcher;
 

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryConnectionPoolTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryConnectionPoolTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryConnectionPoolTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryConnectionPoolTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,222 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import static org.jboss.dna.graph.connector.RepositorySourceLoadHarness.runLoadTest;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionPool;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class RepositoryConnectionPoolTest {
+
+    private RepositoryConnectionPool pool;
+    private RepositorySource source;
+    private ExecutionContext context;
+
+    @Before
+    public void beforeEach() {
+        source = new TimeDelayingRepositorySource("source 1");
+        pool = new RepositoryConnectionPool(source, 1, 1, 100, TimeUnit.SECONDS);
+        context = null;
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        pool.shutdown();
+        pool.awaitTermination(2, TimeUnit.SECONDS);
+    }
+
+    @Test
+    public void shouldBeCreatedInRunningState() {
+        assertThat(pool.isShutdown(), is(false));
+        assertThat(pool.isTerminating(), is(false));
+        assertThat(pool.isTerminated(), is(false));
+        assertThat(pool.getTotalConnectionsCreated(), is(0l));
+        assertThat(pool.getTotalConnectionsUsed(), is(0l));
+    }
+
+    @Test
+    public void shouldShutdownWhenNoConnectionsWereCreatedOrUsed() throws InterruptedException {
+        assertThat(pool.isShutdown(), is(false));
+        assertThat(pool.isTerminating(), is(false));
+        assertThat(pool.isTerminated(), is(false));
+        assertThat(pool.getTotalConnectionsCreated(), is(0l));
+        assertThat(pool.getTotalConnectionsUsed(), is(0l));
+
+        for (int i = 0; i != 4; ++i) {
+            pool.shutdown();
+            assertThat(pool.isShutdown() || pool.isTerminating() || pool.isTerminated(), is(true));
+            pool.awaitTermination(2, TimeUnit.SECONDS);
+            assertThat(pool.isTerminated(), is(true));
+            assertThat(pool.getTotalConnectionsCreated(), is(0l));
+            assertThat(pool.getTotalConnectionsUsed(), is(0l));
+        }
+    }
+
+    @Test
+    public void shouldCreateConnectionAndRecoverWhenClosed() throws RepositorySourceException {
+        assertThat(pool.getTotalConnectionsCreated(), is(0l));
+        assertThat(pool.getTotalConnectionsUsed(), is(0l));
+
+        RepositoryConnection conn = pool.getConnection();
+        assertThat(conn, is(notNullValue()));
+        assertThat(pool.getTotalConnectionsCreated(), is(1l));
+        assertThat(pool.getTotalConnectionsUsed(), is(1l));
+        assertThat(pool.getPoolSize(), is(1));
+
+        conn.close();
+
+        assertThat(pool.getTotalConnectionsCreated(), is(1l));
+        assertThat(pool.getTotalConnectionsUsed(), is(1l));
+        assertThat(pool.getPoolSize(), is(1));
+    }
+
+    @Test
+    public void shouldAllowShutdownToBeCalledMultipleTimesEvenWhenShutdown()
+        throws RepositorySourceException, InterruptedException {
+        assertThat(pool.getTotalConnectionsCreated(), is(0l));
+        assertThat(pool.getTotalConnectionsUsed(), is(0l));
+
+        RepositoryConnection conn = pool.getConnection();
+        assertThat(conn, is(notNullValue()));
+        assertThat(pool.getTotalConnectionsCreated(), is(1l));
+        assertThat(pool.getTotalConnectionsUsed(), is(1l));
+        assertThat(pool.getPoolSize(), is(1));
+
+        conn.close();
+
+        assertThat(pool.getTotalConnectionsCreated(), is(1l));
+        assertThat(pool.getTotalConnectionsUsed(), is(1l));
+        assertThat(pool.getPoolSize(), is(1));
+
+        pool.shutdown();
+        pool.shutdown();
+        pool.awaitTermination(2, TimeUnit.SECONDS);
+        assertThat(pool.isTerminated(), is(true));
+        assertThat(pool.getTotalConnectionsCreated(), is(1l));
+        assertThat(pool.getTotalConnectionsUsed(), is(1l));
+        pool.shutdown();
+        pool.awaitTermination(2, TimeUnit.SECONDS);
+        pool.shutdown();
+        pool.awaitTermination(2, TimeUnit.SECONDS);
+    }
+
+    @Test( expected = IllegalStateException.class )
+    public void shouldNotCreateConnectionIfPoolIsNotRunning() throws RepositorySourceException, InterruptedException {
+        pool.shutdown();
+        pool.awaitTermination(2, TimeUnit.SECONDS);
+        assertThat(pool.isTerminated(), is(true));
+        assertThat(pool.getTotalConnectionsCreated(), is(0l));
+        assertThat(pool.getTotalConnectionsUsed(), is(0l));
+        pool.getConnection(); // this should fail with illegal state
+    }
+
+    @Test
+    public void shouldAllowConnectionsToBeClosedMoreThanOnceWithNoIllEffects() throws RepositorySourceException {
+        assertThat(pool.getTotalConnectionsCreated(), is(0l));
+        assertThat(pool.getTotalConnectionsUsed(), is(0l));
+
+        RepositoryConnection conn = pool.getConnection();
+        assertThat(conn, is(notNullValue()));
+        assertThat(pool.getTotalConnectionsCreated(), is(1l));
+        assertThat(pool.getTotalConnectionsUsed(), is(1l));
+        assertThat(pool.getPoolSize(), is(1));
+
+        conn.close();
+        conn.close();
+    }
+
+    @Test
+    public void shouldBlockClientsWhenNotEnoughConnections() throws Exception {
+        int numConnectionsInPool = 1;
+        int numClients = 2;
+        RepositoryConnectionPool pool = new RepositoryConnectionPool(source);
+        pool.setCorePoolSize(numConnectionsInPool);
+        pool.setMaximumPoolSize(numConnectionsInPool);
+        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
+        runLoadTest(context, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+        pool.shutdown();
+        pool.awaitTermination(4, TimeUnit.SECONDS);
+    }
+
+    @Test
+    public void shouldLimitClientsToRunSequentiallyWithOneConnectionInPool() throws Exception {
+        int numConnectionsInPool = 1;
+        int numClients = 3;
+        RepositoryConnectionPool pool = new RepositoryConnectionPool(source);
+        pool.setCorePoolSize(numConnectionsInPool);
+        pool.setMaximumPoolSize(numConnectionsInPool);
+        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
+        runLoadTest(context, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+        pool.shutdown();
+        pool.awaitTermination(4, TimeUnit.SECONDS);
+    }
+
+    @Test
+    public void shouldClientsToRunConncurrentlyWithTwoConnectionsInPool() throws Exception {
+        int numConnectionsInPool = 2;
+        int numClients = 10;
+        RepositoryConnectionPool pool = new RepositoryConnectionPool(source);
+        pool.setCorePoolSize(numConnectionsInPool);
+        pool.setMaximumPoolSize(numConnectionsInPool);
+        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
+        runLoadTest(context, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+        pool.shutdown();
+        pool.awaitTermination(4, TimeUnit.SECONDS);
+    }
+
+    @Ignore( "doesn't run on hudson" )
+    @Test
+    public void shouldClientsToRunConncurrentlyWithMultipleConnectionInPool() throws Exception {
+        int numConnectionsInPool = 10;
+        int numClients = 50;
+        RepositoryConnectionPool pool = new RepositoryConnectionPool(source);
+        pool.setCorePoolSize(numConnectionsInPool);
+        pool.setMaximumPoolSize(numConnectionsInPool);
+        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(20);
+        List<Future<Integer>> results = runLoadTest(context, pool, numClients, 200, TimeUnit.MILLISECONDS, operationFactory);
+        int total = 0;
+        for (Future<Integer> result : results) {
+            assertThat(result.isDone(), is(true));
+            if (result.isDone()) total += result.get();
+        }
+        assertThat(total, is(20 * numClients));
+        pool.shutdown();
+        pool.awaitTermination(4, TimeUnit.SECONDS);
+    }
+
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryConnectionPoolTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperation.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperation.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperation.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperation.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,70 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+
+/**
+ * An operation that runs against a repository connection.
+ * 
+ * @author Randall Hauch
+ * @param <T> the type of result returned by the client
+ */
+public interface RepositoryOperation<T> {
+
+    /**
+     * Get the name of this operation.
+     * 
+     * @return the operation's name
+     */
+    String getName();
+
+    /**
+     * Run the operation using the supplied connection.
+     * 
+     * @param context the environment in which this operation is executing; may not be null
+     * @param connection the connection; may not be null
+     * @return the result of the operation
+     * @throws RepositorySourceException if there is a problem with the connection
+     * @throws InterruptedException if this thread was interrupted
+     */
+    T run( ExecutionContext context,
+           RepositoryConnection connection ) throws RepositorySourceException, InterruptedException;
+
+    /**
+     * A factory interface for creating repository operations.
+     * 
+     * @param <T> the type of result for the operations
+     * @author Randall Hauch
+     */
+    public static interface Factory<T> {
+
+        /**
+         * Create a repository operation that returns the result of type T.
+         * 
+         * @return the operation
+         */
+        RepositoryOperation<T> create();
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperation.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperations.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperations.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperations.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperations.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Callable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.LogContext;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionPool;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+
+/**
+ * @author Randall Hauch
+ */
+public class RepositoryOperations {
+
+    /**
+     * Call the supplied operation, using a connection from this pool.
+     * 
+     * @param <T> the return type for the operation
+     * @param context the context in which the operation is to execute; may not be null
+     * @param pool the pool to use
+     * @param operation the operation to be run using a new connection obtained from the factory
+     * @return the results from the operation
+     * @throws RepositorySourceException if there was an error obtaining the new connection
+     * @throws InterruptedException if the thread was interrupted during the operation
+     * @throws IllegalArgumentException if the operation is null
+     * @see #createCallable(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
+     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, Iterable)
+     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, RepositoryOperation...)
+     */
+    public static <T> T call( ExecutionContext context,
+                              RepositoryConnectionPool pool,
+                              RepositoryOperation<T> operation ) throws RepositorySourceException, InterruptedException {
+        CheckArg.isNotNull(operation, "repository operation");
+        // Get a connection ...
+        T result = null;
+        LogContext.set("context", operation.getName());
+        RepositoryConnection conn = pool.getConnection();
+        try {
+            // And run the client with the connection ...
+            result = operation.run(context, conn);
+        } finally {
+            conn.close();
+        }
+        LogContext.clear();
+        return result;
+    }
+
+    /**
+     * Return a callable object that, when run, performs the supplied repository operation against a connection obtained from the
+     * supplied factory.
+     * 
+     * @param <T> the return type for the operation
+     * @param context the context in which the operation is to execute; may not be null
+     * @param pool the pool to use
+     * @param operation the operation to be run using a new connection obtained from the factory
+     * @return the callable
+     * @see #call(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
+     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, Iterable)
+     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, RepositoryOperation...)
+     */
+    public static <T> Callable<T> createCallable( final ExecutionContext context,
+                                                  final RepositoryConnectionPool pool,
+                                                  final RepositoryOperation<T> operation ) {
+        CheckArg.isNotNull(operation, "repository operation");
+        return new Callable<T>() {
+
+            /**
+             * Execute by getting a connection from this pool, running the client, and return the connection to the pool.
+             * 
+             * @return the operation's result
+             * @throws Exception
+             */
+            public T call() throws Exception {
+                return RepositoryOperations.call(context, pool, operation);
+            }
+        };
+    }
+
+    /**
+     * Return a collection of callable objects that, when run, perform the supplied repository operations against connections in
+     * this pool.
+     * 
+     * @param <T> the return type for the operations
+     * @param context the context in which the operation is to execute; may not be null
+     * @param pool the pool to use
+     * @param operations the operations to be run using connections from the factory
+     * @return the collection of callables
+     * @see #call(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
+     * @see #createCallable(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
+     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, Iterable)
+     */
+    public static <T> List<Callable<T>> createCallables( final ExecutionContext context,
+                                                         final RepositoryConnectionPool pool,
+                                                         final RepositoryOperation<T>... operations ) {
+        List<Callable<T>> callables = new ArrayList<Callable<T>>();
+        for (final RepositoryOperation<T> operation : operations) {
+            callables.add(createCallable(context, pool, operation));
+        }
+        return callables;
+    }
+
+    /**
+     * Return a collection of callable objects that, when run, perform the supplied repository operations against connections in
+     * this pool.
+     * 
+     * @param <T> the return type for the operations
+     * @param context the context in which the operation is to execute; may not be null
+     * @param pool the pool to use
+     * @param operations the operations to be run using connections from the factory
+     * @return the collection of callables
+     * @see #call(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
+     * @see #createCallable(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
+     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, RepositoryOperation...)
+     */
+    public static <T> List<Callable<T>> createCallables( final ExecutionContext context,
+                                                         final RepositoryConnectionPool pool,
+                                                         Iterable<RepositoryOperation<T>> operations ) {
+        List<Callable<T>> callables = new ArrayList<Callable<T>>();
+        for (final RepositoryOperation<T> operation : operations) {
+            callables.add(createCallable(context, pool, operation));
+        }
+        return callables;
+    }
+
+    /**
+     * Return a collection of callable objects that, when run, perform the supplied repository operations against connections in
+     * this pool.
+     * 
+     * @param <T> the return type for the operations
+     * @param context the context in which the operation is to execute; may not be null
+     * @param pool the pool to use
+     * @param operations the operations to be run using connections from the factory
+     * @return the collection of callables
+     * @see #call(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
+     * @see #createCallable(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
+     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, RepositoryOperation...)
+     */
+    public static <T> List<Callable<T>> createCallables( final ExecutionContext context,
+                                                         final RepositoryConnectionPool pool,
+                                                         Iterator<RepositoryOperation<T>> operations ) {
+        List<Callable<T>> callables = new ArrayList<Callable<T>>();
+        while (operations.hasNext()) {
+            final RepositoryOperation<T> operation = operations.next();
+            callables.add(createCallable(context, pool, operation));
+        }
+        return callables;
+    }
+
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositoryOperations.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositorySourceLoadHarness.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositorySourceLoadHarness.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositorySourceLoadHarness.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositorySourceLoadHarness.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,247 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import org.jboss.dna.common.i18n.MockI18n;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionPool;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.basic.RootPath;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+
+/**
+ * A test harness for using repository connections under load.
+ * 
+ * @author Randall Hauch
+ */
+public class RepositorySourceLoadHarness {
+
+    public static Future<Integer> execute( RepositoryConnectionPool pool,
+                                           ExecutionContext context,
+                                           long maxTime,
+                                           TimeUnit maxTimeUnit ) throws InterruptedException {
+        int numTimes = 1;
+        int numClients = 1;
+        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(numTimes);
+        List<Future<Integer>> results = runLoadTest(context, pool, numClients, maxTime, maxTimeUnit, operationFactory);
+        return results.get(0);
+    }
+
+    public static <T> List<Future<T>> runLoadTest( ExecutionContext context,
+                                                   RepositoryConnectionPool pool,
+                                                   int numClients,
+                                                   long maxTime,
+                                                   TimeUnit maxTimeUnit,
+                                                   RepositoryOperation.Factory<T> clientFactory ) throws InterruptedException {
+        // Create the clients ...
+        Collection<RepositoryOperation<T>> clients = new ArrayList<RepositoryOperation<T>>();
+        for (int i = 0; i != numClients; ++i) {
+            clients.add(clientFactory.create());
+        }
+
+        // and run the test ...
+        return runLoadTest(context, pool, maxTime, maxTimeUnit, clients);
+    }
+
+    public static <T> List<Future<T>> runLoadTest( ExecutionContext context,
+                                                   RepositoryConnectionPool pool,
+                                                   long maxTime,
+                                                   TimeUnit maxTimeUnit,
+                                                   RepositoryOperation<T>... clients ) throws InterruptedException {
+        // Create the client collection ...
+        Collection<RepositoryOperation<T>> clientCollection = new ArrayList<RepositoryOperation<T>>();
+        for (RepositoryOperation<T> client : clients) {
+            if (client != null) clientCollection.add(client);
+        }
+        // and run the test ...
+        return runLoadTest(context, pool, maxTime, maxTimeUnit, clientCollection);
+    }
+
+    public static <T> List<Future<T>> runLoadTest( ExecutionContext context,
+                                                   RepositoryConnectionPool pool,
+                                                   long maxTime,
+                                                   TimeUnit maxTimeUnit,
+                                                   Collection<RepositoryOperation<T>> clients ) throws InterruptedException {
+        assert pool != null;
+        assert clients != null;
+        assert clients.size() > 0;
+
+        // Create an Executor Service, using a thread factory that makes the first 'n' thread all wait for each other ...
+        ExecutorService clientPool = null;
+        if (clients.size() == 1) {
+            clientPool = Executors.newSingleThreadExecutor();
+        } else {
+            final ThreadFactory threadFactory = new TestThreadFactory(clients.size());
+            clientPool = Executors.newFixedThreadPool(clients.size(), threadFactory);
+        }
+
+        try {
+            // Wrap each client by a callable and by another that uses a latch ...
+            List<Callable<T>> callables = RepositoryOperations.createCallables(context, pool, clients);
+
+            // Run the tests ...
+            List<Future<T>> futures = clientPool.invokeAll(callables, maxTime, maxTimeUnit);
+            return futures;
+        } finally {
+            // Shut down the pool of clients ...
+            clientPool.shutdown();
+            if (!clientPool.awaitTermination(5, TimeUnit.SECONDS)) {
+                String msg = "Unable to shutdown clients after 5 seconds";
+                Logger.getLogger(RepositorySourceLoadHarness.class).error(MockI18n.passthrough, msg);
+            }
+        }
+
+    }
+
+    /**
+     * A thread factory that makes an initial set of threads wait until all of those threads are created and ready. This is useful
+     * in testing to ensure that the first threads created don't get a jump start.
+     * 
+     * @author Randall Hauch
+     */
+    protected static class TestThreadFactory implements ThreadFactory {
+
+        protected final int totalNumberOfThreads;
+        protected final CountDownLatch latch;
+
+        public TestThreadFactory( int numberOfThreadsToWait ) {
+            this.latch = new CountDownLatch(numberOfThreadsToWait);
+            this.totalNumberOfThreads = numberOfThreadsToWait;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Thread newThread( Runnable runnable ) {
+            return new Thread(runnable) {
+
+                /**
+                 * {@inheritDoc}
+                 */
+                @Override
+                public void run() {
+                    if (totalNumberOfThreads > 1) {
+                        // There are other threads, and we want to synchronize with them ...
+                        try {
+                            // Count down the number of threads that are to reach this point (if 0, this doesn't do anything)
+                            latch.countDown();
+                            // Wait for all threads to reach this point ...
+                            latch.await();
+                        } catch (InterruptedException e) {
+                            throw new RuntimeException(e);
+                        }
+                    }
+                    super.run();
+                }
+            };
+        }
+    }
+
+    /**
+     * Return an operation factory that produces {@link RepositoryOperation} instances that each call
+     * {@link RepositoryConnection#execute(ExecutionContext, org.jboss.dna.graph.request.Request)} the supplied number of times,
+     * intermixed with random math operations and {@link Thread#yield() yielding}.
+     * 
+     * @param callsPerOperation the number of <code>load</code> calls per RepositoryOperation
+     * @return the factory
+     */
+    public static RepositoryOperation.Factory<Integer> createMultipleLoadOperationFactory( final int callsPerOperation ) {
+        return new RepositoryOperation.Factory<Integer>() {
+
+            public RepositoryOperation<Integer> create() {
+                return new CallLoadMultipleTimes(callsPerOperation);
+            }
+        };
+    }
+
+    public static class CallLoadMultipleTimes implements RepositoryOperation<Integer> {
+
+        private final int count;
+
+        public CallLoadMultipleTimes( int count ) {
+            Logger.getLogger(RepositorySourceLoadHarness.class).debug("Creating repository operation to call {0} times", count);
+            this.count = count;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public String getName() {
+            return Thread.currentThread().getName() + "-CallLoadMultipleTimes";
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryOperation#run(org.jboss.dna.graph.ExecutionContext,
+         *      org.jboss.dna.graph.connector.RepositoryConnection)
+         */
+        public Integer run( ExecutionContext context,
+                            RepositoryConnection connection ) throws RepositorySourceException {
+            Logger.getLogger(RepositorySourceLoadHarness.class).debug("Running {0} operation", this.getClass().getSimpleName());
+            int total = count;
+            for (int i = 0; i != count; ++i) {
+                // Add two random numbers ...
+                int int1 = random(this.hashCode() ^ (int)System.nanoTime() * i);
+                if (i % 2 == 0) {
+                    Thread.yield();
+                }
+                connection.execute(context, new ReadNodeRequest(new Location(RootPath.INSTANCE)));
+                int int2 = random(this.hashCode() ^ (int)System.nanoTime() + i);
+                total += Math.min(Math.abs(Math.max(int1, int2) + int1 * int2 / 3), count);
+            }
+            Logger.getLogger(RepositorySourceLoadHarness.class).debug("Finishing {0} operation", this.getClass().getSimpleName());
+            return total < count ? total : count; // should really always return count
+        }
+    }
+
+    /**
+     * A "random-enough" number generator that is cheap and that has no synchronization issues (like some other random number
+     * generators).
+     * <p>
+     * This was taken from <a href="http://wwww.jcip.org">Java Concurrency In Practice</a> (page 253).
+     * </p>
+     * 
+     * @param seed the seed, typically based on a hash code and nanoTime
+     * @return a number that is "random enough"
+     */
+    public static int random( int seed ) {
+        seed ^= (seed << 6);
+        seed ^= (seed >>> 21);
+        seed ^= (seed << 7);
+        return seed;
+    }
+
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/RepositorySourceLoadHarness.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepository.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepository.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepository.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepository.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,240 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.basic.RootPath;
+
+/**
+ * A very simple repository that maintains properties for nodes identified by a path, and computes the children based upon the set
+ * of paths registered in the {@link #getData() data}.
+ * <p>
+ * Note that the repository does not automatically rename same-name siblings when nodes are
+ * {@link #delete(ExecutionContext, String) deleted} or {@link #create(ExecutionContext, String) explicitly} or
+ * {@link #setProperty(ExecutionContext, String, String, Object...) implicitly} created.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public class SimpleRepository {
+
+    public static final Name DEFAULT_UUID_PROPERTY_NAME = DnaLexicon.UUID;
+
+    private static final ConcurrentMap<String, SimpleRepository> repositoriesByName = new ConcurrentHashMap<String, SimpleRepository>();
+
+    public static SimpleRepository get( String name ) {
+        SimpleRepository newRepository = new SimpleRepository(name);
+        SimpleRepository repository = repositoriesByName.putIfAbsent(name, newRepository);
+        return repository != null ? repository : newRepository;
+    }
+
+    public static void shutdownAll() {
+        for (SimpleRepository repository : repositoriesByName.values()) {
+            repository.shutdown();
+        }
+    }
+
+    private ConcurrentMap<Path, Map<Name, Property>> data = new ConcurrentHashMap<Path, Map<Name, Property>>();
+    private final String repositoryName;
+    private boolean shutdown = false;
+
+    public SimpleRepository( String repositoryName ) {
+        this.repositoryName = repositoryName;
+        // if (repositoriesByName.putIfAbsent(repositoryName, this) != null) {
+        // throw new IllegalArgumentException("Repository \"" + repositoryName + "\" already exists and may not be recreated");
+        // }
+        // Create a root node ...
+        data.putIfAbsent(RootPath.INSTANCE, new HashMap<Name, Property>());
+    }
+
+    /**
+     * @return repositoryName
+     */
+    public String getRepositoryName() {
+        return repositoryName;
+    }
+
+    /**
+     * Get the current modifiable map of property data
+     * 
+     * @return data
+     */
+    public ConcurrentMap<Path, Map<Name, Property>> getData() {
+        return data;
+    }
+
+    /**
+     * Utility method to help set the property on the node given by the supplied path. If the node does not exist, it will be
+     * created.
+     * 
+     * @param context the execution context; may not be null
+     * @param path the path to the node; may not be null
+     * @param propertyName the property name; may not be null
+     * @param values the values of the property
+     * @return this repository, for method chaining
+     */
+    public SimpleRepository setProperty( ExecutionContext context,
+                                         String path,
+                                         String propertyName,
+                                         Object... values ) {
+        NameFactory nameFactory = context.getValueFactories().getNameFactory();
+        return setProperty(context, path, nameFactory.create(propertyName), values);
+    }
+
+    /**
+     * Utility method to help set the property on the node given by the supplied path. If the node does not exist, it will be
+     * created.
+     * 
+     * @param context the execution context; may not be null
+     * @param path the path to the node; may not be null
+     * @param propertyName the property name; may not be null
+     * @param values the values of the property
+     * @return this repository, for method chaining
+     */
+    public SimpleRepository setProperty( ExecutionContext context,
+                                         String path,
+                                         Name propertyName,
+                                         Object... values ) {
+        Logger logger = context.getLogger(getClass());
+        if (logger.isTraceEnabled()) {
+            logger.trace("Setting property {0} on {1} to {2}", propertyName, path, Arrays.asList(values));
+        }
+        PathFactory pathFactory = context.getValueFactories().getPathFactory();
+        PropertyFactory propertyFactory = context.getPropertyFactory();
+        Path pathObj = pathFactory.create(path);
+        if (!pathObj.isRoot()) {
+            create(context, pathObj.getParent().getString(context.getNamespaceRegistry()));
+        }
+        Property property = propertyFactory.create(propertyName, values);
+        Map<Name, Property> newProperties = new HashMap<Name, Property>();
+        Map<Name, Property> existingProperties = data.putIfAbsent(pathObj, newProperties);
+        if (existingProperties == null) {
+            existingProperties = newProperties;
+            UUID uuid = context.getValueFactories().getUuidFactory().create();
+            Property uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID, uuid);
+            newProperties.put(DnaLexicon.UUID, uuidProperty);
+        }
+        existingProperties.put(property.getName(), property);
+        return this;
+    }
+
+    /**
+     * Create the node if it does not exist.
+     * 
+     * @param context the execution context; may not be null
+     * @param path the path to the node; may not be null
+     * @return this repository, for method chaining
+     */
+    public SimpleRepository create( ExecutionContext context,
+                                    String path ) {
+        context.getLogger(getClass()).trace("Creating node {0}", path);
+        PathFactory pathFactory = context.getValueFactories().getPathFactory();
+        Path pathObj = pathFactory.create(path);
+        Path ancestorPath = pathObj;
+        while (!ancestorPath.isRoot()) {
+            // Add a UUID property ...
+            if (!data.containsKey(ancestorPath)) {
+                Map<Name, Property> props = new HashMap<Name, Property>();
+                UUID uuid = context.getValueFactories().getUuidFactory().create();
+                Property uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID, uuid);
+                props.put(DnaLexicon.UUID, uuidProperty);
+                data.putIfAbsent(ancestorPath, props);
+            }
+            ancestorPath = ancestorPath.getParent();
+        }
+        UUID uuid = context.getValueFactories().getUuidFactory().create();
+        Property uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID, uuid);
+        data.get(pathObj).put(DnaLexicon.UUID, uuidProperty);
+        return this;
+    }
+
+    /**
+     * Delete the branch rooted at the supplied path, if it exists.
+     * 
+     * @param context the execution context; may not be null
+     * @param path the path to the branch's top node; may not be null
+     * @return this repository, for method chaining
+     */
+    public SimpleRepository delete( ExecutionContext context,
+                                    String path ) {
+        context.getLogger(getClass()).trace("Deleting node {0}", path);
+        PathFactory pathFactory = context.getValueFactories().getPathFactory();
+        Path pathObj = pathFactory.create(path);
+        List<Path> pathsToRemove = new LinkedList<Path>();
+        for (Path nodePath : data.keySet()) {
+            if (nodePath.equals(pathObj) || nodePath.isDecendantOf(pathObj)) {
+                pathsToRemove.add(nodePath);
+            }
+        }
+        for (Path pathToRemove : pathsToRemove) {
+            data.remove(pathToRemove);
+        }
+        return this;
+    }
+
+    public List<Path> getChildren( ExecutionContext context,
+                                   Path path ) {
+        List<Path> children = new LinkedList<Path>();
+        for (Path nodePath : data.keySet()) {
+            if (nodePath.isRoot()) continue;
+            if (nodePath.getParent().equals(path)) {
+                children.add(nodePath);
+            }
+        }
+        return children;
+    }
+
+    /**
+     * @param data new new map of property data
+     */
+    public void setData( ConcurrentMap<Path, Map<Name, Property>> data ) {
+        this.data = data;
+    }
+
+    public boolean isShutdown() {
+        return shutdown;
+    }
+
+    public void shutdown() {
+        shutdown = true;
+        repositoriesByName.remove(this.repositoryName);
+    }
+
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepository.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepositorySource.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepositorySource.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepositorySource.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,457 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.naming.Reference;
+import javax.transaction.xa.XAResource;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.cache.CachePolicy;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
+
+/**
+ * A {@link RepositorySource} for a {@link SimpleRepository simple repository}.
+ * 
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public class SimpleRepositorySource implements RepositorySource {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * The default limit is {@value} for retrying {@link RepositoryConnection connection} calls to the underlying source.
+     */
+    public static final int DEFAULT_RETRY_LIMIT = 0;
+
+    protected static final RepositorySourceCapabilities CAPABILITIES = new RepositorySourceCapabilities(true, true);
+
+    private String repositoryName;
+    private String name;
+    private final AtomicInteger retryLimit = new AtomicInteger(DEFAULT_RETRY_LIMIT);
+    private CachePolicy defaultCachePolicy;
+    private transient RepositoryContext repositoryContext;
+
+    public SimpleRepositorySource() {
+        super();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
+     */
+    public void initialize( RepositoryContext context ) throws RepositorySourceException {
+        this.repositoryContext = context;
+    }
+
+    /**
+     * @return repositoryContext
+     */
+    public RepositoryContext getRepositoryContext() {
+        return repositoryContext;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#getName()
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @param name Sets name to the specified value.
+     */
+    public void setName( String name ) {
+        this.name = name;
+    }
+
+    /**
+     * @return repositoryName
+     */
+    public String getRepositoryName() {
+        return repositoryName;
+    }
+
+    /**
+     * @param repositoryName Sets repositoryName to the specified value.
+     */
+    public void setRepositoryName( String repositoryName ) {
+        this.repositoryName = repositoryName;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
+     */
+    public int getRetryLimit() {
+        return retryLimit.get();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
+     */
+    public void setRetryLimit( int limit ) {
+        retryLimit.set(limit < 0 ? 0 : limit);
+    }
+
+    /**
+     * @return defaultCachePolicy
+     */
+    public CachePolicy getDefaultCachePolicy() {
+        return defaultCachePolicy;
+    }
+
+    /**
+     * @param defaultCachePolicy Sets defaultCachePolicy to the specified value.
+     */
+    public void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) {
+        this.defaultCachePolicy = defaultCachePolicy;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see javax.naming.Referenceable#getReference()
+     */
+    public Reference getReference() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof SimpleRepositorySource) {
+            SimpleRepositorySource that = (SimpleRepositorySource)obj;
+            if (!this.getName().equals(that.getName())) return false;
+            if (!this.getRepositoryName().equals(that.getRepositoryName())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
+     */
+    public RepositorySourceCapabilities getCapabilities() {
+        return CAPABILITIES;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
+     */
+    public RepositoryConnection getConnection() throws RepositorySourceException {
+        String reposName = this.getRepositoryName();
+        if (reposName == null) throw new RepositorySourceException("Invalid repository source: missing repository name");
+        SimpleRepository repository = SimpleRepository.get(reposName);
+        if (repository == null) {
+            throw new RepositorySourceException(this.getName(), "Unable to find repository \"" + reposName + "\"");
+        }
+        return new Connection(repository, this.getDefaultCachePolicy());
+    }
+
+    protected class Connection implements RepositoryConnection {
+
+        private RepositorySourceListener listener;
+        private final SimpleRepository repository;
+        private final CachePolicy defaultCachePolicy;
+
+        protected Connection( SimpleRepository repository,
+                              CachePolicy defaultCachePolicy ) {
+            assert repository != null;
+            this.repository = repository;
+            this.defaultCachePolicy = defaultCachePolicy;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryConnection#close()
+         */
+        public void close() {
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+         *      org.jboss.dna.graph.request.Request)
+         */
+        public void execute( ExecutionContext context,
+                             Request request ) throws RepositorySourceException {
+            final PathFactory pathFactory = context.getValueFactories().getPathFactory();
+            final SimpleRepository repository = this.repository;
+            RequestProcessor processor = new RequestProcessor(getSourceName(), context) {
+                @Override
+                public void process( ReadAllChildrenRequest request ) {
+                    Map<Name, Property> properties = getProperties(request, request.of());
+                    Path targetPath = request.of().getPath();
+                    if (properties == null) return;
+                    Property uuidProperty = properties.get(DnaLexicon.UUID);
+                    // Iterate through all of the properties, looking for any paths that are children of the path ...
+                    Map<Path, Map<Name, Property>> data = repository.getData();
+                    List<Path.Segment> childSegments = new LinkedList<Path.Segment>();
+                    for (Path path : data.keySet()) {
+                        if (!path.isRoot() && path.getParent().equals(targetPath)) {
+                            childSegments.add(path.getLastSegment());
+                        }
+                    }
+                    // This does not store children order, so sort ...
+                    Collections.sort(childSegments);
+                    // Now get the children ...
+                    for (Path.Segment childSegment : childSegments) {
+                        Path childPath = pathFactory.create(targetPath, childSegment);
+                        Map<Name, Property> childProperties = repository.getData().get(childPath);
+                        Property childUuidProperty = childProperties.get(DnaLexicon.UUID);
+                        request.addChild(childPath, childUuidProperty);
+                    }
+                    request.setActualLocationOfNode(request.of().with(uuidProperty));
+                }
+
+                @Override
+                public void process( ReadAllPropertiesRequest request ) {
+                    Map<Name, Property> properties = getProperties(request, request.at());
+                    if (properties == null) return;
+                    Property uuidProperty = properties.get(DnaLexicon.UUID);
+                    for (Property property : properties.values()) {
+                        if (property != uuidProperty) request.addProperty(property);
+                    }
+                    request.setActualLocationOfNode(request.at().with(uuidProperty));
+                }
+
+                @Override
+                public void process( CopyBranchRequest request ) {
+                    throw new UnsupportedOperationException();
+                }
+
+                @Override
+                public void process( CreateNodeRequest request ) {
+                    Path parentPath = request.under().getPath();
+                    ExecutionContext context = getExecutionContext();
+                    Path targetPath = context.getValueFactories().getPathFactory().create(parentPath, request.named());
+                    final Name childName = request.named();
+                    Map<Name, Property> properties = null;
+                    // Create the path for the new node, but we need to look for existing SNS ...
+                    switch (request.conflictBehavior()) {
+                        case DO_NOT_REPLACE:
+                        case APPEND:
+                            // Need to look for existing SNS ...
+                            int lastSns = 0;
+                            for (Path child : repository.getChildren(context, parentPath)) {
+                                Path.Segment segment = child.getLastSegment();
+                                if (segment.getName().equals(childName)) {
+                                    if (segment.hasIndex()) lastSns = segment.getIndex();
+                                    else ++lastSns;
+                                }
+                                targetPath = context.getValueFactories().getPathFactory().create(parentPath,
+                                                                                                 request.named(),
+                                                                                                 ++lastSns);
+                            }
+                            repository.create(context, targetPath.getString(context.getNamespaceRegistry()));
+                            break;
+                        case REPLACE:
+                            // Remove any existing node with the desired target path ...
+                            repository.delete(context, targetPath.getString(context.getNamespaceRegistry()));
+                            repository.create(context, targetPath.getString(context.getNamespaceRegistry()));
+                            break;
+                        case UPDATE:
+                            // Get the existing properties (if there are any) and merge new properties,
+                            // using the desired target path ...
+                            properties = repository.getData().get(targetPath);
+                            if (properties == null) {
+                                repository.create(context, targetPath.getString(context.getNamespaceRegistry()));
+                            }
+                            break;
+                    }
+                    if (properties == null) properties = repository.getData().get(targetPath);
+                    assert properties != null;
+                    // Set the UUID if the request has one ...
+                    Property uuidProperty = request.under().getIdProperty(DnaLexicon.UUID);
+                    if (uuidProperty != null) {
+                        properties.put(uuidProperty.getName(), uuidProperty);
+                    } else {
+                        uuidProperty = properties.get(DnaLexicon.UUID);
+                    }
+                    Location actual = new Location(targetPath, uuidProperty);
+                    request.setActualLocationOfNode(actual);
+                    for (Property property : request.properties()) {
+                        if (property != null) properties.put(property.getName(), property);
+                    }
+                }
+
+                @Override
+                public void process( DeleteBranchRequest request ) {
+                    // Iterate through all of the dataq, looking for any paths that are children of the path ...
+                    Path targetPath = request.at().getPath();
+                    Map<Path, Map<Name, Property>> data = repository.getData();
+                    Map<Name, Property> properties = repository.getData().get(targetPath);
+                    Property uuidProperty = properties.get(DnaLexicon.UUID);
+                    for (Path path : data.keySet()) {
+                        if (!path.isRoot() && path.isAtOrBelow(targetPath)) {
+                            data.remove(path);
+                        }
+                    }
+                    request.setActualLocationOfNode(request.at().with(uuidProperty));
+                }
+
+                @Override
+                public void process( MoveBranchRequest request ) {
+                    throw new UnsupportedOperationException();
+                }
+
+                @Override
+                public void process( UpdatePropertiesRequest request ) {
+                    Map<Name, Property> properties = getProperties(request, request.on());
+                    if (properties == null) return;
+                    Property uuidProperty = properties.get(DnaLexicon.UUID);
+                    for (Property property : request.properties()) {
+                        if (property != uuidProperty) properties.put(property.getName(), property);
+                    }
+                    request.setActualLocationOfNode(request.on().with(uuidProperty));
+                }
+
+                protected Map<Name, Property> getProperties( Request request,
+                                                             Location location ) {
+                    Path targetPath = location.getPath();
+                    if (targetPath == null) throw new UnsupportedOperationException();
+                    Map<Name, Property> properties = repository.getData().get(targetPath);
+                    if (properties == null) {
+                        Path ancestor = targetPath.getParent();
+                        while (ancestor != null) {
+                            if (repository.getData().get(targetPath) != null) break;
+                            ancestor = ancestor.getParent();
+                        }
+                        if (ancestor == null) ancestor = getExecutionContext().getValueFactories().getPathFactory().createRootPath();
+                        request.setError(new PathNotFoundException(location, ancestor));
+                        return null;
+                    }
+                    return properties;
+                }
+            };
+            processor.process(request);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryConnection#getDefaultCachePolicy()
+         */
+        public CachePolicy getDefaultCachePolicy() {
+            return defaultCachePolicy;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryConnection#getSourceName()
+         */
+        public String getSourceName() {
+            return SimpleRepositorySource.this.getName();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryConnection#getXAResource()
+         */
+        public XAResource getXAResource() {
+            return null;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryConnection#ping(long, java.util.concurrent.TimeUnit)
+         */
+        public boolean ping( long time,
+                             TimeUnit unit ) {
+            return true;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryConnection#setListener(org.jboss.dna.graph.connector.RepositorySourceListener)
+         */
+        public void setListener( RepositorySourceListener listener ) {
+            this.listener = listener;
+        }
+
+        /**
+         * @return listener
+         */
+        public RepositorySourceListener getListener() {
+            return listener;
+        }
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/SimpleRepositorySource.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/TimeDelayingRepositorySource.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/TimeDelayingRepositorySource.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/TimeDelayingRepositorySource.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/TimeDelayingRepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,382 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector;
+
+import static org.mockito.Mockito.mock;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.naming.Reference;
+import javax.transaction.xa.XAResource;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.cache.CachePolicy;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.request.Request;
+
+/**
+ * A simple {@link RepositorySource} that simulates an imaginary source with a built-in delay mechanism.
+ * 
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public class TimeDelayingRepositorySource implements RepositorySource {
+
+    /**
+     */
+    private static final long serialVersionUID = -2756725117087437347L;
+    /**
+     * The default limit is {@value} for retrying {@link RepositoryConnection connection} calls to the underlying source.
+     */
+    public static final int DEFAULT_RETRY_LIMIT = 0;
+
+    protected static final RepositorySourceCapabilities CAPABILITIES = new RepositorySourceCapabilities(true, true);
+
+    private String name;
+    private final AtomicInteger connectionsOpenedCount = new AtomicInteger(0);
+    private final AtomicInteger connectionsClosedCount = new AtomicInteger(0);
+    private final Set<Connection> openConnections = new CopyOnWriteArraySet<Connection>();
+    private final AtomicLong loadCount = new AtomicLong(0);
+    private final AtomicLong loadDelay = new AtomicLong(0);
+    private final AtomicLong pingCount = new AtomicLong(0);
+    private final AtomicLong pingDelay = new AtomicLong(0);
+    private final AtomicInteger retryLimit = new AtomicInteger(DEFAULT_RETRY_LIMIT);
+    private CachePolicy defaultCachePolicy;
+    private transient RepositoryContext repositoryContext;
+
+    public TimeDelayingRepositorySource( String identifier ) {
+        super();
+        this.name = identifier;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
+     */
+    public void initialize( RepositoryContext context ) throws RepositorySourceException {
+        this.repositoryContext = context;
+    }
+
+    /**
+     * @return repositoryContext
+     */
+    public RepositoryContext getRepositoryContext() {
+        return repositoryContext;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * @param name the identifier
+     */
+    public void setName( String name ) {
+        this.name = name;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
+     */
+    public int getRetryLimit() {
+        return retryLimit.get();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
+     */
+    public void setRetryLimit( int limit ) {
+        retryLimit.set(limit < 0 ? 0 : limit);
+    }
+
+    public CachePolicy getDefaultCachePolicy() {
+        return defaultCachePolicy;
+    }
+
+    public void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) {
+        this.defaultCachePolicy = defaultCachePolicy;
+    }
+
+    /**
+     * @return loadCount
+     */
+    public long getTotalExecuteCount() {
+        return this.loadCount.get();
+    }
+
+    /**
+     * @return pingCount
+     */
+    public long getTotalPingCount() {
+        return this.pingCount.get();
+    }
+
+    /**
+     * @return loadDelay
+     */
+    public long getConnectionExecuteDelayInMillis() {
+        return this.loadDelay.get();
+    }
+
+    public void setConnectionExecuteDelay( long time,
+                                           TimeUnit unit ) {
+        this.loadDelay.set(unit.toMillis(time));
+    }
+
+    /**
+     * @return pingDelay
+     */
+    public long getConnectionPingDelayInMillis() {
+        return this.pingDelay.get();
+    }
+
+    public void setConnectionPingDelay( long time,
+                                        TimeUnit unit ) {
+        this.pingDelay.set(unit.toMillis(time));
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
+     */
+    public RepositoryConnection getConnection() throws RepositorySourceException {
+        int connectionNumber = this.connectionsOpenedCount.incrementAndGet();
+        String connectionName = "Connection " + connectionNumber;
+        XAResource xaResource = newXaResource(connectionName);
+        Connection c = newConnection(connectionName, xaResource);
+        this.openConnections.add(c);
+        return c;
+    }
+
+    /**
+     * Factory method that can be overridden by subclasses. This method implementation simply creates a mock {@link XAResource}.
+     * 
+     * @param connectionName the name of the connection
+     * @return the XAResource, or null if this source does not support XA
+     */
+    protected XAResource newXaResource( String connectionName ) {
+        return mock(XAResource.class);
+    }
+
+    /**
+     * Factory method that can be overridden by subclasses. This method implementation creates a new {@link Connection} that uses
+     * standard bean properties for the various delays and counts.
+     * 
+     * @param connectionName
+     * @param xaResource
+     * @return a new Connection
+     * @throws RepositorySourceException
+     */
+    protected Connection newConnection( String connectionName,
+                                        XAResource xaResource ) throws RepositorySourceException {
+        Connection c = new Connection(connectionName, this.loadDelay.get(), this.pingDelay.get());
+        c.setXaResource(xaResource);
+        return c;
+    }
+
+    protected void close( Connection conn ) {
+        if (conn != null && this.openConnections.remove(conn)) {
+            this.connectionsClosedCount.incrementAndGet();
+            this.loadCount.addAndGet(conn.getLoadCount());
+            this.pingCount.addAndGet(conn.getPingCount());
+        }
+    }
+
+    public int getOpenConnectionCount() {
+        return this.openConnections.size();
+    }
+
+    public int getTotalConnectionsCreated() {
+        return this.connectionsOpenedCount.get();
+    }
+
+    public int getTotalConnectionsClosed() {
+        return this.connectionsClosedCount.get();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Reference getReference() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
+     */
+    public RepositorySourceCapabilities getCapabilities() {
+        return CAPABILITIES;
+    }
+
+    public class Connection implements RepositoryConnection {
+
+        private final String connectionName;
+        private final AtomicBoolean closed = new AtomicBoolean(false);
+        private final AtomicBoolean loadResponse = new AtomicBoolean(true);
+        private final AtomicBoolean pingResponse = new AtomicBoolean(true);
+        private final AtomicLong closeCount = new AtomicLong(0);
+        private final AtomicLong loadCount = new AtomicLong(0);
+        private final AtomicLong loadDelay;
+        private final AtomicLong pingCount = new AtomicLong(0);
+        private final AtomicLong pingDelay;
+        private final AtomicReference<XAResource> xaResource = new AtomicReference<XAResource>();
+
+        protected Connection( String connectionName,
+                              long loadDelay,
+                              long pingDelay ) {
+            assert connectionName != null && connectionName.trim().length() != 0;
+            this.loadDelay = new AtomicLong(loadDelay);
+            this.pingDelay = new AtomicLong(pingDelay);
+            this.connectionName = connectionName;
+        }
+
+        public String getConnectionName() {
+            return this.connectionName;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void close() {
+            this.closeCount.incrementAndGet();
+            this.closed.set(true);
+            TimeDelayingRepositorySource.this.close(this);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public String getSourceName() {
+            return TimeDelayingRepositorySource.this.getName();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public CachePolicy getDefaultCachePolicy() {
+            return TimeDelayingRepositorySource.this.getDefaultCachePolicy();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public XAResource getXAResource() {
+            return this.xaResource.get();
+        }
+
+        public void setXaResource( XAResource xaResource ) {
+            this.xaResource.set(xaResource);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+         *      org.jboss.dna.graph.request.Request)
+         */
+        public void execute( ExecutionContext context,
+                             Request request ) throws RepositorySourceException {
+            long delay = this.loadDelay.get();
+            if (delay > 0l) {
+                try {
+                    Thread.sleep(delay);
+                } catch (InterruptedException e) {
+                    Thread.interrupted();
+                    throw new RepositorySourceException(this.getSourceName(), e);
+                }
+            }
+            this.loadCount.incrementAndGet();
+        }
+
+        public void setLoadResponse( boolean response ) {
+            this.loadResponse.set(response);
+        }
+
+        public void setLoadDelay( long time,
+                                  TimeUnit unit ) {
+            this.loadDelay.set(unit.toMillis(time));
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean ping( long time,
+                             TimeUnit unit ) {
+            try {
+                Thread.sleep(this.pingDelay.get());
+            } catch (InterruptedException e) {
+                Thread.interrupted();
+                return false;
+            }
+            return this.pingResponse.get();
+        }
+
+        public void setPingResponse( boolean pingResponse ) {
+            this.pingResponse.set(pingResponse);
+        }
+
+        public void setPingDelay( long time,
+                                  TimeUnit unit ) {
+            this.pingDelay.set(unit.toMillis(time));
+        }
+
+        public long getPingCount() {
+            return this.pingCount.get();
+        }
+
+        public long getLoadCount() {
+            return this.loadCount.get();
+        }
+
+        public long getCloseCount() {
+            return this.closeCount.get();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void setListener( RepositorySourceListener listener ) {
+        }
+
+    }
+
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/TimeDelayingRepositorySource.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test)

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test/AbstractConnectorTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,615 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors.test;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import org.jboss.dna.common.stats.Stopwatch;
-import org.jboss.dna.graph.BasicExecutionContextFactory;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.ExecutionContextFactory;
-import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.Node;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.requests.Request;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-
-/**
- * A class that provides standard reading verification tests for connectors. This class is designed to be extended for each
- * connector, and in each subclass the {@link #setUpSource()} method is defined to provide a valid {@link RepositorySource} for
- * the connector to be tested.
- * <p>
- * By default, this class sets up the repository before each test is run, ensuring that all tests have a pristine environment.
- * However, subclasses with tests that never modify the repository content may wish to set up the repository only once. Note: this
- * should be used with caution, but this can be achieved by overriding {@link #afterEach()} to do nothing. The repository source
- * will be set up during the first test, and will not be shut down until {@link #afterAll() all tests have been run}.
- * </p>
- * 
- * @author Randall Hauch
- */
-public abstract class AbstractConnectorTest {
-
-    protected static ExecutionContextFactory contextFactory;
-    protected static ExecutionContext context;
-    protected static RepositorySource source;
-    protected static Graph graph;
-    private static RepositoryConnectionFactory connectionFactory;
-    private static List<RepositoryConnection> openConnections;
-    private static boolean running;
-    private static Location rootLocation;
-
-    public void startRepository() throws Exception {
-        if (!running) {
-            // Set up the connection factory to other sources ...
-
-            // Set up the execution context ...
-            contextFactory = new BasicExecutionContextFactory();
-            context = setUpExecutionContext(contextFactory);
-
-            // Set up the source ...
-            source = setUpSource();
-
-            // Now set up the connection factory ...
-            openConnections = new ArrayList<RepositoryConnection>();
-            connectionFactory = new RepositoryConnectionFactory() {
-                @SuppressWarnings( "synthetic-access" )
-                public RepositoryConnection createConnection( String sourceName ) throws RepositorySourceException {
-                    if (!source.getName().equals(sourceName)) return null;
-                    RepositoryConnection connection = source.getConnection();
-                    if (connection == null) {
-                        throw new RepositorySourceException("Unable to create a repository connection to " + source.getName());
-                    }
-                    openConnections.add(connection);
-                    return connection;
-                }
-            };
-
-            // Initialize the source with the rest of the environment ...
-            source.initialize(new RepositoryContext() {
-                public ExecutionContextFactory getExecutionContextFactory() {
-                    return contextFactory;
-                }
-
-                @SuppressWarnings( "synthetic-access" )
-                public RepositoryConnectionFactory getRepositoryConnectionFactory() {
-                    return connectionFactory;
-                }
-            });
-
-            // And set up the graph instance ...
-            graph = Graph.create(source.getName(), connectionFactory, context);
-
-            // Now have the source initialize the content (if any) ...
-            initializeContent(graph);
-            running = true;
-        }
-    }
-
-    public static void shutdownRepository() {
-        if (running) {
-            try {
-                // Shut down the connections to the source ...
-                for (RepositoryConnection connection : openConnections) {
-                    connection.close();
-                }
-            } finally {
-                running = false;
-                rootLocation = null;
-            }
-        }
-    }
-
-    /**
-     * Method that is executed before each test. By default, this method {@link #startRepository() sets up the repository}.
-     * 
-     * @throws Exception
-     */
-    @Before
-    public void beforeEach() throws Exception {
-        startRepository();
-    }
-
-    /**
-     * Method that is executed after each test. By default, this method {@link #shutdownRepository() shuts down the repository}.
-     * 
-     * @throws Exception
-     */
-    @After
-    public void afterEach() throws Exception {
-        shutdownRepository();
-    }
-
-    /**
-     * Method executed after all tests have completed. By default, this method ensures that the repository has been shut down (if
-     * this was not done in {@link #afterEach()}).
-     * 
-     * @throws Exception
-     */
-    @AfterClass
-    public static void afterAll() throws Exception {
-        shutdownRepository();
-    }
-
-    // ----------------------------------------------------------------------------------------------------------------
-    // Methods used in the initialization and set up of test methods
-    // ----------------------------------------------------------------------------------------------------------------
-
-    /**
-     * Set up the {@link ExecutionContext} for each unit test.
-     * 
-     * @param contextFactory the context factory that may be used; never null
-     * @return the execution context; may not be null
-     */
-    protected ExecutionContext setUpExecutionContext( ExecutionContextFactory contextFactory ) {
-        return contextFactory.create();
-    }
-
-    /**
-     * Set up a {@link RepositorySource} that should be used for each of the unit tests.
-     * 
-     * @return the repository source
-     * @throws Exception if there is a problem setting up the source
-     */
-    protected abstract RepositorySource setUpSource() throws Exception;
-
-    /**
-     * Initialize the content of the {@link RepositorySource} set up for each of the unit tests. This method is called shortly
-     * after {@link #setUpSource()} is called and the returned RepositorySource is
-     * {@link RepositorySource#initialize(RepositoryContext) initialized}.
-     * 
-     * @param graph the graph for the {@link RepositorySource} returned from {@link #setUpSource()}; never null
-     * @throws Exception if there is a problem initializing the source
-     */
-    protected abstract void initializeContent( Graph graph ) throws Exception;
-
-    // ----------------------------------------------------------------------------------------------------------------
-    // Helper methods commonly needed in unit tests
-    // ----------------------------------------------------------------------------------------------------------------
-
-    /**
-     * Utility to create a {@link Name} from a string.
-     * 
-     * @param name the string form of the name
-     * @return the name object
-     * @throws ValueFormatException if a name could not be created from the supplied string
-     */
-    protected Name name( String name ) {
-        return context.getValueFactories().getNameFactory().create(name);
-    }
-
-    /**
-     * Utility to create a {@link Path.Segment} from a string, where there will be no index
-     * 
-     * @param name the string form of the path segment, which may include a 1-based same-name-sibling index
-     * @return the path object
-     * @throws ValueFormatException if a path could not be created from the supplied string
-     */
-    protected Path.Segment segment( String name ) {
-        return context.getValueFactories().getPathFactory().createSegment(name);
-    }
-
-    /**
-     * Utility to create a {@link Path} from a string.
-     * 
-     * @param path the string form of the path
-     * @return the path object
-     * @throws ValueFormatException if a path could not be created from the supplied string
-     */
-    protected Path path( String path ) {
-        return context.getValueFactories().getPathFactory().create(path);
-    }
-
-    /**
-     * Utility to create a {@link Path} from a parent string and a subpath string.
-     * 
-     * @param parentPath the string form of the parent path
-     * @param subPath the string form of the subpath
-     * @return the path object
-     * @throws ValueFormatException if a path could not be created from the supplied string
-     */
-    protected Path path( String parentPath,
-                         String subPath ) {
-        return path(path(parentPath), subPath);
-    }
-
-    /**
-     * Utility to create a {@link Path} from a parent string and a subpath string.
-     * 
-     * @param parentPath the string form of the parent path
-     * @param subPath the string form of the subpath
-     * @return the path object
-     * @throws ValueFormatException if a path could not be created from the supplied string
-     */
-    protected Path path( Path parentPath,
-                         String subPath ) {
-        return context.getValueFactories().getPathFactory().create(parentPath, subPath);
-    }
-
-    /**
-     * Utility to create a {@link Location} from a string path.
-     * 
-     * @param path the string form of the path
-     * @return the location
-     */
-    protected Location location( String path ) {
-        return new Location(path(path));
-    }
-
-    /**
-     * Utility to create a {@link Location} from a UUID.
-     * 
-     * @param uuid the UUID
-     * @return the location
-     */
-    protected Location location( UUID uuid ) {
-        return new Location(uuid);
-    }
-
-    protected UUID getRootNodeUuid() {
-        if (rootLocation == null) {
-            Node root = graph.getNodeAt("/");
-            rootLocation = root.getLocation();
-        }
-        return rootLocation.getUuid();
-    }
-
-    protected String string( Object value ) {
-        if (value instanceof Property) value = ((Property)value).getFirstValue();
-        return context.getValueFactories().getStringFactory().create(value);
-    }
-
-    protected DateTime date( Object value ) {
-        if (value instanceof Property) value = ((Property)value).getFirstValue();
-        return context.getValueFactories().getDateFactory().create(value);
-    }
-
-    protected long longValue( Object value ) {
-        if (value instanceof Property) value = ((Property)value).getFirstValue();
-        return context.getValueFactories().getLongFactory().create(value);
-    }
-
-    protected Name name( Object value ) {
-        if (value instanceof Property) value = ((Property)value).getFirstValue();
-        return context.getValueFactories().getNameFactory().create(value);
-    }
-
-    // ----------------------------------------------------------------------------------------------------------------
-    // Utility method that may be used to execute requests against a repository ...
-    // ----------------------------------------------------------------------------------------------------------------
-
-    /**
-     * Submit the supplied request to the {@link #source source} for processing, and then return the request.
-     * 
-     * @param request the request to be processed
-     * @return the request after processing (for method chaining purposes)
-     * @param <T> the type of request
-     */
-    protected <T extends Request> T execute( T request ) {
-        // Get a connection ...
-        RepositoryConnection connection = connectionFactory.createConnection(source.getName());
-        try {
-            connection.execute(context, request);
-            return request;
-        } finally {
-            connection.close();
-        }
-    }
-
-    // ----------------------------------------------------------------------------------------------------------------
-    // Utility method that may be used to create content in a repository ...
-    // ----------------------------------------------------------------------------------------------------------------
-
-    /**
-     * Create a structured subgraph by generating nodes with the supplied number of properties and children, to the supplied
-     * maximum subgraph depth.
-     * 
-     * @param graph the graph that should be used; may not be null
-     * @param initialPath the path to the new subgraph, or null if the root path should be used
-     * @param depth the depth of the subgraph; must be a positive number
-     * @param numberOfChildrenPerNode the number of child nodes to create under each node
-     * @param numberOfPropertiesPerNode the number of properties to create on each node; must be 0 or more
-     * @param oneBatch true if all of the nodes are to be created in one batch
-     * @param stopwatch the stopwatch that should be used to measure the timings
-     * @return the number of nodes created in the subgraph
-     */
-    protected int createSubgraph( Graph graph,
-                                  String initialPath,
-                                  int depth,
-                                  int numberOfChildrenPerNode,
-                                  int numberOfPropertiesPerNode,
-                                  boolean oneBatch,
-                                  Stopwatch stopwatch ) {
-        return createSubgraph(graph,
-                              initialPath,
-                              depth,
-                              numberOfChildrenPerNode,
-                              numberOfPropertiesPerNode,
-                              oneBatch,
-                              stopwatch,
-                              null,
-                              null);
-    }
-
-    /**
-     * Create a structured subgraph by generating nodes with the supplied number of properties and children, to the supplied
-     * maximum subgraph depth.
-     * 
-     * @param graph the graph that should be used; may not be null
-     * @param initialPath the path to the new subgraph
-     * @param depth the depth of the subgraph; must be a positive number
-     * @param numberOfChildrenPerNode the number of child nodes to create under each node
-     * @param numberOfPropertiesPerNode the number of properties to create on each node; must be 0 or more
-     * @param oneBatch true if all of the nodes are to be created in one batch
-     * @param stopwatch the stopwatch that should be used to measure the timings
-     * @param output the writer to which metrics and messages should be written, or null if no such information should be written
-     * @param description the description of this subgraph (used for logging and printing), or null if the description should be
-     *        generated automatically
-     * @return the number of nodes created in the subgraph
-     */
-    protected int createSubgraph( Graph graph,
-                                  String initialPath,
-                                  int depth,
-                                  int numberOfChildrenPerNode,
-                                  int numberOfPropertiesPerNode,
-                                  boolean oneBatch,
-                                  Stopwatch stopwatch,
-                                  PrintStream output,
-                                  String description ) {
-        // Calculate the number of nodes that we'll created, but subtrace 1 since it doesn't create the root
-        long totalNumber = calculateTotalNumberOfNodesInTree(numberOfChildrenPerNode, depth, false);
-        if (initialPath == null) initialPath = "";
-        if (description == null) {
-            description = "" + numberOfChildrenPerNode + "x" + depth + " tree with " + numberOfPropertiesPerNode
-                          + " properties per node";
-        }
-
-        if (output != null) output.println(description + " (" + totalNumber + " nodes):");
-        long totalNumberCreated = 0;
-        Graph.Batch batch = oneBatch ? graph.batch() : null;
-        if (batch != null) {
-            totalNumberCreated += createChildren(batch,
-                                                 initialPath,
-                                                 "node",
-                                                 numberOfChildrenPerNode,
-                                                 numberOfPropertiesPerNode,
-                                                 depth,
-                                                 null); // don't output anything
-            if (stopwatch != null) stopwatch.start();
-            batch.execute();
-        } else {
-            if (stopwatch != null) stopwatch.start();
-            totalNumberCreated += createChildren(null,
-                                                 initialPath,
-                                                 "node",
-                                                 numberOfChildrenPerNode,
-                                                 numberOfPropertiesPerNode,
-                                                 depth,
-                                                 null); // don't output anything
-        }
-        if (stopwatch != null) {
-            stopwatch.stop();
-            if (output != null) {
-                long totalDurationInMicroseconds = TimeUnit.NANOSECONDS.toMicros(stopwatch.getTotalDuration().longValue());
-                long avgDuration = totalDurationInMicroseconds / totalNumber / 1000L;
-                String units = " millisecond(s)";
-                if (avgDuration == 0L) {
-                    avgDuration = totalDurationInMicroseconds / totalNumber;
-                    units = " microsecond(s)";
-                }
-                output.println("     Total = " + stopwatch.getTotalDuration() + "; avg = " + avgDuration + units);
-            }
-
-            // Perform second batch ...
-            batch = graph.batch();
-            totalNumberCreated += createChildren(batch, initialPath, "secondBranch", 2, numberOfPropertiesPerNode, 2, null);
-            Stopwatch sw = new Stopwatch();
-            sw.start();
-            batch.execute();
-            sw.stop();
-            long totalDurationInMicroseconds = TimeUnit.NANOSECONDS.toMicros(sw.getTotalDuration().longValue());
-            long avgDuration = totalDurationInMicroseconds / totalNumber / 1000L;
-            String units = " millisecond(s)";
-            if (avgDuration == 0L) {
-                avgDuration = totalDurationInMicroseconds / totalNumber;
-                units = " microsecond(s)";
-            }
-            System.out.println("     Final total = " + sw.getTotalDuration() + "; avg = " + avgDuration + units);
-            assertThat(totalNumberCreated, is(totalNumber + calculateTotalNumberOfNodesInTree(2, 2, false)));
-        }
-        return (int)totalNumberCreated;
-
-    }
-
-    private int createChildren( Graph.Batch useBatch,
-                                String parentPath,
-                                String nodePrefix,
-                                int number,
-                                int numProps,
-                                int depthRemaining,
-                                PrintWriter output ) {
-        int numberCreated = 0;
-        Graph.Batch batch = useBatch;
-        if (batch == null) batch = graph.batch();
-        for (int i = 0; i != number; ++i) {
-            String path = parentPath + "/" + nodePrefix + (i + 1);
-            Graph.Create<Graph.Batch> create = batch.create(path);
-            String originalValue = "The quick brown fox jumped over the moon. What? ";
-            String value = originalValue;
-            for (int j = 0; j != numProps; ++j) {
-                // value = value + originalValue;
-                create = create.with("property" + (j + 1), value);
-            }
-            create.and();
-        }
-        numberCreated += number;
-        if (useBatch == null) {
-            batch.execute();
-            if (output != null) output.println("         total created ... " + numberCreated);
-        }
-        if (depthRemaining > 1) {
-            for (int i = 0; i != number; ++i) {
-                String path = parentPath + "/" + nodePrefix + (i + 1);
-                numberCreated += createChildren(useBatch, path, nodePrefix, number, numProps, depthRemaining - 1, null);
-                if (output != null) output.println("         total created ... " + numberCreated);
-            }
-        }
-        return numberCreated;
-    }
-
-    protected int calculateTotalNumberOfNodesInTree( int numberOfChildrenPerNode,
-                                                     int depth,
-                                                     boolean countRoot ) {
-        assert depth > 0;
-        assert numberOfChildrenPerNode > 0;
-        int totalNumber = 0;
-        for (int i = 0; i <= depth; ++i) {
-            totalNumber += (int)Math.pow(numberOfChildrenPerNode, i);
-        }
-        return countRoot ? totalNumber : totalNumber - 1;
-    }
-
-    // ----------------------------------------------------------------------------------------------------------------
-    // Utility methods to work with nodes
-    // ----------------------------------------------------------------------------------------------------------------
-    /**
-     * Assert that the two supplied nodes represent the exact same node with the same path, same ID properties, same properties,
-     * and same children.
-     * 
-     * @param node1 the first node; may not be null
-     * @param node2 the second node; may not be null
-     */
-    public void assertSameNode( Node node1,
-                                Node node2 ) {
-        assertThat(node1, is(notNullValue()));
-        assertThat(node2, is(notNullValue()));
-
-        // Check the locations ...
-        Location location1 = node1.getLocation();
-        Location location2 = node2.getLocation();
-        assertThat(location1.isSame(location2, true), is(true));
-
-        // Check the paths ...
-        assertThat(location1.getPath(), is(location2.getPath()));
-
-        // Check the ID properties ...
-        assertThat(location1.getIdProperties(), is(location2.getIdProperties()));
-
-        // Check the properties ...
-
-        // Check the children ...
-        assertThat(node1.getChildren(), is(node2.getChildren()));
-        assertThat(node1.getChildrenSegments(), is(node2.getChildrenSegments()));
-    }
-
-    /**
-     * Assert that the node has all of the supplied properties.
-     * 
-     * @param node the node; may not be null
-     * @param properties the expected properties
-     */
-    public void assertSameProperties( Node node,
-                                      Map<Name, Property> properties ) {
-        assertThat(node, is(notNullValue()));
-        assertThat(properties, is(notNullValue()));
-        Set<Name> names = new HashSet<Name>(properties.keySet());
-        for (Property prop1 : node.getProperties()) {
-            Name name = prop1.getName();
-            assertThat(names.remove(name), is(true));
-            assertThat(prop1, is(properties.get(name)));
-        }
-        assertThat(names.isEmpty(), is(true));
-    }
-
-    /**
-     * Assert that the node has all of the supplied properties.
-     * 
-     * @param node the node; may not be null
-     * @param properties the expected properties
-     */
-    public void assertSameProperties( Node node,
-                                      Iterable<Property> properties ) {
-        assertThat(node, is(notNullValue()));
-        assertThat(properties, is(notNullValue()));
-        Set<Name> names = new HashSet<Name>(node.getPropertiesByName().keySet());
-        for (Property prop1 : properties) {
-            Name name = prop1.getName();
-            assertThat(names.remove(name), is(true));
-            assertThat(prop1, is(node.getProperty(name)));
-        }
-        assertThat(names.isEmpty(), is(true));
-    }
-
-    /**
-     * Find the name for a node that does not exist under the supplied parent.
-     * 
-     * @param pathToExistingParent the parent to the node that must exist, under which the non-existent node is to exist
-     * @return the name for a non-existent node; never null
-     */
-    public Path findPathToNonExistentNodeUnder( String pathToExistingParent ) {
-        return findPathToNonExistentNodeUnder(path(pathToExistingParent));
-    }
-
-    /**
-     * Find the name for a node that does not exist under the supplied parent.
-     * 
-     * @param pathToExistingParent the parent to the node that must exist, under which the non-existent node is to exist
-     * @return the name for a non-existent node; never null
-     */
-    public Path findPathToNonExistentNodeUnder( Path pathToExistingParent ) {
-        String nonExistentChildName = "ab39dbyfg739_adf7bg";
-        boolean verifiedNoChildWithName = false;
-        while (!verifiedNoChildWithName) {
-            verifiedNoChildWithName = true;
-            // Verify that no child of the root matches the name ...
-            for (Location childLocation : graph.getChildren().of(pathToExistingParent)) {
-                if (childLocation.getPath().getLastSegment().getName().getLocalName().equals(nonExistentChildName)) {
-                    nonExistentChildName = nonExistentChildName + '2' + nonExistentChildName;
-                    verifiedNoChildWithName = false;
-                    break;
-                }
-            }
-        }
-        return path(pathToExistingParent, nonExistentChildName);
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test/AbstractConnectorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,614 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector.test;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import org.jboss.dna.common.statistic.Stopwatch;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.ExecutionContextFactory;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.Node;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.request.Request;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+
+/**
+ * A class that provides standard reading verification tests for connectors. This class is designed to be extended for each
+ * connector, and in each subclass the {@link #setUpSource()} method is defined to provide a valid {@link RepositorySource} for
+ * the connector to be tested.
+ * <p>
+ * By default, this class sets up the repository before each test is run, ensuring that all tests have a pristine environment.
+ * However, subclasses with tests that never modify the repository content may wish to set up the repository only once. Note: this
+ * should be used with caution, but this can be achieved by overriding {@link #afterEach()} to do nothing. The repository source
+ * will be set up during the first test, and will not be shut down until {@link #afterAll() all tests have been run}.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+public abstract class AbstractConnectorTest {
+
+    protected static ExecutionContextFactory contextFactory;
+    protected static ExecutionContext context;
+    protected static RepositorySource source;
+    protected static Graph graph;
+    private static RepositoryConnectionFactory connectionFactory;
+    private static List<RepositoryConnection> openConnections;
+    private static boolean running;
+    private static Location rootLocation;
+
+    public void startRepository() throws Exception {
+        if (!running) {
+            // Set up the connection factory to other sources ...
+
+            // Set up the execution context ...
+            contextFactory = new ExecutionContext();
+            context = setUpExecutionContext(contextFactory);
+
+            // Set up the source ...
+            source = setUpSource();
+
+            // Now set up the connection factory ...
+            openConnections = new ArrayList<RepositoryConnection>();
+            connectionFactory = new RepositoryConnectionFactory() {
+                @SuppressWarnings( "synthetic-access" )
+                public RepositoryConnection createConnection( String sourceName ) throws RepositorySourceException {
+                    if (!source.getName().equals(sourceName)) return null;
+                    RepositoryConnection connection = source.getConnection();
+                    if (connection == null) {
+                        throw new RepositorySourceException("Unable to create a repository connection to " + source.getName());
+                    }
+                    openConnections.add(connection);
+                    return connection;
+                }
+            };
+
+            // Initialize the source with the rest of the environment ...
+            source.initialize(new RepositoryContext() {
+                public ExecutionContextFactory getExecutionContextFactory() {
+                    return contextFactory;
+                }
+
+                @SuppressWarnings( "synthetic-access" )
+                public RepositoryConnectionFactory getRepositoryConnectionFactory() {
+                    return connectionFactory;
+                }
+            });
+
+            // And set up the graph instance ...
+            graph = Graph.create(source.getName(), connectionFactory, context);
+
+            // Now have the source initialize the content (if any) ...
+            initializeContent(graph);
+            running = true;
+        }
+    }
+
+    public static void shutdownRepository() {
+        if (running) {
+            try {
+                // Shut down the connections to the source ...
+                for (RepositoryConnection connection : openConnections) {
+                    connection.close();
+                }
+            } finally {
+                running = false;
+                rootLocation = null;
+            }
+        }
+    }
+
+    /**
+     * Method that is executed before each test. By default, this method {@link #startRepository() sets up the repository}.
+     * 
+     * @throws Exception
+     */
+    @Before
+    public void beforeEach() throws Exception {
+        startRepository();
+    }
+
+    /**
+     * Method that is executed after each test. By default, this method {@link #shutdownRepository() shuts down the repository}.
+     * 
+     * @throws Exception
+     */
+    @After
+    public void afterEach() throws Exception {
+        shutdownRepository();
+    }
+
+    /**
+     * Method executed after all tests have completed. By default, this method ensures that the repository has been shut down (if
+     * this was not done in {@link #afterEach()}).
+     * 
+     * @throws Exception
+     */
+    @AfterClass
+    public static void afterAll() throws Exception {
+        shutdownRepository();
+    }
+
+    // ----------------------------------------------------------------------------------------------------------------
+    // Methods used in the initialization and set up of test methods
+    // ----------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Set up the {@link ExecutionContext} for each unit test.
+     * 
+     * @param contextFactory the context factory that may be used; never null
+     * @return the execution context; may not be null
+     */
+    protected ExecutionContext setUpExecutionContext( ExecutionContextFactory contextFactory ) {
+        return contextFactory.create();
+    }
+
+    /**
+     * Set up a {@link RepositorySource} that should be used for each of the unit tests.
+     * 
+     * @return the repository source
+     * @throws Exception if there is a problem setting up the source
+     */
+    protected abstract RepositorySource setUpSource() throws Exception;
+
+    /**
+     * Initialize the content of the {@link RepositorySource} set up for each of the unit tests. This method is called shortly
+     * after {@link #setUpSource()} is called and the returned RepositorySource is
+     * {@link RepositorySource#initialize(RepositoryContext) initialized}.
+     * 
+     * @param graph the graph for the {@link RepositorySource} returned from {@link #setUpSource()}; never null
+     * @throws Exception if there is a problem initializing the source
+     */
+    protected abstract void initializeContent( Graph graph ) throws Exception;
+
+    // ----------------------------------------------------------------------------------------------------------------
+    // Helper methods commonly needed in unit tests
+    // ----------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Utility to create a {@link Name} from a string.
+     * 
+     * @param name the string form of the name
+     * @return the name object
+     * @throws ValueFormatException if a name could not be created from the supplied string
+     */
+    protected Name name( String name ) {
+        return context.getValueFactories().getNameFactory().create(name);
+    }
+
+    /**
+     * Utility to create a {@link Path.Segment} from a string, where there will be no index
+     * 
+     * @param name the string form of the path segment, which may include a 1-based same-name-sibling index
+     * @return the path object
+     * @throws ValueFormatException if a path could not be created from the supplied string
+     */
+    protected Path.Segment segment( String name ) {
+        return context.getValueFactories().getPathFactory().createSegment(name);
+    }
+
+    /**
+     * Utility to create a {@link Path} from a string.
+     * 
+     * @param path the string form of the path
+     * @return the path object
+     * @throws ValueFormatException if a path could not be created from the supplied string
+     */
+    protected Path path( String path ) {
+        return context.getValueFactories().getPathFactory().create(path);
+    }
+
+    /**
+     * Utility to create a {@link Path} from a parent string and a subpath string.
+     * 
+     * @param parentPath the string form of the parent path
+     * @param subPath the string form of the subpath
+     * @return the path object
+     * @throws ValueFormatException if a path could not be created from the supplied string
+     */
+    protected Path path( String parentPath,
+                         String subPath ) {
+        return path(path(parentPath), subPath);
+    }
+
+    /**
+     * Utility to create a {@link Path} from a parent string and a subpath string.
+     * 
+     * @param parentPath the string form of the parent path
+     * @param subPath the string form of the subpath
+     * @return the path object
+     * @throws ValueFormatException if a path could not be created from the supplied string
+     */
+    protected Path path( Path parentPath,
+                         String subPath ) {
+        return context.getValueFactories().getPathFactory().create(parentPath, subPath);
+    }
+
+    /**
+     * Utility to create a {@link Location} from a string path.
+     * 
+     * @param path the string form of the path
+     * @return the location
+     */
+    protected Location location( String path ) {
+        return new Location(path(path));
+    }
+
+    /**
+     * Utility to create a {@link Location} from a UUID.
+     * 
+     * @param uuid the UUID
+     * @return the location
+     */
+    protected Location location( UUID uuid ) {
+        return new Location(uuid);
+    }
+
+    protected UUID getRootNodeUuid() {
+        if (rootLocation == null) {
+            Node root = graph.getNodeAt("/");
+            rootLocation = root.getLocation();
+        }
+        return rootLocation.getUuid();
+    }
+
+    protected String string( Object value ) {
+        if (value instanceof Property) value = ((Property)value).getFirstValue();
+        return context.getValueFactories().getStringFactory().create(value);
+    }
+
+    protected DateTime date( Object value ) {
+        if (value instanceof Property) value = ((Property)value).getFirstValue();
+        return context.getValueFactories().getDateFactory().create(value);
+    }
+
+    protected long longValue( Object value ) {
+        if (value instanceof Property) value = ((Property)value).getFirstValue();
+        return context.getValueFactories().getLongFactory().create(value);
+    }
+
+    protected Name name( Object value ) {
+        if (value instanceof Property) value = ((Property)value).getFirstValue();
+        return context.getValueFactories().getNameFactory().create(value);
+    }
+
+    // ----------------------------------------------------------------------------------------------------------------
+    // Utility method that may be used to execute requests against a repository ...
+    // ----------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Submit the supplied request to the {@link #source source} for processing, and then return the request.
+     * 
+     * @param request the request to be processed
+     * @return the request after processing (for method chaining purposes)
+     * @param <T> the type of request
+     */
+    protected <T extends Request> T execute( T request ) {
+        // Get a connection ...
+        RepositoryConnection connection = connectionFactory.createConnection(source.getName());
+        try {
+            connection.execute(context, request);
+            return request;
+        } finally {
+            connection.close();
+        }
+    }
+
+    // ----------------------------------------------------------------------------------------------------------------
+    // Utility method that may be used to create content in a repository ...
+    // ----------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Create a structured subgraph by generating nodes with the supplied number of properties and children, to the supplied
+     * maximum subgraph depth.
+     * 
+     * @param graph the graph that should be used; may not be null
+     * @param initialPath the path to the new subgraph, or null if the root path should be used
+     * @param depth the depth of the subgraph; must be a positive number
+     * @param numberOfChildrenPerNode the number of child nodes to create under each node
+     * @param numberOfPropertiesPerNode the number of properties to create on each node; must be 0 or more
+     * @param oneBatch true if all of the nodes are to be created in one batch
+     * @param stopwatch the stopwatch that should be used to measure the timings
+     * @return the number of nodes created in the subgraph
+     */
+    protected int createSubgraph( Graph graph,
+                                  String initialPath,
+                                  int depth,
+                                  int numberOfChildrenPerNode,
+                                  int numberOfPropertiesPerNode,
+                                  boolean oneBatch,
+                                  Stopwatch stopwatch ) {
+        return createSubgraph(graph,
+                              initialPath,
+                              depth,
+                              numberOfChildrenPerNode,
+                              numberOfPropertiesPerNode,
+                              oneBatch,
+                              stopwatch,
+                              null,
+                              null);
+    }
+
+    /**
+     * Create a structured subgraph by generating nodes with the supplied number of properties and children, to the supplied
+     * maximum subgraph depth.
+     * 
+     * @param graph the graph that should be used; may not be null
+     * @param initialPath the path to the new subgraph
+     * @param depth the depth of the subgraph; must be a positive number
+     * @param numberOfChildrenPerNode the number of child nodes to create under each node
+     * @param numberOfPropertiesPerNode the number of properties to create on each node; must be 0 or more
+     * @param oneBatch true if all of the nodes are to be created in one batch
+     * @param stopwatch the stopwatch that should be used to measure the timings
+     * @param output the writer to which metrics and messages should be written, or null if no such information should be written
+     * @param description the description of this subgraph (used for logging and printing), or null if the description should be
+     *        generated automatically
+     * @return the number of nodes created in the subgraph
+     */
+    protected int createSubgraph( Graph graph,
+                                  String initialPath,
+                                  int depth,
+                                  int numberOfChildrenPerNode,
+                                  int numberOfPropertiesPerNode,
+                                  boolean oneBatch,
+                                  Stopwatch stopwatch,
+                                  PrintStream output,
+                                  String description ) {
+        // Calculate the number of nodes that we'll created, but subtrace 1 since it doesn't create the root
+        long totalNumber = calculateTotalNumberOfNodesInTree(numberOfChildrenPerNode, depth, false);
+        if (initialPath == null) initialPath = "";
+        if (description == null) {
+            description = "" + numberOfChildrenPerNode + "x" + depth + " tree with " + numberOfPropertiesPerNode
+                          + " properties per node";
+        }
+
+        if (output != null) output.println(description + " (" + totalNumber + " nodes):");
+        long totalNumberCreated = 0;
+        Graph.Batch batch = oneBatch ? graph.batch() : null;
+        if (batch != null) {
+            totalNumberCreated += createChildren(batch,
+                                                 initialPath,
+                                                 "node",
+                                                 numberOfChildrenPerNode,
+                                                 numberOfPropertiesPerNode,
+                                                 depth,
+                                                 null); // don't output anything
+            if (stopwatch != null) stopwatch.start();
+            batch.execute();
+        } else {
+            if (stopwatch != null) stopwatch.start();
+            totalNumberCreated += createChildren(null,
+                                                 initialPath,
+                                                 "node",
+                                                 numberOfChildrenPerNode,
+                                                 numberOfPropertiesPerNode,
+                                                 depth,
+                                                 null); // don't output anything
+        }
+        if (stopwatch != null) {
+            stopwatch.stop();
+            if (output != null) {
+                long totalDurationInMicroseconds = TimeUnit.NANOSECONDS.toMicros(stopwatch.getTotalDuration().longValue());
+                long avgDuration = totalDurationInMicroseconds / totalNumber / 1000L;
+                String units = " millisecond(s)";
+                if (avgDuration == 0L) {
+                    avgDuration = totalDurationInMicroseconds / totalNumber;
+                    units = " microsecond(s)";
+                }
+                output.println("     Total = " + stopwatch.getTotalDuration() + "; avg = " + avgDuration + units);
+            }
+
+            // Perform second batch ...
+            batch = graph.batch();
+            totalNumberCreated += createChildren(batch, initialPath, "secondBranch", 2, numberOfPropertiesPerNode, 2, null);
+            Stopwatch sw = new Stopwatch();
+            sw.start();
+            batch.execute();
+            sw.stop();
+            long totalDurationInMicroseconds = TimeUnit.NANOSECONDS.toMicros(sw.getTotalDuration().longValue());
+            long avgDuration = totalDurationInMicroseconds / totalNumber / 1000L;
+            String units = " millisecond(s)";
+            if (avgDuration == 0L) {
+                avgDuration = totalDurationInMicroseconds / totalNumber;
+                units = " microsecond(s)";
+            }
+            System.out.println("     Final total = " + sw.getTotalDuration() + "; avg = " + avgDuration + units);
+            assertThat(totalNumberCreated, is(totalNumber + calculateTotalNumberOfNodesInTree(2, 2, false)));
+        }
+        return (int)totalNumberCreated;
+
+    }
+
+    private int createChildren( Graph.Batch useBatch,
+                                String parentPath,
+                                String nodePrefix,
+                                int number,
+                                int numProps,
+                                int depthRemaining,
+                                PrintWriter output ) {
+        int numberCreated = 0;
+        Graph.Batch batch = useBatch;
+        if (batch == null) batch = graph.batch();
+        for (int i = 0; i != number; ++i) {
+            String path = parentPath + "/" + nodePrefix + (i + 1);
+            Graph.Create<Graph.Batch> create = batch.create(path);
+            String originalValue = "The quick brown fox jumped over the moon. What? ";
+            String value = originalValue;
+            for (int j = 0; j != numProps; ++j) {
+                // value = value + originalValue;
+                create = create.with("property" + (j + 1), value);
+            }
+            create.and();
+        }
+        numberCreated += number;
+        if (useBatch == null) {
+            batch.execute();
+            if (output != null) output.println("         total created ... " + numberCreated);
+        }
+        if (depthRemaining > 1) {
+            for (int i = 0; i != number; ++i) {
+                String path = parentPath + "/" + nodePrefix + (i + 1);
+                numberCreated += createChildren(useBatch, path, nodePrefix, number, numProps, depthRemaining - 1, null);
+                if (output != null) output.println("         total created ... " + numberCreated);
+            }
+        }
+        return numberCreated;
+    }
+
+    protected int calculateTotalNumberOfNodesInTree( int numberOfChildrenPerNode,
+                                                     int depth,
+                                                     boolean countRoot ) {
+        assert depth > 0;
+        assert numberOfChildrenPerNode > 0;
+        int totalNumber = 0;
+        for (int i = 0; i <= depth; ++i) {
+            totalNumber += (int)Math.pow(numberOfChildrenPerNode, i);
+        }
+        return countRoot ? totalNumber : totalNumber - 1;
+    }
+
+    // ----------------------------------------------------------------------------------------------------------------
+    // Utility methods to work with nodes
+    // ----------------------------------------------------------------------------------------------------------------
+    /**
+     * Assert that the two supplied nodes represent the exact same node with the same path, same ID properties, same properties,
+     * and same children.
+     * 
+     * @param node1 the first node; may not be null
+     * @param node2 the second node; may not be null
+     */
+    public void assertSameNode( Node node1,
+                                Node node2 ) {
+        assertThat(node1, is(notNullValue()));
+        assertThat(node2, is(notNullValue()));
+
+        // Check the locations ...
+        Location location1 = node1.getLocation();
+        Location location2 = node2.getLocation();
+        assertThat(location1.isSame(location2, true), is(true));
+
+        // Check the paths ...
+        assertThat(location1.getPath(), is(location2.getPath()));
+
+        // Check the ID properties ...
+        assertThat(location1.getIdProperties(), is(location2.getIdProperties()));
+
+        // Check the properties ...
+
+        // Check the children ...
+        assertThat(node1.getChildren(), is(node2.getChildren()));
+        assertThat(node1.getChildrenSegments(), is(node2.getChildrenSegments()));
+    }
+
+    /**
+     * Assert that the node has all of the supplied properties.
+     * 
+     * @param node the node; may not be null
+     * @param properties the expected properties
+     */
+    public void assertSameProperties( Node node,
+                                      Map<Name, Property> properties ) {
+        assertThat(node, is(notNullValue()));
+        assertThat(properties, is(notNullValue()));
+        Set<Name> names = new HashSet<Name>(properties.keySet());
+        for (Property prop1 : node.getProperties()) {
+            Name name = prop1.getName();
+            assertThat(names.remove(name), is(true));
+            assertThat(prop1, is(properties.get(name)));
+        }
+        assertThat(names.isEmpty(), is(true));
+    }
+
+    /**
+     * Assert that the node has all of the supplied properties.
+     * 
+     * @param node the node; may not be null
+     * @param properties the expected properties
+     */
+    public void assertSameProperties( Node node,
+                                      Iterable<Property> properties ) {
+        assertThat(node, is(notNullValue()));
+        assertThat(properties, is(notNullValue()));
+        Set<Name> names = new HashSet<Name>(node.getPropertiesByName().keySet());
+        for (Property prop1 : properties) {
+            Name name = prop1.getName();
+            assertThat(names.remove(name), is(true));
+            assertThat(prop1, is(node.getProperty(name)));
+        }
+        assertThat(names.isEmpty(), is(true));
+    }
+
+    /**
+     * Find the name for a node that does not exist under the supplied parent.
+     * 
+     * @param pathToExistingParent the parent to the node that must exist, under which the non-existent node is to exist
+     * @return the name for a non-existent node; never null
+     */
+    public Path findPathToNonExistentNodeUnder( String pathToExistingParent ) {
+        return findPathToNonExistentNodeUnder(path(pathToExistingParent));
+    }
+
+    /**
+     * Find the name for a node that does not exist under the supplied parent.
+     * 
+     * @param pathToExistingParent the parent to the node that must exist, under which the non-existent node is to exist
+     * @return the name for a non-existent node; never null
+     */
+    public Path findPathToNonExistentNodeUnder( Path pathToExistingParent ) {
+        String nonExistentChildName = "ab39dbyfg739_adf7bg";
+        boolean verifiedNoChildWithName = false;
+        while (!verifiedNoChildWithName) {
+            verifiedNoChildWithName = true;
+            // Verify that no child of the root matches the name ...
+            for (Location childLocation : graph.getChildren().of(pathToExistingParent)) {
+                if (childLocation.getPath().getLastSegment().getName().getLocalName().equals(nonExistentChildName)) {
+                    nonExistentChildName = nonExistentChildName + '2' + nonExistentChildName;
+                    verifiedNoChildWithName = false;
+                    break;
+                }
+            }
+        }
+        return path(pathToExistingParent, nonExistentChildName);
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test/ReadableConnectorTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,334 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors.test;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.junit.Assert.assertThat;
-import java.util.List;
-import java.util.UUID;
-import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.Node;
-import org.jboss.dna.graph.Subgraph;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.requests.CacheableRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadBranchRequest;
-import org.jboss.dna.graph.requests.ReadNextBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
-import org.jboss.dna.graph.requests.ReadPropertyRequest;
-import org.junit.After;
-import org.junit.Test;
-
-/**
- * A class that provides standard reading verification tests for connectors. This class is designed to be extended for each
- * connector, and in each subclass the {@link #setUpSource()} method is defined to provide a valid {@link RepositorySource} for
- * the connector to be tested.
- * <p>
- * Since these tests only use methods that never modify repository content, the repository is set up only once (before the first
- * test) and is shut down after all tests have completed.
- * </p>
- * 
- * @author Randall Hauch
- */
-public abstract class ReadableConnectorTest extends AbstractConnectorTest {
-
-    /**
-     * Method that is executed after each test. This method does nothing, since the repository is set up once for all of the tests
-     * and then shutdown after all tests have completed.
-     * 
-     * @throws Exception
-     */
-    @Override
-    @After
-    public void afterEach() throws Exception {
-        // Don't shut down the repository
-    }
-
-    /**
-     * Read the node at the supplied location, using a variety of techniques to read the node and compare that each technique
-     * returned the same node. This method reads the entire node (via {@link Graph#getNodeAt(Location)}, which uses
-     * {@link ReadNodeRequest}), reads all of the properties on the node (via {@link Graph#getProperties()}, which uses
-     * {@link ReadAllPropertiesRequest}), and reads all of the children of the node (via {@link Graph#getChildren()}, which uses
-     * {@link ReadAllChildrenRequest}).
-     * 
-     * @param location the location; may not be null
-     * @return the node that was read
-     */
-    public Node readNodeThoroughly( Location location ) {
-        assertThat(location, is(notNullValue()));
-        Node result = null;
-        if (location.hasPath() && location.hasIdProperties()) {
-            // Read the node by the path ...
-            Node resultByPath = graph.getNodeAt(new Location(location.getPath()));
-
-            // Read the node by identification properties ...
-            Node resultByIdProps = graph.getNodeAt(new Location(location.getIdProperties()));
-
-            // Read the node by using the location with both a path and ID properties ...
-            result = graph.getNodeAt(location);
-
-            // Verify that the same node was returned by each ...
-            assertSameNode(resultByPath, result);
-            assertSameNode(resultByIdProps, result);
-
-            // Check the result has the correct location ...
-            assertThat("The node that was read doesn't have the expected location", result.getLocation(), is(location));
-        } else {
-            // Read the node by using the location (as is)
-            result = graph.getNodeAt(location);
-
-            // Check the result has the correct location ...
-            assertThat("The node that was read doesn't have the expected location",
-                       result.getLocation().isSame(location, true),
-                       is(true));
-        }
-
-        // Read all the properties of the node ...
-        assertSameProperties(result, graph.getProperties().on(location));
-
-        // Read all the children of the node ...
-        assertThat(graph.getChildren().of(location), is(result.getChildren()));
-
-        return result;
-    }
-
-    @Test
-    public void shouldAlwaysBeAbleToReadRootNode() {
-        Node root = graph.getNodeAt("/");
-        assertThat("Connector must always have a root node", root, is(notNullValue()));
-        assertThat("Root node must always have a path", root.getLocation().hasPath(), is(true));
-        assertThat("Root node must never have a null path", root.getLocation().getPath(), is(notNullValue()));
-        assertThat("Root node's path must be the root path", root.getLocation().getPath().isRoot(), is(true));
-        List<Property> idProperties = root.getLocation().getIdProperties();
-        if (idProperties == null) {
-            assertThat(root.getLocation().hasIdProperties(), is(false));
-        } else {
-            assertThat(root.getLocation().hasIdProperties(), is(true));
-        }
-    }
-
-    @Test
-    public void shouldReturnEquivalentLocationForRootUponRepeatedCalls() {
-        Node root = graph.getNodeAt("/");
-        for (int i = 0; i != 10; ++i) {
-            Node anotherRoot = graph.getNodeAt("/");
-            assertThat(anotherRoot.getLocation().equals(root.getLocation()), is(true));
-            assertThat(anotherRoot.getLocation().getPath(), is(root.getLocation().getPath()));
-            assertThat(anotherRoot.getLocation().getIdProperties(), is(root.getLocation().getIdProperties()));
-        }
-    }
-
-    @Test
-    public void shouldFindRootByIdentificationProperties() {
-        Node root = graph.getNodeAt("/");
-        Location rootLocation = root.getLocation();
-        if (rootLocation.hasIdProperties()) {
-            List<Property> idProperties = rootLocation.getIdProperties();
-            assertThat("Root node's ID properties was null when there were supposed to be properties",
-                       idProperties,
-                       is(notNullValue()));
-            Property firstProperty = idProperties.get(0);
-            Property[] additionalProperties = new Property[] {};
-            if (idProperties.size() > 1) {
-                List<Property> morePropertiesList = idProperties.subList(1, idProperties.size());
-                assertThat(morePropertiesList.isEmpty(), is(false));
-                additionalProperties = morePropertiesList.toArray(new Property[morePropertiesList.size()]);
-            }
-            // Find the root node using the identification properties ...
-            Node anotherRoot = graph.getNodeAt(firstProperty, additionalProperties);
-            assertThat(anotherRoot.getLocation().equals(root.getLocation()), is(true));
-            assertThat(anotherRoot.getLocation().getPath(), is(root.getLocation().getPath()));
-            assertThat(anotherRoot.getLocation().getIdProperties(), is(root.getLocation().getIdProperties()));
-        }
-    }
-
-    @Test
-    public void shouldFindRootByUUID() {
-        Node root = graph.getNodeAt("/");
-        Location rootLocation = root.getLocation();
-        UUID uuid = rootLocation.getUuid();
-        if (uuid != null) {
-            // Find the root node using the identification properties ...
-            Node anotherRoot = graph.getNodeAt(uuid);
-            assertThat(anotherRoot.getLocation().equals(root.getLocation()), is(true));
-            assertThat(anotherRoot.getLocation().getPath(), is(root.getLocation().getPath()));
-            assertThat(anotherRoot.getLocation().getIdProperties(), is(root.getLocation().getIdProperties()));
-            assertThat(anotherRoot.getLocation().getUuid(), is(root.getLocation().getUuid()));
-        }
-    }
-
-    @Test
-    public void shouldReadTheChildrenOfTheRootNode() {
-        List<Location> children = graph.getChildren().of("/");
-        assertThat(children, is(notNullValue()));
-        for (Location child : children) {
-            // Check the location has a path that has the root as a parent ...
-            assertThat(child.hasPath(), is(true));
-            assertThat(child.getPath().getParent().isRoot(), is(true));
-
-            // Verify that each node can be read multiple ways ...
-            readNodeThoroughly(child);
-        }
-    }
-
-    @Test
-    public void shouldReadSubgraphStartingAtRootAndWithMaximumDepthOfThree() {
-        Subgraph subgraph = graph.getSubgraphOfDepth(3).at("/");
-        assertThat(subgraph, is(notNullValue()));
-
-        // Verify that the root node is the same as getting it directly ...
-        Node root = subgraph.getRoot();
-        assertSameNode(root, graph.getNodeAt("/"));
-
-        // Verify the first-level children ...
-        List<Location> children = graph.getChildren().of("/");
-        assertThat(children, is(notNullValue()));
-        for (Location childLocation : children) {
-            // Verify the child in the subgraph matches the same node obtained directly from the graph ...
-            Node child = subgraph.getNode(childLocation);
-            assertSameNode(child, graph.getNodeAt(childLocation));
-
-            // Now get the second-level children ...
-            List<Location> grandChildren = graph.getChildren().of(childLocation);
-            assertThat(grandChildren, is(notNullValue()));
-            for (Location grandchildLocation : grandChildren) {
-                // Verify the grandchild in the subgraph matches the same node obtained directly from the graph ...
-                Node grandchild = subgraph.getNode(grandchildLocation);
-                assertSameNode(grandchild, graph.getNodeAt(grandchildLocation));
-
-                // The subgraph should contain the children locations and properties for the grandchildren.
-                // However, the subgraph should not a node for the children of the grandchildren ...
-                for (Location greatGrandchild : grandchild.getChildren()) {
-                    assertThat(subgraph.getNode(greatGrandchild), is(nullValue()));
-                }
-            }
-        }
-    }
-
-    @Test
-    public void shouldReadIndividualPropertiesOfNodes() {
-        // Read each node that is a child of the root...
-        for (Location childLocation : graph.getChildren().of("/")) {
-            // For each node ...
-            Node child = graph.getNodeAt(childLocation);
-            for (Property property : child.getProperties()) {
-                Name name = property.getName();
-                // Re-read the property and verify the value(s) match the value(s) in 'property'
-                Property singleProperty = graph.getProperty(name).on(childLocation);
-                assertThat(singleProperty, is(notNullValue()));
-                assertThat(singleProperty, is(property));
-            }
-        }
-    }
-
-    @Test( expected = PathNotFoundException.class )
-    public void shouldFailToReadNodeThatDoesNotExist() {
-        // Look up the child that should not exist, and this should throw an exception ...
-        Path nonExistantChildName = findPathToNonExistentNodeUnder("/");
-        graph.getNodeAt(nonExistantChildName);
-    }
-
-    @Test( expected = PathNotFoundException.class )
-    public void shouldFailToReadPropertyOnNodeThatDoesNotExist() {
-        // Look up the child that should not exist, and this should throw an exception ...
-        Path nonExistantChildName = findPathToNonExistentNodeUnder("/");
-        graph.getProperty("jcr:uuid").on(nonExistantChildName);
-    }
-
-    @Test
-    public void shouldFailToReadPropertyThatDoesNotExistOnExistingNode() {
-        // Read each node that is a child of the root...
-        for (Location childLocation : graph.getChildren().of("/")) {
-            // Find a name for a non-existing property ...
-            String nonExistentPropertyName = "ab39dbyfg739_adf7bg";
-            // For each node ...
-            Property property = graph.getProperty(nonExistentPropertyName).on(childLocation); // will throw exception
-            assertThat(property, is(nullValue()));
-        }
-    }
-
-    @Test
-    public void shouldIncludeTimeLoadedInReadNodeRequests() {
-        CacheableRequest request = new ReadNodeRequest(location("/"));
-        execute(request);
-        assertThat(request.getTimeLoaded(), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldIncludeTimeLoadedInReadAllPropertiesRequests() {
-        CacheableRequest request = new ReadAllPropertiesRequest(location("/"));
-        execute(request);
-        assertThat(request.getTimeLoaded(), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldIncludeTimeLoadedInReadAllChildrenRequests() {
-        CacheableRequest request = new ReadAllChildrenRequest(location("/"));
-        execute(request);
-        assertThat(request.getTimeLoaded(), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldIncludeTimeLoadedInReadBlockOfChildrenRequests() {
-        CacheableRequest request = new ReadBlockOfChildrenRequest(location("/"), 0, 100);
-        execute(request);
-        assertThat(request.getTimeLoaded(), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldIncludeTimeLoadedInReadNextBlockOfChildrenRequests() {
-        // Get the first child ...
-        Location firstChild = graph.getChildren().of("/").get(0);
-        CacheableRequest request = new ReadNextBlockOfChildrenRequest(firstChild, 100);
-        execute(request);
-        assertThat(request.getTimeLoaded(), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldIncludeTimeLoadedInReadPropertyRequests() {
-        // Get each of the properties on the first child ...
-        Location firstChildLocation = graph.getChildren().of("/").get(0);
-        Node firstChild = graph.getNodeAt(firstChildLocation);
-        for (Property property : firstChild.getProperties()) {
-            CacheableRequest request = new ReadPropertyRequest(firstChildLocation, property.getName());
-            execute(request);
-            assertThat(request.getTimeLoaded(), is(notNullValue()));
-        }
-    }
-
-    @Test
-    public void shouldIncludeTimeLoadedInReadBranchRequests() {
-        CacheableRequest request = new ReadBranchRequest(location("/"), 2);
-        execute(request);
-        assertThat(request.getTimeLoaded(), is(notNullValue()));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test/ReadableConnectorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,334 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector.test;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+import java.util.List;
+import java.util.UUID;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.Node;
+import org.jboss.dna.graph.Subgraph;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CacheableRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadBranchRequest;
+import org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+import org.jboss.dna.graph.request.ReadPropertyRequest;
+import org.junit.After;
+import org.junit.Test;
+
+/**
+ * A class that provides standard reading verification tests for connectors. This class is designed to be extended for each
+ * connector, and in each subclass the {@link #setUpSource()} method is defined to provide a valid {@link RepositorySource} for
+ * the connector to be tested.
+ * <p>
+ * Since these tests only use methods that never modify repository content, the repository is set up only once (before the first
+ * test) and is shut down after all tests have completed.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+public abstract class ReadableConnectorTest extends AbstractConnectorTest {
+
+    /**
+     * Method that is executed after each test. This method does nothing, since the repository is set up once for all of the tests
+     * and then shutdown after all tests have completed.
+     * 
+     * @throws Exception
+     */
+    @Override
+    @After
+    public void afterEach() throws Exception {
+        // Don't shut down the repository
+    }
+
+    /**
+     * Read the node at the supplied location, using a variety of techniques to read the node and compare that each technique
+     * returned the same node. This method reads the entire node (via {@link Graph#getNodeAt(Location)}, which uses
+     * {@link ReadNodeRequest}), reads all of the properties on the node (via {@link Graph#getProperties()}, which uses
+     * {@link ReadAllPropertiesRequest}), and reads all of the children of the node (via {@link Graph#getChildren()}, which uses
+     * {@link ReadAllChildrenRequest}).
+     * 
+     * @param location the location; may not be null
+     * @return the node that was read
+     */
+    public Node readNodeThoroughly( Location location ) {
+        assertThat(location, is(notNullValue()));
+        Node result = null;
+        if (location.hasPath() && location.hasIdProperties()) {
+            // Read the node by the path ...
+            Node resultByPath = graph.getNodeAt(new Location(location.getPath()));
+
+            // Read the node by identification properties ...
+            Node resultByIdProps = graph.getNodeAt(new Location(location.getIdProperties()));
+
+            // Read the node by using the location with both a path and ID properties ...
+            result = graph.getNodeAt(location);
+
+            // Verify that the same node was returned by each ...
+            assertSameNode(resultByPath, result);
+            assertSameNode(resultByIdProps, result);
+
+            // Check the result has the correct location ...
+            assertThat("The node that was read doesn't have the expected location", result.getLocation(), is(location));
+        } else {
+            // Read the node by using the location (as is)
+            result = graph.getNodeAt(location);
+
+            // Check the result has the correct location ...
+            assertThat("The node that was read doesn't have the expected location",
+                       result.getLocation().isSame(location, true),
+                       is(true));
+        }
+
+        // Read all the properties of the node ...
+        assertSameProperties(result, graph.getProperties().on(location));
+
+        // Read all the children of the node ...
+        assertThat(graph.getChildren().of(location), is(result.getChildren()));
+
+        return result;
+    }
+
+    @Test
+    public void shouldAlwaysBeAbleToReadRootNode() {
+        Node root = graph.getNodeAt("/");
+        assertThat("Connector must always have a root node", root, is(notNullValue()));
+        assertThat("Root node must always have a path", root.getLocation().hasPath(), is(true));
+        assertThat("Root node must never have a null path", root.getLocation().getPath(), is(notNullValue()));
+        assertThat("Root node's path must be the root path", root.getLocation().getPath().isRoot(), is(true));
+        List<Property> idProperties = root.getLocation().getIdProperties();
+        if (idProperties == null) {
+            assertThat(root.getLocation().hasIdProperties(), is(false));
+        } else {
+            assertThat(root.getLocation().hasIdProperties(), is(true));
+        }
+    }
+
+    @Test
+    public void shouldReturnEquivalentLocationForRootUponRepeatedCalls() {
+        Node root = graph.getNodeAt("/");
+        for (int i = 0; i != 10; ++i) {
+            Node anotherRoot = graph.getNodeAt("/");
+            assertThat(anotherRoot.getLocation().equals(root.getLocation()), is(true));
+            assertThat(anotherRoot.getLocation().getPath(), is(root.getLocation().getPath()));
+            assertThat(anotherRoot.getLocation().getIdProperties(), is(root.getLocation().getIdProperties()));
+        }
+    }
+
+    @Test
+    public void shouldFindRootByIdentificationProperties() {
+        Node root = graph.getNodeAt("/");
+        Location rootLocation = root.getLocation();
+        if (rootLocation.hasIdProperties()) {
+            List<Property> idProperties = rootLocation.getIdProperties();
+            assertThat("Root node's ID properties was null when there were supposed to be properties",
+                       idProperties,
+                       is(notNullValue()));
+            Property firstProperty = idProperties.get(0);
+            Property[] additionalProperties = new Property[] {};
+            if (idProperties.size() > 1) {
+                List<Property> morePropertiesList = idProperties.subList(1, idProperties.size());
+                assertThat(morePropertiesList.isEmpty(), is(false));
+                additionalProperties = morePropertiesList.toArray(new Property[morePropertiesList.size()]);
+            }
+            // Find the root node using the identification properties ...
+            Node anotherRoot = graph.getNodeAt(firstProperty, additionalProperties);
+            assertThat(anotherRoot.getLocation().equals(root.getLocation()), is(true));
+            assertThat(anotherRoot.getLocation().getPath(), is(root.getLocation().getPath()));
+            assertThat(anotherRoot.getLocation().getIdProperties(), is(root.getLocation().getIdProperties()));
+        }
+    }
+
+    @Test
+    public void shouldFindRootByUUID() {
+        Node root = graph.getNodeAt("/");
+        Location rootLocation = root.getLocation();
+        UUID uuid = rootLocation.getUuid();
+        if (uuid != null) {
+            // Find the root node using the identification properties ...
+            Node anotherRoot = graph.getNodeAt(uuid);
+            assertThat(anotherRoot.getLocation().equals(root.getLocation()), is(true));
+            assertThat(anotherRoot.getLocation().getPath(), is(root.getLocation().getPath()));
+            assertThat(anotherRoot.getLocation().getIdProperties(), is(root.getLocation().getIdProperties()));
+            assertThat(anotherRoot.getLocation().getUuid(), is(root.getLocation().getUuid()));
+        }
+    }
+
+    @Test
+    public void shouldReadTheChildrenOfTheRootNode() {
+        List<Location> children = graph.getChildren().of("/");
+        assertThat(children, is(notNullValue()));
+        for (Location child : children) {
+            // Check the location has a path that has the root as a parent ...
+            assertThat(child.hasPath(), is(true));
+            assertThat(child.getPath().getParent().isRoot(), is(true));
+
+            // Verify that each node can be read multiple ways ...
+            readNodeThoroughly(child);
+        }
+    }
+
+    @Test
+    public void shouldReadSubgraphStartingAtRootAndWithMaximumDepthOfThree() {
+        Subgraph subgraph = graph.getSubgraphOfDepth(3).at("/");
+        assertThat(subgraph, is(notNullValue()));
+
+        // Verify that the root node is the same as getting it directly ...
+        Node root = subgraph.getRoot();
+        assertSameNode(root, graph.getNodeAt("/"));
+
+        // Verify the first-level children ...
+        List<Location> children = graph.getChildren().of("/");
+        assertThat(children, is(notNullValue()));
+        for (Location childLocation : children) {
+            // Verify the child in the subgraph matches the same node obtained directly from the graph ...
+            Node child = subgraph.getNode(childLocation);
+            assertSameNode(child, graph.getNodeAt(childLocation));
+
+            // Now get the second-level children ...
+            List<Location> grandChildren = graph.getChildren().of(childLocation);
+            assertThat(grandChildren, is(notNullValue()));
+            for (Location grandchildLocation : grandChildren) {
+                // Verify the grandchild in the subgraph matches the same node obtained directly from the graph ...
+                Node grandchild = subgraph.getNode(grandchildLocation);
+                assertSameNode(grandchild, graph.getNodeAt(grandchildLocation));
+
+                // The subgraph should contain the children locations and properties for the grandchildren.
+                // However, the subgraph should not a node for the children of the grandchildren ...
+                for (Location greatGrandchild : grandchild.getChildren()) {
+                    assertThat(subgraph.getNode(greatGrandchild), is(nullValue()));
+                }
+            }
+        }
+    }
+
+    @Test
+    public void shouldReadIndividualPropertiesOfNodes() {
+        // Read each node that is a child of the root...
+        for (Location childLocation : graph.getChildren().of("/")) {
+            // For each node ...
+            Node child = graph.getNodeAt(childLocation);
+            for (Property property : child.getProperties()) {
+                Name name = property.getName();
+                // Re-read the property and verify the value(s) match the value(s) in 'property'
+                Property singleProperty = graph.getProperty(name).on(childLocation);
+                assertThat(singleProperty, is(notNullValue()));
+                assertThat(singleProperty, is(property));
+            }
+        }
+    }
+
+    @Test( expected = PathNotFoundException.class )
+    public void shouldFailToReadNodeThatDoesNotExist() {
+        // Look up the child that should not exist, and this should throw an exception ...
+        Path nonExistantChildName = findPathToNonExistentNodeUnder("/");
+        graph.getNodeAt(nonExistantChildName);
+    }
+
+    @Test( expected = PathNotFoundException.class )
+    public void shouldFailToReadPropertyOnNodeThatDoesNotExist() {
+        // Look up the child that should not exist, and this should throw an exception ...
+        Path nonExistantChildName = findPathToNonExistentNodeUnder("/");
+        graph.getProperty("jcr:uuid").on(nonExistantChildName);
+    }
+
+    @Test
+    public void shouldFailToReadPropertyThatDoesNotExistOnExistingNode() {
+        // Read each node that is a child of the root...
+        for (Location childLocation : graph.getChildren().of("/")) {
+            // Find a name for a non-existing property ...
+            String nonExistentPropertyName = "ab39dbyfg739_adf7bg";
+            // For each node ...
+            Property property = graph.getProperty(nonExistentPropertyName).on(childLocation); // will throw exception
+            assertThat(property, is(nullValue()));
+        }
+    }
+
+    @Test
+    public void shouldIncludeTimeLoadedInReadNodeRequests() {
+        CacheableRequest request = new ReadNodeRequest(location("/"));
+        execute(request);
+        assertThat(request.getTimeLoaded(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldIncludeTimeLoadedInReadAllPropertiesRequests() {
+        CacheableRequest request = new ReadAllPropertiesRequest(location("/"));
+        execute(request);
+        assertThat(request.getTimeLoaded(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldIncludeTimeLoadedInReadAllChildrenRequests() {
+        CacheableRequest request = new ReadAllChildrenRequest(location("/"));
+        execute(request);
+        assertThat(request.getTimeLoaded(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldIncludeTimeLoadedInReadBlockOfChildrenRequests() {
+        CacheableRequest request = new ReadBlockOfChildrenRequest(location("/"), 0, 100);
+        execute(request);
+        assertThat(request.getTimeLoaded(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldIncludeTimeLoadedInReadNextBlockOfChildrenRequests() {
+        // Get the first child ...
+        Location firstChild = graph.getChildren().of("/").get(0);
+        CacheableRequest request = new ReadNextBlockOfChildrenRequest(firstChild, 100);
+        execute(request);
+        assertThat(request.getTimeLoaded(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldIncludeTimeLoadedInReadPropertyRequests() {
+        // Get each of the properties on the first child ...
+        Location firstChildLocation = graph.getChildren().of("/").get(0);
+        Node firstChild = graph.getNodeAt(firstChildLocation);
+        for (Property property : firstChild.getProperties()) {
+            CacheableRequest request = new ReadPropertyRequest(firstChildLocation, property.getName());
+            execute(request);
+            assertThat(request.getTimeLoaded(), is(notNullValue()));
+        }
+    }
+
+    @Test
+    public void shouldIncludeTimeLoadedInReadBranchRequests() {
+        CacheableRequest request = new ReadBranchRequest(location("/"), 2);
+        execute(request);
+        assertThat(request.getTimeLoaded(), is(notNullValue()));
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test/WritableConnectorTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,806 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors.test;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.jboss.dna.graph.IsNodeWithChildren.hasChild;
-import static org.jboss.dna.graph.IsNodeWithChildren.hasChildren;
-import static org.jboss.dna.graph.IsNodeWithChildren.isEmpty;
-import static org.jboss.dna.graph.IsNodeWithProperty.hasProperty;
-import static org.junit.Assert.assertThat;
-import org.jboss.dna.common.stats.Stopwatch;
-import org.jboss.dna.common.util.IoUtil;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.Node;
-import org.jboss.dna.graph.Subgraph;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.properties.Reference;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * A class that provides standard writing verification tests for connectors that are able to store any content (in any structure).
- * This class is designed to be extended for each connector, and in each subclass the {@link #setUpSource()} method is defined to
- * provide a valid {@link RepositorySource} for the connector to be tested.
- * <p>
- * Since these tests do modify repository content, the repository is set up for each test, given each test a pristine repository
- * (as {@link #initializeContent(Graph) initialized} by the concrete test case class).
- * </p>
- * 
- * @author Randall Hauch
- */
-public abstract class WritableConnectorTest extends AbstractConnectorTest {
-
-    protected String[] validLargeValues;
-
-    @Override
-    @Before
-    public void beforeEach() throws Exception {
-        super.beforeEach();
-
-        // Load in the large value ...
-        validLargeValues = new String[] {IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum1.txt")),
-            IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum2.txt")),
-            IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum3.txt"))};
-    }
-
-    /**
-     * These tests require that the source supports updates, since all of the tests do some form of updates.
-     */
-    @Test
-    public void shouldHaveUpdateCapabilities() {
-        assertThat(source.getCapabilities().supportsUpdates(), is(true));
-    }
-
-    @Test
-    public void shouldSetPropertyOnRootNode() {
-        graph.set("propA").to("valueA").on("/");
-        // Now look up the node ...
-        Node root = graph.getNodeAt("/");
-        assertThat(root, is(notNullValue()));
-        assertThat(root, hasProperty(DnaLexicon.UUID, getRootNodeUuid()));
-        assertThat(root, hasProperty("propA", "valueA"));
-    }
-
-    @Test
-    public void shouldAddChildUnderRootNode() {
-        graph.batch().create("/a").with("propB", "valueB").and("propC", "valueC").execute();
-        // Now look up the root node ...
-        Node root = graph.getNodeAt("/");
-        assertThat(root, is(notNullValue()));
-        assertThat(root, hasProperty(DnaLexicon.UUID, getRootNodeUuid()));
-        assertThat(root.getChildren(), hasChild(segment("a")));
-
-        // Now look up node A ...
-        Node nodeA = graph.getNodeAt("/a");
-        assertThat(nodeA, is(notNullValue()));
-        assertThat(nodeA, hasProperty("propB", "valueB"));
-        assertThat(nodeA, hasProperty("propC", "valueC"));
-        assertThat(nodeA.getChildren(), isEmpty());
-    }
-
-    @Test
-    public void shouldAddChildrenOnRootNode() {
-        graph.batch().set("propA").to("valueA").on("/").and().create("/a").with("propB", "valueB").and("propC", "valueC").and().create("/b").with("propD",
-                                                                                                                                                  "valueD").and("propE",
-                                                                                                                                                                "valueE").execute();
-        // Now look up the root node ...
-        Node root = graph.getNodeAt("/");
-        assertThat(root, is(notNullValue()));
-        assertThat(root, hasProperty(DnaLexicon.UUID, getRootNodeUuid()));
-        assertThat(root, hasProperty("propA", "valueA"));
-        assertThat(root.getChildren(), hasChildren(segment("a"), segment("b")));
-
-        // Now look up node A ...
-        Node nodeA = graph.getNodeAt("/a");
-        assertThat(nodeA, is(notNullValue()));
-        assertThat(nodeA, hasProperty("propB", "valueB"));
-        assertThat(nodeA, hasProperty("propC", "valueC"));
-        assertThat(nodeA.getChildren(), isEmpty());
-
-        // Now look up node B ...
-        Node nodeB = graph.getNodeAt("/b");
-        assertThat(nodeB, is(notNullValue()));
-        assertThat(nodeB, hasProperty("propD", "valueD"));
-        assertThat(nodeB, hasProperty("propE", "valueE"));
-        assertThat(nodeB.getChildren(), isEmpty());
-
-        // Get the subgraph ...
-        Subgraph subgraph = graph.getSubgraphOfDepth(3).at("/");
-        assertThat(subgraph, is(notNullValue()));
-        assertThat(subgraph.getNode("."), hasProperty(DnaLexicon.UUID, getRootNodeUuid()));
-        assertThat(subgraph.getNode("."), hasProperty("propA", "valueA"));
-        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("a"), segment("b")));
-        assertThat(subgraph.getNode("a"), is(notNullValue()));
-        assertThat(subgraph.getNode("a"), hasProperty("propB", "valueB"));
-        assertThat(subgraph.getNode("a"), hasProperty("propC", "valueC"));
-        assertThat(subgraph.getNode("a").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("b"), is(notNullValue()));
-        assertThat(subgraph.getNode("b"), hasProperty("propD", "valueD"));
-        assertThat(subgraph.getNode("b"), hasProperty("propE", "valueE"));
-        assertThat(subgraph.getNode("b").getChildren(), isEmpty());
-    }
-
-    @Test
-    public void shouldStoreManyPropertiesOnANode() {
-        Graph.Create<Graph.Batch> create = graph.batch().create("/a");
-        for (int i = 0; i != 100; ++i) {
-            create = create.with("property" + i, "value" + i);
-        }
-        create.execute();
-        // Now look up all the properties ...
-        Node nodeA = graph.getNodeAt("/a");
-        assertThat(nodeA, is(notNullValue()));
-        for (int i = 0; i != 100; ++i) {
-            assertThat(nodeA, hasProperty("property" + i, "value" + i));
-        }
-        assertThat(nodeA.getChildren(), isEmpty());
-    }
-
-    @Test
-    public void shouldUpdateSmallPropertiesOnANode() {
-        // Create the property and add some properties (including 2 large values) ...
-        Graph.Create<Graph.Batch> create = graph.batch().create("/a");
-        for (int i = 0; i != 10; ++i) {
-            create = create.with("property" + i, "value" + i);
-        }
-        create.execute();
-
-        // Now look up all the properties ...
-        Node nodeA = graph.getNodeAt("/a");
-        assertThat(nodeA, is(notNullValue()));
-        for (int i = 0; i != 10; ++i) {
-            assertThat(nodeA, hasProperty("property" + i, "value" + i));
-        }
-        assertThat(nodeA.getChildren(), isEmpty());
-
-        // Now, remove some of the properties and add some others ...
-        Graph.Batch batch = graph.batch();
-        batch.remove("property0", "property1").on("/a");
-        batch.set("property6").to("new valid 6").on("/a");
-        batch.execute();
-
-        // Re-read the properties ...
-        nodeA = graph.getNodeAt("/a");
-        assertThat(nodeA, is(notNullValue()));
-        for (int i = 0; i != 10; ++i) {
-            if (i == 0 || i == 1) {
-                continue;
-            } else if (i == 6) {
-                assertThat(nodeA, hasProperty("property" + i, "new valid 6"));
-            } else {
-                assertThat(nodeA, hasProperty("property" + i, "value" + i));
-            }
-        }
-        assertThat(nodeA.getChildren(), isEmpty());
-
-    }
-
-    @Test
-    public void shouldUpdateLargePropertiesOnANode() {
-        // Create the property and add some properties (including 2 large values) ...
-        Graph.Create<Graph.Batch> create = graph.batch().create("/a");
-        for (int i = 0; i != 100; ++i) {
-            create = create.with("property" + i, "value" + i);
-        }
-        create = create.with("largeProperty1", validLargeValues[0]);
-        create = create.with("largeProperty2", validLargeValues[1]);
-        create.execute();
-
-        // Now look up all the properties ...
-        Node nodeA = graph.getNodeAt("/a");
-        assertThat(nodeA, is(notNullValue()));
-        for (int i = 0; i != 100; ++i) {
-            assertThat(nodeA, hasProperty("property" + i, "value" + i));
-        }
-        assertThat(nodeA, hasProperty("largeProperty1", validLargeValues[0]));
-        assertThat(nodeA, hasProperty("largeProperty2", validLargeValues[1]));
-        assertThat(nodeA.getChildren(), isEmpty());
-
-        // Now, remove some of the properties and add some others ...
-        Graph.Batch batch = graph.batch();
-        batch.remove("largeProperty1", "property0", "property1").on("/a");
-        batch.set("property50").to("new valid 50").on("/a");
-        batch.set("largeProperty3").to(validLargeValues[2]).on("/a");
-        batch.execute();
-
-        // Re-read the properties ...
-        nodeA = graph.getNodeAt("/a");
-        assertThat(nodeA, is(notNullValue()));
-        for (int i = 0; i != 100; ++i) {
-            if (i == 0 || i == 1) {
-                continue;
-            } else if (i == 50) {
-                assertThat(nodeA, hasProperty("property" + i, "new valid 50"));
-            } else {
-                assertThat(nodeA, hasProperty("property" + i, "value" + i));
-            }
-        }
-        assertThat(nodeA, hasProperty("largeProperty2", validLargeValues[1]));
-        assertThat(nodeA, hasProperty("largeProperty3", validLargeValues[2]));
-        assertThat(nodeA.getChildren(), isEmpty());
-
-    }
-
-    @Test
-    public void shouldCreateDeepBranchUsingIndividualRequests() {
-        String initialPath = "";
-        int depth = 50;
-        int numChildrenPerNode = 1;
-        int numPropertiesPerNode = 7;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = false;
-        String description = "deep and narrow tree, 1x50";
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, description);
-    }
-
-    @Test
-    public void shouldCreateDeepBranchUsingOneBatch() {
-        String initialPath = "";
-        int depth = 50;
-        int numChildrenPerNode = 1;
-        int numPropertiesPerNode = 7;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = true;
-        String description = "deep and narrow tree, 1x50";
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, description);
-    }
-
-    @Test
-    public void shouldCreateFlatAndWideTreeUsingOneBatch() {
-        String initialPath = "";
-        int depth = 1;
-        int numChildrenPerNode = 300;
-        int numPropertiesPerNode = 7;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = true;
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
-    }
-
-    @Test
-    public void shouldCreateBinaryTreeUsingOneBatch() {
-        String initialPath = "";
-        int depth = 8;
-        int numChildrenPerNode = 2;
-        int numPropertiesPerNode = 7;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = true;
-        String description = "binary tree, 2x8";
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, description);
-    }
-
-    @Test
-    public void shouldCreateTreeWith10ChildrenAnd2LevelsDeepUsingIndividualRequests() {
-        String initialPath = "";
-        int depth = 2;
-        int numChildrenPerNode = 10;
-        int numPropertiesPerNode = 7;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = false;
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
-    }
-
-    @Test
-    public void shouldCreateTreeWith10ChildrenAnd2LevelsDeepUsingOneBatch() {
-        String initialPath = "";
-        int depth = 2;
-        int numChildrenPerNode = 10;
-        int numPropertiesPerNode = 7;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = true;
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
-    }
-
-    @Test
-    public void shouldCreateTreeWith10ChildrenAnd3LevelsDeepUsingOneBatch() {
-        String initialPath = "";
-        int depth = 3;
-        int numChildrenPerNode = 10;
-        int numPropertiesPerNode = 7;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = true;
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
-    }
-
-    @Test
-    public void shouldCreateAndReadTree() {
-        // Create the tree (at total of 40 nodes, plus the extra 6 added later)...
-        // /
-        // /node1
-        // /node1/node1
-        // /node1/node1/node1
-        // /node1/node1/node2
-        // /node1/node1/node3
-        // /node1/node2
-        // /node1/node2/node1
-        // /node1/node2/node2
-        // /node1/node2/node3
-        // /node1/node3
-        // /node1/node3/node1
-        // /node1/node3/node2
-        // /node1/node3/node3
-        // /node2
-        // /node2/node1
-        // /node2/node1/node1
-        // /node2/node1/node2
-        // /node2/node1/node3
-        // /node2/node2
-        // /node2/node2/node1
-        // /node2/node2/node2
-        // /node2/node2/node3
-        // /node2/node3
-        // /node2/node3/node1
-        // /node2/node3/node2
-        // /node2/node3/node3
-        // /node3
-        // /node3/node1
-        // /node3/node1/node1
-        // /node3/node1/node2
-        // /node3/node1/node3
-        // /node3/node2
-        // /node3/node2/node1
-        // /node3/node2/node2
-        // /node3/node2/node3
-        // /node3/node3
-        // /node3/node3/node1
-        // /node3/node3/node2
-        // /node3/node3/node3
-        // /secondBranch1
-        // /secondBranch1/secondBranch1
-        // /secondBranch1/secondBranch2
-        // /secondBranch2
-        // /secondBranch2/secondBranch1
-        // /secondBranch2/secondBranch2
-
-        String initialPath = "";
-        int depth = 3;
-        int numChildrenPerNode = 3;
-        int numPropertiesPerNode = 3;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = true;
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
-
-        assertThat(graph.getChildren().of("/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node3/node1"), isEmpty());
-
-        assertThat(graph.getChildren().of("/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node3/node1"), isEmpty());
-
-        assertThat(graph.getChildren().of("/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node3/node1"), isEmpty());
-
-        Subgraph subgraph = graph.getSubgraphOfDepth(2).at("/node3/node2");
-        assertThat(subgraph, is(notNullValue()));
-        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(subgraph.getNode("."), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("."), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("."), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node1").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node1"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node1"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node1"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-
-        subgraph = graph.getSubgraphOfDepth(2).at("/node3");
-        assertThat(subgraph, is(notNullValue()));
-        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(subgraph.getNode("."), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("."), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("."), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node1").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node1"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node1"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node1"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-    }
-
-    @Test
-    public void shouldDeleteNodes() {
-        // Create the tree (at total of 40 nodes, plus the extra 6 added later)...
-        // /
-        // /node1
-        // /node1/node1
-        // /node1/node1/node1
-        // /node1/node1/node2
-        // /node1/node1/node3
-        // /node1/node2
-        // /node1/node2/node1
-        // /node1/node2/node2
-        // /node1/node2/node3
-        // /node1/node3
-        // /node1/node3/node1
-        // /node1/node3/node2
-        // /node1/node3/node3
-        // /node2
-        // /node2/node1
-        // /node2/node1/node1
-        // /node2/node1/node2
-        // /node2/node1/node3
-        // /node2/node2
-        // /node2/node2/node1
-        // /node2/node2/node2
-        // /node2/node2/node3
-        // /node2/node3
-        // /node2/node3/node1
-        // /node2/node3/node2
-        // /node2/node3/node3
-        // /node3
-        // /node3/node1
-        // /node3/node1/node1
-        // /node3/node1/node2
-        // /node3/node1/node3
-        // /node3/node2
-        // /node3/node2/node1
-        // /node3/node2/node2
-        // /node3/node2/node3
-        // /node3/node3
-        // /node3/node3/node1
-        // /node3/node3/node2
-        // /node3/node3/node3
-        // /secondBranch1
-        // /secondBranch1/secondBranch1
-        // /secondBranch1/secondBranch2
-        // /secondBranch2
-        // /secondBranch2/secondBranch1
-        // /secondBranch2/secondBranch2
-
-        String initialPath = "";
-        int depth = 3;
-        int numChildrenPerNode = 3;
-        int numPropertiesPerNode = 3;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = true;
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
-
-        // Delete two branches ...
-        graph.delete("/node2/node2").and().delete("/node3/node1");
-
-        assertThat(graph.getChildren().of("/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node3/node1"), hasChildren());
-
-        assertThat(graph.getChildren().of("/node2"), hasChildren(segment("node1"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node3/node1"), hasChildren());
-
-        assertThat(graph.getChildren().of("/node3"), hasChildren(segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node3/node1"), hasChildren());
-
-        Subgraph subgraph = graph.getSubgraphOfDepth(3).at("/");
-        assertThat(subgraph, is(notNullValue()));
-        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node1"), segment("node3")));
-        assertThat(subgraph.getNode("node1").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(subgraph.getNode("node1"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node1"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node1"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2").getChildren(), hasChildren(segment("node1"), segment("node3")));
-        assertThat(subgraph.getNode("node2"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3").getChildren(), hasChildren(segment("node2"), segment("node3")));
-        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-
-        subgraph = graph.getSubgraphOfDepth(2).at("/node3");
-        assertThat(subgraph, is(notNullValue()));
-        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node2"), segment("node3")));
-        assertThat(subgraph.getNode("."), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("."), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("."), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-    }
-
-    @Test
-    public void shouldCopyNodeWithChildren() {
-        // Create the tree (at total of 40 nodes, plus the extra 6 added later)...
-        // /
-        // /node1
-        // /node1/node1
-        // /node1/node1/node1
-        // /node1/node1/node2
-        // /node1/node1/node3
-        // /node1/node2
-        // /node1/node2/node1
-        // /node1/node2/node2
-        // /node1/node2/node3
-        // /node1/node3
-        // /node1/node3/node1
-        // /node1/node3/node2
-        // /node1/node3/node3
-        // /node2
-        // /node2/node1
-        // /node2/node1/node1
-        // /node2/node1/node2
-        // /node2/node1/node3
-        // /node2/node2
-        // /node2/node2/node1
-        // /node2/node2/node2
-        // /node2/node2/node3
-        // /node2/node3
-        // /node2/node3/node1
-        // /node2/node3/node2
-        // /node2/node3/node3
-        // /node3
-        // /node3/node1
-        // /node3/node1/node1
-        // /node3/node1/node2
-        // /node3/node1/node3
-        // /node3/node2
-        // /node3/node2/node1
-        // /node3/node2/node2
-        // /node3/node2/node3
-        // /node3/node3
-        // /node3/node3/node1
-        // /node3/node3/node2
-        // /node3/node3/node3
-        // /secondBranch1
-        // /secondBranch1/secondBranch1
-        // /secondBranch1/secondBranch2
-        // /secondBranch2
-        // /secondBranch2/secondBranch1
-        // /secondBranch2/secondBranch2
-
-        String initialPath = "";
-        int depth = 3;
-        int numChildrenPerNode = 3;
-        int numPropertiesPerNode = 3;
-        Stopwatch sw = new Stopwatch();
-        boolean batch = true;
-        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
-
-        // Create some references between nodes that aren't involved with the copy ...
-        graph.set("refProp").on("/node1").to(graph.getNodeAt("/node1/node3"));
-        graph.set("refProp").on("/node1/node1").to(graph.getNodeAt("/node3/node2")); // will soon be /node3/node2[1]
-
-        // Create some "inward" references from nodes that are NOT being copied to nodes that are being copied ...
-        graph.set("refProp").on("/node1/node2").to(graph.getNodeAt("/node2/node2"));
-        graph.set("refProp").on("/node1/node3").to(graph.getNodeAt("/node2/node2"));
-
-        // Create some "outward" references from nodes that are being copied to nodes that are NOT being copied ...
-        graph.set("refProp").on("/node2/node1").to(graph.getNodeAt("/node1/node1"));
-        graph.set("refProp").on("/node2/node3").to(graph.getNodeAt("/node1/node2"));
-
-        // Create some "internal" references between nodes that are being copied ...
-        graph.set("refProp").on("/node2/node2").to(graph.getNodeAt("/node2/node2/node1"));
-        graph.set("refProp").on("/node2/node3/node1").to(graph.getNodeAt("/node2/node2/node1"));
-
-        // Verify the references are there ...
-        assertReference("/node1", "refProp", "/node1/node3");
-        assertReference("/node1/node1", "refProp", "/node3/node2");
-        assertReference("/node1/node2", "refProp", "/node2/node2");
-        assertReference("/node1/node3", "refProp", "/node2/node2");
-        assertReference("/node2/node1", "refProp", "/node1/node1");
-        assertReference("/node2/node3", "refProp", "/node1/node2");
-        assertReference("/node2/node2", "refProp", "/node2/node2/node1");
-        assertReference("/node2/node3/node1", "refProp", "/node2/node2/node1");
-
-        // Copy a branches ...
-        graph.copy("/node2").into("/node3");
-
-        // Verify the references are still there ...
-        assertReference("/node1", "refProp", "/node1/node3");
-        assertReference("/node1/node1", "refProp", "/node3/node2[1]");
-        assertReference("/node1/node2", "refProp", "/node2/node2");
-        assertReference("/node1/node3", "refProp", "/node2/node2");
-        assertReference("/node2/node1", "refProp", "/node1/node1");
-        assertReference("/node2/node3", "refProp", "/node1/node2");
-        assertReference("/node2/node2", "refProp", "/node2/node2/node1");
-        assertReference("/node2/node3/node1", "refProp", "/node2/node2/node1");
-
-        // And verify that we have a few new (outward and internal) references in the copy ...
-        assertReference("/node3/node2[2]/node1", "refProp", "/node1/node1"); // outward
-        assertReference("/node3/node2[2]/node3", "refProp", "/node1/node2"); // outward
-        assertReference("/node3/node2[2]/node2", "refProp", "/node3/node2[2]/node2/node1"); // internal
-        assertReference("/node3/node2[2]/node3/node1", "refProp", "/node3/node2[2]/node2/node1"); // internal
-
-        // Now assert the structure ...
-        assertThat(graph.getChildren().of("/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node1/node3/node1"), hasChildren());
-
-        // The original of the copy should still exist ...
-        assertThat(graph.getChildren().of("/node2"), hasChildren(segment("node1"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node2/node3/node1"), hasChildren());
-
-        assertThat(graph.getChildren().of("/node3"), hasChildren(segment("node2[1]"), segment("node3"), segment("node2[2]")));
-        assertThat(graph.getChildren().of("/node3/node2[1]"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node3/node1"), hasChildren());
-        assertThat(graph.getChildren().of("/node3/node2[2]"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node2[2]/node1"), hasChildren(segment("node1"),
-                                                                                segment("node2"),
-                                                                                segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node2[2]/node2"), hasChildren(segment("node1"),
-                                                                                segment("node2"),
-                                                                                segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node2[2]/node3"), hasChildren(segment("node1"),
-                                                                                segment("node2"),
-                                                                                segment("node3")));
-        assertThat(graph.getChildren().of("/node3/node2[2]/node1/node1"), hasChildren());
-
-        Subgraph subgraph = graph.getSubgraphOfDepth(4).at("/node3");
-        assertThat(subgraph, is(notNullValue()));
-        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node2"), segment("node3")));
-        assertThat(subgraph.getNode("."), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("."), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("."), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[1]").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(subgraph.getNode("node2[1]"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[1]"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[1]"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
-        assertThat(subgraph.getNode("node2[2]"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1").getChildren(), hasChildren(segment("node1"),
-                                                                                 segment("node2"),
-                                                                                 segment("node3")));
-        assertThat(subgraph.getNode("node2[2]/node1"), hasProperty("property1",
-                                                                   "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1"), hasProperty("property2",
-                                                                   "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1"), hasProperty("property3",
-                                                                   "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1/node1").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2[2]/node1/node1"), hasProperty("property1",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1/node1"), hasProperty("property2",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1/node1"), hasProperty("property3",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1/node2").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2[2]/node1/node2"), hasProperty("property1",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1/node2"), hasProperty("property2",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1/node2"), hasProperty("property3",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1/node3").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2[2]/node1/node3"), hasProperty("property1",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1/node3"), hasProperty("property2",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node1/node3"), hasProperty("property3",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2").getChildren(), hasChildren(segment("node1"),
-                                                                                 segment("node2"),
-                                                                                 segment("node3")));
-        assertThat(subgraph.getNode("node2[2]/node2"), hasProperty("property1",
-                                                                   "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2"), hasProperty("property2",
-                                                                   "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2"), hasProperty("property3",
-                                                                   "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2/node1").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2[2]/node2/node1"), hasProperty("property1",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2/node1"), hasProperty("property2",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2/node1"), hasProperty("property3",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2/node2").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2[2]/node2/node2"), hasProperty("property1",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2/node2"), hasProperty("property2",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2/node2"), hasProperty("property3",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2/node3").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2[2]/node2/node3"), hasProperty("property1",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2/node3"), hasProperty("property2",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node2/node3"), hasProperty("property3",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3").getChildren(), hasChildren(segment("node1"),
-                                                                                 segment("node2"),
-                                                                                 segment("node3")));
-        assertThat(subgraph.getNode("node2[2]/node3"), hasProperty("property1",
-                                                                   "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3"), hasProperty("property2",
-                                                                   "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3"), hasProperty("property3",
-                                                                   "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3/node1").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2[2]/node3/node1"), hasProperty("property1",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3/node1"), hasProperty("property2",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3/node1"), hasProperty("property3",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3/node2").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2[2]/node3/node2"), hasProperty("property1",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3/node2"), hasProperty("property2",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3/node2"), hasProperty("property3",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3/node3").getChildren(), isEmpty());
-        assertThat(subgraph.getNode("node2[2]/node3/node3"), hasProperty("property1",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3/node3"), hasProperty("property2",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-        assertThat(subgraph.getNode("node2[2]/node3/node3"), hasProperty("property3",
-                                                                         "The quick brown fox jumped over the moon. What? "));
-    }
-
-    protected void assertReference( String fromNodePath,
-                                    String propertyName,
-                                    String... toNodePath ) {
-        Object[] values = graph.getProperty(propertyName).on(fromNodePath).getValuesAsArray();
-        assertThat(values.length, is(toNodePath.length));
-        for (int i = 0; i != values.length; ++i) {
-            Object value = values[i];
-            assertThat(value, is(instanceOf(Reference.class)));
-            Reference ref = (Reference)value;
-            assertThat(graph.resolve(ref), is(graph.getNodeAt(toNodePath[i])));
-        }
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test/WritableConnectorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,806 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.connector.test;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.jboss.dna.graph.IsNodeWithChildren.hasChild;
+import static org.jboss.dna.graph.IsNodeWithChildren.hasChildren;
+import static org.jboss.dna.graph.IsNodeWithChildren.isEmpty;
+import static org.jboss.dna.graph.IsNodeWithProperty.hasProperty;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.common.statistic.Stopwatch;
+import org.jboss.dna.common.util.IoUtil;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.Node;
+import org.jboss.dna.graph.Subgraph;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.property.Reference;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * A class that provides standard writing verification tests for connectors that are able to store any content (in any structure).
+ * This class is designed to be extended for each connector, and in each subclass the {@link #setUpSource()} method is defined to
+ * provide a valid {@link RepositorySource} for the connector to be tested.
+ * <p>
+ * Since these tests do modify repository content, the repository is set up for each test, given each test a pristine repository
+ * (as {@link #initializeContent(Graph) initialized} by the concrete test case class).
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+public abstract class WritableConnectorTest extends AbstractConnectorTest {
+
+    protected String[] validLargeValues;
+
+    @Override
+    @Before
+    public void beforeEach() throws Exception {
+        super.beforeEach();
+
+        // Load in the large value ...
+        validLargeValues = new String[] {IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum1.txt")),
+            IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum2.txt")),
+            IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum3.txt"))};
+    }
+
+    /**
+     * These tests require that the source supports updates, since all of the tests do some form of updates.
+     */
+    @Test
+    public void shouldHaveUpdateCapabilities() {
+        assertThat(source.getCapabilities().supportsUpdates(), is(true));
+    }
+
+    @Test
+    public void shouldSetPropertyOnRootNode() {
+        graph.set("propA").to("valueA").on("/");
+        // Now look up the node ...
+        Node root = graph.getNodeAt("/");
+        assertThat(root, is(notNullValue()));
+        assertThat(root, hasProperty(DnaLexicon.UUID, getRootNodeUuid()));
+        assertThat(root, hasProperty("propA", "valueA"));
+    }
+
+    @Test
+    public void shouldAddChildUnderRootNode() {
+        graph.batch().create("/a").with("propB", "valueB").and("propC", "valueC").execute();
+        // Now look up the root node ...
+        Node root = graph.getNodeAt("/");
+        assertThat(root, is(notNullValue()));
+        assertThat(root, hasProperty(DnaLexicon.UUID, getRootNodeUuid()));
+        assertThat(root.getChildren(), hasChild(segment("a")));
+
+        // Now look up node A ...
+        Node nodeA = graph.getNodeAt("/a");
+        assertThat(nodeA, is(notNullValue()));
+        assertThat(nodeA, hasProperty("propB", "valueB"));
+        assertThat(nodeA, hasProperty("propC", "valueC"));
+        assertThat(nodeA.getChildren(), isEmpty());
+    }
+
+    @Test
+    public void shouldAddChildrenOnRootNode() {
+        graph.batch().set("propA").to("valueA").on("/").and().create("/a").with("propB", "valueB").and("propC", "valueC").and().create("/b").with("propD",
+                                                                                                                                                  "valueD").and("propE",
+                                                                                                                                                                "valueE").execute();
+        // Now look up the root node ...
+        Node root = graph.getNodeAt("/");
+        assertThat(root, is(notNullValue()));
+        assertThat(root, hasProperty(DnaLexicon.UUID, getRootNodeUuid()));
+        assertThat(root, hasProperty("propA", "valueA"));
+        assertThat(root.getChildren(), hasChildren(segment("a"), segment("b")));
+
+        // Now look up node A ...
+        Node nodeA = graph.getNodeAt("/a");
+        assertThat(nodeA, is(notNullValue()));
+        assertThat(nodeA, hasProperty("propB", "valueB"));
+        assertThat(nodeA, hasProperty("propC", "valueC"));
+        assertThat(nodeA.getChildren(), isEmpty());
+
+        // Now look up node B ...
+        Node nodeB = graph.getNodeAt("/b");
+        assertThat(nodeB, is(notNullValue()));
+        assertThat(nodeB, hasProperty("propD", "valueD"));
+        assertThat(nodeB, hasProperty("propE", "valueE"));
+        assertThat(nodeB.getChildren(), isEmpty());
+
+        // Get the subgraph ...
+        Subgraph subgraph = graph.getSubgraphOfDepth(3).at("/");
+        assertThat(subgraph, is(notNullValue()));
+        assertThat(subgraph.getNode("."), hasProperty(DnaLexicon.UUID, getRootNodeUuid()));
+        assertThat(subgraph.getNode("."), hasProperty("propA", "valueA"));
+        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("a"), segment("b")));
+        assertThat(subgraph.getNode("a"), is(notNullValue()));
+        assertThat(subgraph.getNode("a"), hasProperty("propB", "valueB"));
+        assertThat(subgraph.getNode("a"), hasProperty("propC", "valueC"));
+        assertThat(subgraph.getNode("a").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("b"), is(notNullValue()));
+        assertThat(subgraph.getNode("b"), hasProperty("propD", "valueD"));
+        assertThat(subgraph.getNode("b"), hasProperty("propE", "valueE"));
+        assertThat(subgraph.getNode("b").getChildren(), isEmpty());
+    }
+
+    @Test
+    public void shouldStoreManyPropertiesOnANode() {
+        Graph.Create<Graph.Batch> create = graph.batch().create("/a");
+        for (int i = 0; i != 100; ++i) {
+            create = create.with("property" + i, "value" + i);
+        }
+        create.execute();
+        // Now look up all the properties ...
+        Node nodeA = graph.getNodeAt("/a");
+        assertThat(nodeA, is(notNullValue()));
+        for (int i = 0; i != 100; ++i) {
+            assertThat(nodeA, hasProperty("property" + i, "value" + i));
+        }
+        assertThat(nodeA.getChildren(), isEmpty());
+    }
+
+    @Test
+    public void shouldUpdateSmallPropertiesOnANode() {
+        // Create the property and add some properties (including 2 large values) ...
+        Graph.Create<Graph.Batch> create = graph.batch().create("/a");
+        for (int i = 0; i != 10; ++i) {
+            create = create.with("property" + i, "value" + i);
+        }
+        create.execute();
+
+        // Now look up all the properties ...
+        Node nodeA = graph.getNodeAt("/a");
+        assertThat(nodeA, is(notNullValue()));
+        for (int i = 0; i != 10; ++i) {
+            assertThat(nodeA, hasProperty("property" + i, "value" + i));
+        }
+        assertThat(nodeA.getChildren(), isEmpty());
+
+        // Now, remove some of the properties and add some others ...
+        Graph.Batch batch = graph.batch();
+        batch.remove("property0", "property1").on("/a");
+        batch.set("property6").to("new valid 6").on("/a");
+        batch.execute();
+
+        // Re-read the properties ...
+        nodeA = graph.getNodeAt("/a");
+        assertThat(nodeA, is(notNullValue()));
+        for (int i = 0; i != 10; ++i) {
+            if (i == 0 || i == 1) {
+                continue;
+            } else if (i == 6) {
+                assertThat(nodeA, hasProperty("property" + i, "new valid 6"));
+            } else {
+                assertThat(nodeA, hasProperty("property" + i, "value" + i));
+            }
+        }
+        assertThat(nodeA.getChildren(), isEmpty());
+
+    }
+
+    @Test
+    public void shouldUpdateLargePropertiesOnANode() {
+        // Create the property and add some properties (including 2 large values) ...
+        Graph.Create<Graph.Batch> create = graph.batch().create("/a");
+        for (int i = 0; i != 100; ++i) {
+            create = create.with("property" + i, "value" + i);
+        }
+        create = create.with("largeProperty1", validLargeValues[0]);
+        create = create.with("largeProperty2", validLargeValues[1]);
+        create.execute();
+
+        // Now look up all the properties ...
+        Node nodeA = graph.getNodeAt("/a");
+        assertThat(nodeA, is(notNullValue()));
+        for (int i = 0; i != 100; ++i) {
+            assertThat(nodeA, hasProperty("property" + i, "value" + i));
+        }
+        assertThat(nodeA, hasProperty("largeProperty1", validLargeValues[0]));
+        assertThat(nodeA, hasProperty("largeProperty2", validLargeValues[1]));
+        assertThat(nodeA.getChildren(), isEmpty());
+
+        // Now, remove some of the properties and add some others ...
+        Graph.Batch batch = graph.batch();
+        batch.remove("largeProperty1", "property0", "property1").on("/a");
+        batch.set("property50").to("new valid 50").on("/a");
+        batch.set("largeProperty3").to(validLargeValues[2]).on("/a");
+        batch.execute();
+
+        // Re-read the properties ...
+        nodeA = graph.getNodeAt("/a");
+        assertThat(nodeA, is(notNullValue()));
+        for (int i = 0; i != 100; ++i) {
+            if (i == 0 || i == 1) {
+                continue;
+            } else if (i == 50) {
+                assertThat(nodeA, hasProperty("property" + i, "new valid 50"));
+            } else {
+                assertThat(nodeA, hasProperty("property" + i, "value" + i));
+            }
+        }
+        assertThat(nodeA, hasProperty("largeProperty2", validLargeValues[1]));
+        assertThat(nodeA, hasProperty("largeProperty3", validLargeValues[2]));
+        assertThat(nodeA.getChildren(), isEmpty());
+
+    }
+
+    @Test
+    public void shouldCreateDeepBranchUsingIndividualRequests() {
+        String initialPath = "";
+        int depth = 50;
+        int numChildrenPerNode = 1;
+        int numPropertiesPerNode = 7;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = false;
+        String description = "deep and narrow tree, 1x50";
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, description);
+    }
+
+    @Test
+    public void shouldCreateDeepBranchUsingOneBatch() {
+        String initialPath = "";
+        int depth = 50;
+        int numChildrenPerNode = 1;
+        int numPropertiesPerNode = 7;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        String description = "deep and narrow tree, 1x50";
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, description);
+    }
+
+    @Test
+    public void shouldCreateFlatAndWideTreeUsingOneBatch() {
+        String initialPath = "";
+        int depth = 1;
+        int numChildrenPerNode = 300;
+        int numPropertiesPerNode = 7;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
+    }
+
+    @Test
+    public void shouldCreateBinaryTreeUsingOneBatch() {
+        String initialPath = "";
+        int depth = 8;
+        int numChildrenPerNode = 2;
+        int numPropertiesPerNode = 7;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        String description = "binary tree, 2x8";
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, description);
+    }
+
+    @Test
+    public void shouldCreateTreeWith10ChildrenAnd2LevelsDeepUsingIndividualRequests() {
+        String initialPath = "";
+        int depth = 2;
+        int numChildrenPerNode = 10;
+        int numPropertiesPerNode = 7;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = false;
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
+    }
+
+    @Test
+    public void shouldCreateTreeWith10ChildrenAnd2LevelsDeepUsingOneBatch() {
+        String initialPath = "";
+        int depth = 2;
+        int numChildrenPerNode = 10;
+        int numPropertiesPerNode = 7;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
+    }
+
+    @Test
+    public void shouldCreateTreeWith10ChildrenAnd3LevelsDeepUsingOneBatch() {
+        String initialPath = "";
+        int depth = 3;
+        int numChildrenPerNode = 10;
+        int numPropertiesPerNode = 7;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
+    }
+
+    @Test
+    public void shouldCreateAndReadTree() {
+        // Create the tree (at total of 40 nodes, plus the extra 6 added later)...
+        // /
+        // /node1
+        // /node1/node1
+        // /node1/node1/node1
+        // /node1/node1/node2
+        // /node1/node1/node3
+        // /node1/node2
+        // /node1/node2/node1
+        // /node1/node2/node2
+        // /node1/node2/node3
+        // /node1/node3
+        // /node1/node3/node1
+        // /node1/node3/node2
+        // /node1/node3/node3
+        // /node2
+        // /node2/node1
+        // /node2/node1/node1
+        // /node2/node1/node2
+        // /node2/node1/node3
+        // /node2/node2
+        // /node2/node2/node1
+        // /node2/node2/node2
+        // /node2/node2/node3
+        // /node2/node3
+        // /node2/node3/node1
+        // /node2/node3/node2
+        // /node2/node3/node3
+        // /node3
+        // /node3/node1
+        // /node3/node1/node1
+        // /node3/node1/node2
+        // /node3/node1/node3
+        // /node3/node2
+        // /node3/node2/node1
+        // /node3/node2/node2
+        // /node3/node2/node3
+        // /node3/node3
+        // /node3/node3/node1
+        // /node3/node3/node2
+        // /node3/node3/node3
+        // /secondBranch1
+        // /secondBranch1/secondBranch1
+        // /secondBranch1/secondBranch2
+        // /secondBranch2
+        // /secondBranch2/secondBranch1
+        // /secondBranch2/secondBranch2
+
+        String initialPath = "";
+        int depth = 3;
+        int numChildrenPerNode = 3;
+        int numPropertiesPerNode = 3;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
+
+        assertThat(graph.getChildren().of("/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node3/node1"), isEmpty());
+
+        assertThat(graph.getChildren().of("/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node3/node1"), isEmpty());
+
+        assertThat(graph.getChildren().of("/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node3/node1"), isEmpty());
+
+        Subgraph subgraph = graph.getSubgraphOfDepth(2).at("/node3/node2");
+        assertThat(subgraph, is(notNullValue()));
+        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(subgraph.getNode("."), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("."), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("."), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node1").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node1"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node1"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node1"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+
+        subgraph = graph.getSubgraphOfDepth(2).at("/node3");
+        assertThat(subgraph, is(notNullValue()));
+        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(subgraph.getNode("."), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("."), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("."), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node1").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node1"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node1"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node1"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+    }
+
+    @Test
+    public void shouldDeleteNodes() {
+        // Create the tree (at total of 40 nodes, plus the extra 6 added later)...
+        // /
+        // /node1
+        // /node1/node1
+        // /node1/node1/node1
+        // /node1/node1/node2
+        // /node1/node1/node3
+        // /node1/node2
+        // /node1/node2/node1
+        // /node1/node2/node2
+        // /node1/node2/node3
+        // /node1/node3
+        // /node1/node3/node1
+        // /node1/node3/node2
+        // /node1/node3/node3
+        // /node2
+        // /node2/node1
+        // /node2/node1/node1
+        // /node2/node1/node2
+        // /node2/node1/node3
+        // /node2/node2
+        // /node2/node2/node1
+        // /node2/node2/node2
+        // /node2/node2/node3
+        // /node2/node3
+        // /node2/node3/node1
+        // /node2/node3/node2
+        // /node2/node3/node3
+        // /node3
+        // /node3/node1
+        // /node3/node1/node1
+        // /node3/node1/node2
+        // /node3/node1/node3
+        // /node3/node2
+        // /node3/node2/node1
+        // /node3/node2/node2
+        // /node3/node2/node3
+        // /node3/node3
+        // /node3/node3/node1
+        // /node3/node3/node2
+        // /node3/node3/node3
+        // /secondBranch1
+        // /secondBranch1/secondBranch1
+        // /secondBranch1/secondBranch2
+        // /secondBranch2
+        // /secondBranch2/secondBranch1
+        // /secondBranch2/secondBranch2
+
+        String initialPath = "";
+        int depth = 3;
+        int numChildrenPerNode = 3;
+        int numPropertiesPerNode = 3;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
+
+        // Delete two branches ...
+        graph.delete("/node2/node2").and().delete("/node3/node1");
+
+        assertThat(graph.getChildren().of("/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node3/node1"), hasChildren());
+
+        assertThat(graph.getChildren().of("/node2"), hasChildren(segment("node1"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node3/node1"), hasChildren());
+
+        assertThat(graph.getChildren().of("/node3"), hasChildren(segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node3/node1"), hasChildren());
+
+        Subgraph subgraph = graph.getSubgraphOfDepth(3).at("/");
+        assertThat(subgraph, is(notNullValue()));
+        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node1"), segment("node3")));
+        assertThat(subgraph.getNode("node1").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(subgraph.getNode("node1"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node1"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node1"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2").getChildren(), hasChildren(segment("node1"), segment("node3")));
+        assertThat(subgraph.getNode("node2"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3").getChildren(), hasChildren(segment("node2"), segment("node3")));
+        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+
+        subgraph = graph.getSubgraphOfDepth(2).at("/node3");
+        assertThat(subgraph, is(notNullValue()));
+        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node2"), segment("node3")));
+        assertThat(subgraph.getNode("."), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("."), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("."), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+    }
+
+    @Test
+    public void shouldCopyNodeWithChildren() {
+        // Create the tree (at total of 40 nodes, plus the extra 6 added later)...
+        // /
+        // /node1
+        // /node1/node1
+        // /node1/node1/node1
+        // /node1/node1/node2
+        // /node1/node1/node3
+        // /node1/node2
+        // /node1/node2/node1
+        // /node1/node2/node2
+        // /node1/node2/node3
+        // /node1/node3
+        // /node1/node3/node1
+        // /node1/node3/node2
+        // /node1/node3/node3
+        // /node2
+        // /node2/node1
+        // /node2/node1/node1
+        // /node2/node1/node2
+        // /node2/node1/node3
+        // /node2/node2
+        // /node2/node2/node1
+        // /node2/node2/node2
+        // /node2/node2/node3
+        // /node2/node3
+        // /node2/node3/node1
+        // /node2/node3/node2
+        // /node2/node3/node3
+        // /node3
+        // /node3/node1
+        // /node3/node1/node1
+        // /node3/node1/node2
+        // /node3/node1/node3
+        // /node3/node2
+        // /node3/node2/node1
+        // /node3/node2/node2
+        // /node3/node2/node3
+        // /node3/node3
+        // /node3/node3/node1
+        // /node3/node3/node2
+        // /node3/node3/node3
+        // /secondBranch1
+        // /secondBranch1/secondBranch1
+        // /secondBranch1/secondBranch2
+        // /secondBranch2
+        // /secondBranch2/secondBranch1
+        // /secondBranch2/secondBranch2
+
+        String initialPath = "";
+        int depth = 3;
+        int numChildrenPerNode = 3;
+        int numPropertiesPerNode = 3;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
+
+        // Create some references between nodes that aren't involved with the copy ...
+        graph.set("refProp").on("/node1").to(graph.getNodeAt("/node1/node3"));
+        graph.set("refProp").on("/node1/node1").to(graph.getNodeAt("/node3/node2")); // will soon be /node3/node2[1]
+
+        // Create some "inward" references from nodes that are NOT being copied to nodes that are being copied ...
+        graph.set("refProp").on("/node1/node2").to(graph.getNodeAt("/node2/node2"));
+        graph.set("refProp").on("/node1/node3").to(graph.getNodeAt("/node2/node2"));
+
+        // Create some "outward" references from nodes that are being copied to nodes that are NOT being copied ...
+        graph.set("refProp").on("/node2/node1").to(graph.getNodeAt("/node1/node1"));
+        graph.set("refProp").on("/node2/node3").to(graph.getNodeAt("/node1/node2"));
+
+        // Create some "internal" references between nodes that are being copied ...
+        graph.set("refProp").on("/node2/node2").to(graph.getNodeAt("/node2/node2/node1"));
+        graph.set("refProp").on("/node2/node3/node1").to(graph.getNodeAt("/node2/node2/node1"));
+
+        // Verify the references are there ...
+        assertReference("/node1", "refProp", "/node1/node3");
+        assertReference("/node1/node1", "refProp", "/node3/node2");
+        assertReference("/node1/node2", "refProp", "/node2/node2");
+        assertReference("/node1/node3", "refProp", "/node2/node2");
+        assertReference("/node2/node1", "refProp", "/node1/node1");
+        assertReference("/node2/node3", "refProp", "/node1/node2");
+        assertReference("/node2/node2", "refProp", "/node2/node2/node1");
+        assertReference("/node2/node3/node1", "refProp", "/node2/node2/node1");
+
+        // Copy a branches ...
+        graph.copy("/node2").into("/node3");
+
+        // Verify the references are still there ...
+        assertReference("/node1", "refProp", "/node1/node3");
+        assertReference("/node1/node1", "refProp", "/node3/node2[1]");
+        assertReference("/node1/node2", "refProp", "/node2/node2");
+        assertReference("/node1/node3", "refProp", "/node2/node2");
+        assertReference("/node2/node1", "refProp", "/node1/node1");
+        assertReference("/node2/node3", "refProp", "/node1/node2");
+        assertReference("/node2/node2", "refProp", "/node2/node2/node1");
+        assertReference("/node2/node3/node1", "refProp", "/node2/node2/node1");
+
+        // And verify that we have a few new (outward and internal) references in the copy ...
+        assertReference("/node3/node2[2]/node1", "refProp", "/node1/node1"); // outward
+        assertReference("/node3/node2[2]/node3", "refProp", "/node1/node2"); // outward
+        assertReference("/node3/node2[2]/node2", "refProp", "/node3/node2[2]/node2/node1"); // internal
+        assertReference("/node3/node2[2]/node3/node1", "refProp", "/node3/node2[2]/node2/node1"); // internal
+
+        // Now assert the structure ...
+        assertThat(graph.getChildren().of("/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node2"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node1/node3/node1"), hasChildren());
+
+        // The original of the copy should still exist ...
+        assertThat(graph.getChildren().of("/node2"), hasChildren(segment("node1"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node1"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node2/node3/node1"), hasChildren());
+
+        assertThat(graph.getChildren().of("/node3"), hasChildren(segment("node2[1]"), segment("node3"), segment("node2[2]")));
+        assertThat(graph.getChildren().of("/node3/node2[1]"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node3"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node3/node1"), hasChildren());
+        assertThat(graph.getChildren().of("/node3/node2[2]"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node2[2]/node1"), hasChildren(segment("node1"),
+                                                                                segment("node2"),
+                                                                                segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node2[2]/node2"), hasChildren(segment("node1"),
+                                                                                segment("node2"),
+                                                                                segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node2[2]/node3"), hasChildren(segment("node1"),
+                                                                                segment("node2"),
+                                                                                segment("node3")));
+        assertThat(graph.getChildren().of("/node3/node2[2]/node1/node1"), hasChildren());
+
+        Subgraph subgraph = graph.getSubgraphOfDepth(4).at("/node3");
+        assertThat(subgraph, is(notNullValue()));
+        assertThat(subgraph.getNode(".").getChildren(), hasChildren(segment("node2"), segment("node3")));
+        assertThat(subgraph.getNode("."), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("."), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("."), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[1]").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(subgraph.getNode("node2[1]"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[1]"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[1]"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node3"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node3"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]").getChildren(), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+        assertThat(subgraph.getNode("node2[2]"), hasProperty("property1", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]"), hasProperty("property2", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]"), hasProperty("property3", "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1").getChildren(), hasChildren(segment("node1"),
+                                                                                 segment("node2"),
+                                                                                 segment("node3")));
+        assertThat(subgraph.getNode("node2[2]/node1"), hasProperty("property1",
+                                                                   "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1"), hasProperty("property2",
+                                                                   "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1"), hasProperty("property3",
+                                                                   "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1/node1").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2[2]/node1/node1"), hasProperty("property1",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1/node1"), hasProperty("property2",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1/node1"), hasProperty("property3",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1/node2").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2[2]/node1/node2"), hasProperty("property1",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1/node2"), hasProperty("property2",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1/node2"), hasProperty("property3",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1/node3").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2[2]/node1/node3"), hasProperty("property1",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1/node3"), hasProperty("property2",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node1/node3"), hasProperty("property3",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2").getChildren(), hasChildren(segment("node1"),
+                                                                                 segment("node2"),
+                                                                                 segment("node3")));
+        assertThat(subgraph.getNode("node2[2]/node2"), hasProperty("property1",
+                                                                   "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2"), hasProperty("property2",
+                                                                   "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2"), hasProperty("property3",
+                                                                   "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2/node1").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2[2]/node2/node1"), hasProperty("property1",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2/node1"), hasProperty("property2",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2/node1"), hasProperty("property3",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2/node2").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2[2]/node2/node2"), hasProperty("property1",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2/node2"), hasProperty("property2",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2/node2"), hasProperty("property3",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2/node3").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2[2]/node2/node3"), hasProperty("property1",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2/node3"), hasProperty("property2",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node2/node3"), hasProperty("property3",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3").getChildren(), hasChildren(segment("node1"),
+                                                                                 segment("node2"),
+                                                                                 segment("node3")));
+        assertThat(subgraph.getNode("node2[2]/node3"), hasProperty("property1",
+                                                                   "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3"), hasProperty("property2",
+                                                                   "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3"), hasProperty("property3",
+                                                                   "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3/node1").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2[2]/node3/node1"), hasProperty("property1",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3/node1"), hasProperty("property2",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3/node1"), hasProperty("property3",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3/node2").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2[2]/node3/node2"), hasProperty("property1",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3/node2"), hasProperty("property2",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3/node2"), hasProperty("property3",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3/node3").getChildren(), isEmpty());
+        assertThat(subgraph.getNode("node2[2]/node3/node3"), hasProperty("property1",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3/node3"), hasProperty("property2",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+        assertThat(subgraph.getNode("node2[2]/node3/node3"), hasProperty("property3",
+                                                                         "The quick brown fox jumped over the moon. What? "));
+    }
+
+    protected void assertReference( String fromNodePath,
+                                    String propertyName,
+                                    String... toNodePath ) {
+        Object[] values = graph.getProperty(propertyName).on(fromNodePath).getValuesAsArray();
+        assertThat(values.length, is(toNodePath.length));
+        for (int i = 0; i != values.length; ++i) {
+            Object value = values[i];
+            assertThat(value, is(instanceOf(Reference.class)));
+            Reference ref = (Reference)value;
+            assertThat(graph.resolve(ref), is(graph.getNodeAt(toNodePath[i])));
+        }
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/package-info.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test/package-info.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,50 +0,0 @@
-/**
- * This package provides a set of unit tests that can be used to verify that a connector behaves correctly 
- * and in such a way that matches DNA's expectations.  These unit tests utilize JUnit 4 annotations, and are written
- * in a <a href="http://behaviour-driven.org/">Behavior-Driven Development</a> style where each test method
- * is named to describe the behavior being tested (e.g., "<code>shouldAlwaysBeAbleToReadRootNode()</code>").
- * This style helps to make more obvious the requirements and behavior that the test is verifying.
- * <p>
- * To use these unit tests, you simply extend the unit tests provided by this package.  But rather than write a
- * whole slew of test methods, your tests inherit all the test methods.  So, it's pretty easy to get a lot of
- * tests for almost no cost.
- * </p>
- * <p>
- * All unit tests (directly or indirectly) subclass {@link AbstractConnectorTest}, which does all the work of 
- * setting up and tearing down the connector, its environment, and common utility objects needed for many of
- * the tests.  This class defines two abstract methods that each of your test classes will have to implement:
- * <ul>
- *   <li>{@link AbstractConnectorTest#setUpSource() setUpSource()} - This method allows you to configure your
- *   {@link org.jboss.dna.graph.connectors.RepositorySource}, and will be called once during the set up of each test method.</li>
- *   <li>{@link AbstractConnectorTest#initializeContent(org.jboss.dna.graph.Graph) initializeContent()} - This method allows you to
- *   populate the repository with some predefined content, using the supplied {@link org.jboss.dna.graph.Graph graph}.
- *   This method will be called once during the set up of each test method (after {@link AbstractConnectorTest#setUpSource()}), 
- *   ensuring that each test method gets a fresh repository with content.
- *   If your connector is accessing an empty source, you should use this method to populate the source with some content.
- *   On the other hand, if your connector is accessing a system that already has its own content, you may still want
- *   to use this method to prepare the content or check that the content is what you're expecting.
- *   </li>
- * </ul>
- * The class also defines a number of utility methods that may be useful in different test methods.  These include (among others)
- * {@link AbstractConnectorTest#name(String)} to create a name from a string, {@link AbstractConnectorTest#path(String)} to
- * create a path from a string, {@link AbstractConnectorTest#segment(String)} to create a path segment from a string,
- * and several forms of {@link AbstractConnectorTest#createSubgraph(org.jboss.dna.graph.Graph, String, int, int, int, boolean, org.jboss.dna.common.stats.Stopwatch, java.io.PrintStream, String) createSubgraph(...)}
- * that is useful for creating a highly-structured subgraph.
- * </p>
- * <p>
- * While you may choose to extend <code>AbstractConnectorTest</code>, you'll more likely want to extend one of the
- * other test classes that define test methods, including:
- * <ul>
- *  <li>{@link ReadableConnectorTest} - Reads the content of your source through a variety of methods, including
- *  {@link org.jboss.dna.graph.requests.ReadNodeRequest reading one node at a time}, 
- *  {@link org.jboss.dna.graph.requests.ReadBranchRequest reading branches}, 
- *  {@link org.jboss.dna.graph.requests.ReadPropertyRequest reading one property at a time},
- *  {@link org.jboss.dna.graph.requests.ReadAllPropertiesRequest reading all properties}, 
- *  {@link org.jboss.dna.graph.requests.ReadAllChildrenRequest reading children}, etc.  These methods really just
- *  verify that the content read is consistent, and cannot verify that all the information is correct.
- *  </li>
- * </ul>
- * </p>
- */
-
-package org.jboss.dna.graph.connectors.test;
\ No newline at end of file

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/package-info.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/test/package-info.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/package-info.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/package-info.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,50 @@
+/**
+ * This package provides a set of unit tests that can be used to verify that a connector behaves correctly 
+ * and in such a way that matches DNA's expectations.  These unit tests utilize JUnit 4 annotations, and are written
+ * in a <a href="http://behaviour-driven.org/">Behavior-Driven Development</a> style where each test method
+ * is named to describe the behavior being tested (e.g., "<code>shouldAlwaysBeAbleToReadRootNode()</code>").
+ * This style helps to make more obvious the requirements and behavior that the test is verifying.
+ * <p>
+ * To use these unit tests, you simply extend the unit tests provided by this package.  But rather than write a
+ * whole slew of test methods, your tests inherit all the test methods.  So, it's pretty easy to get a lot of
+ * tests for almost no cost.
+ * </p>
+ * <p>
+ * All unit tests (directly or indirectly) subclass {@link AbstractConnectorTest}, which does all the work of 
+ * setting up and tearing down the connector, its environment, and common utility objects needed for many of
+ * the tests.  This class defines two abstract methods that each of your test classes will have to implement:
+ * <ul>
+ *   <li>{@link AbstractConnectorTest#setUpSource() setUpSource()} - This method allows you to configure your
+ *   {@link org.jboss.dna.graph.connector.RepositorySource}, and will be called once during the set up of each test method.</li>
+ *   <li>{@link AbstractConnectorTest#initializeContent(org.jboss.dna.graph.Graph) initializeContent()} - This method allows you to
+ *   populate the repository with some predefined content, using the supplied {@link org.jboss.dna.graph.Graph graph}.
+ *   This method will be called once during the set up of each test method (after {@link AbstractConnectorTest#setUpSource()}), 
+ *   ensuring that each test method gets a fresh repository with content.
+ *   If your connector is accessing an empty source, you should use this method to populate the source with some content.
+ *   On the other hand, if your connector is accessing a system that already has its own content, you may still want
+ *   to use this method to prepare the content or check that the content is what you're expecting.
+ *   </li>
+ * </ul>
+ * The class also defines a number of utility methods that may be useful in different test methods.  These include (among others)
+ * {@link AbstractConnectorTest#name(String)} to create a name from a string, {@link AbstractConnectorTest#path(String)} to
+ * create a path from a string, {@link AbstractConnectorTest#segment(String)} to create a path segment from a string,
+ * and several forms of {@link AbstractConnectorTest#createSubgraph(org.jboss.dna.graph.Graph, String, int, int, int, boolean, org.jboss.dna.common.statistic.Stopwatch, java.io.PrintStream, String) createSubgraph(...)}
+ * that is useful for creating a highly-structured subgraph.
+ * </p>
+ * <p>
+ * While you may choose to extend <code>AbstractConnectorTest</code>, you'll more likely want to extend one of the
+ * other test classes that define test methods, including:
+ * <ul>
+ *  <li>{@link ReadableConnectorTest} - Reads the content of your source through a variety of methods, including
+ *  {@link org.jboss.dna.graph.request.ReadNodeRequest reading one node at a time}, 
+ *  {@link org.jboss.dna.graph.request.ReadBranchRequest reading branches}, 
+ *  {@link org.jboss.dna.graph.request.ReadPropertyRequest reading one property at a time},
+ *  {@link org.jboss.dna.graph.request.ReadAllPropertiesRequest reading all properties}, 
+ *  {@link org.jboss.dna.graph.request.ReadAllChildrenRequest reading children}, etc.  These methods really just
+ *  verify that the content read is consistent, and cannot verify that all the information is correct.
+ *  </li>
+ * </ul>
+ * </p>
+ */
+
+package org.jboss.dna.graph.connector.test;
\ No newline at end of file

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryConnectionPoolTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryConnectionPoolTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryConnectionPoolTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,222 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import static org.jboss.dna.graph.connectors.RepositorySourceLoadHarness.runLoadTest;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionPool;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class RepositoryConnectionPoolTest {
-
-    private RepositoryConnectionPool pool;
-    private RepositorySource source;
-    private ExecutionContext context;
-
-    @Before
-    public void beforeEach() {
-        source = new TimeDelayingRepositorySource("source 1");
-        pool = new RepositoryConnectionPool(source, 1, 1, 100, TimeUnit.SECONDS);
-        context = null;
-    }
-
-    @After
-    public void afterEach() throws Exception {
-        pool.shutdown();
-        pool.awaitTermination(2, TimeUnit.SECONDS);
-    }
-
-    @Test
-    public void shouldBeCreatedInRunningState() {
-        assertThat(pool.isShutdown(), is(false));
-        assertThat(pool.isTerminating(), is(false));
-        assertThat(pool.isTerminated(), is(false));
-        assertThat(pool.getTotalConnectionsCreated(), is(0l));
-        assertThat(pool.getTotalConnectionsUsed(), is(0l));
-    }
-
-    @Test
-    public void shouldShutdownWhenNoConnectionsWereCreatedOrUsed() throws InterruptedException {
-        assertThat(pool.isShutdown(), is(false));
-        assertThat(pool.isTerminating(), is(false));
-        assertThat(pool.isTerminated(), is(false));
-        assertThat(pool.getTotalConnectionsCreated(), is(0l));
-        assertThat(pool.getTotalConnectionsUsed(), is(0l));
-
-        for (int i = 0; i != 4; ++i) {
-            pool.shutdown();
-            assertThat(pool.isShutdown() || pool.isTerminating() || pool.isTerminated(), is(true));
-            pool.awaitTermination(2, TimeUnit.SECONDS);
-            assertThat(pool.isTerminated(), is(true));
-            assertThat(pool.getTotalConnectionsCreated(), is(0l));
-            assertThat(pool.getTotalConnectionsUsed(), is(0l));
-        }
-    }
-
-    @Test
-    public void shouldCreateConnectionAndRecoverWhenClosed() throws RepositorySourceException {
-        assertThat(pool.getTotalConnectionsCreated(), is(0l));
-        assertThat(pool.getTotalConnectionsUsed(), is(0l));
-
-        RepositoryConnection conn = pool.getConnection();
-        assertThat(conn, is(notNullValue()));
-        assertThat(pool.getTotalConnectionsCreated(), is(1l));
-        assertThat(pool.getTotalConnectionsUsed(), is(1l));
-        assertThat(pool.getPoolSize(), is(1));
-
-        conn.close();
-
-        assertThat(pool.getTotalConnectionsCreated(), is(1l));
-        assertThat(pool.getTotalConnectionsUsed(), is(1l));
-        assertThat(pool.getPoolSize(), is(1));
-    }
-
-    @Test
-    public void shouldAllowShutdownToBeCalledMultipleTimesEvenWhenShutdown()
-        throws RepositorySourceException, InterruptedException {
-        assertThat(pool.getTotalConnectionsCreated(), is(0l));
-        assertThat(pool.getTotalConnectionsUsed(), is(0l));
-
-        RepositoryConnection conn = pool.getConnection();
-        assertThat(conn, is(notNullValue()));
-        assertThat(pool.getTotalConnectionsCreated(), is(1l));
-        assertThat(pool.getTotalConnectionsUsed(), is(1l));
-        assertThat(pool.getPoolSize(), is(1));
-
-        conn.close();
-
-        assertThat(pool.getTotalConnectionsCreated(), is(1l));
-        assertThat(pool.getTotalConnectionsUsed(), is(1l));
-        assertThat(pool.getPoolSize(), is(1));
-
-        pool.shutdown();
-        pool.shutdown();
-        pool.awaitTermination(2, TimeUnit.SECONDS);
-        assertThat(pool.isTerminated(), is(true));
-        assertThat(pool.getTotalConnectionsCreated(), is(1l));
-        assertThat(pool.getTotalConnectionsUsed(), is(1l));
-        pool.shutdown();
-        pool.awaitTermination(2, TimeUnit.SECONDS);
-        pool.shutdown();
-        pool.awaitTermination(2, TimeUnit.SECONDS);
-    }
-
-    @Test( expected = IllegalStateException.class )
-    public void shouldNotCreateConnectionIfPoolIsNotRunning() throws RepositorySourceException, InterruptedException {
-        pool.shutdown();
-        pool.awaitTermination(2, TimeUnit.SECONDS);
-        assertThat(pool.isTerminated(), is(true));
-        assertThat(pool.getTotalConnectionsCreated(), is(0l));
-        assertThat(pool.getTotalConnectionsUsed(), is(0l));
-        pool.getConnection(); // this should fail with illegal state
-    }
-
-    @Test
-    public void shouldAllowConnectionsToBeClosedMoreThanOnceWithNoIllEffects() throws RepositorySourceException {
-        assertThat(pool.getTotalConnectionsCreated(), is(0l));
-        assertThat(pool.getTotalConnectionsUsed(), is(0l));
-
-        RepositoryConnection conn = pool.getConnection();
-        assertThat(conn, is(notNullValue()));
-        assertThat(pool.getTotalConnectionsCreated(), is(1l));
-        assertThat(pool.getTotalConnectionsUsed(), is(1l));
-        assertThat(pool.getPoolSize(), is(1));
-
-        conn.close();
-        conn.close();
-    }
-
-    @Test
-    public void shouldBlockClientsWhenNotEnoughConnections() throws Exception {
-        int numConnectionsInPool = 1;
-        int numClients = 2;
-        RepositoryConnectionPool pool = new RepositoryConnectionPool(source);
-        pool.setCorePoolSize(numConnectionsInPool);
-        pool.setMaximumPoolSize(numConnectionsInPool);
-        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
-        runLoadTest(context, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
-        pool.shutdown();
-        pool.awaitTermination(4, TimeUnit.SECONDS);
-    }
-
-    @Test
-    public void shouldLimitClientsToRunSequentiallyWithOneConnectionInPool() throws Exception {
-        int numConnectionsInPool = 1;
-        int numClients = 3;
-        RepositoryConnectionPool pool = new RepositoryConnectionPool(source);
-        pool.setCorePoolSize(numConnectionsInPool);
-        pool.setMaximumPoolSize(numConnectionsInPool);
-        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
-        runLoadTest(context, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
-        pool.shutdown();
-        pool.awaitTermination(4, TimeUnit.SECONDS);
-    }
-
-    @Test
-    public void shouldClientsToRunConncurrentlyWithTwoConnectionsInPool() throws Exception {
-        int numConnectionsInPool = 2;
-        int numClients = 10;
-        RepositoryConnectionPool pool = new RepositoryConnectionPool(source);
-        pool.setCorePoolSize(numConnectionsInPool);
-        pool.setMaximumPoolSize(numConnectionsInPool);
-        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
-        runLoadTest(context, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
-        pool.shutdown();
-        pool.awaitTermination(4, TimeUnit.SECONDS);
-    }
-
-    @Ignore( "doesn't run on hudson" )
-    @Test
-    public void shouldClientsToRunConncurrentlyWithMultipleConnectionInPool() throws Exception {
-        int numConnectionsInPool = 10;
-        int numClients = 50;
-        RepositoryConnectionPool pool = new RepositoryConnectionPool(source);
-        pool.setCorePoolSize(numConnectionsInPool);
-        pool.setMaximumPoolSize(numConnectionsInPool);
-        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(20);
-        List<Future<Integer>> results = runLoadTest(context, pool, numClients, 200, TimeUnit.MILLISECONDS, operationFactory);
-        int total = 0;
-        for (Future<Integer> result : results) {
-            assertThat(result.isDone(), is(true));
-            if (result.isDone()) total += result.get();
-        }
-        assertThat(total, is(20 * numClients));
-        pool.shutdown();
-        pool.awaitTermination(4, TimeUnit.SECONDS);
-    }
-
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperation.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperation.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperation.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,70 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-
-/**
- * An operation that runs against a repository connection.
- * 
- * @author Randall Hauch
- * @param <T> the type of result returned by the client
- */
-public interface RepositoryOperation<T> {
-
-    /**
-     * Get the name of this operation.
-     * 
-     * @return the operation's name
-     */
-    String getName();
-
-    /**
-     * Run the operation using the supplied connection.
-     * 
-     * @param context the environment in which this operation is executing; may not be null
-     * @param connection the connection; may not be null
-     * @return the result of the operation
-     * @throws RepositorySourceException if there is a problem with the connection
-     * @throws InterruptedException if this thread was interrupted
-     */
-    T run( ExecutionContext context,
-           RepositoryConnection connection ) throws RepositorySourceException, InterruptedException;
-
-    /**
-     * A factory interface for creating repository operations.
-     * 
-     * @param <T> the type of result for the operations
-     * @author Randall Hauch
-     */
-    public static interface Factory<T> {
-
-        /**
-         * Create a repository operation that returns the result of type T.
-         * 
-         * @return the operation
-         */
-        RepositoryOperation<T> create();
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperations.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperations.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositoryOperations.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,174 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.Callable;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.LogContext;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionPool;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-
-/**
- * @author Randall Hauch
- */
-public class RepositoryOperations {
-
-    /**
-     * Call the supplied operation, using a connection from this pool.
-     * 
-     * @param <T> the return type for the operation
-     * @param context the context in which the operation is to execute; may not be null
-     * @param pool the pool to use
-     * @param operation the operation to be run using a new connection obtained from the factory
-     * @return the results from the operation
-     * @throws RepositorySourceException if there was an error obtaining the new connection
-     * @throws InterruptedException if the thread was interrupted during the operation
-     * @throws IllegalArgumentException if the operation is null
-     * @see #createCallable(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
-     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, Iterable)
-     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, RepositoryOperation...)
-     */
-    public static <T> T call( ExecutionContext context,
-                              RepositoryConnectionPool pool,
-                              RepositoryOperation<T> operation ) throws RepositorySourceException, InterruptedException {
-        CheckArg.isNotNull(operation, "repository operation");
-        // Get a connection ...
-        T result = null;
-        LogContext.set("context", operation.getName());
-        RepositoryConnection conn = pool.getConnection();
-        try {
-            // And run the client with the connection ...
-            result = operation.run(context, conn);
-        } finally {
-            conn.close();
-        }
-        LogContext.clear();
-        return result;
-    }
-
-    /**
-     * Return a callable object that, when run, performs the supplied repository operation against a connection obtained from the
-     * supplied factory.
-     * 
-     * @param <T> the return type for the operation
-     * @param context the context in which the operation is to execute; may not be null
-     * @param pool the pool to use
-     * @param operation the operation to be run using a new connection obtained from the factory
-     * @return the callable
-     * @see #call(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
-     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, Iterable)
-     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, RepositoryOperation...)
-     */
-    public static <T> Callable<T> createCallable( final ExecutionContext context,
-                                                  final RepositoryConnectionPool pool,
-                                                  final RepositoryOperation<T> operation ) {
-        CheckArg.isNotNull(operation, "repository operation");
-        return new Callable<T>() {
-
-            /**
-             * Execute by getting a connection from this pool, running the client, and return the connection to the pool.
-             * 
-             * @return the operation's result
-             * @throws Exception
-             */
-            public T call() throws Exception {
-                return RepositoryOperations.call(context, pool, operation);
-            }
-        };
-    }
-
-    /**
-     * Return a collection of callable objects that, when run, perform the supplied repository operations against connections in
-     * this pool.
-     * 
-     * @param <T> the return type for the operations
-     * @param context the context in which the operation is to execute; may not be null
-     * @param pool the pool to use
-     * @param operations the operations to be run using connections from the factory
-     * @return the collection of callables
-     * @see #call(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
-     * @see #createCallable(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
-     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, Iterable)
-     */
-    public static <T> List<Callable<T>> createCallables( final ExecutionContext context,
-                                                         final RepositoryConnectionPool pool,
-                                                         final RepositoryOperation<T>... operations ) {
-        List<Callable<T>> callables = new ArrayList<Callable<T>>();
-        for (final RepositoryOperation<T> operation : operations) {
-            callables.add(createCallable(context, pool, operation));
-        }
-        return callables;
-    }
-
-    /**
-     * Return a collection of callable objects that, when run, perform the supplied repository operations against connections in
-     * this pool.
-     * 
-     * @param <T> the return type for the operations
-     * @param context the context in which the operation is to execute; may not be null
-     * @param pool the pool to use
-     * @param operations the operations to be run using connections from the factory
-     * @return the collection of callables
-     * @see #call(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
-     * @see #createCallable(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
-     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, RepositoryOperation...)
-     */
-    public static <T> List<Callable<T>> createCallables( final ExecutionContext context,
-                                                         final RepositoryConnectionPool pool,
-                                                         Iterable<RepositoryOperation<T>> operations ) {
-        List<Callable<T>> callables = new ArrayList<Callable<T>>();
-        for (final RepositoryOperation<T> operation : operations) {
-            callables.add(createCallable(context, pool, operation));
-        }
-        return callables;
-    }
-
-    /**
-     * Return a collection of callable objects that, when run, perform the supplied repository operations against connections in
-     * this pool.
-     * 
-     * @param <T> the return type for the operations
-     * @param context the context in which the operation is to execute; may not be null
-     * @param pool the pool to use
-     * @param operations the operations to be run using connections from the factory
-     * @return the collection of callables
-     * @see #call(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
-     * @see #createCallable(ExecutionContext, RepositoryConnectionPool, RepositoryOperation)
-     * @see #createCallables(ExecutionContext, RepositoryConnectionPool, RepositoryOperation...)
-     */
-    public static <T> List<Callable<T>> createCallables( final ExecutionContext context,
-                                                         final RepositoryConnectionPool pool,
-                                                         Iterator<RepositoryOperation<T>> operations ) {
-        List<Callable<T>> callables = new ArrayList<Callable<T>>();
-        while (operations.hasNext()) {
-            final RepositoryOperation<T> operation = operations.next();
-            callables.add(createCallable(context, pool, operation));
-        }
-        return callables;
-    }
-
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositorySourceLoadHarness.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositorySourceLoadHarness.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositorySourceLoadHarness.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,244 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import org.jboss.dna.common.i18n.MockI18n;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.basic.RootPath;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
-
-/**
- * A test harness for using repository connections under load.
- * 
- * @author Randall Hauch
- */
-public class RepositorySourceLoadHarness {
-
-    public static Future<Integer> execute( RepositoryConnectionPool pool,
-                                           ExecutionContext context,
-                                           long maxTime,
-                                           TimeUnit maxTimeUnit ) throws InterruptedException {
-        int numTimes = 1;
-        int numClients = 1;
-        RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(numTimes);
-        List<Future<Integer>> results = runLoadTest(context, pool, numClients, maxTime, maxTimeUnit, operationFactory);
-        return results.get(0);
-    }
-
-    public static <T> List<Future<T>> runLoadTest( ExecutionContext context,
-                                                   RepositoryConnectionPool pool,
-                                                   int numClients,
-                                                   long maxTime,
-                                                   TimeUnit maxTimeUnit,
-                                                   RepositoryOperation.Factory<T> clientFactory ) throws InterruptedException {
-        // Create the clients ...
-        Collection<RepositoryOperation<T>> clients = new ArrayList<RepositoryOperation<T>>();
-        for (int i = 0; i != numClients; ++i) {
-            clients.add(clientFactory.create());
-        }
-
-        // and run the test ...
-        return runLoadTest(context, pool, maxTime, maxTimeUnit, clients);
-    }
-
-    public static <T> List<Future<T>> runLoadTest( ExecutionContext context,
-                                                   RepositoryConnectionPool pool,
-                                                   long maxTime,
-                                                   TimeUnit maxTimeUnit,
-                                                   RepositoryOperation<T>... clients ) throws InterruptedException {
-        // Create the client collection ...
-        Collection<RepositoryOperation<T>> clientCollection = new ArrayList<RepositoryOperation<T>>();
-        for (RepositoryOperation<T> client : clients) {
-            if (client != null) clientCollection.add(client);
-        }
-        // and run the test ...
-        return runLoadTest(context, pool, maxTime, maxTimeUnit, clientCollection);
-    }
-
-    public static <T> List<Future<T>> runLoadTest( ExecutionContext context,
-                                                   RepositoryConnectionPool pool,
-                                                   long maxTime,
-                                                   TimeUnit maxTimeUnit,
-                                                   Collection<RepositoryOperation<T>> clients ) throws InterruptedException {
-        assert pool != null;
-        assert clients != null;
-        assert clients.size() > 0;
-
-        // Create an Executor Service, using a thread factory that makes the first 'n' thread all wait for each other ...
-        ExecutorService clientPool = null;
-        if (clients.size() == 1) {
-            clientPool = Executors.newSingleThreadExecutor();
-        } else {
-            final ThreadFactory threadFactory = new TestThreadFactory(clients.size());
-            clientPool = Executors.newFixedThreadPool(clients.size(), threadFactory);
-        }
-
-        try {
-            // Wrap each client by a callable and by another that uses a latch ...
-            List<Callable<T>> callables = RepositoryOperations.createCallables(context, pool, clients);
-
-            // Run the tests ...
-            List<Future<T>> futures = clientPool.invokeAll(callables, maxTime, maxTimeUnit);
-            return futures;
-        } finally {
-            // Shut down the pool of clients ...
-            clientPool.shutdown();
-            if (!clientPool.awaitTermination(5, TimeUnit.SECONDS)) {
-                String msg = "Unable to shutdown clients after 5 seconds";
-                Logger.getLogger(RepositorySourceLoadHarness.class).error(MockI18n.passthrough, msg);
-            }
-        }
-
-    }
-
-    /**
-     * A thread factory that makes an initial set of threads wait until all of those threads are created and ready. This is useful
-     * in testing to ensure that the first threads created don't get a jump start.
-     * 
-     * @author Randall Hauch
-     */
-    protected static class TestThreadFactory implements ThreadFactory {
-
-        protected final int totalNumberOfThreads;
-        protected final CountDownLatch latch;
-
-        public TestThreadFactory( int numberOfThreadsToWait ) {
-            this.latch = new CountDownLatch(numberOfThreadsToWait);
-            this.totalNumberOfThreads = numberOfThreadsToWait;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Thread newThread( Runnable runnable ) {
-            return new Thread(runnable) {
-
-                /**
-                 * {@inheritDoc}
-                 */
-                @Override
-                public void run() {
-                    if (totalNumberOfThreads > 1) {
-                        // There are other threads, and we want to synchronize with them ...
-                        try {
-                            // Count down the number of threads that are to reach this point (if 0, this doesn't do anything)
-                            latch.countDown();
-                            // Wait for all threads to reach this point ...
-                            latch.await();
-                        } catch (InterruptedException e) {
-                            throw new RuntimeException(e);
-                        }
-                    }
-                    super.run();
-                }
-            };
-        }
-    }
-
-    /**
-     * Return an operation factory that produces {@link RepositoryOperation} instances that each call
-     * {@link RepositoryConnection#execute(ExecutionContext, org.jboss.dna.graph.requests.Request)} the supplied number of times,
-     * intermixed with random math operations and {@link Thread#yield() yielding}.
-     * 
-     * @param callsPerOperation the number of <code>load</code> calls per RepositoryOperation
-     * @return the factory
-     */
-    public static RepositoryOperation.Factory<Integer> createMultipleLoadOperationFactory( final int callsPerOperation ) {
-        return new RepositoryOperation.Factory<Integer>() {
-
-            public RepositoryOperation<Integer> create() {
-                return new CallLoadMultipleTimes(callsPerOperation);
-            }
-        };
-    }
-
-    public static class CallLoadMultipleTimes implements RepositoryOperation<Integer> {
-
-        private final int count;
-
-        public CallLoadMultipleTimes( int count ) {
-            Logger.getLogger(RepositorySourceLoadHarness.class).debug("Creating repository operation to call {0} times", count);
-            this.count = count;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public String getName() {
-            return Thread.currentThread().getName() + "-CallLoadMultipleTimes";
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryOperation#run(org.jboss.dna.graph.ExecutionContext,
-         *      org.jboss.dna.graph.connectors.RepositoryConnection)
-         */
-        public Integer run( ExecutionContext context,
-                            RepositoryConnection connection ) throws RepositorySourceException {
-            Logger.getLogger(RepositorySourceLoadHarness.class).debug("Running {0} operation", this.getClass().getSimpleName());
-            int total = count;
-            for (int i = 0; i != count; ++i) {
-                // Add two random numbers ...
-                int int1 = random(this.hashCode() ^ (int)System.nanoTime() * i);
-                if (i % 2 == 0) {
-                    Thread.yield();
-                }
-                connection.execute(context, new ReadNodeRequest(new Location(RootPath.INSTANCE)));
-                int int2 = random(this.hashCode() ^ (int)System.nanoTime() + i);
-                total += Math.min(Math.abs(Math.max(int1, int2) + int1 * int2 / 3), count);
-            }
-            Logger.getLogger(RepositorySourceLoadHarness.class).debug("Finishing {0} operation", this.getClass().getSimpleName());
-            return total < count ? total : count; // should really always return count
-        }
-    }
-
-    /**
-     * A "random-enough" number generator that is cheap and that has no synchronization issues (like some other random number
-     * generators).
-     * <p>
-     * This was taken from <a href="http://wwww.jcip.org">Java Concurrency In Practice</a> (page 253).
-     * </p>
-     * 
-     * @param seed the seed, typically based on a hash code and nanoTime
-     * @return a number that is "random enough"
-     */
-    public static int random( int seed ) {
-        seed ^= (seed << 6);
-        seed ^= (seed >>> 21);
-        seed ^= (seed << 7);
-        return seed;
-    }
-
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepository.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepository.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepository.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,240 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.basic.RootPath;
-
-/**
- * A very simple repository that maintains properties for nodes identified by a path, and computes the children based upon the set
- * of paths registered in the {@link #getData() data}.
- * <p>
- * Note that the repository does not automatically rename same-name siblings when nodes are
- * {@link #delete(ExecutionContext, String) deleted} or {@link #create(ExecutionContext, String) explicitly} or
- * {@link #setProperty(ExecutionContext, String, String, Object...) implicitly} created.
- * </p>
- * 
- * @author Randall Hauch
- */
- at ThreadSafe
-public class SimpleRepository {
-
-    public static final Name DEFAULT_UUID_PROPERTY_NAME = DnaLexicon.UUID;
-
-    private static final ConcurrentMap<String, SimpleRepository> repositoriesByName = new ConcurrentHashMap<String, SimpleRepository>();
-
-    public static SimpleRepository get( String name ) {
-        SimpleRepository newRepository = new SimpleRepository(name);
-        SimpleRepository repository = repositoriesByName.putIfAbsent(name, newRepository);
-        return repository != null ? repository : newRepository;
-    }
-
-    public static void shutdownAll() {
-        for (SimpleRepository repository : repositoriesByName.values()) {
-            repository.shutdown();
-        }
-    }
-
-    private ConcurrentMap<Path, Map<Name, Property>> data = new ConcurrentHashMap<Path, Map<Name, Property>>();
-    private final String repositoryName;
-    private boolean shutdown = false;
-
-    public SimpleRepository( String repositoryName ) {
-        this.repositoryName = repositoryName;
-        // if (repositoriesByName.putIfAbsent(repositoryName, this) != null) {
-        // throw new IllegalArgumentException("Repository \"" + repositoryName + "\" already exists and may not be recreated");
-        // }
-        // Create a root node ...
-        data.putIfAbsent(RootPath.INSTANCE, new HashMap<Name, Property>());
-    }
-
-    /**
-     * @return repositoryName
-     */
-    public String getRepositoryName() {
-        return repositoryName;
-    }
-
-    /**
-     * Get the current modifiable map of property data
-     * 
-     * @return data
-     */
-    public ConcurrentMap<Path, Map<Name, Property>> getData() {
-        return data;
-    }
-
-    /**
-     * Utility method to help set the property on the node given by the supplied path. If the node does not exist, it will be
-     * created.
-     * 
-     * @param context the execution context; may not be null
-     * @param path the path to the node; may not be null
-     * @param propertyName the property name; may not be null
-     * @param values the values of the property
-     * @return this repository, for method chaining
-     */
-    public SimpleRepository setProperty( ExecutionContext context,
-                                         String path,
-                                         String propertyName,
-                                         Object... values ) {
-        NameFactory nameFactory = context.getValueFactories().getNameFactory();
-        return setProperty(context, path, nameFactory.create(propertyName), values);
-    }
-
-    /**
-     * Utility method to help set the property on the node given by the supplied path. If the node does not exist, it will be
-     * created.
-     * 
-     * @param context the execution context; may not be null
-     * @param path the path to the node; may not be null
-     * @param propertyName the property name; may not be null
-     * @param values the values of the property
-     * @return this repository, for method chaining
-     */
-    public SimpleRepository setProperty( ExecutionContext context,
-                                         String path,
-                                         Name propertyName,
-                                         Object... values ) {
-        Logger logger = context.getLogger(getClass());
-        if (logger.isTraceEnabled()) {
-            logger.trace("Setting property {0} on {1} to {2}", propertyName, path, Arrays.asList(values));
-        }
-        PathFactory pathFactory = context.getValueFactories().getPathFactory();
-        PropertyFactory propertyFactory = context.getPropertyFactory();
-        Path pathObj = pathFactory.create(path);
-        if (!pathObj.isRoot()) {
-            create(context, pathObj.getParent().getString(context.getNamespaceRegistry()));
-        }
-        Property property = propertyFactory.create(propertyName, values);
-        Map<Name, Property> newProperties = new HashMap<Name, Property>();
-        Map<Name, Property> existingProperties = data.putIfAbsent(pathObj, newProperties);
-        if (existingProperties == null) {
-            existingProperties = newProperties;
-            UUID uuid = context.getValueFactories().getUuidFactory().create();
-            Property uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID, uuid);
-            newProperties.put(DnaLexicon.UUID, uuidProperty);
-        }
-        existingProperties.put(property.getName(), property);
-        return this;
-    }
-
-    /**
-     * Create the node if it does not exist.
-     * 
-     * @param context the execution context; may not be null
-     * @param path the path to the node; may not be null
-     * @return this repository, for method chaining
-     */
-    public SimpleRepository create( ExecutionContext context,
-                                    String path ) {
-        context.getLogger(getClass()).trace("Creating node {0}", path);
-        PathFactory pathFactory = context.getValueFactories().getPathFactory();
-        Path pathObj = pathFactory.create(path);
-        Path ancestorPath = pathObj;
-        while (!ancestorPath.isRoot()) {
-            // Add a UUID property ...
-            if (!data.containsKey(ancestorPath)) {
-                Map<Name, Property> props = new HashMap<Name, Property>();
-                UUID uuid = context.getValueFactories().getUuidFactory().create();
-                Property uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID, uuid);
-                props.put(DnaLexicon.UUID, uuidProperty);
-                data.putIfAbsent(ancestorPath, props);
-            }
-            ancestorPath = ancestorPath.getParent();
-        }
-        UUID uuid = context.getValueFactories().getUuidFactory().create();
-        Property uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID, uuid);
-        data.get(pathObj).put(DnaLexicon.UUID, uuidProperty);
-        return this;
-    }
-
-    /**
-     * Delete the branch rooted at the supplied path, if it exists.
-     * 
-     * @param context the execution context; may not be null
-     * @param path the path to the branch's top node; may not be null
-     * @return this repository, for method chaining
-     */
-    public SimpleRepository delete( ExecutionContext context,
-                                    String path ) {
-        context.getLogger(getClass()).trace("Deleting node {0}", path);
-        PathFactory pathFactory = context.getValueFactories().getPathFactory();
-        Path pathObj = pathFactory.create(path);
-        List<Path> pathsToRemove = new LinkedList<Path>();
-        for (Path nodePath : data.keySet()) {
-            if (nodePath.equals(pathObj) || nodePath.isDecendantOf(pathObj)) {
-                pathsToRemove.add(nodePath);
-            }
-        }
-        for (Path pathToRemove : pathsToRemove) {
-            data.remove(pathToRemove);
-        }
-        return this;
-    }
-
-    public List<Path> getChildren( ExecutionContext context,
-                                   Path path ) {
-        List<Path> children = new LinkedList<Path>();
-        for (Path nodePath : data.keySet()) {
-            if (nodePath.isRoot()) continue;
-            if (nodePath.getParent().equals(path)) {
-                children.add(nodePath);
-            }
-        }
-        return children;
-    }
-
-    /**
-     * @param data new new map of property data
-     */
-    public void setData( ConcurrentMap<Path, Map<Name, Property>> data ) {
-        this.data = data;
-    }
-
-    public boolean isShutdown() {
-        return shutdown;
-    }
-
-    public void shutdown() {
-        shutdown = true;
-        repositoriesByName.remove(this.repositoryName);
-    }
-
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepositorySource.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepositorySource.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,451 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.naming.Reference;
-import javax.transaction.xa.XAResource;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
-
-/**
- * A {@link RepositorySource} for a {@link SimpleRepository simple repository}.
- * 
- * @author Randall Hauch
- */
- at ThreadSafe
-public class SimpleRepositorySource implements RepositorySource {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * The default limit is {@value} for retrying {@link RepositoryConnection connection} calls to the underlying source.
-     */
-    public static final int DEFAULT_RETRY_LIMIT = 0;
-
-    protected static final RepositorySourceCapabilities CAPABILITIES = new RepositorySourceCapabilities(true, true);
-
-    private String repositoryName;
-    private String name;
-    private final AtomicInteger retryLimit = new AtomicInteger(DEFAULT_RETRY_LIMIT);
-    private CachePolicy defaultCachePolicy;
-    private transient RepositoryContext repositoryContext;
-
-    public SimpleRepositorySource() {
-        super();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#initialize(org.jboss.dna.graph.connectors.RepositoryContext)
-     */
-    public void initialize( RepositoryContext context ) throws RepositorySourceException {
-        this.repositoryContext = context;
-    }
-
-    /**
-     * @return repositoryContext
-     */
-    public RepositoryContext getRepositoryContext() {
-        return repositoryContext;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getName()
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * @param name Sets name to the specified value.
-     */
-    public void setName( String name ) {
-        this.name = name;
-    }
-
-    /**
-     * @return repositoryName
-     */
-    public String getRepositoryName() {
-        return repositoryName;
-    }
-
-    /**
-     * @param repositoryName Sets repositoryName to the specified value.
-     */
-    public void setRepositoryName( String repositoryName ) {
-        this.repositoryName = repositoryName;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getRetryLimit()
-     */
-    public int getRetryLimit() {
-        return retryLimit.get();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#setRetryLimit(int)
-     */
-    public void setRetryLimit( int limit ) {
-        retryLimit.set(limit < 0 ? 0 : limit);
-    }
-
-    /**
-     * @return defaultCachePolicy
-     */
-    public CachePolicy getDefaultCachePolicy() {
-        return defaultCachePolicy;
-    }
-
-    /**
-     * @param defaultCachePolicy Sets defaultCachePolicy to the specified value.
-     */
-    public void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) {
-        this.defaultCachePolicy = defaultCachePolicy;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see javax.naming.Referenceable#getReference()
-     */
-    public Reference getReference() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return name.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof SimpleRepositorySource) {
-            SimpleRepositorySource that = (SimpleRepositorySource)obj;
-            if (!this.getName().equals(that.getName())) return false;
-            if (!this.getRepositoryName().equals(that.getRepositoryName())) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getCapabilities()
-     */
-    public RepositorySourceCapabilities getCapabilities() {
-        return CAPABILITIES;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getConnection()
-     */
-    public RepositoryConnection getConnection() throws RepositorySourceException {
-        String reposName = this.getRepositoryName();
-        if (reposName == null) throw new RepositorySourceException("Invalid repository source: missing repository name");
-        SimpleRepository repository = SimpleRepository.get(reposName);
-        if (repository == null) {
-            throw new RepositorySourceException(this.getName(), "Unable to find repository \"" + reposName + "\"");
-        }
-        return new Connection(repository, this.getDefaultCachePolicy());
-    }
-
-    protected class Connection implements RepositoryConnection {
-
-        private RepositorySourceListener listener;
-        private final SimpleRepository repository;
-        private final CachePolicy defaultCachePolicy;
-
-        protected Connection( SimpleRepository repository,
-                              CachePolicy defaultCachePolicy ) {
-            assert repository != null;
-            this.repository = repository;
-            this.defaultCachePolicy = defaultCachePolicy;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryConnection#close()
-         */
-        public void close() {
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-         *      org.jboss.dna.graph.requests.Request)
-         */
-        public void execute( ExecutionContext context,
-                             Request request ) throws RepositorySourceException {
-            final PathFactory pathFactory = context.getValueFactories().getPathFactory();
-            final SimpleRepository repository = this.repository;
-            RequestProcessor processor = new RequestProcessor(getSourceName(), context) {
-                @Override
-                public void process( ReadAllChildrenRequest request ) {
-                    Map<Name, Property> properties = getProperties(request, request.of());
-                    Path targetPath = request.of().getPath();
-                    if (properties == null) return;
-                    Property uuidProperty = properties.get(DnaLexicon.UUID);
-                    // Iterate through all of the properties, looking for any paths that are children of the path ...
-                    Map<Path, Map<Name, Property>> data = repository.getData();
-                    List<Path.Segment> childSegments = new LinkedList<Path.Segment>();
-                    for (Path path : data.keySet()) {
-                        if (!path.isRoot() && path.getParent().equals(targetPath)) {
-                            childSegments.add(path.getLastSegment());
-                        }
-                    }
-                    // This does not store children order, so sort ...
-                    Collections.sort(childSegments);
-                    // Now get the children ...
-                    for (Path.Segment childSegment : childSegments) {
-                        Path childPath = pathFactory.create(targetPath, childSegment);
-                        Map<Name, Property> childProperties = repository.getData().get(childPath);
-                        Property childUuidProperty = childProperties.get(DnaLexicon.UUID);
-                        request.addChild(childPath, childUuidProperty);
-                    }
-                    request.setActualLocationOfNode(request.of().with(uuidProperty));
-                }
-
-                @Override
-                public void process( ReadAllPropertiesRequest request ) {
-                    Map<Name, Property> properties = getProperties(request, request.at());
-                    if (properties == null) return;
-                    Property uuidProperty = properties.get(DnaLexicon.UUID);
-                    for (Property property : properties.values()) {
-                        if (property != uuidProperty) request.addProperty(property);
-                    }
-                    request.setActualLocationOfNode(request.at().with(uuidProperty));
-                }
-
-                @Override
-                public void process( CopyBranchRequest request ) {
-                    throw new UnsupportedOperationException();
-                }
-
-                @Override
-                public void process( CreateNodeRequest request ) {
-                    Path parentPath = request.under().getPath();
-                    ExecutionContext context = getExecutionContext();
-                    Path targetPath = context.getValueFactories().getPathFactory().create(parentPath, request.named());
-                    final Name childName = request.named();
-                    Map<Name, Property> properties = null;
-                    // Create the path for the new node, but we need to look for existing SNS ...
-                    switch (request.conflictBehavior()) {
-                        case DO_NOT_REPLACE:
-                        case APPEND:
-                            // Need to look for existing SNS ...
-                            int lastSns = 0;
-                            for (Path child : repository.getChildren(context, parentPath)) {
-                                Path.Segment segment = child.getLastSegment();
-                                if (segment.getName().equals(childName)) {
-                                    if (segment.hasIndex()) lastSns = segment.getIndex();
-                                    else ++lastSns;
-                                }
-                                targetPath = context.getValueFactories().getPathFactory().create(parentPath,
-                                                                                                 request.named(),
-                                                                                                 ++lastSns);
-                            }
-                            repository.create(context, targetPath.getString(context.getNamespaceRegistry()));
-                            break;
-                        case REPLACE:
-                            // Remove any existing node with the desired target path ...
-                            repository.delete(context, targetPath.getString(context.getNamespaceRegistry()));
-                            repository.create(context, targetPath.getString(context.getNamespaceRegistry()));
-                            break;
-                        case UPDATE:
-                            // Get the existing properties (if there are any) and merge new properties,
-                            // using the desired target path ...
-                            properties = repository.getData().get(targetPath);
-                            if (properties == null) {
-                                repository.create(context, targetPath.getString(context.getNamespaceRegistry()));
-                            }
-                            break;
-                    }
-                    if (properties == null) properties = repository.getData().get(targetPath);
-                    assert properties != null;
-                    // Set the UUID if the request has one ...
-                    Property uuidProperty = request.under().getIdProperty(DnaLexicon.UUID);
-                    if (uuidProperty != null) {
-                        properties.put(uuidProperty.getName(), uuidProperty);
-                    } else {
-                        uuidProperty = properties.get(DnaLexicon.UUID);
-                    }
-                    Location actual = new Location(targetPath, uuidProperty);
-                    request.setActualLocationOfNode(actual);
-                    for (Property property : request.properties()) {
-                        if (property != null) properties.put(property.getName(), property);
-                    }
-                }
-
-                @Override
-                public void process( DeleteBranchRequest request ) {
-                    // Iterate through all of the dataq, looking for any paths that are children of the path ...
-                    Path targetPath = request.at().getPath();
-                    Map<Path, Map<Name, Property>> data = repository.getData();
-                    Map<Name, Property> properties = repository.getData().get(targetPath);
-                    Property uuidProperty = properties.get(DnaLexicon.UUID);
-                    for (Path path : data.keySet()) {
-                        if (!path.isRoot() && path.isAtOrBelow(targetPath)) {
-                            data.remove(path);
-                        }
-                    }
-                    request.setActualLocationOfNode(request.at().with(uuidProperty));
-                }
-
-                @Override
-                public void process( MoveBranchRequest request ) {
-                    throw new UnsupportedOperationException();
-                }
-
-                @Override
-                public void process( UpdatePropertiesRequest request ) {
-                    Map<Name, Property> properties = getProperties(request, request.on());
-                    if (properties == null) return;
-                    Property uuidProperty = properties.get(DnaLexicon.UUID);
-                    for (Property property : request.properties()) {
-                        if (property != uuidProperty) properties.put(property.getName(), property);
-                    }
-                    request.setActualLocationOfNode(request.on().with(uuidProperty));
-                }
-
-                protected Map<Name, Property> getProperties( Request request,
-                                                             Location location ) {
-                    Path targetPath = location.getPath();
-                    if (targetPath == null) throw new UnsupportedOperationException();
-                    Map<Name, Property> properties = repository.getData().get(targetPath);
-                    if (properties == null) {
-                        Path ancestor = targetPath.getParent();
-                        while (ancestor != null) {
-                            if (repository.getData().get(targetPath) != null) break;
-                            ancestor = ancestor.getParent();
-                        }
-                        if (ancestor == null) ancestor = getExecutionContext().getValueFactories().getPathFactory().createRootPath();
-                        request.setError(new PathNotFoundException(location, ancestor));
-                        return null;
-                    }
-                    return properties;
-                }
-            };
-            processor.process(request);
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryConnection#getDefaultCachePolicy()
-         */
-        public CachePolicy getDefaultCachePolicy() {
-            return defaultCachePolicy;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryConnection#getSourceName()
-         */
-        public String getSourceName() {
-            return SimpleRepositorySource.this.getName();
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryConnection#getXAResource()
-         */
-        public XAResource getXAResource() {
-            return null;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryConnection#ping(long, java.util.concurrent.TimeUnit)
-         */
-        public boolean ping( long time,
-                             TimeUnit unit ) {
-            return true;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryConnection#setListener(org.jboss.dna.graph.connectors.RepositorySourceListener)
-         */
-        public void setListener( RepositorySourceListener listener ) {
-            this.listener = listener;
-        }
-
-        /**
-         * @return listener
-         */
-        public RepositorySourceListener getListener() {
-            return listener;
-        }
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/TimeDelayingRepositorySource.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/TimeDelayingRepositorySource.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/TimeDelayingRepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,376 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.connectors;
-
-import static org.mockito.Mockito.mock;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import javax.naming.Reference;
-import javax.transaction.xa.XAResource;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.requests.Request;
-
-/**
- * A simple {@link RepositorySource} that simulates an imaginary source with a built-in delay mechanism.
- * 
- * @author Randall Hauch
- */
- at ThreadSafe
-public class TimeDelayingRepositorySource implements RepositorySource {
-
-    /**
-     */
-    private static final long serialVersionUID = -2756725117087437347L;
-    /**
-     * The default limit is {@value} for retrying {@link RepositoryConnection connection} calls to the underlying source.
-     */
-    public static final int DEFAULT_RETRY_LIMIT = 0;
-
-    protected static final RepositorySourceCapabilities CAPABILITIES = new RepositorySourceCapabilities(true, true);
-
-    private String name;
-    private final AtomicInteger connectionsOpenedCount = new AtomicInteger(0);
-    private final AtomicInteger connectionsClosedCount = new AtomicInteger(0);
-    private final Set<Connection> openConnections = new CopyOnWriteArraySet<Connection>();
-    private final AtomicLong loadCount = new AtomicLong(0);
-    private final AtomicLong loadDelay = new AtomicLong(0);
-    private final AtomicLong pingCount = new AtomicLong(0);
-    private final AtomicLong pingDelay = new AtomicLong(0);
-    private final AtomicInteger retryLimit = new AtomicInteger(DEFAULT_RETRY_LIMIT);
-    private CachePolicy defaultCachePolicy;
-    private transient RepositoryContext repositoryContext;
-
-    public TimeDelayingRepositorySource( String identifier ) {
-        super();
-        this.name = identifier;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#initialize(org.jboss.dna.graph.connectors.RepositoryContext)
-     */
-    public void initialize( RepositoryContext context ) throws RepositorySourceException {
-        this.repositoryContext = context;
-    }
-
-    /**
-     * @return repositoryContext
-     */
-    public RepositoryContext getRepositoryContext() {
-        return repositoryContext;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getName() {
-        return this.name;
-    }
-
-    /**
-     * @param name the identifier
-     */
-    public void setName( String name ) {
-        this.name = name;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getRetryLimit()
-     */
-    public int getRetryLimit() {
-        return retryLimit.get();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#setRetryLimit(int)
-     */
-    public void setRetryLimit( int limit ) {
-        retryLimit.set(limit < 0 ? 0 : limit);
-    }
-
-    public CachePolicy getDefaultCachePolicy() {
-        return defaultCachePolicy;
-    }
-
-    public void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) {
-        this.defaultCachePolicy = defaultCachePolicy;
-    }
-
-    /**
-     * @return loadCount
-     */
-    public long getTotalExecuteCount() {
-        return this.loadCount.get();
-    }
-
-    /**
-     * @return pingCount
-     */
-    public long getTotalPingCount() {
-        return this.pingCount.get();
-    }
-
-    /**
-     * @return loadDelay
-     */
-    public long getConnectionExecuteDelayInMillis() {
-        return this.loadDelay.get();
-    }
-
-    public void setConnectionExecuteDelay( long time,
-                                           TimeUnit unit ) {
-        this.loadDelay.set(unit.toMillis(time));
-    }
-
-    /**
-     * @return pingDelay
-     */
-    public long getConnectionPingDelayInMillis() {
-        return this.pingDelay.get();
-    }
-
-    public void setConnectionPingDelay( long time,
-                                        TimeUnit unit ) {
-        this.pingDelay.set(unit.toMillis(time));
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getConnection()
-     */
-    public RepositoryConnection getConnection() throws RepositorySourceException {
-        int connectionNumber = this.connectionsOpenedCount.incrementAndGet();
-        String connectionName = "Connection " + connectionNumber;
-        XAResource xaResource = newXaResource(connectionName);
-        Connection c = newConnection(connectionName, xaResource);
-        this.openConnections.add(c);
-        return c;
-    }
-
-    /**
-     * Factory method that can be overridden by subclasses. This method implementation simply creates a mock {@link XAResource}.
-     * 
-     * @param connectionName the name of the connection
-     * @return the XAResource, or null if this source does not support XA
-     */
-    protected XAResource newXaResource( String connectionName ) {
-        return mock(XAResource.class);
-    }
-
-    /**
-     * Factory method that can be overridden by subclasses. This method implementation creates a new {@link Connection} that uses
-     * standard bean properties for the various delays and counts.
-     * 
-     * @param connectionName
-     * @param xaResource
-     * @return a new Connection
-     * @throws RepositorySourceException
-     */
-    protected Connection newConnection( String connectionName,
-                                        XAResource xaResource ) throws RepositorySourceException {
-        Connection c = new Connection(connectionName, this.loadDelay.get(), this.pingDelay.get());
-        c.setXaResource(xaResource);
-        return c;
-    }
-
-    protected void close( Connection conn ) {
-        if (conn != null && this.openConnections.remove(conn)) {
-            this.connectionsClosedCount.incrementAndGet();
-            this.loadCount.addAndGet(conn.getLoadCount());
-            this.pingCount.addAndGet(conn.getPingCount());
-        }
-    }
-
-    public int getOpenConnectionCount() {
-        return this.openConnections.size();
-    }
-
-    public int getTotalConnectionsCreated() {
-        return this.connectionsOpenedCount.get();
-    }
-
-    public int getTotalConnectionsClosed() {
-        return this.connectionsClosedCount.get();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Reference getReference() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getCapabilities()
-     */
-    public RepositorySourceCapabilities getCapabilities() {
-        return CAPABILITIES;
-    }
-
-    public class Connection implements RepositoryConnection {
-
-        private final String connectionName;
-        private final AtomicBoolean closed = new AtomicBoolean(false);
-        private final AtomicBoolean loadResponse = new AtomicBoolean(true);
-        private final AtomicBoolean pingResponse = new AtomicBoolean(true);
-        private final AtomicLong closeCount = new AtomicLong(0);
-        private final AtomicLong loadCount = new AtomicLong(0);
-        private final AtomicLong loadDelay;
-        private final AtomicLong pingCount = new AtomicLong(0);
-        private final AtomicLong pingDelay;
-        private final AtomicReference<XAResource> xaResource = new AtomicReference<XAResource>();
-
-        protected Connection( String connectionName,
-                              long loadDelay,
-                              long pingDelay ) {
-            assert connectionName != null && connectionName.trim().length() != 0;
-            this.loadDelay = new AtomicLong(loadDelay);
-            this.pingDelay = new AtomicLong(pingDelay);
-            this.connectionName = connectionName;
-        }
-
-        public String getConnectionName() {
-            return this.connectionName;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void close() {
-            this.closeCount.incrementAndGet();
-            this.closed.set(true);
-            TimeDelayingRepositorySource.this.close(this);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public String getSourceName() {
-            return TimeDelayingRepositorySource.this.getName();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public CachePolicy getDefaultCachePolicy() {
-            return TimeDelayingRepositorySource.this.getDefaultCachePolicy();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public XAResource getXAResource() {
-            return this.xaResource.get();
-        }
-
-        public void setXaResource( XAResource xaResource ) {
-            this.xaResource.set(xaResource);
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-         *      org.jboss.dna.graph.requests.Request)
-         */
-        public void execute( ExecutionContext context,
-                             Request request ) throws RepositorySourceException {
-            long delay = this.loadDelay.get();
-            if (delay > 0l) {
-                try {
-                    Thread.sleep(delay);
-                } catch (InterruptedException e) {
-                    Thread.interrupted();
-                    throw new RepositorySourceException(this.getSourceName(), e);
-                }
-            }
-            this.loadCount.incrementAndGet();
-        }
-
-        public void setLoadResponse( boolean response ) {
-            this.loadResponse.set(response);
-        }
-
-        public void setLoadDelay( long time,
-                                  TimeUnit unit ) {
-            this.loadDelay.set(unit.toMillis(time));
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean ping( long time,
-                             TimeUnit unit ) {
-            try {
-                Thread.sleep(this.pingDelay.get());
-            } catch (InterruptedException e) {
-                Thread.interrupted();
-                return false;
-            }
-            return this.pingResponse.get();
-        }
-
-        public void setPingResponse( boolean pingResponse ) {
-            this.pingResponse.set(pingResponse);
-        }
-
-        public void setPingDelay( long time,
-                                  TimeUnit unit ) {
-            this.pingDelay.set(unit.toMillis(time));
-        }
-
-        public long getPingCount() {
-            return this.pingCount.get();
-        }
-
-        public long getLoadCount() {
-            return this.loadCount.get();
-        }
-
-        public long getCloseCount() {
-            return this.closeCount.get();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void setListener( RepositorySourceListener listener ) {
-        }
-
-    }
-
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/AbstractValueComparatorsTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/AbstractValueComparatorsTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/AbstractValueComparatorsTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,137 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
-import org.jboss.dna.graph.properties.basic.StandardValueFactories;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @param <T>
- */
-public abstract class AbstractValueComparatorsTest<T> {
-
-    public static final BasicNamespaceRegistry NAMESPACE_REGISTRY = new BasicNamespaceRegistry();
-    public static final ValueFactories VALUE_FACTORIES = new StandardValueFactories(NAMESPACE_REGISTRY);
-
-    protected final Comparator<T> comparator;
-    protected final T[] validNonNullValues;
-
-    protected AbstractValueComparatorsTest( Comparator<T> comparator, T... validNonNullValues ) {
-        CheckArg.isNotNull(comparator, "comparator");
-        CheckArg.isNotEmpty(validNonNullValues, "validNonNullValues");
-        this.comparator = comparator;
-        this.validNonNullValues = validNonNullValues;
-    }
-
-    protected Comparator<T> getComparator() {
-        return this.comparator;
-    }
-
-    @Test
-    public void shouldConsiderNullLessThanValidNonNull() {
-        assertThat(comparator.compare(validNonNullValues[0], null) > 0, is(true));
-        assertThat(comparator.compare(null, validNonNullValues[0]) < 0, is(true));
-    }
-
-    @Test
-    public void shouldConsiderTwoNullsToBeEquivalent() {
-        assertThat(comparator.compare(null, null), is(0));
-    }
-
-    @Test
-    public void shouldConsiderSameInstanceToBeEquivalent() {
-        for (T validNonNullValue : validNonNullValues) {
-            assertThat(comparator.compare(validNonNullValue, validNonNullValue), is(0));
-        }
-    }
-
-    protected List<T> getValues( boolean includeNull ) {
-        List<T> values = new ArrayList<T>(validNonNullValues.length);
-        for (T validNonNullValue : validNonNullValues) {
-            assertThat(validNonNullValue, is(notNullValue()));
-            values.add(validNonNullValue);
-        }
-        if (includeNull) values.add(null);
-        return values;
-    }
-
-    protected List<T> getSortedValues( boolean includeNull ) {
-        List<T> values = getValues(includeNull);
-        Collections.sort(values, comparator);
-        return values;
-    }
-
-    // protected void assertSortsSimilarTo( Comparator<T> otherComparator ) {
-    // assertThat(otherComparator, is(notNullValue()));
-    // List<T> values = getValues(true);
-    // List<T> otherValues = getValues(true);
-    // Collections.sort(values, comparator);
-    // Collections.sort(otherValues, comparator);
-    // assertThat(values, is(otherValues));
-    //
-    // values = getValues(false);
-    // otherValues = getValues(false);
-    // Collections.sort(values, comparator);
-    // Collections.sort(otherValues, comparator);
-    // assertThat(values, is(otherValues));
-    // }
-
-    @SuppressWarnings( "unchecked" )
-    @Test
-    public void shouldBeCompatibleWithCompareTo() {
-        List<T> values = getValues(false);
-        Collections.sort(values, comparator);
-        for (int i = 0; i != (values.size() - 1); ++i) {
-            T value1 = values.get(i);
-            T value2 = values.get(i + 1);
-            assertThat(value1, is(instanceOf(Comparable.class)));
-            Comparable<T> comparable1 = (Comparable<T>)value1;
-            int result = comparable1.compareTo(value2);
-            assertThat(result < 0 || result == 0, is(true));
-            assertThat(comparable1.compareTo(value1), is(0));
-        }
-    }
-
-    protected void assertValuesCompareUsing( T value1, T value2 ) {
-        int value1ToValue2 = comparator.compare(value1, value2);
-        int value2ToValue1 = comparator.compare(value2, value1);
-        if (value1ToValue2 == 0) {
-            assertThat(value2ToValue1, is(0));
-        } else if (value1ToValue2 < 0) {
-            assertThat(value2ToValue1 > 0, is(true));
-        } else { // if ( value1ToValue2 > 0 )
-            assertThat(value2ToValue1 < 0, is(true));
-        }
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BinaryValueComparatorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BinaryValueComparatorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BinaryValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,48 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.ValueComparators;
-import org.jboss.dna.graph.properties.ValueFactory;
-
-/**
- * @author Randall Hauch
- */
-public class BinaryValueComparatorTest extends AbstractValueComparatorsTest<Binary> {
-
-    private static final ValueFactory<Binary> FACTORY;
-    private static final Binary BINARY1;
-    private static final Binary BINARY2;
-    private static final Binary BINARY3;
-
-    static {
-        FACTORY = VALUE_FACTORIES.getBinaryFactory();
-        BINARY1 = FACTORY.create("This is the binary 1 value");
-        BINARY2 = FACTORY.create("This is the binary 2 value");
-        BINARY3 = FACTORY.create("This is the binary 3 value");
-    }
-
-    public BinaryValueComparatorTest() {
-        super(ValueComparators.BINARY_COMPARATOR, BINARY1, BINARY2, BINARY3);
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BooleanValueComparatorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BooleanValueComparatorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BooleanValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,34 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import org.jboss.dna.graph.properties.ValueComparators;
-
-/**
- * @author Randall Hauch
- */
-public class BooleanValueComparatorTest extends AbstractValueComparatorsTest<Boolean> {
-
-    public BooleanValueComparatorTest() {
-        super(ValueComparators.BOOLEAN_COMPARATOR, Boolean.TRUE, Boolean.FALSE);
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DateValueComparatorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DateValueComparatorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DateValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,47 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.util.Calendar;
-import org.jboss.dna.graph.properties.ValueComparators;
-
-/**
- * @author Randall Hauch
- */
-public class DateValueComparatorTest extends AbstractValueComparatorsTest<Calendar> {
-
-    private static final Calendar TODAY = Calendar.getInstance();
-    private static final Calendar YESTERDAY;
-    private static final Calendar TOMORROW;
-
-    static {
-        YESTERDAY = (Calendar)TODAY.clone();
-        YESTERDAY.roll(Calendar.DAY_OF_YEAR, false);
-
-        TOMORROW = (Calendar)TODAY.clone();
-        TOMORROW.roll(Calendar.DAY_OF_YEAR, true);
-    }
-
-    public DateValueComparatorTest() {
-        super(ValueComparators.CALENDAR_COMPARATOR, TODAY, TOMORROW, YESTERDAY);
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DecimalValueComparatorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DecimalValueComparatorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DecimalValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,35 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import java.math.BigDecimal;
-import org.jboss.dna.graph.properties.ValueComparators;
-
-/**
- * @author Randall Hauch
- */
-public class DecimalValueComparatorTest extends AbstractValueComparatorsTest<BigDecimal> {
-
-    public DecimalValueComparatorTest() {
-        super(ValueComparators.DECIMAL_COMPARATOR, new BigDecimal(100), new BigDecimal(200.0), new BigDecimal(300.0), new BigDecimal(-1.0), new BigDecimal(0.0));
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DoubleValueComparatorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DoubleValueComparatorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DoubleValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,34 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import org.jboss.dna.graph.properties.ValueComparators;
-
-/**
- * @author Randall Hauch
- */
-public class DoubleValueComparatorTest extends AbstractValueComparatorsTest<Double> {
-
-    public DoubleValueComparatorTest() {
-        super(ValueComparators.DOUBLE_COMPARATOR, 100.0d, 200.0d, 300.0d, -1.0d, 0.0d);
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/LongValueComparatorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/LongValueComparatorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/LongValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,34 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import org.jboss.dna.graph.properties.ValueComparators;
-
-/**
- * @author Randall Hauch
- */
-public class LongValueComparatorTest extends AbstractValueComparatorsTest<Long> {
-
-    public LongValueComparatorTest() {
-        super(ValueComparators.LONG_COMPARATOR, 100l, 200l, 300l, -1l, 0l);
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/NameValueComparatorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/NameValueComparatorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/NameValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,76 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.junit.Assert.assertThat;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.ValueComparators;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class NameValueComparatorTest extends AbstractValueComparatorsTest<Name> {
-
-    private static final ValueFactory<Name> FACTORY;
-    private static final Name NAME1;
-    private static final Name NAME2;
-    private static final Name NAME3;
-    private static final Name NAME4;
-    private static final Name NAME5;
-    private static final Name NAME6;
-
-    static {
-        NAMESPACE_REGISTRY.register("dna", "http://www.jboss.org/dna/namespaces/Test");
-        NAMESPACE_REGISTRY.register("acme", "http://www.acme.com/");
-        NAMESPACE_REGISTRY.register("dna-b", "http://www.jboss.org/dna/namespaces/Test/b");
-        NAMESPACE_REGISTRY.register("dna-c", "http://www.jboss.org/dna/namespaces/TEST");
-        FACTORY = VALUE_FACTORIES.getNameFactory();
-        NAME1 = FACTORY.create("dna:alpha");
-        NAME2 = FACTORY.create("dna:beta");
-        NAME3 = FACTORY.create("acme:beta");
-        NAME4 = FACTORY.create("dna:beta");
-        NAME5 = FACTORY.create("dna:ALPHA");
-        NAME6 = FACTORY.create("dna-c:ALPHA");
-    }
-
-    public NameValueComparatorTest() {
-        super(ValueComparators.NAME_COMPARATOR, NAME1, NAME2, NAME3, NAME4, NAME5, NAME6);
-    }
-
-    @Test
-    public void shouldConsiderNamesWithSameNamespaceUriAndLocalPartToBeComparable() {
-        System.out.println(NAME2);
-        System.out.println(NAME4);
-        assertThat(comparator.compare(NAME2, NAME4), is(0));
-    }
-
-    @Test
-    public void shouldBeCaseSensitive() {
-        assertThat(comparator.compare(NAME2, NAME4), is(0));
-        assertThat(comparator.compare(NAME1, NAME5), is(not(0)));
-        assertThat(comparator.compare(NAME6, NAME5), is(not(0)));
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/PathExpressionTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/PathExpressionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/PathExpressionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,585 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.junit.Assert.assertThat;
-import org.jboss.dna.graph.properties.InvalidPathExpressionException;
-import org.jboss.dna.graph.properties.PathExpression;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class PathExpressionTest {
-
-    private PathExpression expr;
-
-    @Before
-    public void beforeEach() throws Exception {
-        expr = new PathExpression(".*");
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotCompileNullExpression() {
-        PathExpression.compile(null);
-    }
-
-    @Test( expected = InvalidPathExpressionException.class )
-    public void shouldNotCompileZeroLengthExpression() {
-        PathExpression.compile("");
-    }
-
-    @Test( expected = InvalidPathExpressionException.class )
-    public void shouldNotCompileBlankExpression() {
-        PathExpression.compile("    ");
-    }
-
-    @Test
-    public void shouldCompileExpressionWithAnyNode() {
-        expr = PathExpression.compile("/*");
-        assertThat(expr.getSelectExpression(), is("/*"));
-        assertThat(expr.matcher("/a").matches(), is(true));
-        assertThat(expr.matcher("/a").getInputPath(), is("/a"));
-        assertThat(expr.matcher("/a").getSelectedNodePath(), is("/a"));
-        assertThat(expr.matcher("/a").groupCount(), is(0));
-    }
-
-    @Test
-    public void shouldCompileExpressionWithAnySequenceOfNodes() {
-        expr = PathExpression.compile("//");
-        assertThat(expr.getSelectExpression(), is("//"));
-        assertThat(expr.matcher("/a").matches(), is(true));
-        assertThat(expr.matcher("/a").getInputPath(), is("/a"));
-        assertThat(expr.matcher("/a").getSelectedNodePath(), is("/a"));
-        assertThat(expr.matcher("/a").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b").matches(), is(true));
-        assertThat(expr.matcher("/a/b").getInputPath(), is("/a/b"));
-        assertThat(expr.matcher("/a/b").getSelectedNodePath(), is("/a/b"));
-        assertThat(expr.matcher("/a/b").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b/c").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c").getInputPath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c").groupCount(), is(0));
-    }
-
-    @Test
-    public void shouldCompileExpressionWithExtraWhitespace() {
-        expr = PathExpression.compile(" /a/b/c ");
-        assertThat(expr, is(notNullValue()));
-        assertThat(expr.getSelectExpression(), is("/a/b/c"));
-
-        expr = PathExpression.compile("  /a/b/c ");
-        assertThat(expr, is(notNullValue()));
-        assertThat(expr.getSelectExpression(), is("/a/b/c"));
-    }
-
-    @Test
-    public void shouldCompileExpressionWithIndexes() {
-        assertThat(PathExpression.compile("/a/b[0]/c[1]/d/e"), is(notNullValue()));
-        assertThat(PathExpression.compile("/a/b[0]/c[1]/d/e[2]"), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldNotRemoveUsedPredicates() {
-        assertThat(expr.removeUnusedPredicates("/a/b/c"), is("/a/b/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[0]/c"), is("/a/b[0]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[1]/c"), is("/a/b[1]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[10]/c"), is("/a/b[10]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[100]/c"), is("/a/b[100]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[1000]/c"), is("/a/b[1000]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[]/c"), is("/a/b[]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[*]/c"), is("/a/b[*]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[1,2]/c"), is("/a/b[1,2]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[1,2,3,4,5]/c"), is("/a/b[1,2,3,4,5]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b/c[@title]"), is("/a/b/c[@title]"));
-        assertThat(expr.removeUnusedPredicates("/a/b/c[d/e/@title]"), is("/a/b/c[d/e/@title]"));
-        assertThat(expr.removeUnusedPredicates("/a/(b/c)[(d|e)/(f|g)/@something]"), is("/a/(b/c)[(d|e)/(f|g)/@something]"));
-        assertThat(expr.removeUnusedPredicates("/*"), is("/*"));
-        assertThat(expr.removeUnusedPredicates("/*[]"), is("/*[]"));
-        assertThat(expr.removeUnusedPredicates("/*[3]"), is("/*[3]"));
-        // These are legal, but aren't really useful ...
-        assertThat(expr.removeUnusedPredicates("/a/b[1][2][3]/c"), is("/a/b[1][2][3]/c"));
-    }
-
-    @Test
-    public void shouldRemoveUnusedPredicates() {
-        assertThat(expr.removeUnusedPredicates("/a/b[-1]/c"), is("/a/b/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[@name='wacky']/c"), is("/a/b/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[3][@name='wacky']/c"), is("/a/b[3]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[3][@name]/c"), is("/a/b[3]/c"));
-        assertThat(expr.removeUnusedPredicates("/a/b[length(@name)=3]/c"), is("/a/b/c"));
-    }
-
-    @Test
-    public void shouldRemoveAllPredicates() {
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b/c"), is("/a/b/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[0]/c"), is("/a/b[0]/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[1]/c"), is("/a/b[1]/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[10]/c"), is("/a/b[10]/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[100]/c"), is("/a/b[100]/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[1000]/c"), is("/a/b[1000]/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[]/c"), is("/a/b[]/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[*]/c"), is("/a/b[*]/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b/c[@title]"), is("/a/b/c"));
-        // These are legal, but aren't really useful ...
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[1][2][3]/c"), is("/a/b[1][2][3]/c"));
-
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[-1]/c"), is("/a/b/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[@name='wacky']/c"), is("/a/b/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[3][@name='wacky']/c"), is("/a/b[3]/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[3][@name]/c"), is("/a/b[3]/c"));
-        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[length(@name)=3]/c"), is("/a/b/c"));
-    }
-
-    @Test
-    public void shouldReplaceAllXPathPatterns() {
-        assertThat(expr.replaceXPathPatterns("/a/b[3]/c"), is("/a/b\\[3\\]/c"));
-        assertThat(expr.replaceXPathPatterns("/a/b[*]/c"), is("/a/b(?:\\[\\d+\\])?/c"));
-        assertThat(expr.replaceXPathPatterns("/a/b[]/c"), is("/a/b(?:\\[\\d+\\])?/c"));
-        assertThat(expr.replaceXPathPatterns("/a/b[0]/c"), is("/a/b(?:\\[0\\])?/c"));
-        assertThat(expr.replaceXPathPatterns("/a/b[0,1,2,4]/c"), is("/a/b(?:\\[(?:1|2|4)\\])?/c"));
-        assertThat(expr.replaceXPathPatterns("/a/b[1,2,4,0]/c"), is("/a/b(?:\\[(?:1|2|4)\\])?/c"));
-        assertThat(expr.replaceXPathPatterns("/a/b[1,2,0,4]/c"), is("/a/b(?:\\[(?:1|2|4)\\])?/c"));
-        assertThat(expr.replaceXPathPatterns("/a/b[0,1,2,0,4,0]/c"), is("/a/b(?:\\[(?:1|2|4)\\])?/c"));
-        assertThat(expr.replaceXPathPatterns("/a/b[1,2,4]/c"), is("/a/b\\[(?:1|2|4)\\]/c"));
-        assertThat(expr.replaceXPathPatterns("/a/b[@param]"), is("/a/b/@param"));
-        assertThat(expr.replaceXPathPatterns("/a/b[3][@param]"), is("/a/b\\[3\\]/@param"));
-        assertThat(expr.replaceXPathPatterns("/a/b[c/d/@param]"), is("/a/b/c/d/@param"));
-
-        assertThat(expr.replaceXPathPatterns("/a/(b|c|d)/e"), is("/a/(b|c|d)/e"));
-        assertThat(expr.replaceXPathPatterns("/a/(b||c|d)/e"), is("/a/(b|c|d)/e"));
-        assertThat(expr.replaceXPathPatterns("/a/(b|||c|d)/e"), is("/a/(b|c|d)/e"));
-        assertThat(expr.replaceXPathPatterns("/a/(|b|c|d)/e"), is("/a(?:/(b|c|d))?/e"));
-        assertThat(expr.replaceXPathPatterns("/a/(b|c|d|)/e"), is("/a(?:/(b|c|d))?/e"));
-        assertThat(expr.replaceXPathPatterns("/a/(b|c|d)[]/e"), is("/a/(b|c|d)(?:\\[\\d+\\])?/e"));
-        assertThat(expr.replaceXPathPatterns("/a/(b|c[2]|d[])/e"), is("/a/(b|c\\[2\\]|d(?:\\[\\d+\\])?)/e"));
-        assertThat(expr.replaceXPathPatterns("/a/(b|c/d|e)/f"), is("/a/(b|c/d|e)/f"));
-        assertThat(expr.replaceXPathPatterns("/a/(b/c)[(d|e)/(f|g)/@something]"), is("/a/(b/c)/(d|e)/(f|g)/@something"));
-
-        assertThat(expr.replaceXPathPatterns("/a/*/f"), is("/a/[^/]*/f"));
-        assertThat(expr.replaceXPathPatterns("/a//f"), is("/a(?:/[^/]*)*/f"));
-        assertThat(expr.replaceXPathPatterns("/a///f"), is("/a(?:/[^/]*)*/f"));
-        assertThat(expr.replaceXPathPatterns("/a/////f"), is("/a(?:/[^/]*)*/f"));
-
-        assertThat(expr.replaceXPathPatterns("/*"), is("/[^/]*"));
-        assertThat(expr.replaceXPathPatterns("/*[]"), is("/[^/]*(?:\\[\\d+\\])?"));
-        assertThat(expr.replaceXPathPatterns("/*[3]"), is("/[^/]*\\[3\\]"));
-    }
-
-    @Test
-    public void shouldDetermineIfPatternMatchesAnything() {
-        assertThat(PathExpression.compile("/.").matchesAnything(), is(true));
-        assertThat(PathExpression.compile("//").matchesAnything(), is(true));
-        assertThat(PathExpression.compile("///").matchesAnything(), is(true));
-        assertThat(PathExpression.compile("///").matchesAnything(), is(true));
-        assertThat(PathExpression.compile("/*").matchesAnything(), is(true));
-        assertThat(PathExpression.compile("*").matchesAnything(), is(true));
-        assertThat(PathExpression.compile("*[*]").matchesAnything(), is(true));
-        assertThat(PathExpression.compile("*[]").matchesAnything(), is(true));
-
-        assertThat(PathExpression.compile("/a").matchesAnything(), is(false));
-        assertThat(PathExpression.compile("/*[3]").matchesAnything(), is(false));
-        assertThat(PathExpression.compile("/a/b/c").matchesAnything(), is(false));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithoutRegardToCase() {
-        expr = PathExpression.compile("/a/b/c/d/e[@something]");
-        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c/d/e"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b/c/d/E/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/E/@something").getInputPath(), is("/a/b/c/d/E/@something"));
-        assertThat(expr.matcher("/a/b/c/d/E/@something").getSelectedNodePath(), is("/a/b/c/d/E"));
-        assertThat(expr.matcher("/a/b/c/d/E/@something").groupCount(), is(0));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithExactFullPath() {
-        expr = PathExpression.compile("/a/b/c/d/e[@something]");
-        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c/d/e"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b/c/d/E/@something2").matches(), is(false));
-        assertThat(expr.matcher("/a/b/c/d/ex/@something").matches(), is(false));
-        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(false));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithExactFullPathAndExtraPathInsideMatch() {
-        expr = PathExpression.compile("/a/b/c[d/e/@something]");
-        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b/c/d/E/@something2").matches(), is(false));
-        assertThat(expr.matcher("/a/b/c/d/ex/@something").matches(), is(false));
-        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(false));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithWildcardSelection() {
-        expr = PathExpression.compile("/a/*/c[d/e/@something]");
-        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/rt/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/rt/c/d/e/@something").getInputPath(), is("/a/rt/c/d/e/@something"));
-        assertThat(expr.matcher("/a/rt/c/d/e/@something").getSelectedNodePath(), is("/a/rt/c"));
-        assertThat(expr.matcher("/a/rt/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/ac/d/e/@something").matches(), is(false));
-        assertThat(expr.matcher("/a/d/e/@something").matches(), is(false));
-        assertThat(expr.matcher("/a/b/b2/b3/d/e/@something").matches(), is(false));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithFilenameLikeWildcardSelection() {
-        expr = PathExpression.compile("/a/*.txt[@something]");
-        assertThat(expr.matcher("/a/b.txt/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b.txt/@something").getInputPath(), is("/a/b.txt/@something"));
-        assertThat(expr.matcher("/a/b.txt/@something").getSelectedNodePath(), is("/a/b.txt"));
-        assertThat(expr.matcher("/a/b.txt/@something").groupCount(), is(0));
-        assertThat(expr.matcher("/a/b.tx/@something").matches(), is(false));
-
-        expr = PathExpression.compile("/a/*.txt/c[@something]");
-        assertThat(expr.matcher("/a/b.txt/c/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b.txt/c/@something").getInputPath(), is("/a/b.txt/c/@something"));
-        assertThat(expr.matcher("/a/b.txt/c/@something").getSelectedNodePath(), is("/a/b.txt/c"));
-        assertThat(expr.matcher("/a/b.txt/c/@something").groupCount(), is(0));
-        assertThat(expr.matcher("/a/b.tx/c/@something").matches(), is(false));
-
-        expr = PathExpression.compile("//*.txt[*]/c[@something]");
-        assertThat(expr.matcher("/a/b.txt/c/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b.txt/c/@something").getInputPath(), is("/a/b.txt/c/@something"));
-        assertThat(expr.matcher("/a/b.txt/c/@something").getSelectedNodePath(), is("/a/b.txt/c"));
-        assertThat(expr.matcher("/a/b.txt/c/@something").groupCount(), is(0));
-        assertThat(expr.matcher("/a/b.tx/c/@something").matches(), is(false));
-
-        assertThat(expr.matcher("/z/a/b.txt/c/@something").matches(), is(true));
-        assertThat(expr.matcher("/z/a/b.txt/c/@something").getInputPath(), is("/z/a/b.txt/c/@something"));
-        assertThat(expr.matcher("/z/a/b.txt/c/@something").getSelectedNodePath(), is("/z/a/b.txt/c"));
-        assertThat(expr.matcher("/z/a/b.txt/c/@something").groupCount(), is(0));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithSegmentWildcardSelection() {
-        expr = PathExpression.compile("/a//c[d/e/@something]");
-        assertThat(expr.matcher("/a/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/c/d/e/@something").getInputPath(), is("/a/c/d/e/@something"));
-        assertThat(expr.matcher("/a/c/d/e/@something").getSelectedNodePath(), is("/a/c"));
-        assertThat(expr.matcher("/a/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/rt/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/rt/c/d/e/@something").getInputPath(), is("/a/rt/c/d/e/@something"));
-        assertThat(expr.matcher("/a/rt/c/d/e/@something").getSelectedNodePath(), is("/a/rt/c"));
-        assertThat(expr.matcher("/a/rt/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/r/s/t/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/r/s/t/c/d/e/@something").getInputPath(), is("/a/r/s/t/c/d/e/@something"));
-        assertThat(expr.matcher("/a/r/s/t/c/d/e/@something").getSelectedNodePath(), is("/a/r/s/t/c"));
-        assertThat(expr.matcher("/a/r/s/t/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something").getInputPath(), is("/a/r[1]/s[2]/t[33]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something").getSelectedNodePath(), is("/a/r[1]/s[2]/t[33]/c"));
-        assertThat(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a[3]/c/d/e/@something").matches(), is(false));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithSegmentWildcardAtEnd() {
-        expr = PathExpression.compile("/a/b/c//");
-        assertThat(expr.matcher("/a/b/c").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c").getInputPath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b/c/d").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d").getInputPath(), is("/a/b/c/d"));
-        assertThat(expr.matcher("/a/b/c/d").getSelectedNodePath(), is("/a/b/c/d"));
-        assertThat(expr.matcher("/a/b/c/d").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b/c/a").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/a").getInputPath(), is("/a/b/c/a"));
-        assertThat(expr.matcher("/a/b/c/a").getSelectedNodePath(), is("/a/b/c/a"));
-        assertThat(expr.matcher("/a/b/c/a").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b/c/d/e/f/g/h").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/e/f/g/h").getInputPath(), is("/a/b/c/d/e/f/g/h"));
-        assertThat(expr.matcher("/a/b/c/d/e/f/g/h").getSelectedNodePath(), is("/a/b/c/d/e/f/g/h"));
-        assertThat(expr.matcher("/a/b/c/d/e/f/g/h").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b").matches(), is(false));
-        assertThat(expr.matcher("/a/b/d").matches(), is(false));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithExtraLargeSegmentWildcardAtEnd() {
-        expr = PathExpression.compile("/a/b/c////");
-        assertThat(expr.matcher("/a/b/c").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c").getInputPath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c").groupCount(), is(0));
-
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithIndexesInSelectionPaths() {
-        expr = PathExpression.compile("/a/b[2,3,4,5]/c/d/e[@something]");
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c/d/e"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getInputPath(), is("/a/b[3]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getSelectedNodePath(), is("/a/b[3]/c/d/e"));
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getInputPath(), is("/a/b[4]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getSelectedNodePath(), is("/a/b[4]/c/d/e"));
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getInputPath(), is("/a/b[5]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getSelectedNodePath(), is("/a/b[5]/c/d/e"));
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(false));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(false));
-        assertThat(expr.matcher("/a[1]/b/c/d/e/@something").matches(), is(false));
-
-        expr = PathExpression.compile("/a/b[0,2,3,4,5]/c/d/e[@something]");
-        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c/d/e"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c/d/e"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getInputPath(), is("/a/b[3]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getSelectedNodePath(), is("/a/b[3]/c/d/e"));
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getInputPath(), is("/a/b[4]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getSelectedNodePath(), is("/a/b[4]/c/d/e"));
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getInputPath(), is("/a/b[5]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getSelectedNodePath(), is("/a/b[5]/c/d/e"));
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[0]/c/d/e/@something").matches(), is(false));
-        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(false));
-        assertThat(expr.matcher("/a[1]/b/c/d/e/@something").matches(), is(false));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithAnyIndexesInSelectionPaths() {
-        expr = PathExpression.compile("/a/b[*]/c[]/d/e[@something]");
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c/d/e"));
-        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getInputPath(), is("/a/b[3]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getSelectedNodePath(), is("/a/b[3]/c/d/e"));
-        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getInputPath(), is("/a/b[4]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getSelectedNodePath(), is("/a/b[4]/c/d/e"));
-        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getInputPath(), is("/a/b[5]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getSelectedNodePath(), is("/a/b[5]/c/d/e"));
-        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").getInputPath(), is("/a/b[1]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").getSelectedNodePath(), is("/a/b[1]/c/d/e"));
-        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[6]/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[6]/c/d/e/@something").getInputPath(), is("/a/b[6]/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b[6]/c/d/e/@something").getSelectedNodePath(), is("/a/b[6]/c/d/e"));
-        assertThat(expr.matcher("/a/b[6]/c/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b[6]/c[1]/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b[6]/c[1]/d/e/@something").getInputPath(), is("/a/b[6]/c[1]/d/e/@something"));
-        assertThat(expr.matcher("/a/b[6]/c[1]/d/e/@something").getSelectedNodePath(), is("/a/b[6]/c[1]/d/e"));
-        assertThat(expr.matcher("/a/b[6]/c[1]/d/e/@something").groupCount(), is(0));
-
-        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c/d/e"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithRepositoryInSelectionPath() {
-        expr = PathExpression.compile("reposA:/a/b/c[d/e/@something]");
-        assertThat(expr.matcher("reposA:/a/b/c/d/e/@something").matches(), is(true));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithNamedGroups() {
-        expr = PathExpression.compile("/a(//c)[d/e/@something]");
-        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(1));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").group(0), is("/a/b/c/d/e/@something"));
-        assertThat(expr.matcher("/a/b/c/d/e/@something").group(1), is("/b/c"));
-
-        expr = PathExpression.compile("/a(/(b|c|d|)/e)[f/g/@something]");
-        assertThat(expr.matcher("/a/b/e/f/g/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/e/f/g/@something").getInputPath(), is("/a/b/e/f/g/@something"));
-        assertThat(expr.matcher("/a/b/e/f/g/@something").getSelectedNodePath(), is("/a/b/e"));
-        assertThat(expr.matcher("/a/b/e/f/g/@something").groupCount(), is(2));
-        assertThat(expr.matcher("/a/b/e/f/g/@something").group(0), is("/a/b/e/f/g/@something"));
-        assertThat(expr.matcher("/a/b/e/f/g/@something").group(1), is("/b/e"));
-        assertThat(expr.matcher("/a/b/e/f/g/@something").group(2), is("b"));
-
-        assertThat(expr.matcher("/a/c/e/f/g/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/c/e/f/g/@something").getInputPath(), is("/a/c/e/f/g/@something"));
-        assertThat(expr.matcher("/a/c/e/f/g/@something").getSelectedNodePath(), is("/a/c/e"));
-        assertThat(expr.matcher("/a/c/e/f/g/@something").groupCount(), is(2));
-        assertThat(expr.matcher("/a/c/e/f/g/@something").group(0), is("/a/c/e/f/g/@something"));
-        assertThat(expr.matcher("/a/c/e/f/g/@something").group(1), is("/c/e"));
-        assertThat(expr.matcher("/a/c/e/f/g/@something").group(2), is("c"));
-
-        assertThat(expr.matcher("/a/d/e/f/g/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/d/e/f/g/@something").getInputPath(), is("/a/d/e/f/g/@something"));
-        assertThat(expr.matcher("/a/d/e/f/g/@something").getSelectedNodePath(), is("/a/d/e"));
-        assertThat(expr.matcher("/a/d/e/f/g/@something").groupCount(), is(2));
-        assertThat(expr.matcher("/a/d/e/f/g/@something").group(0), is("/a/d/e/f/g/@something"));
-        assertThat(expr.matcher("/a/d/e/f/g/@something").group(1), is("/d/e"));
-        assertThat(expr.matcher("/a/d/e/f/g/@something").group(2), is("d"));
-
-        assertThat(expr.matcher("/a/e/f/g/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/e/f/g/@something").getInputPath(), is("/a/e/f/g/@something"));
-        assertThat(expr.matcher("/a/e/f/g/@something").getSelectedNodePath(), is("/a/e"));
-        assertThat(expr.matcher("/a/e/f/g/@something").groupCount(), is(2));
-        assertThat(expr.matcher("/a/e/f/g/@something").group(0), is("/a/e/f/g/@something"));
-        assertThat(expr.matcher("/a/e/f/g/@something").group(1), is("/e"));
-        assertThat(expr.matcher("/a/e/f/g/@something").group(2), is(nullValue()));
-
-        assertThat(expr.matcher("/a/t/e/f/g/@something").matches(), is(false));
-
-        expr = PathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something]");
-        assertThat(expr.matcher("/a/b/c/d/f/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").getInputPath(), is("/a/b/c/d/f/@something"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").groupCount(), is(3));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").group(0), is("/a/b/c/d/f/@something"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").group(1), is("b/c"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").group(2), is("d"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").group(3), is("f"));
-
-        assertThat(expr.matcher("/a/b/c/e/f/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/e/f/@something").getInputPath(), is("/a/b/c/e/f/@something"));
-        assertThat(expr.matcher("/a/b/c/e/f/@something").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c/e/f/@something").groupCount(), is(3));
-        assertThat(expr.matcher("/a/b/c/e/f/@something").group(0), is("/a/b/c/e/f/@something"));
-        assertThat(expr.matcher("/a/b/c/e/f/@something").group(1), is("b/c"));
-        assertThat(expr.matcher("/a/b/c/e/f/@something").group(2), is("e"));
-        assertThat(expr.matcher("/a/b/c/e/f/@something").group(3), is("f"));
-
-        assertThat(expr.matcher("/a/b/c/d/g/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/g/@something").getInputPath(), is("/a/b/c/d/g/@something"));
-        assertThat(expr.matcher("/a/b/c/d/g/@something").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c/d/g/@something").groupCount(), is(3));
-        assertThat(expr.matcher("/a/b/c/d/g/@something").group(0), is("/a/b/c/d/g/@something"));
-        assertThat(expr.matcher("/a/b/c/d/g/@something").group(1), is("b/c"));
-        assertThat(expr.matcher("/a/b/c/d/g/@something").group(2), is("d"));
-        assertThat(expr.matcher("/a/b/c/d/g/@something").group(3), is("g"));
-
-        assertThat(expr.matcher("/a/b/c/e/g/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/e/g/@something").getInputPath(), is("/a/b/c/e/g/@something"));
-        assertThat(expr.matcher("/a/b/c/e/g/@something").getSelectedNodePath(), is("/a/b/c"));
-        assertThat(expr.matcher("/a/b/c/e/g/@something").groupCount(), is(3));
-        assertThat(expr.matcher("/a/b/c/e/g/@something").group(0), is("/a/b/c/e/g/@something"));
-        assertThat(expr.matcher("/a/b/c/e/g/@something").group(1), is("b/c"));
-        assertThat(expr.matcher("/a/b/c/e/g/@something").group(2), is("e"));
-        assertThat(expr.matcher("/a/b/c/e/g/@something").group(3), is("g"));
-
-        expr = PathExpression.compile("/a/(b/c)/(d|e)/(f|g)/@something");
-        assertThat(expr.matcher("/a/b/c/d/f/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").getInputPath(), is("/a/b/c/d/f/@something"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").getSelectedNodePath(), is("/a/b/c/d/f"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").groupCount(), is(3));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").group(0), is("/a/b/c/d/f/@something"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").group(1), is("b/c"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").group(2), is("d"));
-        assertThat(expr.matcher("/a/b/c/d/f/@something").group(3), is("f"));
-
-        assertThat(expr.matcher("/a/b/c/e/f/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/d/g/@something").matches(), is(true));
-        assertThat(expr.matcher("/a/b/c/e/g/@something").matches(), is(true));
-    }
-
-    @Test
-    public void shouldMatchExpressionWithFilenamePatternAndChildProperty() {
-        expr = PathExpression.compile("//(*.(jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data]");
-        assertThat(expr.matcher("/a/b/caution.png/jcr:content/@jcr:data").matches(), is(true));
-    }
-}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/StringValueComparatorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/StringValueComparatorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/StringValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,58 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import org.jboss.dna.graph.properties.ValueComparators;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class StringValueComparatorTest extends AbstractValueComparatorsTest<String> {
-
-    public StringValueComparatorTest() {
-        super(ValueComparators.STRING_COMPARATOR, "valid value 1", "Valid valid 2");
-    }
-
-    @Test
-    public void shouldBeCaseInsensitive() {
-        assertThat(comparator.compare(validNonNullValues[0].toUpperCase(), validNonNullValues[0].toLowerCase()), is(not(0)));
-    }
-
-    @Test
-    public void shouldMatchStringCompareToMethod() {
-        assertThat(comparator.compare(validNonNullValues[0], validNonNullValues[1]), is(validNonNullValues[0].compareTo(validNonNullValues[1])));
-        assertThat(comparator.compare(validNonNullValues[1], validNonNullValues[0]), is(validNonNullValues[1].compareTo(validNonNullValues[0])));
-        assertThat(comparator.compare(validNonNullValues[1], validNonNullValues[1]), is(validNonNullValues[1].compareTo(validNonNullValues[1])));
-        assertThat(comparator.compare(validNonNullValues[0], validNonNullValues[0]), is(validNonNullValues[0].compareTo(validNonNullValues[0])));
-    }
-
-    @Test
-    public void shouldSortValues() {
-        assertThat(getSortedValues(false), hasItems(validNonNullValues[0], validNonNullValues[1]));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/AbstractValueComparatorsTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/AbstractValueComparatorsTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/AbstractValueComparatorsTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/AbstractValueComparatorsTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,137 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.StandardValueFactories;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @param <T>
+ */
+public abstract class AbstractValueComparatorsTest<T> {
+
+    public static final BasicNamespaceRegistry NAMESPACE_REGISTRY = new BasicNamespaceRegistry();
+    public static final ValueFactories VALUE_FACTORIES = new StandardValueFactories(NAMESPACE_REGISTRY);
+
+    protected final Comparator<T> comparator;
+    protected final T[] validNonNullValues;
+
+    protected AbstractValueComparatorsTest( Comparator<T> comparator, T... validNonNullValues ) {
+        CheckArg.isNotNull(comparator, "comparator");
+        CheckArg.isNotEmpty(validNonNullValues, "validNonNullValues");
+        this.comparator = comparator;
+        this.validNonNullValues = validNonNullValues;
+    }
+
+    protected Comparator<T> getComparator() {
+        return this.comparator;
+    }
+
+    @Test
+    public void shouldConsiderNullLessThanValidNonNull() {
+        assertThat(comparator.compare(validNonNullValues[0], null) > 0, is(true));
+        assertThat(comparator.compare(null, validNonNullValues[0]) < 0, is(true));
+    }
+
+    @Test
+    public void shouldConsiderTwoNullsToBeEquivalent() {
+        assertThat(comparator.compare(null, null), is(0));
+    }
+
+    @Test
+    public void shouldConsiderSameInstanceToBeEquivalent() {
+        for (T validNonNullValue : validNonNullValues) {
+            assertThat(comparator.compare(validNonNullValue, validNonNullValue), is(0));
+        }
+    }
+
+    protected List<T> getValues( boolean includeNull ) {
+        List<T> values = new ArrayList<T>(validNonNullValues.length);
+        for (T validNonNullValue : validNonNullValues) {
+            assertThat(validNonNullValue, is(notNullValue()));
+            values.add(validNonNullValue);
+        }
+        if (includeNull) values.add(null);
+        return values;
+    }
+
+    protected List<T> getSortedValues( boolean includeNull ) {
+        List<T> values = getValues(includeNull);
+        Collections.sort(values, comparator);
+        return values;
+    }
+
+    // protected void assertSortsSimilarTo( Comparator<T> otherComparator ) {
+    // assertThat(otherComparator, is(notNullValue()));
+    // List<T> values = getValues(true);
+    // List<T> otherValues = getValues(true);
+    // Collections.sort(values, comparator);
+    // Collections.sort(otherValues, comparator);
+    // assertThat(values, is(otherValues));
+    //
+    // values = getValues(false);
+    // otherValues = getValues(false);
+    // Collections.sort(values, comparator);
+    // Collections.sort(otherValues, comparator);
+    // assertThat(values, is(otherValues));
+    // }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldBeCompatibleWithCompareTo() {
+        List<T> values = getValues(false);
+        Collections.sort(values, comparator);
+        for (int i = 0; i != (values.size() - 1); ++i) {
+            T value1 = values.get(i);
+            T value2 = values.get(i + 1);
+            assertThat(value1, is(instanceOf(Comparable.class)));
+            Comparable<T> comparable1 = (Comparable<T>)value1;
+            int result = comparable1.compareTo(value2);
+            assertThat(result < 0 || result == 0, is(true));
+            assertThat(comparable1.compareTo(value1), is(0));
+        }
+    }
+
+    protected void assertValuesCompareUsing( T value1, T value2 ) {
+        int value1ToValue2 = comparator.compare(value1, value2);
+        int value2ToValue1 = comparator.compare(value2, value1);
+        if (value1ToValue2 == 0) {
+            assertThat(value2ToValue1, is(0));
+        } else if (value1ToValue2 < 0) {
+            assertThat(value2ToValue1 > 0, is(true));
+        } else { // if ( value1ToValue2 > 0 )
+            assertThat(value2ToValue1 < 0, is(true));
+        }
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/AbstractValueComparatorsTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BinaryValueComparatorTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BinaryValueComparatorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BinaryValueComparatorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BinaryValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.ValueComparators;
+import org.jboss.dna.graph.property.ValueFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public class BinaryValueComparatorTest extends AbstractValueComparatorsTest<Binary> {
+
+    private static final ValueFactory<Binary> FACTORY;
+    private static final Binary BINARY1;
+    private static final Binary BINARY2;
+    private static final Binary BINARY3;
+
+    static {
+        FACTORY = VALUE_FACTORIES.getBinaryFactory();
+        BINARY1 = FACTORY.create("This is the binary 1 value");
+        BINARY2 = FACTORY.create("This is the binary 2 value");
+        BINARY3 = FACTORY.create("This is the binary 3 value");
+    }
+
+    public BinaryValueComparatorTest() {
+        super(ValueComparators.BINARY_COMPARATOR, BINARY1, BINARY2, BINARY3);
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BinaryValueComparatorTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BooleanValueComparatorTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/BooleanValueComparatorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BooleanValueComparatorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BooleanValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import org.jboss.dna.graph.property.ValueComparators;
+
+/**
+ * @author Randall Hauch
+ */
+public class BooleanValueComparatorTest extends AbstractValueComparatorsTest<Boolean> {
+
+    public BooleanValueComparatorTest() {
+        super(ValueComparators.BOOLEAN_COMPARATOR, Boolean.TRUE, Boolean.FALSE);
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/BooleanValueComparatorTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DateValueComparatorTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DateValueComparatorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DateValueComparatorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DateValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,47 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.util.Calendar;
+import org.jboss.dna.graph.property.ValueComparators;
+
+/**
+ * @author Randall Hauch
+ */
+public class DateValueComparatorTest extends AbstractValueComparatorsTest<Calendar> {
+
+    private static final Calendar TODAY = Calendar.getInstance();
+    private static final Calendar YESTERDAY;
+    private static final Calendar TOMORROW;
+
+    static {
+        YESTERDAY = (Calendar)TODAY.clone();
+        YESTERDAY.roll(Calendar.DAY_OF_YEAR, false);
+
+        TOMORROW = (Calendar)TODAY.clone();
+        TOMORROW.roll(Calendar.DAY_OF_YEAR, true);
+    }
+
+    public DateValueComparatorTest() {
+        super(ValueComparators.CALENDAR_COMPARATOR, TODAY, TOMORROW, YESTERDAY);
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DateValueComparatorTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DecimalValueComparatorTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DecimalValueComparatorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DecimalValueComparatorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DecimalValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,35 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import java.math.BigDecimal;
+import org.jboss.dna.graph.property.ValueComparators;
+
+/**
+ * @author Randall Hauch
+ */
+public class DecimalValueComparatorTest extends AbstractValueComparatorsTest<BigDecimal> {
+
+    public DecimalValueComparatorTest() {
+        super(ValueComparators.DECIMAL_COMPARATOR, new BigDecimal(100), new BigDecimal(200.0), new BigDecimal(300.0), new BigDecimal(-1.0), new BigDecimal(0.0));
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DecimalValueComparatorTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DoubleValueComparatorTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/DoubleValueComparatorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DoubleValueComparatorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DoubleValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import org.jboss.dna.graph.property.ValueComparators;
+
+/**
+ * @author Randall Hauch
+ */
+public class DoubleValueComparatorTest extends AbstractValueComparatorsTest<Double> {
+
+    public DoubleValueComparatorTest() {
+        super(ValueComparators.DOUBLE_COMPARATOR, 100.0d, 200.0d, 300.0d, -1.0d, 0.0d);
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/DoubleValueComparatorTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/LongValueComparatorTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/LongValueComparatorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/LongValueComparatorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/LongValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import org.jboss.dna.graph.property.ValueComparators;
+
+/**
+ * @author Randall Hauch
+ */
+public class LongValueComparatorTest extends AbstractValueComparatorsTest<Long> {
+
+    public LongValueComparatorTest() {
+        super(ValueComparators.LONG_COMPARATOR, 100l, 200l, 300l, -1l, 0l);
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/LongValueComparatorTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/NameValueComparatorTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/NameValueComparatorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/NameValueComparatorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/NameValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.ValueComparators;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class NameValueComparatorTest extends AbstractValueComparatorsTest<Name> {
+
+    private static final ValueFactory<Name> FACTORY;
+    private static final Name NAME1;
+    private static final Name NAME2;
+    private static final Name NAME3;
+    private static final Name NAME4;
+    private static final Name NAME5;
+    private static final Name NAME6;
+
+    static {
+        NAMESPACE_REGISTRY.register("dna", "http://www.jboss.org/dna/namespaces/Test");
+        NAMESPACE_REGISTRY.register("acme", "http://www.acme.com/");
+        NAMESPACE_REGISTRY.register("dna-b", "http://www.jboss.org/dna/namespaces/Test/b");
+        NAMESPACE_REGISTRY.register("dna-c", "http://www.jboss.org/dna/namespaces/TEST");
+        FACTORY = VALUE_FACTORIES.getNameFactory();
+        NAME1 = FACTORY.create("dna:alpha");
+        NAME2 = FACTORY.create("dna:beta");
+        NAME3 = FACTORY.create("acme:beta");
+        NAME4 = FACTORY.create("dna:beta");
+        NAME5 = FACTORY.create("dna:ALPHA");
+        NAME6 = FACTORY.create("dna-c:ALPHA");
+    }
+
+    public NameValueComparatorTest() {
+        super(ValueComparators.NAME_COMPARATOR, NAME1, NAME2, NAME3, NAME4, NAME5, NAME6);
+    }
+
+    @Test
+    public void shouldConsiderNamesWithSameNamespaceUriAndLocalPartToBeComparable() {
+        System.out.println(NAME2);
+        System.out.println(NAME4);
+        assertThat(comparator.compare(NAME2, NAME4), is(0));
+    }
+
+    @Test
+    public void shouldBeCaseSensitive() {
+        assertThat(comparator.compare(NAME2, NAME4), is(0));
+        assertThat(comparator.compare(NAME1, NAME5), is(not(0)));
+        assertThat(comparator.compare(NAME6, NAME5), is(not(0)));
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/NameValueComparatorTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/PathExpressionTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/PathExpressionTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/PathExpressionTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/PathExpressionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,585 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.property.InvalidPathExpressionException;
+import org.jboss.dna.graph.property.PathExpression;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class PathExpressionTest {
+
+    private PathExpression expr;
+
+    @Before
+    public void beforeEach() throws Exception {
+        expr = new PathExpression(".*");
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotCompileNullExpression() {
+        PathExpression.compile(null);
+    }
+
+    @Test( expected = InvalidPathExpressionException.class )
+    public void shouldNotCompileZeroLengthExpression() {
+        PathExpression.compile("");
+    }
+
+    @Test( expected = InvalidPathExpressionException.class )
+    public void shouldNotCompileBlankExpression() {
+        PathExpression.compile("    ");
+    }
+
+    @Test
+    public void shouldCompileExpressionWithAnyNode() {
+        expr = PathExpression.compile("/*");
+        assertThat(expr.getSelectExpression(), is("/*"));
+        assertThat(expr.matcher("/a").matches(), is(true));
+        assertThat(expr.matcher("/a").getInputPath(), is("/a"));
+        assertThat(expr.matcher("/a").getSelectedNodePath(), is("/a"));
+        assertThat(expr.matcher("/a").groupCount(), is(0));
+    }
+
+    @Test
+    public void shouldCompileExpressionWithAnySequenceOfNodes() {
+        expr = PathExpression.compile("//");
+        assertThat(expr.getSelectExpression(), is("//"));
+        assertThat(expr.matcher("/a").matches(), is(true));
+        assertThat(expr.matcher("/a").getInputPath(), is("/a"));
+        assertThat(expr.matcher("/a").getSelectedNodePath(), is("/a"));
+        assertThat(expr.matcher("/a").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b").matches(), is(true));
+        assertThat(expr.matcher("/a/b").getInputPath(), is("/a/b"));
+        assertThat(expr.matcher("/a/b").getSelectedNodePath(), is("/a/b"));
+        assertThat(expr.matcher("/a/b").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b/c").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c").getInputPath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c").groupCount(), is(0));
+    }
+
+    @Test
+    public void shouldCompileExpressionWithExtraWhitespace() {
+        expr = PathExpression.compile(" /a/b/c ");
+        assertThat(expr, is(notNullValue()));
+        assertThat(expr.getSelectExpression(), is("/a/b/c"));
+
+        expr = PathExpression.compile("  /a/b/c ");
+        assertThat(expr, is(notNullValue()));
+        assertThat(expr.getSelectExpression(), is("/a/b/c"));
+    }
+
+    @Test
+    public void shouldCompileExpressionWithIndexes() {
+        assertThat(PathExpression.compile("/a/b[0]/c[1]/d/e"), is(notNullValue()));
+        assertThat(PathExpression.compile("/a/b[0]/c[1]/d/e[2]"), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldNotRemoveUsedPredicates() {
+        assertThat(expr.removeUnusedPredicates("/a/b/c"), is("/a/b/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[0]/c"), is("/a/b[0]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[1]/c"), is("/a/b[1]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[10]/c"), is("/a/b[10]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[100]/c"), is("/a/b[100]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[1000]/c"), is("/a/b[1000]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[]/c"), is("/a/b[]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[*]/c"), is("/a/b[*]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[1,2]/c"), is("/a/b[1,2]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[1,2,3,4,5]/c"), is("/a/b[1,2,3,4,5]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b/c[@title]"), is("/a/b/c[@title]"));
+        assertThat(expr.removeUnusedPredicates("/a/b/c[d/e/@title]"), is("/a/b/c[d/e/@title]"));
+        assertThat(expr.removeUnusedPredicates("/a/(b/c)[(d|e)/(f|g)/@something]"), is("/a/(b/c)[(d|e)/(f|g)/@something]"));
+        assertThat(expr.removeUnusedPredicates("/*"), is("/*"));
+        assertThat(expr.removeUnusedPredicates("/*[]"), is("/*[]"));
+        assertThat(expr.removeUnusedPredicates("/*[3]"), is("/*[3]"));
+        // These are legal, but aren't really useful ...
+        assertThat(expr.removeUnusedPredicates("/a/b[1][2][3]/c"), is("/a/b[1][2][3]/c"));
+    }
+
+    @Test
+    public void shouldRemoveUnusedPredicates() {
+        assertThat(expr.removeUnusedPredicates("/a/b[-1]/c"), is("/a/b/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[@name='wacky']/c"), is("/a/b/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[3][@name='wacky']/c"), is("/a/b[3]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[3][@name]/c"), is("/a/b[3]/c"));
+        assertThat(expr.removeUnusedPredicates("/a/b[length(@name)=3]/c"), is("/a/b/c"));
+    }
+
+    @Test
+    public void shouldRemoveAllPredicates() {
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b/c"), is("/a/b/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[0]/c"), is("/a/b[0]/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[1]/c"), is("/a/b[1]/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[10]/c"), is("/a/b[10]/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[100]/c"), is("/a/b[100]/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[1000]/c"), is("/a/b[1000]/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[]/c"), is("/a/b[]/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[*]/c"), is("/a/b[*]/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b/c[@title]"), is("/a/b/c"));
+        // These are legal, but aren't really useful ...
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[1][2][3]/c"), is("/a/b[1][2][3]/c"));
+
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[-1]/c"), is("/a/b/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[@name='wacky']/c"), is("/a/b/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[3][@name='wacky']/c"), is("/a/b[3]/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[3][@name]/c"), is("/a/b[3]/c"));
+        assertThat(expr.removeAllPredicatesExceptIndexes("/a/b[length(@name)=3]/c"), is("/a/b/c"));
+    }
+
+    @Test
+    public void shouldReplaceAllXPathPatterns() {
+        assertThat(expr.replaceXPathPatterns("/a/b[3]/c"), is("/a/b\\[3\\]/c"));
+        assertThat(expr.replaceXPathPatterns("/a/b[*]/c"), is("/a/b(?:\\[\\d+\\])?/c"));
+        assertThat(expr.replaceXPathPatterns("/a/b[]/c"), is("/a/b(?:\\[\\d+\\])?/c"));
+        assertThat(expr.replaceXPathPatterns("/a/b[0]/c"), is("/a/b(?:\\[0\\])?/c"));
+        assertThat(expr.replaceXPathPatterns("/a/b[0,1,2,4]/c"), is("/a/b(?:\\[(?:1|2|4)\\])?/c"));
+        assertThat(expr.replaceXPathPatterns("/a/b[1,2,4,0]/c"), is("/a/b(?:\\[(?:1|2|4)\\])?/c"));
+        assertThat(expr.replaceXPathPatterns("/a/b[1,2,0,4]/c"), is("/a/b(?:\\[(?:1|2|4)\\])?/c"));
+        assertThat(expr.replaceXPathPatterns("/a/b[0,1,2,0,4,0]/c"), is("/a/b(?:\\[(?:1|2|4)\\])?/c"));
+        assertThat(expr.replaceXPathPatterns("/a/b[1,2,4]/c"), is("/a/b\\[(?:1|2|4)\\]/c"));
+        assertThat(expr.replaceXPathPatterns("/a/b[@param]"), is("/a/b/@param"));
+        assertThat(expr.replaceXPathPatterns("/a/b[3][@param]"), is("/a/b\\[3\\]/@param"));
+        assertThat(expr.replaceXPathPatterns("/a/b[c/d/@param]"), is("/a/b/c/d/@param"));
+
+        assertThat(expr.replaceXPathPatterns("/a/(b|c|d)/e"), is("/a/(b|c|d)/e"));
+        assertThat(expr.replaceXPathPatterns("/a/(b||c|d)/e"), is("/a/(b|c|d)/e"));
+        assertThat(expr.replaceXPathPatterns("/a/(b|||c|d)/e"), is("/a/(b|c|d)/e"));
+        assertThat(expr.replaceXPathPatterns("/a/(|b|c|d)/e"), is("/a(?:/(b|c|d))?/e"));
+        assertThat(expr.replaceXPathPatterns("/a/(b|c|d|)/e"), is("/a(?:/(b|c|d))?/e"));
+        assertThat(expr.replaceXPathPatterns("/a/(b|c|d)[]/e"), is("/a/(b|c|d)(?:\\[\\d+\\])?/e"));
+        assertThat(expr.replaceXPathPatterns("/a/(b|c[2]|d[])/e"), is("/a/(b|c\\[2\\]|d(?:\\[\\d+\\])?)/e"));
+        assertThat(expr.replaceXPathPatterns("/a/(b|c/d|e)/f"), is("/a/(b|c/d|e)/f"));
+        assertThat(expr.replaceXPathPatterns("/a/(b/c)[(d|e)/(f|g)/@something]"), is("/a/(b/c)/(d|e)/(f|g)/@something"));
+
+        assertThat(expr.replaceXPathPatterns("/a/*/f"), is("/a/[^/]*/f"));
+        assertThat(expr.replaceXPathPatterns("/a//f"), is("/a(?:/[^/]*)*/f"));
+        assertThat(expr.replaceXPathPatterns("/a///f"), is("/a(?:/[^/]*)*/f"));
+        assertThat(expr.replaceXPathPatterns("/a/////f"), is("/a(?:/[^/]*)*/f"));
+
+        assertThat(expr.replaceXPathPatterns("/*"), is("/[^/]*"));
+        assertThat(expr.replaceXPathPatterns("/*[]"), is("/[^/]*(?:\\[\\d+\\])?"));
+        assertThat(expr.replaceXPathPatterns("/*[3]"), is("/[^/]*\\[3\\]"));
+    }
+
+    @Test
+    public void shouldDetermineIfPatternMatchesAnything() {
+        assertThat(PathExpression.compile("/.").matchesAnything(), is(true));
+        assertThat(PathExpression.compile("//").matchesAnything(), is(true));
+        assertThat(PathExpression.compile("///").matchesAnything(), is(true));
+        assertThat(PathExpression.compile("///").matchesAnything(), is(true));
+        assertThat(PathExpression.compile("/*").matchesAnything(), is(true));
+        assertThat(PathExpression.compile("*").matchesAnything(), is(true));
+        assertThat(PathExpression.compile("*[*]").matchesAnything(), is(true));
+        assertThat(PathExpression.compile("*[]").matchesAnything(), is(true));
+
+        assertThat(PathExpression.compile("/a").matchesAnything(), is(false));
+        assertThat(PathExpression.compile("/*[3]").matchesAnything(), is(false));
+        assertThat(PathExpression.compile("/a/b/c").matchesAnything(), is(false));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithoutRegardToCase() {
+        expr = PathExpression.compile("/a/b/c/d/e[@something]");
+        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c/d/e"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b/c/d/E/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/E/@something").getInputPath(), is("/a/b/c/d/E/@something"));
+        assertThat(expr.matcher("/a/b/c/d/E/@something").getSelectedNodePath(), is("/a/b/c/d/E"));
+        assertThat(expr.matcher("/a/b/c/d/E/@something").groupCount(), is(0));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithExactFullPath() {
+        expr = PathExpression.compile("/a/b/c/d/e[@something]");
+        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c/d/e"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b/c/d/E/@something2").matches(), is(false));
+        assertThat(expr.matcher("/a/b/c/d/ex/@something").matches(), is(false));
+        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(false));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithExactFullPathAndExtraPathInsideMatch() {
+        expr = PathExpression.compile("/a/b/c[d/e/@something]");
+        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b/c/d/E/@something2").matches(), is(false));
+        assertThat(expr.matcher("/a/b/c/d/ex/@something").matches(), is(false));
+        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(false));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithWildcardSelection() {
+        expr = PathExpression.compile("/a/*/c[d/e/@something]");
+        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/rt/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/rt/c/d/e/@something").getInputPath(), is("/a/rt/c/d/e/@something"));
+        assertThat(expr.matcher("/a/rt/c/d/e/@something").getSelectedNodePath(), is("/a/rt/c"));
+        assertThat(expr.matcher("/a/rt/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/ac/d/e/@something").matches(), is(false));
+        assertThat(expr.matcher("/a/d/e/@something").matches(), is(false));
+        assertThat(expr.matcher("/a/b/b2/b3/d/e/@something").matches(), is(false));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithFilenameLikeWildcardSelection() {
+        expr = PathExpression.compile("/a/*.txt[@something]");
+        assertThat(expr.matcher("/a/b.txt/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b.txt/@something").getInputPath(), is("/a/b.txt/@something"));
+        assertThat(expr.matcher("/a/b.txt/@something").getSelectedNodePath(), is("/a/b.txt"));
+        assertThat(expr.matcher("/a/b.txt/@something").groupCount(), is(0));
+        assertThat(expr.matcher("/a/b.tx/@something").matches(), is(false));
+
+        expr = PathExpression.compile("/a/*.txt/c[@something]");
+        assertThat(expr.matcher("/a/b.txt/c/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b.txt/c/@something").getInputPath(), is("/a/b.txt/c/@something"));
+        assertThat(expr.matcher("/a/b.txt/c/@something").getSelectedNodePath(), is("/a/b.txt/c"));
+        assertThat(expr.matcher("/a/b.txt/c/@something").groupCount(), is(0));
+        assertThat(expr.matcher("/a/b.tx/c/@something").matches(), is(false));
+
+        expr = PathExpression.compile("//*.txt[*]/c[@something]");
+        assertThat(expr.matcher("/a/b.txt/c/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b.txt/c/@something").getInputPath(), is("/a/b.txt/c/@something"));
+        assertThat(expr.matcher("/a/b.txt/c/@something").getSelectedNodePath(), is("/a/b.txt/c"));
+        assertThat(expr.matcher("/a/b.txt/c/@something").groupCount(), is(0));
+        assertThat(expr.matcher("/a/b.tx/c/@something").matches(), is(false));
+
+        assertThat(expr.matcher("/z/a/b.txt/c/@something").matches(), is(true));
+        assertThat(expr.matcher("/z/a/b.txt/c/@something").getInputPath(), is("/z/a/b.txt/c/@something"));
+        assertThat(expr.matcher("/z/a/b.txt/c/@something").getSelectedNodePath(), is("/z/a/b.txt/c"));
+        assertThat(expr.matcher("/z/a/b.txt/c/@something").groupCount(), is(0));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithSegmentWildcardSelection() {
+        expr = PathExpression.compile("/a//c[d/e/@something]");
+        assertThat(expr.matcher("/a/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/c/d/e/@something").getInputPath(), is("/a/c/d/e/@something"));
+        assertThat(expr.matcher("/a/c/d/e/@something").getSelectedNodePath(), is("/a/c"));
+        assertThat(expr.matcher("/a/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/rt/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/rt/c/d/e/@something").getInputPath(), is("/a/rt/c/d/e/@something"));
+        assertThat(expr.matcher("/a/rt/c/d/e/@something").getSelectedNodePath(), is("/a/rt/c"));
+        assertThat(expr.matcher("/a/rt/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/r/s/t/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/r/s/t/c/d/e/@something").getInputPath(), is("/a/r/s/t/c/d/e/@something"));
+        assertThat(expr.matcher("/a/r/s/t/c/d/e/@something").getSelectedNodePath(), is("/a/r/s/t/c"));
+        assertThat(expr.matcher("/a/r/s/t/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something").getInputPath(), is("/a/r[1]/s[2]/t[33]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something").getSelectedNodePath(), is("/a/r[1]/s[2]/t[33]/c"));
+        assertThat(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a[3]/c/d/e/@something").matches(), is(false));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithSegmentWildcardAtEnd() {
+        expr = PathExpression.compile("/a/b/c//");
+        assertThat(expr.matcher("/a/b/c").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c").getInputPath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b/c/d").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d").getInputPath(), is("/a/b/c/d"));
+        assertThat(expr.matcher("/a/b/c/d").getSelectedNodePath(), is("/a/b/c/d"));
+        assertThat(expr.matcher("/a/b/c/d").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b/c/a").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/a").getInputPath(), is("/a/b/c/a"));
+        assertThat(expr.matcher("/a/b/c/a").getSelectedNodePath(), is("/a/b/c/a"));
+        assertThat(expr.matcher("/a/b/c/a").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b/c/d/e/f/g/h").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/e/f/g/h").getInputPath(), is("/a/b/c/d/e/f/g/h"));
+        assertThat(expr.matcher("/a/b/c/d/e/f/g/h").getSelectedNodePath(), is("/a/b/c/d/e/f/g/h"));
+        assertThat(expr.matcher("/a/b/c/d/e/f/g/h").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b").matches(), is(false));
+        assertThat(expr.matcher("/a/b/d").matches(), is(false));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithExtraLargeSegmentWildcardAtEnd() {
+        expr = PathExpression.compile("/a/b/c////");
+        assertThat(expr.matcher("/a/b/c").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c").getInputPath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c").groupCount(), is(0));
+
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithIndexesInSelectionPaths() {
+        expr = PathExpression.compile("/a/b[2,3,4,5]/c/d/e[@something]");
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c/d/e"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getInputPath(), is("/a/b[3]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getSelectedNodePath(), is("/a/b[3]/c/d/e"));
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getInputPath(), is("/a/b[4]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getSelectedNodePath(), is("/a/b[4]/c/d/e"));
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getInputPath(), is("/a/b[5]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getSelectedNodePath(), is("/a/b[5]/c/d/e"));
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(false));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(false));
+        assertThat(expr.matcher("/a[1]/b/c/d/e/@something").matches(), is(false));
+
+        expr = PathExpression.compile("/a/b[0,2,3,4,5]/c/d/e[@something]");
+        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c/d/e"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c/d/e"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getInputPath(), is("/a/b[3]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getSelectedNodePath(), is("/a/b[3]/c/d/e"));
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getInputPath(), is("/a/b[4]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getSelectedNodePath(), is("/a/b[4]/c/d/e"));
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getInputPath(), is("/a/b[5]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getSelectedNodePath(), is("/a/b[5]/c/d/e"));
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[0]/c/d/e/@something").matches(), is(false));
+        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(false));
+        assertThat(expr.matcher("/a[1]/b/c/d/e/@something").matches(), is(false));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithAnyIndexesInSelectionPaths() {
+        expr = PathExpression.compile("/a/b[*]/c[]/d/e[@something]");
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getInputPath(), is("/a/b[2]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").getSelectedNodePath(), is("/a/b[2]/c/d/e"));
+        assertThat(expr.matcher("/a/b[2]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getInputPath(), is("/a/b[3]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").getSelectedNodePath(), is("/a/b[3]/c/d/e"));
+        assertThat(expr.matcher("/a/b[3]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getInputPath(), is("/a/b[4]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").getSelectedNodePath(), is("/a/b[4]/c/d/e"));
+        assertThat(expr.matcher("/a/b[4]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getInputPath(), is("/a/b[5]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").getSelectedNodePath(), is("/a/b[5]/c/d/e"));
+        assertThat(expr.matcher("/a/b[5]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").getInputPath(), is("/a/b[1]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").getSelectedNodePath(), is("/a/b[1]/c/d/e"));
+        assertThat(expr.matcher("/a/b[1]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[6]/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[6]/c/d/e/@something").getInputPath(), is("/a/b[6]/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b[6]/c/d/e/@something").getSelectedNodePath(), is("/a/b[6]/c/d/e"));
+        assertThat(expr.matcher("/a/b[6]/c/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b[6]/c[1]/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b[6]/c[1]/d/e/@something").getInputPath(), is("/a/b[6]/c[1]/d/e/@something"));
+        assertThat(expr.matcher("/a/b[6]/c[1]/d/e/@something").getSelectedNodePath(), is("/a/b[6]/c[1]/d/e"));
+        assertThat(expr.matcher("/a/b[6]/c[1]/d/e/@something").groupCount(), is(0));
+
+        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c/d/e"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(0));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithRepositoryInSelectionPath() {
+        expr = PathExpression.compile("reposA:/a/b/c[d/e/@something]");
+        assertThat(expr.matcher("reposA:/a/b/c/d/e/@something").matches(), is(true));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithNamedGroups() {
+        expr = PathExpression.compile("/a(//c)[d/e/@something]");
+        assertThat(expr.matcher("/a/b/c/d/e/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getInputPath(), is("/a/b/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").groupCount(), is(1));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").group(0), is("/a/b/c/d/e/@something"));
+        assertThat(expr.matcher("/a/b/c/d/e/@something").group(1), is("/b/c"));
+
+        expr = PathExpression.compile("/a(/(b|c|d|)/e)[f/g/@something]");
+        assertThat(expr.matcher("/a/b/e/f/g/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/e/f/g/@something").getInputPath(), is("/a/b/e/f/g/@something"));
+        assertThat(expr.matcher("/a/b/e/f/g/@something").getSelectedNodePath(), is("/a/b/e"));
+        assertThat(expr.matcher("/a/b/e/f/g/@something").groupCount(), is(2));
+        assertThat(expr.matcher("/a/b/e/f/g/@something").group(0), is("/a/b/e/f/g/@something"));
+        assertThat(expr.matcher("/a/b/e/f/g/@something").group(1), is("/b/e"));
+        assertThat(expr.matcher("/a/b/e/f/g/@something").group(2), is("b"));
+
+        assertThat(expr.matcher("/a/c/e/f/g/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/c/e/f/g/@something").getInputPath(), is("/a/c/e/f/g/@something"));
+        assertThat(expr.matcher("/a/c/e/f/g/@something").getSelectedNodePath(), is("/a/c/e"));
+        assertThat(expr.matcher("/a/c/e/f/g/@something").groupCount(), is(2));
+        assertThat(expr.matcher("/a/c/e/f/g/@something").group(0), is("/a/c/e/f/g/@something"));
+        assertThat(expr.matcher("/a/c/e/f/g/@something").group(1), is("/c/e"));
+        assertThat(expr.matcher("/a/c/e/f/g/@something").group(2), is("c"));
+
+        assertThat(expr.matcher("/a/d/e/f/g/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/d/e/f/g/@something").getInputPath(), is("/a/d/e/f/g/@something"));
+        assertThat(expr.matcher("/a/d/e/f/g/@something").getSelectedNodePath(), is("/a/d/e"));
+        assertThat(expr.matcher("/a/d/e/f/g/@something").groupCount(), is(2));
+        assertThat(expr.matcher("/a/d/e/f/g/@something").group(0), is("/a/d/e/f/g/@something"));
+        assertThat(expr.matcher("/a/d/e/f/g/@something").group(1), is("/d/e"));
+        assertThat(expr.matcher("/a/d/e/f/g/@something").group(2), is("d"));
+
+        assertThat(expr.matcher("/a/e/f/g/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/e/f/g/@something").getInputPath(), is("/a/e/f/g/@something"));
+        assertThat(expr.matcher("/a/e/f/g/@something").getSelectedNodePath(), is("/a/e"));
+        assertThat(expr.matcher("/a/e/f/g/@something").groupCount(), is(2));
+        assertThat(expr.matcher("/a/e/f/g/@something").group(0), is("/a/e/f/g/@something"));
+        assertThat(expr.matcher("/a/e/f/g/@something").group(1), is("/e"));
+        assertThat(expr.matcher("/a/e/f/g/@something").group(2), is(nullValue()));
+
+        assertThat(expr.matcher("/a/t/e/f/g/@something").matches(), is(false));
+
+        expr = PathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something]");
+        assertThat(expr.matcher("/a/b/c/d/f/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").getInputPath(), is("/a/b/c/d/f/@something"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").groupCount(), is(3));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").group(0), is("/a/b/c/d/f/@something"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").group(1), is("b/c"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").group(2), is("d"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").group(3), is("f"));
+
+        assertThat(expr.matcher("/a/b/c/e/f/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/e/f/@something").getInputPath(), is("/a/b/c/e/f/@something"));
+        assertThat(expr.matcher("/a/b/c/e/f/@something").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c/e/f/@something").groupCount(), is(3));
+        assertThat(expr.matcher("/a/b/c/e/f/@something").group(0), is("/a/b/c/e/f/@something"));
+        assertThat(expr.matcher("/a/b/c/e/f/@something").group(1), is("b/c"));
+        assertThat(expr.matcher("/a/b/c/e/f/@something").group(2), is("e"));
+        assertThat(expr.matcher("/a/b/c/e/f/@something").group(3), is("f"));
+
+        assertThat(expr.matcher("/a/b/c/d/g/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/g/@something").getInputPath(), is("/a/b/c/d/g/@something"));
+        assertThat(expr.matcher("/a/b/c/d/g/@something").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c/d/g/@something").groupCount(), is(3));
+        assertThat(expr.matcher("/a/b/c/d/g/@something").group(0), is("/a/b/c/d/g/@something"));
+        assertThat(expr.matcher("/a/b/c/d/g/@something").group(1), is("b/c"));
+        assertThat(expr.matcher("/a/b/c/d/g/@something").group(2), is("d"));
+        assertThat(expr.matcher("/a/b/c/d/g/@something").group(3), is("g"));
+
+        assertThat(expr.matcher("/a/b/c/e/g/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/e/g/@something").getInputPath(), is("/a/b/c/e/g/@something"));
+        assertThat(expr.matcher("/a/b/c/e/g/@something").getSelectedNodePath(), is("/a/b/c"));
+        assertThat(expr.matcher("/a/b/c/e/g/@something").groupCount(), is(3));
+        assertThat(expr.matcher("/a/b/c/e/g/@something").group(0), is("/a/b/c/e/g/@something"));
+        assertThat(expr.matcher("/a/b/c/e/g/@something").group(1), is("b/c"));
+        assertThat(expr.matcher("/a/b/c/e/g/@something").group(2), is("e"));
+        assertThat(expr.matcher("/a/b/c/e/g/@something").group(3), is("g"));
+
+        expr = PathExpression.compile("/a/(b/c)/(d|e)/(f|g)/@something");
+        assertThat(expr.matcher("/a/b/c/d/f/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").getInputPath(), is("/a/b/c/d/f/@something"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").getSelectedNodePath(), is("/a/b/c/d/f"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").groupCount(), is(3));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").group(0), is("/a/b/c/d/f/@something"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").group(1), is("b/c"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").group(2), is("d"));
+        assertThat(expr.matcher("/a/b/c/d/f/@something").group(3), is("f"));
+
+        assertThat(expr.matcher("/a/b/c/e/f/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/d/g/@something").matches(), is(true));
+        assertThat(expr.matcher("/a/b/c/e/g/@something").matches(), is(true));
+    }
+
+    @Test
+    public void shouldMatchExpressionWithFilenamePatternAndChildProperty() {
+        expr = PathExpression.compile("//(*.(jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data]");
+        assertThat(expr.matcher("/a/b/caution.png/jcr:content/@jcr:data").matches(), is(true));
+    }
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/PathExpressionTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/StringValueComparatorTest.java (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/StringValueComparatorTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/StringValueComparatorTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/StringValueComparatorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import org.jboss.dna.graph.property.ValueComparators;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class StringValueComparatorTest extends AbstractValueComparatorsTest<String> {
+
+    public StringValueComparatorTest() {
+        super(ValueComparators.STRING_COMPARATOR, "valid value 1", "Valid valid 2");
+    }
+
+    @Test
+    public void shouldBeCaseInsensitive() {
+        assertThat(comparator.compare(validNonNullValues[0].toUpperCase(), validNonNullValues[0].toLowerCase()), is(not(0)));
+    }
+
+    @Test
+    public void shouldMatchStringCompareToMethod() {
+        assertThat(comparator.compare(validNonNullValues[0], validNonNullValues[1]), is(validNonNullValues[0].compareTo(validNonNullValues[1])));
+        assertThat(comparator.compare(validNonNullValues[1], validNonNullValues[0]), is(validNonNullValues[1].compareTo(validNonNullValues[0])));
+        assertThat(comparator.compare(validNonNullValues[1], validNonNullValues[1]), is(validNonNullValues[1].compareTo(validNonNullValues[1])));
+        assertThat(comparator.compare(validNonNullValues[0], validNonNullValues[0]), is(validNonNullValues[0].compareTo(validNonNullValues[0])));
+    }
+
+    @Test
+    public void shouldSortValues() {
+        assertThat(getSortedValues(false), hasItems(validNonNullValues[0], validNonNullValues[1]));
+    }
+
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/StringValueComparatorTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic)

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractPathTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/AbstractPathTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractPathTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,232 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
-import java.util.Iterator;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Path.Segment;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public abstract class AbstractPathTest {
-
-    protected Path path;
-
-    @Before
-    public void beforeEach() {
-    }
-
-    @Test
-    public void shouldReturnNoAncestorForRoot() {
-        if (path.isRoot()) assertThat(path.getParent(), nullValue());
-    }
-
-    @Test
-    public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
-        assertThat(path.getAncestor(path.size()).isRoot(), is(true));
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotAllowAncestorDegreeLargerThanSize() {
-        path.getAncestor(path.size() + 1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNegativeAncestorDegree() {
-        path.getAncestor(-1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowGettingAncestorOfNullPath() {
-        path.getCommonAncestor(null);
-    }
-
-    @Test
-    public void shouldNotConsiderNodeToBeAncestorOfItself() {
-        assertThat(path.isAncestorOf(path), is(false));
-    }
-
-    @Test
-    public void shouldNotConsiderNodeToBeDecendantOfItself() {
-        assertThat(path.isDecendantOf(path), is(false));
-    }
-
-    @Test
-    public void shouldConsiderANodeToHaveSameAncestorAsItself() {
-        assertThat(path.hasSameAncestor(path), is(true));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailForSameAncestorOfNullPath() {
-        path.hasSameAncestor(null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailForDecendantOfNullPath() {
-        path.isDecendantOf(null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailForAtOrAboveNullPath() {
-        path.isAtOrAbove(null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailForAtOrBelowNullPath() {
-        path.isAtOrBelow(null);
-    }
-
-    @Test
-    public void shouldConsiderNodeToBeAtOrAboveItself() {
-        assertThat(path.isAtOrAbove(path), is(true));
-    }
-
-    @Test
-    public void shouldConsiderNodeToBeAtOrBelowItself() {
-        assertThat(path.isAtOrBelow(path), is(true));
-    }
-
-    @Test
-    public void shouldReturnNullForLastSegmentOfRoot() {
-        if (path.isRoot()) {
-            assertThat(path.getLastSegment(), is(nullValue()));
-        }
-    }
-
-    @Test
-    public void shouldNeverReturnNullForLastSegmentOfNonRoot() {
-        if (!path.isRoot()) {
-            assertThat(path.getLastSegment(), is(notNullValue()));
-        }
-    }
-
-    @Test
-    public void shouldReturnNonNullIteratorOverSegments() {
-        assertThat(path.iterator(), is(notNullValue()));
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSegmentAtIndexEqualToSize() {
-        path.getSegment(path.size());
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailToReturnSegmentAtNegativeIndex() {
-        path.getSegment(-1);
-    }
-
-    @Test
-    public void shouldReturnNonNullSegmentsArray() {
-        assertThat(path.getSegmentsArray(), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldReturnNonNullSegmentsList() {
-        assertThat(path.getSegmentsList(), is(notNullValue()));
-    }
-
-    @Test( expected = UnsupportedOperationException.class )
-    public void shouldReturnImmutableSegmentsList() {
-        path.getSegmentsList().add(null);
-    }
-
-    @Test( expected = UnsupportedOperationException.class )
-    public void shouldReturnImmutableSegmentsIterator() {
-        Iterator<Segment> iter = path.iterator();
-        if (iter.hasNext()) {
-            iter.remove();
-        }
-    }
-
-    @Test
-    public void shouldAlwaysReturnNonNullStringForGetString() {
-        assertThat(path.getString(), is(notNullValue()));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNullNamespaceRegistry() {
-        path.getString((NamespaceRegistry)null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNullNamespaceRegistryWithNonNullTextEncoder() {
-        TextEncoder encoder = mock(TextEncoder.class);
-        path.getString((NamespaceRegistry)null, encoder);
-    }
-
-    @Test
-    public void shouldReturnSelfForSubpathStartingAtZero() {
-        assertThat(path.subpath(0), is(sameInstance(path)));
-        assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowSubpathStartingAtNegativeNumber() {
-        path.subpath(-1);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldNotAllowSubpathStartingAtIndexEqualToSize() {
-        if (path.isRoot()) path.subpath(1);
-        path.subpath(path.size());
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldNotAllowSubpathEndingAtMoreThanSize() {
-        path.subpath(0, path.size() + 1);
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotFindRelativePathToAnotherRelativePath() {
-        Path other = mock(Path.class);
-        stub(other.isAbsolute()).toReturn(false);
-        path.relativeTo(other);
-    }
-
-    @Test
-    public void shouldAlwaysConsiderPathEqualToItself() {
-        Path other = mock(Path.class);
-        stub(other.isRoot()).toReturn(true);
-        assertThat(path.compareTo(path), is(0));
-        assertThat(path.equals(path), is(true));
-    }
-
-    @Test
-    public void shouldAlwaysReturnNonNullToString() {
-        assertThat(path.toString(), is(notNullValue()));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractPathTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/AbstractPathTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractPathTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractPathTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,232 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import java.util.Iterator;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Path.Segment;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public abstract class AbstractPathTest {
+
+    protected Path path;
+
+    @Before
+    public void beforeEach() {
+    }
+
+    @Test
+    public void shouldReturnNoAncestorForRoot() {
+        if (path.isRoot()) assertThat(path.getParent(), nullValue());
+    }
+
+    @Test
+    public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
+        assertThat(path.getAncestor(path.size()).isRoot(), is(true));
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotAllowAncestorDegreeLargerThanSize() {
+        path.getAncestor(path.size() + 1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNegativeAncestorDegree() {
+        path.getAncestor(-1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowGettingAncestorOfNullPath() {
+        path.getCommonAncestor(null);
+    }
+
+    @Test
+    public void shouldNotConsiderNodeToBeAncestorOfItself() {
+        assertThat(path.isAncestorOf(path), is(false));
+    }
+
+    @Test
+    public void shouldNotConsiderNodeToBeDecendantOfItself() {
+        assertThat(path.isDecendantOf(path), is(false));
+    }
+
+    @Test
+    public void shouldConsiderANodeToHaveSameAncestorAsItself() {
+        assertThat(path.hasSameAncestor(path), is(true));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailForSameAncestorOfNullPath() {
+        path.hasSameAncestor(null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailForDecendantOfNullPath() {
+        path.isDecendantOf(null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailForAtOrAboveNullPath() {
+        path.isAtOrAbove(null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailForAtOrBelowNullPath() {
+        path.isAtOrBelow(null);
+    }
+
+    @Test
+    public void shouldConsiderNodeToBeAtOrAboveItself() {
+        assertThat(path.isAtOrAbove(path), is(true));
+    }
+
+    @Test
+    public void shouldConsiderNodeToBeAtOrBelowItself() {
+        assertThat(path.isAtOrBelow(path), is(true));
+    }
+
+    @Test
+    public void shouldReturnNullForLastSegmentOfRoot() {
+        if (path.isRoot()) {
+            assertThat(path.getLastSegment(), is(nullValue()));
+        }
+    }
+
+    @Test
+    public void shouldNeverReturnNullForLastSegmentOfNonRoot() {
+        if (!path.isRoot()) {
+            assertThat(path.getLastSegment(), is(notNullValue()));
+        }
+    }
+
+    @Test
+    public void shouldReturnNonNullIteratorOverSegments() {
+        assertThat(path.iterator(), is(notNullValue()));
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSegmentAtIndexEqualToSize() {
+        path.getSegment(path.size());
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailToReturnSegmentAtNegativeIndex() {
+        path.getSegment(-1);
+    }
+
+    @Test
+    public void shouldReturnNonNullSegmentsArray() {
+        assertThat(path.getSegmentsArray(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldReturnNonNullSegmentsList() {
+        assertThat(path.getSegmentsList(), is(notNullValue()));
+    }
+
+    @Test( expected = UnsupportedOperationException.class )
+    public void shouldReturnImmutableSegmentsList() {
+        path.getSegmentsList().add(null);
+    }
+
+    @Test( expected = UnsupportedOperationException.class )
+    public void shouldReturnImmutableSegmentsIterator() {
+        Iterator<Segment> iter = path.iterator();
+        if (iter.hasNext()) {
+            iter.remove();
+        }
+    }
+
+    @Test
+    public void shouldAlwaysReturnNonNullStringForGetString() {
+        assertThat(path.getString(), is(notNullValue()));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNullNamespaceRegistry() {
+        path.getString((NamespaceRegistry)null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNullNamespaceRegistryWithNonNullTextEncoder() {
+        TextEncoder encoder = mock(TextEncoder.class);
+        path.getString((NamespaceRegistry)null, encoder);
+    }
+
+    @Test
+    public void shouldReturnSelfForSubpathStartingAtZero() {
+        assertThat(path.subpath(0), is(sameInstance(path)));
+        assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowSubpathStartingAtNegativeNumber() {
+        path.subpath(-1);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldNotAllowSubpathStartingAtIndexEqualToSize() {
+        if (path.isRoot()) path.subpath(1);
+        path.subpath(path.size());
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldNotAllowSubpathEndingAtMoreThanSize() {
+        path.subpath(0, path.size() + 1);
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotFindRelativePathToAnotherRelativePath() {
+        Path other = mock(Path.class);
+        stub(other.isAbsolute()).toReturn(false);
+        path.relativeTo(other);
+    }
+
+    @Test
+    public void shouldAlwaysConsiderPathEqualToItself() {
+        Path other = mock(Path.class);
+        stub(other.isRoot()).toReturn(true);
+        assertThat(path.compareTo(path), is(0));
+        assertThat(path.equals(path), is(true));
+    }
+
+    @Test
+    public void shouldAlwaysReturnNonNullToString() {
+        assertThat(path.toString(), is(notNullValue()));
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/AbstractValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,202 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.UUID;
-import org.jboss.dna.common.text.NoOpEncoder;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.IoException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.basic.AbstractValueFactory;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class AbstractValueFactoryTest {
-
-    public static final TextDecoder CUSTOM_DECODER = new NoOpEncoder();
-
-    private static class MockFactory extends AbstractValueFactory<String> {
-
-        protected MockFactory( TextDecoder decoder,
-                               StringValueFactory stringValueFactory ) {
-            super(PropertyType.STRING, decoder, stringValueFactory);
-        }
-
-        public String create( String value ) {
-            return null;
-        }
-
-        public String create( String value,
-                              TextDecoder decoder ) {
-            return null;
-        }
-
-        public String create( int value ) {
-            return null;
-        }
-
-        public String create( long value ) {
-            return null;
-        }
-
-        public String create( boolean value ) {
-            return null;
-        }
-
-        public String create( float value ) {
-            return null;
-        }
-
-        public String create( double value ) {
-            return null;
-        }
-
-        public String create( BigDecimal value ) {
-            return null;
-        }
-
-        public String create( Calendar value ) {
-            return null;
-        }
-
-        public String create( Date value ) {
-            return null;
-        }
-
-        public String create( DateTime value ) throws ValueFormatException {
-            return null;
-        }
-
-        public String create( Name value ) {
-            return null;
-        }
-
-        public String create( Path value ) {
-            return null;
-        }
-
-        public String create( Reference value ) {
-            return null;
-        }
-
-        public String create( URI value ) {
-            return null;
-        }
-
-        public String create( UUID value ) {
-            return null;
-        }
-
-        public String create( byte[] value ) {
-            return null;
-        }
-
-        public String create( Binary value ) throws ValueFormatException, IoException {
-            return null;
-        }
-
-        public String create( InputStream stream,
-                              long approximateLength ) {
-            return null;
-        }
-
-        public String create( Reader reader,
-                              long approximateLength ) {
-            return null;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        protected String[] createEmptyArray( int length ) {
-            return new String[length];
-        }
-    }
-
-    private AbstractValueFactory<String> factory;
-
-    @Before
-    public void beforeEach() {
-        factory = new MockFactory(null, null);
-    }
-
-    @Test
-    public void shouldHaveDefaultEncoderIfNullPassedIntoConstructor() {
-        assertThat(factory.getDecoder(), is(notNullValue()));
-        assertThat(factory.getDecoder(), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
-    }
-
-    @Test
-    public void shouldReturnTextEncoderPassedIntoConstructor() {
-        factory = new MockFactory(CUSTOM_DECODER, null);
-        assertThat(factory.getDecoder(), is(notNullValue()));
-        assertThat(factory.getDecoder(), is(sameInstance(CUSTOM_DECODER)));
-    }
-
-    @Test
-    public void shouldReturnDefaultTextEncoderWhenNullPassedToGetEncoder() {
-        assertThat(factory.getDecoder(), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
-        assertThat(factory.getDecoder(null), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
-        assertThat(factory.getDecoder(CUSTOM_DECODER), is(sameInstance(CUSTOM_DECODER)));
-    }
-
-    @Test
-    public void shouldReturnSuppliedTextEncoderWhenNonNullPassedToGetEncoder() {
-        assertThat(factory.getDecoder(), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
-        assertThat(factory.getDecoder(null), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
-        assertThat(factory.getDecoder(CUSTOM_DECODER), is(sameInstance(CUSTOM_DECODER)));
-    }
-
-    @Test
-    public void shouldHaveNullStringValueFactoryIfNullPassedIntoConstructor() {
-        assertThat(factory.getStringValueFactory(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldHaveExpectedPropertyType() {
-        assertThat(factory.getPropertyType(), is(sameInstance(PropertyType.STRING)));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/AbstractValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/AbstractValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,202 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import org.jboss.dna.common.text.NoOpEncoder;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.IoException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.AbstractValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class AbstractValueFactoryTest {
+
+    public static final TextDecoder CUSTOM_DECODER = new NoOpEncoder();
+
+    private static class MockFactory extends AbstractValueFactory<String> {
+
+        protected MockFactory( TextDecoder decoder,
+                               StringValueFactory stringValueFactory ) {
+            super(PropertyType.STRING, decoder, stringValueFactory);
+        }
+
+        public String create( String value ) {
+            return null;
+        }
+
+        public String create( String value,
+                              TextDecoder decoder ) {
+            return null;
+        }
+
+        public String create( int value ) {
+            return null;
+        }
+
+        public String create( long value ) {
+            return null;
+        }
+
+        public String create( boolean value ) {
+            return null;
+        }
+
+        public String create( float value ) {
+            return null;
+        }
+
+        public String create( double value ) {
+            return null;
+        }
+
+        public String create( BigDecimal value ) {
+            return null;
+        }
+
+        public String create( Calendar value ) {
+            return null;
+        }
+
+        public String create( Date value ) {
+            return null;
+        }
+
+        public String create( DateTime value ) throws ValueFormatException {
+            return null;
+        }
+
+        public String create( Name value ) {
+            return null;
+        }
+
+        public String create( Path value ) {
+            return null;
+        }
+
+        public String create( Reference value ) {
+            return null;
+        }
+
+        public String create( URI value ) {
+            return null;
+        }
+
+        public String create( UUID value ) {
+            return null;
+        }
+
+        public String create( byte[] value ) {
+            return null;
+        }
+
+        public String create( Binary value ) throws ValueFormatException, IoException {
+            return null;
+        }
+
+        public String create( InputStream stream,
+                              long approximateLength ) {
+            return null;
+        }
+
+        public String create( Reader reader,
+                              long approximateLength ) {
+            return null;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected String[] createEmptyArray( int length ) {
+            return new String[length];
+        }
+    }
+
+    private AbstractValueFactory<String> factory;
+
+    @Before
+    public void beforeEach() {
+        factory = new MockFactory(null, null);
+    }
+
+    @Test
+    public void shouldHaveDefaultEncoderIfNullPassedIntoConstructor() {
+        assertThat(factory.getDecoder(), is(notNullValue()));
+        assertThat(factory.getDecoder(), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
+    }
+
+    @Test
+    public void shouldReturnTextEncoderPassedIntoConstructor() {
+        factory = new MockFactory(CUSTOM_DECODER, null);
+        assertThat(factory.getDecoder(), is(notNullValue()));
+        assertThat(factory.getDecoder(), is(sameInstance(CUSTOM_DECODER)));
+    }
+
+    @Test
+    public void shouldReturnDefaultTextEncoderWhenNullPassedToGetEncoder() {
+        assertThat(factory.getDecoder(), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
+        assertThat(factory.getDecoder(null), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
+        assertThat(factory.getDecoder(CUSTOM_DECODER), is(sameInstance(CUSTOM_DECODER)));
+    }
+
+    @Test
+    public void shouldReturnSuppliedTextEncoderWhenNonNullPassedToGetEncoder() {
+        assertThat(factory.getDecoder(), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
+        assertThat(factory.getDecoder(null), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
+        assertThat(factory.getDecoder(CUSTOM_DECODER), is(sameInstance(CUSTOM_DECODER)));
+    }
+
+    @Test
+    public void shouldHaveNullStringValueFactoryIfNullPassedIntoConstructor() {
+        assertThat(factory.getStringValueFactory(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldHaveExpectedPropertyType() {
+        assertThat(factory.getPropertyType(), is(sameInstance(PropertyType.STRING)));
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicNameTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,191 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.containsString;
-import org.jboss.dna.common.text.Jsr283Encoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class BasicNameTest {
-
-    private BasicNamespaceRegistry namespaceRegistry;
-    private Name name;
-    private String validNamespaceUri;
-    private String validLocalName;
-    private TextEncoder encoder;
-    private TextEncoder delimiterEncoder;
-    private String validNamespacePrefix;
-
-    @Before
-    public void beforeEach() {
-        this.validNamespacePrefix = DnaLexicon.Namespace.PREFIX;
-        this.validNamespaceUri = DnaLexicon.Namespace.URI;
-        this.validLocalName = "localPart";
-        this.name = new BasicName(validNamespaceUri, validLocalName);
-        this.encoder = Path.URL_ENCODER;
-        this.namespaceRegistry = new BasicNamespaceRegistry();
-        this.namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
-        this.delimiterEncoder = new TextEncoder() {
-            public String encode( String text ) {
-                if (":".equals(text)) return "\\:";
-                if ("{".equals(text)) return "\\{";
-                if ("}".equals(text)) return "\\}";
-                return text;
-            }
-        };
-    }
-
-    @Test
-    public void shouldAllowNullNamespaceUriInConstructorAndConvertToEmptyString() {
-        name = new BasicName(null, validLocalName);
-        assertThat(name.getNamespaceUri(), is(""));
-    }
-
-    @Test
-    public void shouldAllowEmptyNamespaceUriInConstructor() {
-        name = new BasicName("", validLocalName);
-        assertThat(name.getNamespaceUri(), is(""));
-    }
-
-    @Test
-    public void shouldTrimNamespaceUriInConstructor() {
-        name = new BasicName("  " + validNamespaceUri + "\t \t", validLocalName);
-        assertThat(name.getNamespaceUri(), is(validNamespaceUri.trim()));
-
-        name = new BasicName("  \t  \t", validLocalName);
-        assertThat(name.getNamespaceUri(), is(""));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNullLocalNameInConstructor() {
-        new BasicName(validNamespaceUri, null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldAllowEmptyLocalNameInConstructor() {
-        new BasicName(validNamespaceUri, "");
-    }
-
-    @Test
-    public void shouldAcceptLocalNameWithColon() {
-        validLocalName = "some:name:with:colons";
-        name = new BasicName(validNamespaceUri, validLocalName);
-        assertThat(name.getLocalName(), is(validLocalName));
-    }
-
-    @Test
-    public void shouldReturnSameHashCodeForNamesWithSameNamespaceUriAndLocalPart() {
-        Name other = new BasicName(name.getNamespaceUri(), name.getLocalName());
-        assertThat(name.hashCode(), is(other.hashCode()));
-    }
-
-    @Test
-    public void shouldConsiderNamesEqualIfTheyHaveTheSameNamespaceUriAndLocalPart() {
-        Name other = new BasicName(name.getNamespaceUri(), name.getLocalName());
-        assertThat(name.equals(other), is(true));
-        assertThat(name.compareTo(other), is(0));
-    }
-
-    @Test
-    public void shouldConsiderSameInstanceEqualToItself() {
-        assertThat(name.equals(name), is(true));
-        assertThat(name.compareTo(name), is(0));
-    }
-
-    @Test( expected = NullPointerException.class )
-    public void shouldNotSupportNullInCompareTo() {
-        name.compareTo(null);
-    }
-
-    @Test
-    public void shouldSupportNullInEquals() {
-        assertThat(name.equals(null), is(false));
-    }
-
-    @Test
-    public void shouldUseFullNamespaceUriInResultFromGetStringWithoutNamespaceRegistry() {
-        String encodedNamespaceUri = Path.DEFAULT_ENCODER.encode(validNamespaceUri);
-        String encodedLocalName = Path.DEFAULT_ENCODER.encode(validLocalName);
-        String result = name.getString();
-        assertThat(result, containsString(encodedNamespaceUri));
-        assertThat(result, containsString(encodedLocalName));
-        assertThat(result, is("{" + encodedNamespaceUri + "}" + encodedLocalName));
-    }
-
-    @Test
-    public void shouldEncodeColonInLocalNameAndNamespaceUriInResultFromGetStringWithoutNamespaceRegistry() {
-        validLocalName = "some:name:with:colons";
-        name = new BasicName(validNamespaceUri, validLocalName);
-        String encodedNamespaceUri = encoder.encode(validNamespaceUri);
-        String encodedLocalName = encoder.encode(validLocalName);
-        String result = name.getString(encoder);
-        assertThat(result, is("{" + encodedNamespaceUri + "}" + encodedLocalName));
-        assertThat(encodedNamespaceUri, is("http%3a%2f%2fwww.jboss.org%2fdna"));
-        assertThat(encodedLocalName, is("some%3aname%3awith%3acolons"));
-    }
-
-    @Test
-    public void shouldUseNamespacePrefixInResultFromGetStringWithNamespaceRegistry() {
-        String result = name.getString(namespaceRegistry, encoder);
-        assertThat(result, is("dna:" + validLocalName));
-
-        validLocalName = "some:name:with:colons";
-        name = new BasicName(validNamespaceUri, validLocalName);
-        result = name.getString(namespaceRegistry, encoder);
-        assertThat(result, is("dna:some%3aname%3awith%3acolons"));
-    }
-
-    @Test
-    public void shouldNotIncludeNamespacePrefixOrColonInResultFromGetStringWithNamespaceRegistry() {
-        validNamespaceUri = namespaceRegistry.getDefaultNamespaceUri();
-        name = new BasicName(validNamespaceUri, validLocalName);
-        String result = name.getString(namespaceRegistry, encoder);
-        assertThat(result, is(validLocalName));
-        result = name.getString(namespaceRegistry); // default encoder
-        assertThat(result, is(validLocalName));
-
-        validLocalName = "some:name:with:colons";
-        name = new BasicName(validNamespaceUri, validLocalName);
-        result = name.getString(namespaceRegistry, encoder);
-        assertThat(result, is("some:name:with:colons"));
-    }
-
-    @Test
-    public void shouldUseDelimiterEncoderToEncodeDelimiterBetweenPrefixAndLocalPart() {
-        encoder = new Jsr283Encoder();
-        name = new BasicName(DnaLexicon.Namespace.URI, "some:name:with:colons");
-        assertThat(name.getString(namespaceRegistry, encoder, delimiterEncoder), is("dna\\:some\uf03aname\uf03awith\uf03acolons"));
-        assertThat(name.getString(null, encoder, delimiterEncoder), is("\\{" + encoder.encode(DnaLexicon.Namespace.URI)
-                                                                       + "\\}some\uf03aname\uf03awith\uf03acolons"));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicNameTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,193 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import org.jboss.dna.common.text.Jsr283Encoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class BasicNameTest {
+
+    private BasicNamespaceRegistry namespaceRegistry;
+    private Name name;
+    private String validNamespaceUri;
+    private String validLocalName;
+    private TextEncoder encoder;
+    private TextEncoder delimiterEncoder;
+    private String validNamespacePrefix;
+
+    @Before
+    public void beforeEach() {
+        this.validNamespacePrefix = DnaLexicon.Namespace.PREFIX;
+        this.validNamespaceUri = DnaLexicon.Namespace.URI;
+        this.validLocalName = "localPart";
+        this.name = new BasicName(validNamespaceUri, validLocalName);
+        this.encoder = Path.URL_ENCODER;
+        this.namespaceRegistry = new BasicNamespaceRegistry();
+        this.namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
+        this.delimiterEncoder = new TextEncoder() {
+            public String encode( String text ) {
+                if (":".equals(text)) return "\\:";
+                if ("{".equals(text)) return "\\{";
+                if ("}".equals(text)) return "\\}";
+                return text;
+            }
+        };
+    }
+
+    @Test
+    public void shouldAllowNullNamespaceUriInConstructorAndConvertToEmptyString() {
+        name = new BasicName(null, validLocalName);
+        assertThat(name.getNamespaceUri(), is(""));
+    }
+
+    @Test
+    public void shouldAllowEmptyNamespaceUriInConstructor() {
+        name = new BasicName("", validLocalName);
+        assertThat(name.getNamespaceUri(), is(""));
+    }
+
+    @Test
+    public void shouldTrimNamespaceUriInConstructor() {
+        name = new BasicName("  " + validNamespaceUri + "\t \t", validLocalName);
+        assertThat(name.getNamespaceUri(), is(validNamespaceUri.trim()));
+
+        name = new BasicName("  \t  \t", validLocalName);
+        assertThat(name.getNamespaceUri(), is(""));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNullLocalNameInConstructor() {
+        new BasicName(validNamespaceUri, null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldAllowEmptyLocalNameInConstructor() {
+        new BasicName(validNamespaceUri, "");
+    }
+
+    @Test
+    public void shouldAcceptLocalNameWithColon() {
+        validLocalName = "some:name:with:colons";
+        name = new BasicName(validNamespaceUri, validLocalName);
+        assertThat(name.getLocalName(), is(validLocalName));
+    }
+
+    @Test
+    public void shouldReturnSameHashCodeForNamesWithSameNamespaceUriAndLocalPart() {
+        Name other = new BasicName(name.getNamespaceUri(), name.getLocalName());
+        assertThat(name.hashCode(), is(other.hashCode()));
+    }
+
+    @Test
+    public void shouldConsiderNamesEqualIfTheyHaveTheSameNamespaceUriAndLocalPart() {
+        Name other = new BasicName(name.getNamespaceUri(), name.getLocalName());
+        assertThat(name.equals(other), is(true));
+        assertThat(name.compareTo(other), is(0));
+    }
+
+    @Test
+    public void shouldConsiderSameInstanceEqualToItself() {
+        assertThat(name.equals(name), is(true));
+        assertThat(name.compareTo(name), is(0));
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void shouldNotSupportNullInCompareTo() {
+        name.compareTo(null);
+    }
+
+    @Test
+    public void shouldSupportNullInEquals() {
+        assertThat(name.equals(null), is(false));
+    }
+
+    @Test
+    public void shouldUseFullNamespaceUriInResultFromGetStringWithoutNamespaceRegistry() {
+        String encodedNamespaceUri = Path.DEFAULT_ENCODER.encode(validNamespaceUri);
+        String encodedLocalName = Path.DEFAULT_ENCODER.encode(validLocalName);
+        String result = name.getString();
+        assertThat(result, containsString(encodedNamespaceUri));
+        assertThat(result, containsString(encodedLocalName));
+        assertThat(result, is("{" + encodedNamespaceUri + "}" + encodedLocalName));
+    }
+
+    @Test
+    public void shouldEncodeColonInLocalNameAndNamespaceUriInResultFromGetStringWithoutNamespaceRegistry() {
+        validLocalName = "some:name:with:colons";
+        name = new BasicName(validNamespaceUri, validLocalName);
+        String encodedNamespaceUri = encoder.encode(validNamespaceUri);
+        String encodedLocalName = encoder.encode(validLocalName);
+        String result = name.getString(encoder);
+        assertThat(result, is("{" + encodedNamespaceUri + "}" + encodedLocalName));
+        assertThat(encodedNamespaceUri, is("http%3a%2f%2fwww.jboss.org%2fdna"));
+        assertThat(encodedLocalName, is("some%3aname%3awith%3acolons"));
+    }
+
+    @Test
+    public void shouldUseNamespacePrefixInResultFromGetStringWithNamespaceRegistry() {
+        String result = name.getString(namespaceRegistry, encoder);
+        assertThat(result, is("dna:" + validLocalName));
+
+        validLocalName = "some:name:with:colons";
+        name = new BasicName(validNamespaceUri, validLocalName);
+        result = name.getString(namespaceRegistry, encoder);
+        assertThat(result, is("dna:some%3aname%3awith%3acolons"));
+    }
+
+    @Test
+    public void shouldNotIncludeNamespacePrefixOrColonInResultFromGetStringWithNamespaceRegistry() {
+        validNamespaceUri = namespaceRegistry.getDefaultNamespaceUri();
+        name = new BasicName(validNamespaceUri, validLocalName);
+        String result = name.getString(namespaceRegistry, encoder);
+        assertThat(result, is(validLocalName));
+        result = name.getString(namespaceRegistry); // default encoder
+        assertThat(result, is(validLocalName));
+
+        validLocalName = "some:name:with:colons";
+        name = new BasicName(validNamespaceUri, validLocalName);
+        result = name.getString(namespaceRegistry, encoder);
+        assertThat(result, is("some:name:with:colons"));
+    }
+
+    @Test
+    public void shouldUseDelimiterEncoderToEncodeDelimiterBetweenPrefixAndLocalPart() {
+        encoder = new Jsr283Encoder();
+        name = new BasicName(DnaLexicon.Namespace.URI, "some:name:with:colons");
+        assertThat(name.getString(namespaceRegistry, encoder, delimiterEncoder), is("dna\\:some\uf03aname\uf03awith\uf03acolons"));
+        assertThat(name.getString(null, encoder, delimiterEncoder), is("\\{" + encoder.encode(DnaLexicon.Namespace.URI)
+                                                                       + "\\}some\uf03aname\uf03awith\uf03acolons"));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicNamespaceRegistryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,184 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItem;
-import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class BasicNamespaceRegistryTest {
-
-    private String validNamespaceUri1;
-    private String validNamespaceUri2;
-    private String validNamespaceUri3;
-    private String validPrefix1;
-    private String validPrefix2;
-    private BasicNamespaceRegistry namespaceRegistry;
-
-    @Before
-    public void setUp() {
-        namespaceRegistry = new BasicNamespaceRegistry();
-        validNamespaceUri1 = "http://www.jboss.org/dna/2";
-        validNamespaceUri2 = "http://acme.com/something";
-        validNamespaceUri3 = "http://www.redhat.com";
-        validPrefix1 = "dna";
-        validPrefix2 = "acme";
-    }
-
-    @Test
-    public void shouldReturnNullForNamespaceUriIfPrefixIsNotRegistered() {
-        assertThat(namespaceRegistry.getNamespaceForPrefix("notfound"), is(nullValue()));
-        // now register some namespaces ...
-        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
-        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
-        assertThat(namespaceRegistry.getNamespaceForPrefix("notfound"), is(nullValue()));
-    }
-
-    @Test
-    public void shouldReturnNamespaceUriForPrefixThatIsRegistered() {
-        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
-        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
-        assertThat(namespaceRegistry.getNamespaceForPrefix(validPrefix1), is(validNamespaceUri1));
-        assertThat(namespaceRegistry.getNamespaceForPrefix(validPrefix2), is(validNamespaceUri2));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNullPrefixParameterWhenGettingNamespaceUri() {
-        namespaceRegistry.getNamespaceForPrefix(null);
-    }
-
-    @Test
-    public void shouldReturnNullForPrefixIfNamespaceUriIsNotRegistered() {
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(nullValue()));
-        // now register some namespaces ...
-        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
-        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(nullValue()));
-    }
-
-    @Test
-    public void shouldGeneratePrefixIfNamespaceUriIsNotRegistered() {
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(nullValue()));
-        // Now get the generated prefix ...
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, true), is("ns001"));
-        // Change the template ...
-        namespaceRegistry.setGeneratedPrefixTemplate("xyz0000abc");
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, true), is("xyz0002abc"));
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, true), is("xyz0002abc"));
-        // Change the template again ...
-        namespaceRegistry.setGeneratedPrefixTemplate("xyz####abc");
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri1, true), is("xyz3abc"));
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri1, true), is("xyz3abc"));
-    }
-
-    @Test
-    public void shouldReturnPrefixForNamespaceUriThatIsRegistered() {
-        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
-        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri1, false), is(validPrefix1));
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, false), is(validPrefix2));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNullNamespaceUriParameterWhenGettingPrefix() {
-        namespaceRegistry.getPrefixForNamespaceUri(null, false);
-    }
-
-    @Test
-    public void shouldAlwaysHaveDefaultNamespaceRegistered() {
-        assertThat(namespaceRegistry.getDefaultNamespaceUri(), is(notNullValue()));
-        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
-        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
-        assertThat(namespaceRegistry.getDefaultNamespaceUri(), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldReturnNonNullDefaultNamespaceUriWhenThereAreNamespacesRegisteredIncludineOneWithZeroLengthPrefix() {
-        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
-        namespaceRegistry.register("", validNamespaceUri2);
-        assertThat(namespaceRegistry.getDefaultNamespaceUri(), is(validNamespaceUri2));
-        assertThat(namespaceRegistry.getNamespaceForPrefix(""), is(validNamespaceUri2));
-        assertThat(namespaceRegistry.getRegisteredNamespaceUris(), hasItem(validNamespaceUri2));
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, false), is(""));
-    }
-
-    @Test
-    public void shouldNotFindRegisteredNamespaceIfNamespaceNotRegistered() {
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(false));
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(false));
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri3), is(false));
-        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
-        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(true));
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(true));
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri3), is(false));
-    }
-
-    @Test
-    public void shouldFindRegisteredNamespace() {
-        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
-        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(true));
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(true));
-    }
-
-    @Test
-    public void shouldBeAbleToCopyNamespacesToAnotherRegistry() {
-        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
-        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
-        namespaceRegistry.register("", validNamespaceUri3);
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(true));
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(true));
-        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri3), is(true));
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri1, false), is(validPrefix1));
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, false), is(validPrefix2));
-        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(""));
-        assertThat(namespaceRegistry.getNamespaceForPrefix(validPrefix1), is(validNamespaceUri1));
-        assertThat(namespaceRegistry.getNamespaceForPrefix(validPrefix2), is(validNamespaceUri2));
-        assertThat(namespaceRegistry.getNamespaceForPrefix(""), is(validNamespaceUri3));
-
-        BasicNamespaceRegistry newRegistry = new BasicNamespaceRegistry();
-        for (String uri : this.namespaceRegistry.getRegisteredNamespaceUris()) {
-            String prefix = this.namespaceRegistry.getPrefixForNamespaceUri(uri, false);
-            newRegistry.register(prefix, uri);
-        }
-        assertThat(newRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(true));
-        assertThat(newRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(true));
-        assertThat(newRegistry.isRegisteredNamespaceUri(validNamespaceUri3), is(true));
-        assertThat(newRegistry.getPrefixForNamespaceUri(validNamespaceUri1, false), is(validPrefix1));
-        assertThat(newRegistry.getPrefixForNamespaceUri(validNamespaceUri2, false), is(validPrefix2));
-        assertThat(newRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(""));
-        assertThat(newRegistry.getNamespaceForPrefix(validPrefix1), is(validNamespaceUri1));
-        assertThat(newRegistry.getNamespaceForPrefix(validPrefix2), is(validNamespaceUri2));
-        assertThat(newRegistry.getNamespaceForPrefix(""), is(validNamespaceUri3));
-
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicNamespaceRegistryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceRegistryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,184 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItem;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicNamespaceRegistryTest {
+
+    private String validNamespaceUri1;
+    private String validNamespaceUri2;
+    private String validNamespaceUri3;
+    private String validPrefix1;
+    private String validPrefix2;
+    private BasicNamespaceRegistry namespaceRegistry;
+
+    @Before
+    public void setUp() {
+        namespaceRegistry = new BasicNamespaceRegistry();
+        validNamespaceUri1 = "http://www.jboss.org/dna/2";
+        validNamespaceUri2 = "http://acme.com/something";
+        validNamespaceUri3 = "http://www.redhat.com";
+        validPrefix1 = "dna";
+        validPrefix2 = "acme";
+    }
+
+    @Test
+    public void shouldReturnNullForNamespaceUriIfPrefixIsNotRegistered() {
+        assertThat(namespaceRegistry.getNamespaceForPrefix("notfound"), is(nullValue()));
+        // now register some namespaces ...
+        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
+        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
+        assertThat(namespaceRegistry.getNamespaceForPrefix("notfound"), is(nullValue()));
+    }
+
+    @Test
+    public void shouldReturnNamespaceUriForPrefixThatIsRegistered() {
+        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
+        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
+        assertThat(namespaceRegistry.getNamespaceForPrefix(validPrefix1), is(validNamespaceUri1));
+        assertThat(namespaceRegistry.getNamespaceForPrefix(validPrefix2), is(validNamespaceUri2));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNullPrefixParameterWhenGettingNamespaceUri() {
+        namespaceRegistry.getNamespaceForPrefix(null);
+    }
+
+    @Test
+    public void shouldReturnNullForPrefixIfNamespaceUriIsNotRegistered() {
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(nullValue()));
+        // now register some namespaces ...
+        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
+        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(nullValue()));
+    }
+
+    @Test
+    public void shouldGeneratePrefixIfNamespaceUriIsNotRegistered() {
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(nullValue()));
+        // Now get the generated prefix ...
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, true), is("ns001"));
+        // Change the template ...
+        namespaceRegistry.setGeneratedPrefixTemplate("xyz0000abc");
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, true), is("xyz0002abc"));
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, true), is("xyz0002abc"));
+        // Change the template again ...
+        namespaceRegistry.setGeneratedPrefixTemplate("xyz####abc");
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri1, true), is("xyz3abc"));
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri1, true), is("xyz3abc"));
+    }
+
+    @Test
+    public void shouldReturnPrefixForNamespaceUriThatIsRegistered() {
+        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
+        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri1, false), is(validPrefix1));
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, false), is(validPrefix2));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNullNamespaceUriParameterWhenGettingPrefix() {
+        namespaceRegistry.getPrefixForNamespaceUri(null, false);
+    }
+
+    @Test
+    public void shouldAlwaysHaveDefaultNamespaceRegistered() {
+        assertThat(namespaceRegistry.getDefaultNamespaceUri(), is(notNullValue()));
+        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
+        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
+        assertThat(namespaceRegistry.getDefaultNamespaceUri(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldReturnNonNullDefaultNamespaceUriWhenThereAreNamespacesRegisteredIncludineOneWithZeroLengthPrefix() {
+        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
+        namespaceRegistry.register("", validNamespaceUri2);
+        assertThat(namespaceRegistry.getDefaultNamespaceUri(), is(validNamespaceUri2));
+        assertThat(namespaceRegistry.getNamespaceForPrefix(""), is(validNamespaceUri2));
+        assertThat(namespaceRegistry.getRegisteredNamespaceUris(), hasItem(validNamespaceUri2));
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, false), is(""));
+    }
+
+    @Test
+    public void shouldNotFindRegisteredNamespaceIfNamespaceNotRegistered() {
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(false));
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(false));
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri3), is(false));
+        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
+        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(true));
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(true));
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri3), is(false));
+    }
+
+    @Test
+    public void shouldFindRegisteredNamespace() {
+        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
+        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(true));
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(true));
+    }
+
+    @Test
+    public void shouldBeAbleToCopyNamespacesToAnotherRegistry() {
+        namespaceRegistry.register(validPrefix1, validNamespaceUri1);
+        namespaceRegistry.register(validPrefix2, validNamespaceUri2);
+        namespaceRegistry.register("", validNamespaceUri3);
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(true));
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(true));
+        assertThat(namespaceRegistry.isRegisteredNamespaceUri(validNamespaceUri3), is(true));
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri1, false), is(validPrefix1));
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri2, false), is(validPrefix2));
+        assertThat(namespaceRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(""));
+        assertThat(namespaceRegistry.getNamespaceForPrefix(validPrefix1), is(validNamespaceUri1));
+        assertThat(namespaceRegistry.getNamespaceForPrefix(validPrefix2), is(validNamespaceUri2));
+        assertThat(namespaceRegistry.getNamespaceForPrefix(""), is(validNamespaceUri3));
+
+        BasicNamespaceRegistry newRegistry = new BasicNamespaceRegistry();
+        for (String uri : this.namespaceRegistry.getRegisteredNamespaceUris()) {
+            String prefix = this.namespaceRegistry.getPrefixForNamespaceUri(uri, false);
+            newRegistry.register(prefix, uri);
+        }
+        assertThat(newRegistry.isRegisteredNamespaceUri(validNamespaceUri1), is(true));
+        assertThat(newRegistry.isRegisteredNamespaceUri(validNamespaceUri2), is(true));
+        assertThat(newRegistry.isRegisteredNamespaceUri(validNamespaceUri3), is(true));
+        assertThat(newRegistry.getPrefixForNamespaceUri(validNamespaceUri1, false), is(validPrefix1));
+        assertThat(newRegistry.getPrefixForNamespaceUri(validNamespaceUri2, false), is(validPrefix2));
+        assertThat(newRegistry.getPrefixForNamespaceUri(validNamespaceUri3, false), is(""));
+        assertThat(newRegistry.getNamespaceForPrefix(validPrefix1), is(validNamespaceUri1));
+        assertThat(newRegistry.getNamespaceForPrefix(validPrefix2), is(validNamespaceUri2));
+        assertThat(newRegistry.getNamespaceForPrefix(""), is(validNamespaceUri3));
+
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicNamespaceTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,96 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class BasicNamespaceTest {
-
-    private BasicNamespace ns1;
-    private BasicNamespace ns2;
-    private BasicNamespace ns3;
-    private BasicNamespace ns4;
-    private BasicNamespace ns5;
-    private String validUri1;
-    private String validUri2;
-    private String validUri3;
-    private String validPrefix1;
-    private String validPrefix2;
-    private String validPrefix3;
-
-    @Before
-    public void beforeEach() {
-        validUri1 = "";
-        validUri2 = "http://www.example.com";
-        validUri3 = "http://www.acme.com";
-        validPrefix1 = "";
-        validPrefix2 = "a";
-        validPrefix3 = "b";
-        ns1 = new BasicNamespace(validPrefix1, validUri1);
-        ns2 = new BasicNamespace(validPrefix1, validUri2);
-        ns3 = new BasicNamespace(validPrefix2, validUri1);
-        ns4 = new BasicNamespace(validPrefix2, validUri2);
-        ns5 = new BasicNamespace(validPrefix3, validUri3);
-    }
-
-    @Test
-    public void shouldHaveSamePrefixPassedIntoConstructor() {
-        assertThat(ns1.getPrefix(), is(validPrefix1));
-        assertThat(ns2.getPrefix(), is(validPrefix1));
-        assertThat(ns3.getPrefix(), is(validPrefix2));
-        assertThat(ns4.getPrefix(), is(validPrefix2));
-        assertThat(ns5.getPrefix(), is(validPrefix3));
-    }
-
-    @Test
-    public void shouldHaveSameNamespaceUriPassedIntoConstructor() {
-        assertThat(ns1.getNamespaceUri(), is(validUri1));
-        assertThat(ns2.getNamespaceUri(), is(validUri2));
-        assertThat(ns3.getNamespaceUri(), is(validUri1));
-        assertThat(ns4.getNamespaceUri(), is(validUri2));
-        assertThat(ns5.getNamespaceUri(), is(validUri3));
-    }
-
-    @Test
-    public void shouldConsiderAsEqualAnyNamespacesWithSameUri() {
-        assertThat(ns1.equals(ns3), is(true));
-        assertThat(ns3.equals(ns1), is(true));
-        assertThat(ns2.equals(ns4), is(true));
-        assertThat(ns4.equals(ns2), is(true));
-        assertThat(ns5.equals(ns5), is(true));
-    }
-
-    @Test
-    public void shouldNotConsiderAsEqualAnyNamespacesWithDifferentUris() {
-        assertThat(ns1.equals(ns2), is(false));
-        assertThat(ns2.equals(ns1), is(false));
-        assertThat(ns3.equals(ns4), is(false));
-        assertThat(ns4.equals(ns3), is(false));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicNamespaceTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNamespaceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,97 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.property.basic.BasicNamespace;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicNamespaceTest {
+
+    private BasicNamespace ns1;
+    private BasicNamespace ns2;
+    private BasicNamespace ns3;
+    private BasicNamespace ns4;
+    private BasicNamespace ns5;
+    private String validUri1;
+    private String validUri2;
+    private String validUri3;
+    private String validPrefix1;
+    private String validPrefix2;
+    private String validPrefix3;
+
+    @Before
+    public void beforeEach() {
+        validUri1 = "";
+        validUri2 = "http://www.example.com";
+        validUri3 = "http://www.acme.com";
+        validPrefix1 = "";
+        validPrefix2 = "a";
+        validPrefix3 = "b";
+        ns1 = new BasicNamespace(validPrefix1, validUri1);
+        ns2 = new BasicNamespace(validPrefix1, validUri2);
+        ns3 = new BasicNamespace(validPrefix2, validUri1);
+        ns4 = new BasicNamespace(validPrefix2, validUri2);
+        ns5 = new BasicNamespace(validPrefix3, validUri3);
+    }
+
+    @Test
+    public void shouldHaveSamePrefixPassedIntoConstructor() {
+        assertThat(ns1.getPrefix(), is(validPrefix1));
+        assertThat(ns2.getPrefix(), is(validPrefix1));
+        assertThat(ns3.getPrefix(), is(validPrefix2));
+        assertThat(ns4.getPrefix(), is(validPrefix2));
+        assertThat(ns5.getPrefix(), is(validPrefix3));
+    }
+
+    @Test
+    public void shouldHaveSameNamespaceUriPassedIntoConstructor() {
+        assertThat(ns1.getNamespaceUri(), is(validUri1));
+        assertThat(ns2.getNamespaceUri(), is(validUri2));
+        assertThat(ns3.getNamespaceUri(), is(validUri1));
+        assertThat(ns4.getNamespaceUri(), is(validUri2));
+        assertThat(ns5.getNamespaceUri(), is(validUri3));
+    }
+
+    @Test
+    public void shouldConsiderAsEqualAnyNamespacesWithSameUri() {
+        assertThat(ns1.equals(ns3), is(true));
+        assertThat(ns3.equals(ns1), is(true));
+        assertThat(ns2.equals(ns4), is(true));
+        assertThat(ns4.equals(ns2), is(true));
+        assertThat(ns5.equals(ns5), is(true));
+    }
+
+    @Test
+    public void shouldNotConsiderAsEqualAnyNamespacesWithDifferentUris() {
+        assertThat(ns1.equals(ns2), is(false));
+        assertThat(ns2.equals(ns1), is(false));
+        assertThat(ns3.equals(ns4), is(false));
+        assertThat(ns4.equals(ns3), is(false));
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathOldTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathOldTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathOldTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,952 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.jboss.dna.graph.properties.basic.IsPathContaining.hasSegments;
-import static org.junit.Assert.assertThat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.common.text.Jsr283Encoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class BasicPathOldTest {
-
-    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
-    public static final Path ROOT = RootPath.INSTANCE;
-
-    private BasicNamespaceRegistry namespaceRegistry;
-    private String validNamespaceUri;
-    private Path path;
-    private Path path2;
-    private Path.Segment[] validSegments;
-    private List<Path.Segment> validSegmentsList;
-    private Name[] validSegmentNames;
-    private String validNamespacePrefix;
-    private PathValueFactory pathFactory;
-
-    @Before
-    public void beforeEach() {
-        validNamespacePrefix = DnaLexicon.Namespace.PREFIX;
-        validNamespaceUri = DnaLexicon.Namespace.URI;
-        validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"), new BasicName(validNamespaceUri, "b"),
-            new BasicName(validNamespaceUri, "c")};
-        validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]),
-            new BasicPathSegment(validSegmentNames[1]), new BasicPathSegment(validSegmentNames[1])};
-        validSegmentsList = new ArrayList<Path.Segment>();
-        for (Path.Segment segment : validSegments) {
-            validSegmentsList.add(segment);
-        }
-        path = new BasicPath(validSegmentsList, true);
-        namespaceRegistry = new BasicNamespaceRegistry();
-        namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
-        StringValueFactory stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
-        NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry, Path.DEFAULT_DECODER, stringValueFactory);
-        pathFactory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameValueFactory);
-    }
-
-    @Test
-    public void shouldCreateAbsolutePathFromListOfValidSegments() {
-        path = new BasicPath(validSegmentsList, true);
-        assertThat(path.isAbsolute(), is(true));
-        assertThat(path.isNormalized(), is(true));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateRelativePathFromListOfValidSegments() {
-        path = new BasicPath(validSegmentsList, false);
-        assertThat(path.isAbsolute(), is(false));
-        assertThat(path.isNormalized(), is(true));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateAbsolutePathWithParentSegment() {
-        validSegmentsList.add(Path.PARENT_SEGMENT);
-        path = new BasicPath(validSegmentsList, true);
-        assertThat(path.isAbsolute(), is(true));
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateRelativePathWithParentSegment() {
-        validSegmentsList.add(Path.PARENT_SEGMENT);
-        path = new BasicPath(validSegmentsList, false);
-        assertThat(path.isAbsolute(), is(false));
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateAbsolutePathWithSelfSegment() {
-        validSegmentsList.add(Path.SELF_SEGMENT);
-        path = new BasicPath(validSegmentsList, true);
-        assertThat(path.isAbsolute(), is(true));
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateRelativePathWithSelfSegment() {
-        validSegmentsList.add(Path.SELF_SEGMENT);
-        path = new BasicPath(validSegmentsList, false);
-        assertThat(path.isAbsolute(), is(false));
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreatePathWithNoNamespacePrefixes() {
-        path = pathFactory.create("/a/b/c/");
-        assertThat(path.size(), is(3));
-        assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
-    }
-
-    @Test
-    public void shouldConstructRelativePath() {
-        assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
-        assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
-        assertThat(pathFactory.create("a/b/c").size(), is(3));
-        assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry), is("a/b/c"));
-    }
-
-    @Test
-    public void shouldConstructRelativePathToSelf() {
-        assertThat(pathFactory.create(".").isAbsolute(), is(false));
-        assertThat(pathFactory.create(".").size(), is(1));
-        assertThat(pathFactory.create("."), hasSegments(pathFactory, Path.SELF));
-
-        assertThat(pathFactory.create("./").isAbsolute(), is(false));
-        assertThat(pathFactory.create("./").size(), is(1));
-        assertThat(pathFactory.create("./"), hasSegments(pathFactory, Path.SELF));
-    }
-
-    @Test
-    public void shouldConstructRelativePathToParent() {
-        assertThat(pathFactory.create("..").isAbsolute(), is(false));
-        assertThat(pathFactory.create("..").size(), is(1));
-        assertThat(pathFactory.create(".."), hasSegments(pathFactory, Path.PARENT));
-
-        assertThat(pathFactory.create("../").isAbsolute(), is(false));
-        assertThat(pathFactory.create("../").size(), is(1));
-        assertThat(pathFactory.create("../"), hasSegments(pathFactory, Path.PARENT));
-    }
-
-    @Test
-    public void shouldConstructRootPathFromStringWithSingleDelimiter() {
-        assertThat(pathFactory.create("/"), is(ROOT));
-        assertThat(pathFactory.create("/").isRoot(), is(true));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotConstructPathWithSuccessiveDelimiters() {
-        pathFactory.create("///a/b///c//d//");
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotConstructPathWithOnlyDelimiters() {
-        pathFactory.create("///");
-    }
-
-    @Test
-    public void shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
-        assertThat(pathFactory.create(" \t /  \t").toString(), is("/"));
-    }
-
-    @Test
-    public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
-        assertThat(pathFactory.create("a"), hasSegments(pathFactory, "a"));
-    }
-
-    @Test
-    public void shouldHaveSizeThatReflectsNumberOfSegments() {
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldIterateOverAllSegmentsReturnedByList() {
-        Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
-        for (Path.Segment segment : path) {
-            assertThat(segment, is(expectedIter.next()));
-        }
-
-        expectedIter = path.getSegmentsList().iterator();
-        for (Path.Segment segment : path) {
-            assertThat(segment, is(expectedIter.next()));
-        }
-    }
-
-    @Test
-    public void shouldReturnNoAncestorForRoot() {
-        assertThat(RootPath.INSTANCE.getParent(), nullValue());
-    }
-
-    @Test
-    public void shouldReturnAncestorForNodeOtherThanRoot() {
-        assertThat(path.getParent(), is(pathFactory.create("/dna:a/dna:b")));
-        assertThat(path.getParent().getParent(), is(pathFactory.create("/dna:a")));
-        assertThat(path.getParent().getParent().getParent(), is(ROOT));
-    }
-
-    @Test
-    public void shouldReturnNthDegreeAncestor() {
-        assertThat(path.getAncestor(1), is(pathFactory.create("/dna:a/dna:b")));
-        assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
-        assertThat(path.getAncestor(3), is(ROOT));
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotAllowAncestorDegreeLargerThanSize() {
-        path.getAncestor(path.size() + 1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNegativeAncestorDegree() {
-        path.getAncestor(-1);
-    }
-
-    @Test
-    public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
-        assertThat(path.getAncestor(path.size()), is(ROOT));
-        assertThat(ROOT.getAncestor(0), is(ROOT));
-    }
-
-    @Test
-    public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
-        assertThat(path.getCommonAncestor(ROOT), is(ROOT));
-        assertThat(ROOT.getCommonAncestor(path), is(ROOT));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
-        path.getCommonAncestor(null);
-    }
-
-    @Test
-    public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path common = pathFactory.create("/a");
-        assertThat(path1.getCommonAncestor(path2), is(common));
-
-        path1 = pathFactory.create("/a/b/c");
-        path2 = pathFactory.create("/a/b/c/d");
-        common = path1;
-        assertThat(path1.getCommonAncestor(path2), is(common));
-
-        path1 = pathFactory.create("/a/b/c/x/y/");
-        path2 = pathFactory.create("/a/b/c/d/e/f/");
-        common = pathFactory.create("/a/b/c");
-        assertThat(path1.getCommonAncestor(path2), is(common));
-    }
-
-    @Test
-    public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
-        Path path1 = pathFactory.create("/x/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path common = ROOT;
-        assertThat(path1.getCommonAncestor(path2), is(common));
-    }
-
-    @Test
-    public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        Path common = pathFactory.create("/a");
-        assertThat(common.isAncestorOf(path1), is(true));
-        assertThat(common.isAncestorOf(path2), is(true));
-        assertThat(common.isAncestorOf(path3), is(false));
-
-        assertThat(path1.getParent().isAncestorOf(path1), is(true));
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
-        }
-    }
-
-    @Test
-    public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        Path common = pathFactory.create("/a");
-        assertThat(path1.isDecendantOf(common), is(true));
-        assertThat(path2.isDecendantOf(common), is(true));
-        assertThat(path3.isDecendantOf(common), is(false));
-
-        assertThat(path1.getParent().isAncestorOf(path1), is(true));
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
-        }
-    }
-
-    @Test
-    public void shouldNotConsiderNodeToBeAncestorOfItself() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        assertThat(path1.isAncestorOf(path1), is(false));
-        assertThat(path2.isAncestorOf(path2), is(false));
-        assertThat(path3.isAncestorOf(path3), is(false));
-        assertThat(ROOT.isAncestorOf(ROOT), is(false));
-    }
-
-    @Test
-    public void shouldNotConsiderNodeToBeDecendantOfItself() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        assertThat(path1.isDecendantOf(path1), is(false));
-        assertThat(path2.isDecendantOf(path2), is(false));
-        assertThat(path3.isDecendantOf(path3), is(false));
-        assertThat(ROOT.isDecendantOf(ROOT), is(false));
-    }
-
-    @Test
-    public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path common = pathFactory.create("/a");
-        assertThat(ROOT.isDecendantOf(path1), is(false));
-        assertThat(ROOT.isDecendantOf(path2), is(false));
-        assertThat(ROOT.isDecendantOf(path3), is(false));
-        assertThat(ROOT.isDecendantOf(common), is(false));
-    }
-
-    @Test
-    public void shouldConsiderRootToBeAncestorOfAnyNode() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path common = pathFactory.create("/a");
-        assertThat(ROOT.isAncestorOf(path1), is(true));
-        assertThat(ROOT.isAncestorOf(path2), is(true));
-        assertThat(ROOT.isAncestorOf(path3), is(true));
-        assertThat(ROOT.isAncestorOf(common), is(true));
-    }
-
-    @Test
-    public void shouldNotConsiderRootToBeAncestorOfItself() {
-        assertThat(ROOT.isAncestorOf(ROOT), is(false));
-    }
-
-    @Test
-    public void shouldNotConsiderRootToBeDecendantOfItself() {
-        assertThat(ROOT.isDecendantOf(ROOT), is(false));
-    }
-
-    @Test
-    public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
-        assertThat(ROOT.hasSameAncestor(ROOT), is(true));
-    }
-
-    @Test
-    public void shouldConsiderTwoNotRootSiblingNodesToHaveSameAncestor() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/y/c");
-        assertThat(path1.hasSameAncestor(path2), is(true));
-
-        path1 = pathFactory.create("/a/z");
-        path2 = pathFactory.create("/a/c");
-        assertThat(path1.hasSameAncestor(path2), is(true));
-
-        path1 = pathFactory.create("/z");
-        path2 = pathFactory.create("/c");
-        assertThat(path1.hasSameAncestor(path2), is(true));
-    }
-
-    @Test
-    public void shouldNotConsiderTwoNonSiblingNodesToHaveSameAncestor() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/x/c");
-        assertThat(path1.hasSameAncestor(path2), is(false));
-
-        path1 = pathFactory.create("/a/z");
-        path2 = pathFactory.create("/b/c");
-        assertThat(path1.hasSameAncestor(path2), is(false));
-
-        path1 = pathFactory.create("/z");
-        path2 = pathFactory.create("/a/c");
-        assertThat(path1.hasSameAncestor(path2), is(false));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailForSameAncestorOfNullPath() {
-        path.hasSameAncestor(null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailForDecendantOfNullPath() {
-        path.isDecendantOf(null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailForAtOrAboveNullPath() {
-        path.isAtOrAbove(null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailForAtOrBelowNullPath() {
-        path.isAtOrBelow(null);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSegmentAtIndexGreatherThanSize() {
-        path.getSegment(path.size() + 1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailToReturnSegmentAtNegativeIndex() {
-        path.getSegment(-1);
-    }
-
-    @Test
-    public void shouldConsiderNodeToBeAtOrAboveItself() {
-        assertThat(path.isAtOrAbove(path), is(true));
-    }
-
-    @Test
-    public void shouldConsiderNodeToBeAtOrBelowItself() {
-        assertThat(path.isAtOrBelow(path), is(true));
-    }
-
-    @Test
-    public void shouldConsiderAncestorToBeAtOrAboveTheDecendant() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.getAncestor(i).isAtOrAbove(path1), is(true));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.getAncestor(i).isAtOrAbove(path2), is(true));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.getAncestor(i).isAtOrAbove(path3), is(true));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.getAncestor(i).isAtOrAbove(path4), is(true));
-        }
-    }
-
-    @Test
-    public void shouldConsiderDecendantToBeAtOrBelowTheAncestor() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.isAtOrBelow(path1.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.isAtOrBelow(path2.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.isAtOrBelow(path3.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.isAtOrBelow(path4.getAncestor(i)), is(true));
-        }
-    }
-
-    @Test
-    public void shouldNotConsiderAncestorToBeAtOrBelowTheDecendant() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.getAncestor(i).isAtOrBelow(path1), is(false));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.getAncestor(i).isAtOrBelow(path2), is(false));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.getAncestor(i).isAtOrBelow(path3), is(false));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.getAncestor(i).isAtOrBelow(path4), is(false));
-        }
-    }
-
-    @Test
-    public void shouldNotConsiderDecendantToBeAtOrAboveTheAncestor() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.isAtOrAbove(path1.getAncestor(i)), is(false));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.isAtOrAbove(path2.getAncestor(i)), is(false));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.isAtOrAbove(path3.getAncestor(i)), is(false));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.isAtOrAbove(path4.getAncestor(i)), is(false));
-        }
-    }
-
-    @Test
-    public void shouldReturnNullForLastSegmentOfRoot() {
-        assertThat(ROOT.getLastSegment(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldReturnLastSegmentOfNonRootPath() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
-        assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
-        assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
-        assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
-        assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
-    }
-
-    @Test
-    public void shouldNormalizePathWithSelfAndParentReferences() {
-        path = pathFactory.create("/a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getNormalizedPath().isAbsolute(), is(true));
-        assertThat(path.getNormalizedPath().isNormalized(), is(true));
-
-        path = pathFactory.create("a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getNormalizedPath().isAbsolute(), is(false));
-        assertThat(path.getNormalizedPath().isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
-        assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
-        assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
-        assertThat(pathFactory.create("a").isNormalized(), is(true));
-        assertThat(pathFactory.create("/a").isNormalized(), is(true));
-        assertThat(ROOT.isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
-        assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(), is(false));
-        assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(), is(false));
-        assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
-        assertThat(pathFactory.create("/a/b/c/../d").isNormalized(), is(false));
-        assertThat(pathFactory.create(".").isNormalized(), is(false));
-        assertThat(pathFactory.create("/.").isNormalized(), is(false));
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
-        path = pathFactory.create("/a/../../../..");
-        assertThat(path.isNormalized(), is(false));
-        path.getNormalizedPath();
-    }
-
-    @Test
-    public void shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
-        // "/a/../b/../c/.." => "/"
-        path = pathFactory.create("/a/../b/../c/../");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), is(ROOT));
-    }
-
-    @Test
-    public void shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
-        // "a/../b/../c/.." => "."
-        path = pathFactory.create("a/../b/../c/../");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath().size(), is(1));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
-    }
-
-    @Test
-    public void shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
-        path = pathFactory.create("/a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getNormalizedPath().isAbsolute(), is(true));
-        assertThat(path.getNormalizedPath().isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
-        path = pathFactory.create("a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getNormalizedPath().isAbsolute(), is(false));
-        assertThat(path.getNormalizedPath().isNormalized(), is(true));
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
-        pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
-    }
-
-    @Test
-    public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
-        path = pathFactory.create("/a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.isAbsolute(), is(true));
-        assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getCanonicalPath().isAbsolute(), is(true));
-        assertThat(path.getCanonicalPath().isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
-        testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
-        testSegmentsByIteratorAndListAndArray("/a/b/c", "a", "b", "c");
-        testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
-        testSegmentsByIteratorAndListAndArray("a/b/c", "a", "b", "c");
-        testSegmentsByIteratorAndListAndArray("");
-        testSegmentsByIteratorAndListAndArray(ROOT.getString());
-    }
-
-    public void testSegmentsByIteratorAndListAndArray( String pathStr,
-                                                       String... expectedSegmentStrings ) {
-        path = pathFactory.create(pathStr);
-        assertThat(expectedSegmentStrings.length, is(path.size()));
-        Path.Segment[] segmentArray = path.getSegmentsArray();
-        List<Path.Segment> segmentList = path.getSegmentsList();
-        assertThat(segmentArray.length, is(path.size()));
-        assertThat(segmentList.size(), is(path.size()));
-        Iterator<Path.Segment> iter = path.iterator();
-        Iterator<Path.Segment> listIter = segmentList.iterator();
-        for (int i = 0; i != path.size(); ++i) {
-            Path.Segment expected = pathFactory.createSegment(expectedSegmentStrings[i]);
-            assertThat(path.getSegment(i), is(expected));
-            assertThat(segmentArray[i], is(expected));
-            assertThat(segmentList.get(i), is(expected));
-            assertThat(iter.next(), is(expected));
-            assertThat(listIter.next(), is(expected));
-        }
-        assertThat(iter.hasNext(), is(false));
-        assertThat(listIter.hasNext(), is(false));
-    }
-
-    @Test
-    public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.getString(NO_OP_ENCODER),
-                   is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../{}d/./{http://www.jboss.org/dna}e/../.."));
-    }
-
-    @Test
-    public void shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna:a/b/dna:c/../d/./dna:e/../.."));
-        namespaceRegistry.register("dna2", validNamespaceUri);
-        assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(-1);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(path.size() + 1);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(path.size() + 1, path.size() + 2);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(2, 1);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(2, path.size() + 1);
-    }
-
-    @Test
-    public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.subpath(0, 0), is(ROOT));
-    }
-
-    @Test
-    public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(0), is(path));
-        assertThat(path.subpath(0), is(sameInstance(path)));
-        assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
-        assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
-        assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
-
-        path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(0), is(path));
-        assertThat(path.subpath(0), is(sameInstance(path)));
-        assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
-        assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
-        assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
-    }
-
-    @Test
-    public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.subpath(0, path.size()), hasSegments(pathFactory,
-                                                             "dna:a",
-                                                             "b",
-                                                             "dna:c",
-                                                             "..",
-                                                             "d",
-                                                             ".",
-                                                             "dna:e",
-                                                             "..",
-                                                             ".."));
-        assertThat(path.subpath(0, path.size()), is(path));
-        assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
-        assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(2, path.size()), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(6, path.size()), hasSegments(pathFactory, "dna:e", "..", ".."));
-        assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..", ".."));
-        assertThat(path.subpath(8, path.size()), hasSegments(pathFactory, ".."));
-
-        assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a", "b"));
-        assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
-        assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b", "dna:c", "..", "d"));
-        assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c", "..", "d"));
-        assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..", "d"));
-    }
-
-    @Test
-    public void shouldFindRelativePaths() {
-        path = pathFactory.create("/a/b/c/d");
-        assertThat(path.relativeTo(pathFactory.create("/a/e/f")), is(pathFactory.create("../../b/c/d")));
-        assertThat(path.relativeTo(pathFactory.create("/e/f")), is(pathFactory.create("../../a/b/c/d")));
-
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
-        path = pathFactory.create("a/b/c/d");
-        path.relativeTo(pathFactory.create("/e/f"));
-
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotResolveRelativePathToAnotherRelativePath() {
-        path = pathFactory.create("/a/b/c/d");
-        path.relativeTo(pathFactory.create("e/f"));
-
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
-        path = pathFactory.create("/a/b/c/d");
-        path.resolve(pathFactory.create("/e/f"));
-    }
-
-    @Test
-    public void shouldResolveRelativePathToAbsolutePath() {
-        path = pathFactory.create("/a/b/c/d");
-        path2 = path.resolve(pathFactory.create("../../e/f"));
-        assertThat(path2, is(pathFactory.create("/a/b/e/f")));
-        assertThat(path2.isAbsolute(), is(true));
-        assertThat(path2.isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldOrderPathsCorrectly() {
-        List<Path> paths = new ArrayList<Path>();
-        paths.add(pathFactory.create("/a"));
-        paths.add(pathFactory.create("/a/b"));
-        paths.add(pathFactory.create("/a/b/alpha"));
-        paths.add(pathFactory.create("/a/b/beta"));
-        paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
-        paths.add(pathFactory.create("/a/b/dna:name"));
-        paths.add(pathFactory.create("/a/b/dna:primaryType"));
-        paths.add(pathFactory.create("/a/c[1]"));
-        paths.add(pathFactory.create("/a/c[1]/alpha"));
-        paths.add(pathFactory.create("/a/c[1]/beta"));
-        paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
-        paths.add(pathFactory.create("/a/c[1]/dna:name"));
-        paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
-        paths.add(pathFactory.create("/a/c[2]"));
-        paths.add(pathFactory.create("/a/c[2]/alpha"));
-        paths.add(pathFactory.create("/a/c[2]/beta"));
-        paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
-        paths.add(pathFactory.create("/a/c[2]/dna:name"));
-        paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
-
-        // Randomize the list of paths, so we have something to sort ...
-        List<Path> randomizedPaths = new ArrayList<Path>(paths);
-        Collections.shuffle(randomizedPaths);
-        assertThat(randomizedPaths, is(not(paths)));
-
-        // Sort ...
-        Collections.sort(randomizedPaths);
-        assertThat(randomizedPaths, is(paths));
-    }
-
-    @Test
-    public void shouldGetNormalizedPathOfSelfShouldBeSame() {
-        assertThat(pathFactory.create(".").getNormalizedPath(), is(pathFactory.create(".")));
-        assertThat(pathFactory.create("./").getNormalizedPath(), is(pathFactory.create(".")));
-        assertThat(pathFactory.create("./././").getNormalizedPath(), is(pathFactory.create(".")));
-    }
-
-    @Test
-    public void shouldGetNormalizedPathWithParentReferences() {
-        assertThat(pathFactory.create("..").getNormalizedPath(), is(pathFactory.create("..")));
-        assertThat(pathFactory.create("../").getNormalizedPath(), is(pathFactory.create("../")));
-        assertThat(pathFactory.create("../../../../../..").getNormalizedPath(), is(pathFactory.create("../../../../../..")));
-    }
-
-    @Test
-    public void shouldGetRelativePathUsingSelf() {
-        path = pathFactory.create("/a/b/c/d/e/f");
-        assertThat(path.resolve(pathFactory.create(".")), is(sameInstance(path)));
-        assertThat(path.resolve(pathFactory.create("././.")), is(sameInstance(path)));
-    }
-
-    @Test
-    public void shouldResolveRelativePathToParent() {
-        path = pathFactory.create("/a/b/c/d/e/f");
-        assertThat(path.resolve(pathFactory.create("..")), is(path.getParent()));
-        assertThat(path.resolve(pathFactory.create("..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
-    }
-
-    @Test
-    public void shouldResolveRelativePaths() {
-        path = pathFactory.create("/a/b/c/d/e/f");
-        assertThat(path.resolve(pathFactory.create("../../../../../..")), is(sameInstance(ROOT)));
-        assertThat(path.resolve(pathFactory.create("../..")), is(path.getParent().getParent()));
-        assertThat(path.resolve(pathFactory.create("../..")), hasSegments(pathFactory, "a", "b", "c", "d"));
-        assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), is(path.getParent()));
-        assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
-        assertThat(path.resolve(pathFactory.create("../x")), hasSegments(pathFactory, "a", "b", "c", "d", "e", "x"));
-    }
-
-    public void shouldResolveNonAbsolutePaths() {
-        path = pathFactory.create("a/b/c");
-        assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
-    }
-
-    @Test
-    public void shouldConvertPathToString() {
-        TextEncoder encoder = new Jsr283Encoder();
-        TextEncoder delimEncoder = new TextEncoder() {
-            public String encode( String text ) {
-                if ("/".equals(text)) return "\\/";
-                if (":".equals(text)) return "\\:";
-                if ("{".equals(text)) return "\\{";
-                if ("}".equals(text)) return "\\}";
-                return text;
-            }
-        };
-        Path path = pathFactory.create("a/b/c");
-        assertThat(path.getString(namespaceRegistry), is("a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder), is("a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("a\\/b\\/c"));
-
-        path = pathFactory.create("/a/b/c");
-        assertThat(path.getString(namespaceRegistry), is("/a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder), is("/a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("\\/a\\/b\\/c"));
-
-        path = pathFactory.create("/dna:a/b/c");
-        assertThat(path.getString(encoder), is("/{" + encoder.encode(DnaLexicon.Namespace.URI) + "}a/{}b/{}c"));
-        assertThat(path.getString(null, encoder, delimEncoder), is("\\/\\{" + encoder.encode(DnaLexicon.Namespace.URI)
-                                                                   + "\\}a\\/\\{\\}b\\/\\{\\}c"));
-        assertThat(path.getString(namespaceRegistry), is("/dna:a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder), is("/dna:a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("\\/dna\\:a\\/b\\/c"));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathOldTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathOldTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathOldTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathOldTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,960 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.jboss.dna.graph.property.basic.IsPathContaining.hasSegments;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.common.text.Jsr283Encoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.BasicPath;
+import org.jboss.dna.graph.property.basic.BasicPathSegment;
+import org.jboss.dna.graph.property.basic.NameValueFactory;
+import org.jboss.dna.graph.property.basic.PathValueFactory;
+import org.jboss.dna.graph.property.basic.RootPath;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class BasicPathOldTest {
+
+    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+    public static final Path ROOT = RootPath.INSTANCE;
+
+    private BasicNamespaceRegistry namespaceRegistry;
+    private String validNamespaceUri;
+    private Path path;
+    private Path path2;
+    private Path.Segment[] validSegments;
+    private List<Path.Segment> validSegmentsList;
+    private Name[] validSegmentNames;
+    private String validNamespacePrefix;
+    private PathValueFactory pathFactory;
+
+    @Before
+    public void beforeEach() {
+        validNamespacePrefix = DnaLexicon.Namespace.PREFIX;
+        validNamespaceUri = DnaLexicon.Namespace.URI;
+        validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"), new BasicName(validNamespaceUri, "b"),
+            new BasicName(validNamespaceUri, "c")};
+        validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]),
+            new BasicPathSegment(validSegmentNames[1]), new BasicPathSegment(validSegmentNames[1])};
+        validSegmentsList = new ArrayList<Path.Segment>();
+        for (Path.Segment segment : validSegments) {
+            validSegmentsList.add(segment);
+        }
+        path = new BasicPath(validSegmentsList, true);
+        namespaceRegistry = new BasicNamespaceRegistry();
+        namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
+        StringValueFactory stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
+        NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry, Path.DEFAULT_DECODER, stringValueFactory);
+        pathFactory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameValueFactory);
+    }
+
+    @Test
+    public void shouldCreateAbsolutePathFromListOfValidSegments() {
+        path = new BasicPath(validSegmentsList, true);
+        assertThat(path.isAbsolute(), is(true));
+        assertThat(path.isNormalized(), is(true));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateRelativePathFromListOfValidSegments() {
+        path = new BasicPath(validSegmentsList, false);
+        assertThat(path.isAbsolute(), is(false));
+        assertThat(path.isNormalized(), is(true));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateAbsolutePathWithParentSegment() {
+        validSegmentsList.add(Path.PARENT_SEGMENT);
+        path = new BasicPath(validSegmentsList, true);
+        assertThat(path.isAbsolute(), is(true));
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateRelativePathWithParentSegment() {
+        validSegmentsList.add(Path.PARENT_SEGMENT);
+        path = new BasicPath(validSegmentsList, false);
+        assertThat(path.isAbsolute(), is(false));
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateAbsolutePathWithSelfSegment() {
+        validSegmentsList.add(Path.SELF_SEGMENT);
+        path = new BasicPath(validSegmentsList, true);
+        assertThat(path.isAbsolute(), is(true));
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateRelativePathWithSelfSegment() {
+        validSegmentsList.add(Path.SELF_SEGMENT);
+        path = new BasicPath(validSegmentsList, false);
+        assertThat(path.isAbsolute(), is(false));
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreatePathWithNoNamespacePrefixes() {
+        path = pathFactory.create("/a/b/c/");
+        assertThat(path.size(), is(3));
+        assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
+    }
+
+    @Test
+    public void shouldConstructRelativePath() {
+        assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
+        assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
+        assertThat(pathFactory.create("a/b/c").size(), is(3));
+        assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry), is("a/b/c"));
+    }
+
+    @Test
+    public void shouldConstructRelativePathToSelf() {
+        assertThat(pathFactory.create(".").isAbsolute(), is(false));
+        assertThat(pathFactory.create(".").size(), is(1));
+        assertThat(pathFactory.create("."), hasSegments(pathFactory, Path.SELF));
+
+        assertThat(pathFactory.create("./").isAbsolute(), is(false));
+        assertThat(pathFactory.create("./").size(), is(1));
+        assertThat(pathFactory.create("./"), hasSegments(pathFactory, Path.SELF));
+    }
+
+    @Test
+    public void shouldConstructRelativePathToParent() {
+        assertThat(pathFactory.create("..").isAbsolute(), is(false));
+        assertThat(pathFactory.create("..").size(), is(1));
+        assertThat(pathFactory.create(".."), hasSegments(pathFactory, Path.PARENT));
+
+        assertThat(pathFactory.create("../").isAbsolute(), is(false));
+        assertThat(pathFactory.create("../").size(), is(1));
+        assertThat(pathFactory.create("../"), hasSegments(pathFactory, Path.PARENT));
+    }
+
+    @Test
+    public void shouldConstructRootPathFromStringWithSingleDelimiter() {
+        assertThat(pathFactory.create("/"), is(ROOT));
+        assertThat(pathFactory.create("/").isRoot(), is(true));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotConstructPathWithSuccessiveDelimiters() {
+        pathFactory.create("///a/b///c//d//");
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotConstructPathWithOnlyDelimiters() {
+        pathFactory.create("///");
+    }
+
+    @Test
+    public void shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
+        assertThat(pathFactory.create(" \t /  \t").toString(), is("/"));
+    }
+
+    @Test
+    public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
+        assertThat(pathFactory.create("a"), hasSegments(pathFactory, "a"));
+    }
+
+    @Test
+    public void shouldHaveSizeThatReflectsNumberOfSegments() {
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldIterateOverAllSegmentsReturnedByList() {
+        Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
+        for (Path.Segment segment : path) {
+            assertThat(segment, is(expectedIter.next()));
+        }
+
+        expectedIter = path.getSegmentsList().iterator();
+        for (Path.Segment segment : path) {
+            assertThat(segment, is(expectedIter.next()));
+        }
+    }
+
+    @Test
+    public void shouldReturnNoAncestorForRoot() {
+        assertThat(RootPath.INSTANCE.getParent(), nullValue());
+    }
+
+    @Test
+    public void shouldReturnAncestorForNodeOtherThanRoot() {
+        assertThat(path.getParent(), is(pathFactory.create("/dna:a/dna:b")));
+        assertThat(path.getParent().getParent(), is(pathFactory.create("/dna:a")));
+        assertThat(path.getParent().getParent().getParent(), is(ROOT));
+    }
+
+    @Test
+    public void shouldReturnNthDegreeAncestor() {
+        assertThat(path.getAncestor(1), is(pathFactory.create("/dna:a/dna:b")));
+        assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
+        assertThat(path.getAncestor(3), is(ROOT));
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotAllowAncestorDegreeLargerThanSize() {
+        path.getAncestor(path.size() + 1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNegativeAncestorDegree() {
+        path.getAncestor(-1);
+    }
+
+    @Test
+    public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
+        assertThat(path.getAncestor(path.size()), is(ROOT));
+        assertThat(ROOT.getAncestor(0), is(ROOT));
+    }
+
+    @Test
+    public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
+        assertThat(path.getCommonAncestor(ROOT), is(ROOT));
+        assertThat(ROOT.getCommonAncestor(path), is(ROOT));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
+        path.getCommonAncestor(null);
+    }
+
+    @Test
+    public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path common = pathFactory.create("/a");
+        assertThat(path1.getCommonAncestor(path2), is(common));
+
+        path1 = pathFactory.create("/a/b/c");
+        path2 = pathFactory.create("/a/b/c/d");
+        common = path1;
+        assertThat(path1.getCommonAncestor(path2), is(common));
+
+        path1 = pathFactory.create("/a/b/c/x/y/");
+        path2 = pathFactory.create("/a/b/c/d/e/f/");
+        common = pathFactory.create("/a/b/c");
+        assertThat(path1.getCommonAncestor(path2), is(common));
+    }
+
+    @Test
+    public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
+        Path path1 = pathFactory.create("/x/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path common = ROOT;
+        assertThat(path1.getCommonAncestor(path2), is(common));
+    }
+
+    @Test
+    public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        Path common = pathFactory.create("/a");
+        assertThat(common.isAncestorOf(path1), is(true));
+        assertThat(common.isAncestorOf(path2), is(true));
+        assertThat(common.isAncestorOf(path3), is(false));
+
+        assertThat(path1.getParent().isAncestorOf(path1), is(true));
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
+        }
+    }
+
+    @Test
+    public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        Path common = pathFactory.create("/a");
+        assertThat(path1.isDecendantOf(common), is(true));
+        assertThat(path2.isDecendantOf(common), is(true));
+        assertThat(path3.isDecendantOf(common), is(false));
+
+        assertThat(path1.getParent().isAncestorOf(path1), is(true));
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
+        }
+    }
+
+    @Test
+    public void shouldNotConsiderNodeToBeAncestorOfItself() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        assertThat(path1.isAncestorOf(path1), is(false));
+        assertThat(path2.isAncestorOf(path2), is(false));
+        assertThat(path3.isAncestorOf(path3), is(false));
+        assertThat(ROOT.isAncestorOf(ROOT), is(false));
+    }
+
+    @Test
+    public void shouldNotConsiderNodeToBeDecendantOfItself() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        assertThat(path1.isDecendantOf(path1), is(false));
+        assertThat(path2.isDecendantOf(path2), is(false));
+        assertThat(path3.isDecendantOf(path3), is(false));
+        assertThat(ROOT.isDecendantOf(ROOT), is(false));
+    }
+
+    @Test
+    public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path common = pathFactory.create("/a");
+        assertThat(ROOT.isDecendantOf(path1), is(false));
+        assertThat(ROOT.isDecendantOf(path2), is(false));
+        assertThat(ROOT.isDecendantOf(path3), is(false));
+        assertThat(ROOT.isDecendantOf(common), is(false));
+    }
+
+    @Test
+    public void shouldConsiderRootToBeAncestorOfAnyNode() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path common = pathFactory.create("/a");
+        assertThat(ROOT.isAncestorOf(path1), is(true));
+        assertThat(ROOT.isAncestorOf(path2), is(true));
+        assertThat(ROOT.isAncestorOf(path3), is(true));
+        assertThat(ROOT.isAncestorOf(common), is(true));
+    }
+
+    @Test
+    public void shouldNotConsiderRootToBeAncestorOfItself() {
+        assertThat(ROOT.isAncestorOf(ROOT), is(false));
+    }
+
+    @Test
+    public void shouldNotConsiderRootToBeDecendantOfItself() {
+        assertThat(ROOT.isDecendantOf(ROOT), is(false));
+    }
+
+    @Test
+    public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
+        assertThat(ROOT.hasSameAncestor(ROOT), is(true));
+    }
+
+    @Test
+    public void shouldConsiderTwoNotRootSiblingNodesToHaveSameAncestor() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/y/c");
+        assertThat(path1.hasSameAncestor(path2), is(true));
+
+        path1 = pathFactory.create("/a/z");
+        path2 = pathFactory.create("/a/c");
+        assertThat(path1.hasSameAncestor(path2), is(true));
+
+        path1 = pathFactory.create("/z");
+        path2 = pathFactory.create("/c");
+        assertThat(path1.hasSameAncestor(path2), is(true));
+    }
+
+    @Test
+    public void shouldNotConsiderTwoNonSiblingNodesToHaveSameAncestor() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/x/c");
+        assertThat(path1.hasSameAncestor(path2), is(false));
+
+        path1 = pathFactory.create("/a/z");
+        path2 = pathFactory.create("/b/c");
+        assertThat(path1.hasSameAncestor(path2), is(false));
+
+        path1 = pathFactory.create("/z");
+        path2 = pathFactory.create("/a/c");
+        assertThat(path1.hasSameAncestor(path2), is(false));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailForSameAncestorOfNullPath() {
+        path.hasSameAncestor(null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailForDecendantOfNullPath() {
+        path.isDecendantOf(null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailForAtOrAboveNullPath() {
+        path.isAtOrAbove(null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailForAtOrBelowNullPath() {
+        path.isAtOrBelow(null);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSegmentAtIndexGreatherThanSize() {
+        path.getSegment(path.size() + 1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailToReturnSegmentAtNegativeIndex() {
+        path.getSegment(-1);
+    }
+
+    @Test
+    public void shouldConsiderNodeToBeAtOrAboveItself() {
+        assertThat(path.isAtOrAbove(path), is(true));
+    }
+
+    @Test
+    public void shouldConsiderNodeToBeAtOrBelowItself() {
+        assertThat(path.isAtOrBelow(path), is(true));
+    }
+
+    @Test
+    public void shouldConsiderAncestorToBeAtOrAboveTheDecendant() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.getAncestor(i).isAtOrAbove(path1), is(true));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.getAncestor(i).isAtOrAbove(path2), is(true));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.getAncestor(i).isAtOrAbove(path3), is(true));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.getAncestor(i).isAtOrAbove(path4), is(true));
+        }
+    }
+
+    @Test
+    public void shouldConsiderDecendantToBeAtOrBelowTheAncestor() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.isAtOrBelow(path1.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.isAtOrBelow(path2.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.isAtOrBelow(path3.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.isAtOrBelow(path4.getAncestor(i)), is(true));
+        }
+    }
+
+    @Test
+    public void shouldNotConsiderAncestorToBeAtOrBelowTheDecendant() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.getAncestor(i).isAtOrBelow(path1), is(false));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.getAncestor(i).isAtOrBelow(path2), is(false));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.getAncestor(i).isAtOrBelow(path3), is(false));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.getAncestor(i).isAtOrBelow(path4), is(false));
+        }
+    }
+
+    @Test
+    public void shouldNotConsiderDecendantToBeAtOrAboveTheAncestor() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.isAtOrAbove(path1.getAncestor(i)), is(false));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.isAtOrAbove(path2.getAncestor(i)), is(false));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.isAtOrAbove(path3.getAncestor(i)), is(false));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.isAtOrAbove(path4.getAncestor(i)), is(false));
+        }
+    }
+
+    @Test
+    public void shouldReturnNullForLastSegmentOfRoot() {
+        assertThat(ROOT.getLastSegment(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldReturnLastSegmentOfNonRootPath() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
+        assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
+        assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
+        assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
+        assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
+    }
+
+    @Test
+    public void shouldNormalizePathWithSelfAndParentReferences() {
+        path = pathFactory.create("/a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+        assertThat(path.getNormalizedPath().isNormalized(), is(true));
+
+        path = pathFactory.create("a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+        assertThat(path.getNormalizedPath().isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
+        assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
+        assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
+        assertThat(pathFactory.create("a").isNormalized(), is(true));
+        assertThat(pathFactory.create("/a").isNormalized(), is(true));
+        assertThat(ROOT.isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
+        assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(), is(false));
+        assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(), is(false));
+        assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
+        assertThat(pathFactory.create("/a/b/c/../d").isNormalized(), is(false));
+        assertThat(pathFactory.create(".").isNormalized(), is(false));
+        assertThat(pathFactory.create("/.").isNormalized(), is(false));
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
+        path = pathFactory.create("/a/../../../..");
+        assertThat(path.isNormalized(), is(false));
+        path.getNormalizedPath();
+    }
+
+    @Test
+    public void shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
+        // "/a/../b/../c/.." => "/"
+        path = pathFactory.create("/a/../b/../c/../");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), is(ROOT));
+    }
+
+    @Test
+    public void shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
+        // "a/../b/../c/.." => "."
+        path = pathFactory.create("a/../b/../c/../");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath().size(), is(1));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
+    }
+
+    @Test
+    public void shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
+        path = pathFactory.create("/a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+        assertThat(path.getNormalizedPath().isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
+        path = pathFactory.create("a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+        assertThat(path.getNormalizedPath().isNormalized(), is(true));
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
+        pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
+    }
+
+    @Test
+    public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
+        path = pathFactory.create("/a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.isAbsolute(), is(true));
+        assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getCanonicalPath().isAbsolute(), is(true));
+        assertThat(path.getCanonicalPath().isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
+        testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
+        testSegmentsByIteratorAndListAndArray("/a/b/c", "a", "b", "c");
+        testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
+        testSegmentsByIteratorAndListAndArray("a/b/c", "a", "b", "c");
+        testSegmentsByIteratorAndListAndArray("");
+        testSegmentsByIteratorAndListAndArray(ROOT.getString());
+    }
+
+    public void testSegmentsByIteratorAndListAndArray( String pathStr,
+                                                       String... expectedSegmentStrings ) {
+        path = pathFactory.create(pathStr);
+        assertThat(expectedSegmentStrings.length, is(path.size()));
+        Path.Segment[] segmentArray = path.getSegmentsArray();
+        List<Path.Segment> segmentList = path.getSegmentsList();
+        assertThat(segmentArray.length, is(path.size()));
+        assertThat(segmentList.size(), is(path.size()));
+        Iterator<Path.Segment> iter = path.iterator();
+        Iterator<Path.Segment> listIter = segmentList.iterator();
+        for (int i = 0; i != path.size(); ++i) {
+            Path.Segment expected = pathFactory.createSegment(expectedSegmentStrings[i]);
+            assertThat(path.getSegment(i), is(expected));
+            assertThat(segmentArray[i], is(expected));
+            assertThat(segmentList.get(i), is(expected));
+            assertThat(iter.next(), is(expected));
+            assertThat(listIter.next(), is(expected));
+        }
+        assertThat(iter.hasNext(), is(false));
+        assertThat(listIter.hasNext(), is(false));
+    }
+
+    @Test
+    public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.getString(NO_OP_ENCODER),
+                   is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../{}d/./{http://www.jboss.org/dna}e/../.."));
+    }
+
+    @Test
+    public void shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna:a/b/dna:c/../d/./dna:e/../.."));
+        namespaceRegistry.register("dna2", validNamespaceUri);
+        assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(-1);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(path.size() + 1);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(path.size() + 1, path.size() + 2);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(2, 1);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(2, path.size() + 1);
+    }
+
+    @Test
+    public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.subpath(0, 0), is(ROOT));
+    }
+
+    @Test
+    public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(0), is(path));
+        assertThat(path.subpath(0), is(sameInstance(path)));
+        assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
+        assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
+        assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+
+        path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(0), is(path));
+        assertThat(path.subpath(0), is(sameInstance(path)));
+        assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
+        assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
+        assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+    }
+
+    @Test
+    public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.subpath(0, path.size()), hasSegments(pathFactory,
+                                                             "dna:a",
+                                                             "b",
+                                                             "dna:c",
+                                                             "..",
+                                                             "d",
+                                                             ".",
+                                                             "dna:e",
+                                                             "..",
+                                                             ".."));
+        assertThat(path.subpath(0, path.size()), is(path));
+        assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
+        assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(2, path.size()), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(6, path.size()), hasSegments(pathFactory, "dna:e", "..", ".."));
+        assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..", ".."));
+        assertThat(path.subpath(8, path.size()), hasSegments(pathFactory, ".."));
+
+        assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a", "b"));
+        assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
+        assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b", "dna:c", "..", "d"));
+        assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c", "..", "d"));
+        assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..", "d"));
+    }
+
+    @Test
+    public void shouldFindRelativePaths() {
+        path = pathFactory.create("/a/b/c/d");
+        assertThat(path.relativeTo(pathFactory.create("/a/e/f")), is(pathFactory.create("../../b/c/d")));
+        assertThat(path.relativeTo(pathFactory.create("/e/f")), is(pathFactory.create("../../a/b/c/d")));
+
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
+        path = pathFactory.create("a/b/c/d");
+        path.relativeTo(pathFactory.create("/e/f"));
+
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotResolveRelativePathToAnotherRelativePath() {
+        path = pathFactory.create("/a/b/c/d");
+        path.relativeTo(pathFactory.create("e/f"));
+
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+        path = pathFactory.create("/a/b/c/d");
+        path.resolve(pathFactory.create("/e/f"));
+    }
+
+    @Test
+    public void shouldResolveRelativePathToAbsolutePath() {
+        path = pathFactory.create("/a/b/c/d");
+        path2 = path.resolve(pathFactory.create("../../e/f"));
+        assertThat(path2, is(pathFactory.create("/a/b/e/f")));
+        assertThat(path2.isAbsolute(), is(true));
+        assertThat(path2.isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldOrderPathsCorrectly() {
+        List<Path> paths = new ArrayList<Path>();
+        paths.add(pathFactory.create("/a"));
+        paths.add(pathFactory.create("/a/b"));
+        paths.add(pathFactory.create("/a/b/alpha"));
+        paths.add(pathFactory.create("/a/b/beta"));
+        paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
+        paths.add(pathFactory.create("/a/b/dna:name"));
+        paths.add(pathFactory.create("/a/b/dna:primaryType"));
+        paths.add(pathFactory.create("/a/c[1]"));
+        paths.add(pathFactory.create("/a/c[1]/alpha"));
+        paths.add(pathFactory.create("/a/c[1]/beta"));
+        paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
+        paths.add(pathFactory.create("/a/c[1]/dna:name"));
+        paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
+        paths.add(pathFactory.create("/a/c[2]"));
+        paths.add(pathFactory.create("/a/c[2]/alpha"));
+        paths.add(pathFactory.create("/a/c[2]/beta"));
+        paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
+        paths.add(pathFactory.create("/a/c[2]/dna:name"));
+        paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
+
+        // Randomize the list of paths, so we have something to sort ...
+        List<Path> randomizedPaths = new ArrayList<Path>(paths);
+        Collections.shuffle(randomizedPaths);
+        assertThat(randomizedPaths, is(not(paths)));
+
+        // Sort ...
+        Collections.sort(randomizedPaths);
+        assertThat(randomizedPaths, is(paths));
+    }
+
+    @Test
+    public void shouldGetNormalizedPathOfSelfShouldBeSame() {
+        assertThat(pathFactory.create(".").getNormalizedPath(), is(pathFactory.create(".")));
+        assertThat(pathFactory.create("./").getNormalizedPath(), is(pathFactory.create(".")));
+        assertThat(pathFactory.create("./././").getNormalizedPath(), is(pathFactory.create(".")));
+    }
+
+    @Test
+    public void shouldGetNormalizedPathWithParentReferences() {
+        assertThat(pathFactory.create("..").getNormalizedPath(), is(pathFactory.create("..")));
+        assertThat(pathFactory.create("../").getNormalizedPath(), is(pathFactory.create("../")));
+        assertThat(pathFactory.create("../../../../../..").getNormalizedPath(), is(pathFactory.create("../../../../../..")));
+    }
+
+    @Test
+    public void shouldGetRelativePathUsingSelf() {
+        path = pathFactory.create("/a/b/c/d/e/f");
+        assertThat(path.resolve(pathFactory.create(".")), is(sameInstance(path)));
+        assertThat(path.resolve(pathFactory.create("././.")), is(sameInstance(path)));
+    }
+
+    @Test
+    public void shouldResolveRelativePathToParent() {
+        path = pathFactory.create("/a/b/c/d/e/f");
+        assertThat(path.resolve(pathFactory.create("..")), is(path.getParent()));
+        assertThat(path.resolve(pathFactory.create("..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
+    }
+
+    @Test
+    public void shouldResolveRelativePaths() {
+        path = pathFactory.create("/a/b/c/d/e/f");
+        assertThat(path.resolve(pathFactory.create("../../../../../..")), is(sameInstance(ROOT)));
+        assertThat(path.resolve(pathFactory.create("../..")), is(path.getParent().getParent()));
+        assertThat(path.resolve(pathFactory.create("../..")), hasSegments(pathFactory, "a", "b", "c", "d"));
+        assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), is(path.getParent()));
+        assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
+        assertThat(path.resolve(pathFactory.create("../x")), hasSegments(pathFactory, "a", "b", "c", "d", "e", "x"));
+    }
+
+    public void shouldResolveNonAbsolutePaths() {
+        path = pathFactory.create("a/b/c");
+        assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
+    }
+
+    @Test
+    public void shouldConvertPathToString() {
+        TextEncoder encoder = new Jsr283Encoder();
+        TextEncoder delimEncoder = new TextEncoder() {
+            public String encode( String text ) {
+                if ("/".equals(text)) return "\\/";
+                if (":".equals(text)) return "\\:";
+                if ("{".equals(text)) return "\\{";
+                if ("}".equals(text)) return "\\}";
+                return text;
+            }
+        };
+        Path path = pathFactory.create("a/b/c");
+        assertThat(path.getString(namespaceRegistry), is("a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder), is("a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("a\\/b\\/c"));
+
+        path = pathFactory.create("/a/b/c");
+        assertThat(path.getString(namespaceRegistry), is("/a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder), is("/a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("\\/a\\/b\\/c"));
+
+        path = pathFactory.create("/dna:a/b/c");
+        assertThat(path.getString(encoder), is("/{" + encoder.encode(DnaLexicon.Namespace.URI) + "}a/{}b/{}c"));
+        assertThat(path.getString(null, encoder, delimEncoder), is("\\/\\{" + encoder.encode(DnaLexicon.Namespace.URI)
+                                                                   + "\\}a\\/\\{\\}b\\/\\{\\}c"));
+        assertThat(path.getString(namespaceRegistry), is("/dna:a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder), is("/dna:a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("\\/dna\\:a\\/b\\/c"));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathSegmentTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathSegmentTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathSegmentTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,174 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.junit.Assert.assertThat;
-import org.jboss.dna.common.text.Jsr283Encoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class BasicPathSegmentTest {
-
-    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
-
-    private BasicNamespaceRegistry registry;
-    private ValueFactory<String> stringValueFactory;
-    private NameValueFactory nameFactory;
-    private PathValueFactory factory;
-    private Name validName;
-    private Path.Segment segment;
-    private Path.Segment segment2;
-
-    @Before
-    public void beforeEach() {
-        this.registry = new BasicNamespaceRegistry();
-        this.registry.register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
-        this.stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
-        this.nameFactory = new NameValueFactory(registry, Path.DEFAULT_DECODER, stringValueFactory);
-        this.validName = nameFactory.create("dna:something");
-        this.factory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameFactory);
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoSegmentsWithSameNameAndIndex() {
-        segment = new BasicPathSegment(validName);
-        segment2 = new BasicPathSegment(validName);
-        assertThat(segment.equals(segment2), is(true));
-        assertThat(segment.isSelfReference(), is(false));
-        assertThat(segment.isParentReference(), is(false));
-        assertThat(segment.getName(), is(validName));
-    }
-
-    @Test
-    public void shouldHaveIndexSpecifiedInConstructor() {
-        segment = new BasicPathSegment(validName, 3);
-        assertThat(segment.getIndex(), is(3));
-        assertThat(segment.hasIndex(), is(true));
-        assertThat(segment.isSelfReference(), is(false));
-        assertThat(segment.isParentReference(), is(false));
-        assertThat(segment.getName(), is(validName));
-    }
-
-    @Test
-    public void shouldNotHaveIndexByDefault() {
-        segment = new BasicPathSegment(validName);
-        assertThat(segment.getIndex(), is(Path.NO_INDEX));
-        assertThat(segment.hasIndex(), is(false));
-        assertThat(segment.isSelfReference(), is(false));
-        assertThat(segment.isParentReference(), is(false));
-        assertThat(segment.getName(), is(validName));
-    }
-
-    @Test
-    public void shouldCreateSelfReferenceSegmentIfPassedSelfReferenceStringRegardlessOfIndex() {
-        segment = factory.createSegment(Path.SELF);
-        assertThat(segment.getIndex(), is(Path.NO_INDEX));
-        assertThat(segment.hasIndex(), is(false));
-        assertThat(segment.isSelfReference(), is(true));
-        assertThat(segment.isParentReference(), is(false));
-        assertThat(segment.getName().getLocalName(), is(Path.SELF));
-        assertThat(segment.getName().getNamespaceUri().length(), is(0));
-
-        segment = factory.createSegment(Path.SELF, 1);
-        assertThat(segment.getIndex(), is(Path.NO_INDEX));
-        assertThat(segment.hasIndex(), is(false));
-        assertThat(segment.isSelfReference(), is(true));
-        assertThat(segment.isParentReference(), is(false));
-        assertThat(segment.getName().getLocalName(), is(Path.SELF));
-        assertThat(segment.getName().getNamespaceUri().length(), is(0));
-    }
-
-    @Test
-    public void shouldCreateParentReferenceSegmentIfPassedParentReferenceStringRegardlessOfIndex() {
-        segment = factory.createSegment(Path.PARENT);
-        assertThat(segment.getIndex(), is(Path.NO_INDEX));
-        assertThat(segment.hasIndex(), is(false));
-        assertThat(segment.isSelfReference(), is(false));
-        assertThat(segment.isParentReference(), is(true));
-        assertThat(segment.getName().getLocalName(), is(Path.PARENT));
-        assertThat(segment.getName().getNamespaceUri().length(), is(0));
-
-        segment = factory.createSegment(Path.PARENT, 1);
-        assertThat(segment.getIndex(), is(Path.NO_INDEX));
-        assertThat(segment.hasIndex(), is(false));
-        assertThat(segment.isSelfReference(), is(false));
-        assertThat(segment.isParentReference(), is(true));
-        assertThat(segment.getName().getLocalName(), is(Path.PARENT));
-        assertThat(segment.getName().getNamespaceUri().length(), is(0));
-    }
-
-    @Test
-    public void shouldConsiderSegmentCreatedWithSelfReferenceToBeEqualToStaticSingleton() {
-        segment = factory.createSegment(Path.SELF);
-        assertThat(segment.equals(Path.SELF_SEGMENT), is(true));
-    }
-
-    @Test
-    public void shouldConsiderSegmentCreatedWithParentReferenceToBeEqualToStaticSingleton() {
-        segment = factory.createSegment(Path.PARENT);
-        assertThat(segment.equals(Path.PARENT_SEGMENT), is(true));
-    }
-
-    @Test
-    public void shouldConsiderSegmentWithSameNameSiblingIndexOfOneToBeEqualToSegmentWithSameNameButNoIndex() {
-        segment = new BasicPathSegment(validName, Path.NO_INDEX);
-        Path.Segment segment2 = new BasicPathSegment(validName, 1);
-        assertThat(segment, is(segment2));
-    }
-
-    @Test
-    public void shouldConsiderSegmentWithSameNameSiblingIndexOfTwoOrMoreToNotBeEqualToSegmentWithSameNameButNoIndex() {
-        segment = new BasicPathSegment(validName, Path.NO_INDEX);
-        Path.Segment segment2 = new BasicPathSegment(validName, 2);
-        assertThat(segment, is(not(segment2)));
-        segment2 = new BasicPathSegment(validName, 3);
-        assertThat(segment, is(not(segment2)));
-    }
-
-    @Test
-    public void shouldUseDelimiterEncoderToEncodeDelimiterBetweenPrefixAndLocalPart() {
-        TextEncoder encoder = new Jsr283Encoder();
-        validName = new BasicName(DnaLexicon.Namespace.URI, "some:name:with:colons");
-        segment = new BasicPathSegment(validName, Path.NO_INDEX);
-        TextEncoder delimiterEncoder = new TextEncoder() {
-            public String encode( String text ) {
-                if (":".equals(text)) return "\\:";
-                if ("{".equals(text)) return "\\{";
-                if ("}".equals(text)) return "\\}";
-                return text;
-            }
-        };
-        assertThat(segment.getString(registry, encoder, delimiterEncoder), is("dna\\:some\uf03aname\uf03awith\uf03acolons"));
-        assertThat(segment.getString(null, encoder, delimiterEncoder), is("\\{" + encoder.encode(DnaLexicon.Namespace.URI)
-                                                                          + "\\}some\uf03aname\uf03awith\uf03acolons"));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathSegmentTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathSegmentTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathSegmentTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathSegmentTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,180 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.common.text.Jsr283Encoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.BasicPathSegment;
+import org.jboss.dna.graph.property.basic.NameValueFactory;
+import org.jboss.dna.graph.property.basic.PathValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicPathSegmentTest {
+
+    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+
+    private BasicNamespaceRegistry registry;
+    private ValueFactory<String> stringValueFactory;
+    private NameValueFactory nameFactory;
+    private PathValueFactory factory;
+    private Name validName;
+    private Path.Segment segment;
+    private Path.Segment segment2;
+
+    @Before
+    public void beforeEach() {
+        this.registry = new BasicNamespaceRegistry();
+        this.registry.register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
+        this.stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
+        this.nameFactory = new NameValueFactory(registry, Path.DEFAULT_DECODER, stringValueFactory);
+        this.validName = nameFactory.create("dna:something");
+        this.factory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameFactory);
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoSegmentsWithSameNameAndIndex() {
+        segment = new BasicPathSegment(validName);
+        segment2 = new BasicPathSegment(validName);
+        assertThat(segment.equals(segment2), is(true));
+        assertThat(segment.isSelfReference(), is(false));
+        assertThat(segment.isParentReference(), is(false));
+        assertThat(segment.getName(), is(validName));
+    }
+
+    @Test
+    public void shouldHaveIndexSpecifiedInConstructor() {
+        segment = new BasicPathSegment(validName, 3);
+        assertThat(segment.getIndex(), is(3));
+        assertThat(segment.hasIndex(), is(true));
+        assertThat(segment.isSelfReference(), is(false));
+        assertThat(segment.isParentReference(), is(false));
+        assertThat(segment.getName(), is(validName));
+    }
+
+    @Test
+    public void shouldNotHaveIndexByDefault() {
+        segment = new BasicPathSegment(validName);
+        assertThat(segment.getIndex(), is(Path.NO_INDEX));
+        assertThat(segment.hasIndex(), is(false));
+        assertThat(segment.isSelfReference(), is(false));
+        assertThat(segment.isParentReference(), is(false));
+        assertThat(segment.getName(), is(validName));
+    }
+
+    @Test
+    public void shouldCreateSelfReferenceSegmentIfPassedSelfReferenceStringRegardlessOfIndex() {
+        segment = factory.createSegment(Path.SELF);
+        assertThat(segment.getIndex(), is(Path.NO_INDEX));
+        assertThat(segment.hasIndex(), is(false));
+        assertThat(segment.isSelfReference(), is(true));
+        assertThat(segment.isParentReference(), is(false));
+        assertThat(segment.getName().getLocalName(), is(Path.SELF));
+        assertThat(segment.getName().getNamespaceUri().length(), is(0));
+
+        segment = factory.createSegment(Path.SELF, 1);
+        assertThat(segment.getIndex(), is(Path.NO_INDEX));
+        assertThat(segment.hasIndex(), is(false));
+        assertThat(segment.isSelfReference(), is(true));
+        assertThat(segment.isParentReference(), is(false));
+        assertThat(segment.getName().getLocalName(), is(Path.SELF));
+        assertThat(segment.getName().getNamespaceUri().length(), is(0));
+    }
+
+    @Test
+    public void shouldCreateParentReferenceSegmentIfPassedParentReferenceStringRegardlessOfIndex() {
+        segment = factory.createSegment(Path.PARENT);
+        assertThat(segment.getIndex(), is(Path.NO_INDEX));
+        assertThat(segment.hasIndex(), is(false));
+        assertThat(segment.isSelfReference(), is(false));
+        assertThat(segment.isParentReference(), is(true));
+        assertThat(segment.getName().getLocalName(), is(Path.PARENT));
+        assertThat(segment.getName().getNamespaceUri().length(), is(0));
+
+        segment = factory.createSegment(Path.PARENT, 1);
+        assertThat(segment.getIndex(), is(Path.NO_INDEX));
+        assertThat(segment.hasIndex(), is(false));
+        assertThat(segment.isSelfReference(), is(false));
+        assertThat(segment.isParentReference(), is(true));
+        assertThat(segment.getName().getLocalName(), is(Path.PARENT));
+        assertThat(segment.getName().getNamespaceUri().length(), is(0));
+    }
+
+    @Test
+    public void shouldConsiderSegmentCreatedWithSelfReferenceToBeEqualToStaticSingleton() {
+        segment = factory.createSegment(Path.SELF);
+        assertThat(segment.equals(Path.SELF_SEGMENT), is(true));
+    }
+
+    @Test
+    public void shouldConsiderSegmentCreatedWithParentReferenceToBeEqualToStaticSingleton() {
+        segment = factory.createSegment(Path.PARENT);
+        assertThat(segment.equals(Path.PARENT_SEGMENT), is(true));
+    }
+
+    @Test
+    public void shouldConsiderSegmentWithSameNameSiblingIndexOfOneToBeEqualToSegmentWithSameNameButNoIndex() {
+        segment = new BasicPathSegment(validName, Path.NO_INDEX);
+        Path.Segment segment2 = new BasicPathSegment(validName, 1);
+        assertThat(segment, is(segment2));
+    }
+
+    @Test
+    public void shouldConsiderSegmentWithSameNameSiblingIndexOfTwoOrMoreToNotBeEqualToSegmentWithSameNameButNoIndex() {
+        segment = new BasicPathSegment(validName, Path.NO_INDEX);
+        Path.Segment segment2 = new BasicPathSegment(validName, 2);
+        assertThat(segment, is(not(segment2)));
+        segment2 = new BasicPathSegment(validName, 3);
+        assertThat(segment, is(not(segment2)));
+    }
+
+    @Test
+    public void shouldUseDelimiterEncoderToEncodeDelimiterBetweenPrefixAndLocalPart() {
+        TextEncoder encoder = new Jsr283Encoder();
+        validName = new BasicName(DnaLexicon.Namespace.URI, "some:name:with:colons");
+        segment = new BasicPathSegment(validName, Path.NO_INDEX);
+        TextEncoder delimiterEncoder = new TextEncoder() {
+            public String encode( String text ) {
+                if (":".equals(text)) return "\\:";
+                if ("{".equals(text)) return "\\{";
+                if ("}".equals(text)) return "\\}";
+                return text;
+            }
+        };
+        assertThat(segment.getString(registry, encoder, delimiterEncoder), is("dna\\:some\uf03aname\uf03awith\uf03acolons"));
+        assertThat(segment.getString(null, encoder, delimiterEncoder), is("\\{" + encoder.encode(DnaLexicon.Namespace.URI)
+                                                                          + "\\}some\uf03aname\uf03awith\uf03acolons"));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,882 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.jboss.dna.graph.properties.basic.IsPathContaining.hasSegments;
-import static org.junit.Assert.assertThat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.common.text.Jsr283Encoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
-import org.jboss.dna.graph.properties.basic.BasicPath;
-import org.jboss.dna.graph.properties.basic.BasicPathSegment;
-import org.jboss.dna.graph.properties.basic.NameValueFactory;
-import org.jboss.dna.graph.properties.basic.PathValueFactory;
-import org.jboss.dna.graph.properties.basic.RootPath;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class BasicPathTest extends AbstractPathTest {
-
-    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
-    public static final Path ROOT = RootPath.INSTANCE;
-
-    private BasicNamespaceRegistry namespaceRegistry;
-    private String validNamespaceUri;
-    private Path path2;
-    private Path.Segment[] validSegments;
-    private List<Path.Segment> validSegmentsList;
-    private Name[] validSegmentNames;
-    private String validNamespacePrefix;
-    private PathValueFactory pathFactory;
-
-    @Before
-    @Override
-    public void beforeEach() {
-        validNamespacePrefix = DnaLexicon.Namespace.PREFIX;
-        validNamespaceUri = DnaLexicon.Namespace.URI;
-        validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"), new BasicName(validNamespaceUri, "b"),
-            new BasicName(validNamespaceUri, "c")};
-        validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]),
-            new BasicPathSegment(validSegmentNames[1]), new BasicPathSegment(validSegmentNames[1])};
-        validSegmentsList = new ArrayList<Path.Segment>();
-        for (Path.Segment segment : validSegments) {
-            validSegmentsList.add(segment);
-        }
-        super.path = new BasicPath(validSegmentsList, true);
-        namespaceRegistry = new BasicNamespaceRegistry();
-        namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
-        StringValueFactory stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
-        NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry, Path.DEFAULT_DECODER, stringValueFactory);
-        pathFactory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameValueFactory);
-    }
-
-    @Test
-    public void shouldCreateAbsolutePathFromListOfValidSegments() {
-        path = new BasicPath(validSegmentsList, true);
-        assertThat(path.isAbsolute(), is(true));
-        assertThat(path.isNormalized(), is(true));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateRelativePathFromListOfValidSegments() {
-        path = new BasicPath(validSegmentsList, false);
-        assertThat(path.isAbsolute(), is(false));
-        assertThat(path.isNormalized(), is(true));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateAbsolutePathWithParentSegment() {
-        validSegmentsList.add(Path.PARENT_SEGMENT);
-        path = new BasicPath(validSegmentsList, true);
-        assertThat(path.isAbsolute(), is(true));
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateRelativePathWithParentSegment() {
-        validSegmentsList.add(Path.PARENT_SEGMENT);
-        path = new BasicPath(validSegmentsList, false);
-        assertThat(path.isAbsolute(), is(false));
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateAbsolutePathWithSelfSegment() {
-        validSegmentsList.add(Path.SELF_SEGMENT);
-        path = new BasicPath(validSegmentsList, true);
-        assertThat(path.isAbsolute(), is(true));
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreateRelativePathWithSelfSegment() {
-        validSegmentsList.add(Path.SELF_SEGMENT);
-        path = new BasicPath(validSegmentsList, false);
-        assertThat(path.isAbsolute(), is(false));
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getSegmentsList(), is(validSegmentsList));
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldCreatePathWithNoNamespacePrefixes() {
-        path = pathFactory.create("/a/b/c/");
-        assertThat(path.size(), is(3));
-        assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
-    }
-
-    @Test
-    public void shouldConstructRelativePath() {
-        assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
-        assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
-        assertThat(pathFactory.create("a/b/c").size(), is(3));
-        assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry), is("a/b/c"));
-    }
-
-    @Test
-    public void shouldConstructRelativePathToSelf() {
-        assertThat(pathFactory.create(".").isAbsolute(), is(false));
-        assertThat(pathFactory.create(".").size(), is(1));
-        assertThat(pathFactory.create("."), hasSegments(pathFactory, Path.SELF));
-
-        assertThat(pathFactory.create("./").isAbsolute(), is(false));
-        assertThat(pathFactory.create("./").size(), is(1));
-        assertThat(pathFactory.create("./"), hasSegments(pathFactory, Path.SELF));
-    }
-
-    @Test
-    public void shouldConstructRelativePathToParent() {
-        assertThat(pathFactory.create("..").isAbsolute(), is(false));
-        assertThat(pathFactory.create("..").size(), is(1));
-        assertThat(pathFactory.create(".."), hasSegments(pathFactory, Path.PARENT));
-
-        assertThat(pathFactory.create("../").isAbsolute(), is(false));
-        assertThat(pathFactory.create("../").size(), is(1));
-        assertThat(pathFactory.create("../"), hasSegments(pathFactory, Path.PARENT));
-    }
-
-    @Test
-    public void shouldConstructRootPathFromStringWithSingleDelimiter() {
-        assertThat(pathFactory.create("/"), is(ROOT));
-        assertThat(pathFactory.create("/").isRoot(), is(true));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotConstructPathWithSuccessiveDelimiters() {
-        pathFactory.create("///a/b///c//d//");
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotConstructPathWithOnlyDelimiters() {
-        pathFactory.create("///");
-    }
-
-    @Test
-    public void shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
-        assertThat(pathFactory.create(" \t /  \t").toString(), is("/"));
-    }
-
-    @Test
-    public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
-        assertThat(pathFactory.create("a"), hasSegments(pathFactory, "a"));
-    }
-
-    @Test
-    public void shouldHaveSizeThatReflectsNumberOfSegments() {
-        assertThat(path.size(), is(validSegmentsList.size()));
-    }
-
-    @Test
-    public void shouldIterateOverAllSegmentsReturnedByList() {
-        Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
-        for (Path.Segment segment : path) {
-            assertThat(segment, is(expectedIter.next()));
-        }
-
-        expectedIter = path.getSegmentsList().iterator();
-        for (Path.Segment segment : path) {
-            assertThat(segment, is(expectedIter.next()));
-        }
-    }
-
-    @Test
-    public void shouldReturnAncestorForNodeOtherThanRoot() {
-        assertThat(path.getParent(), is(pathFactory.create("/dna:a/dna:b")));
-        assertThat(path.getParent().getParent(), is(pathFactory.create("/dna:a")));
-        assertThat(path.getParent().getParent().getParent(), is(ROOT));
-    }
-
-    @Test
-    public void shouldReturnNthDegreeAncestor() {
-        assertThat(path.getAncestor(1), is(pathFactory.create("/dna:a/dna:b")));
-        assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
-        assertThat(path.getAncestor(3), is(ROOT));
-    }
-
-    @Test
-    public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
-        assertThat(path.getCommonAncestor(ROOT), is(ROOT));
-        assertThat(ROOT.getCommonAncestor(path), is(ROOT));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
-        path.getCommonAncestor(null);
-    }
-
-    @Test
-    public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path common = pathFactory.create("/a");
-        assertThat(path1.getCommonAncestor(path2), is(common));
-
-        path1 = pathFactory.create("/a/b/c");
-        path2 = pathFactory.create("/a/b/c/d");
-        common = path1;
-        assertThat(path1.getCommonAncestor(path2), is(common));
-
-        path1 = pathFactory.create("/a/b/c/x/y/");
-        path2 = pathFactory.create("/a/b/c/d/e/f/");
-        common = pathFactory.create("/a/b/c");
-        assertThat(path1.getCommonAncestor(path2), is(common));
-    }
-
-    @Test
-    public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
-        Path path1 = pathFactory.create("/x/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path common = ROOT;
-        assertThat(path1.getCommonAncestor(path2), is(common));
-    }
-
-    @Test
-    public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        Path common = pathFactory.create("/a");
-        assertThat(common.isAncestorOf(path1), is(true));
-        assertThat(common.isAncestorOf(path2), is(true));
-        assertThat(common.isAncestorOf(path3), is(false));
-
-        assertThat(path1.getParent().isAncestorOf(path1), is(true));
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
-        }
-    }
-
-    @Test
-    public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        Path common = pathFactory.create("/a");
-        assertThat(path1.isDecendantOf(common), is(true));
-        assertThat(path2.isDecendantOf(common), is(true));
-        assertThat(path3.isDecendantOf(common), is(false));
-
-        assertThat(path1.getParent().isAncestorOf(path1), is(true));
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
-        }
-    }
-
-    @Override
-    @Test
-    public void shouldNotConsiderNodeToBeAncestorOfItself() {
-        super.shouldNotConsiderNodeToBeAncestorOfItself();
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        assertThat(path1.isAncestorOf(path1), is(false));
-        assertThat(path2.isAncestorOf(path2), is(false));
-        assertThat(path3.isAncestorOf(path3), is(false));
-        assertThat(ROOT.isAncestorOf(ROOT), is(false));
-    }
-
-    @Override
-    @Test
-    public void shouldNotConsiderNodeToBeDecendantOfItself() {
-        super.shouldNotConsiderNodeToBeDecendantOfItself();
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        assertThat(path1.isDecendantOf(path1), is(false));
-        assertThat(path2.isDecendantOf(path2), is(false));
-        assertThat(path3.isDecendantOf(path3), is(false));
-        assertThat(ROOT.isDecendantOf(ROOT), is(false));
-    }
-
-    @Test
-    public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path common = pathFactory.create("/a");
-        assertThat(ROOT.isDecendantOf(path1), is(false));
-        assertThat(ROOT.isDecendantOf(path2), is(false));
-        assertThat(ROOT.isDecendantOf(path3), is(false));
-        assertThat(ROOT.isDecendantOf(common), is(false));
-    }
-
-    @Test
-    public void shouldConsiderRootToBeAncestorOfAnyNode() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path common = pathFactory.create("/a");
-        assertThat(ROOT.isAncestorOf(path1), is(true));
-        assertThat(ROOT.isAncestorOf(path2), is(true));
-        assertThat(ROOT.isAncestorOf(path3), is(true));
-        assertThat(ROOT.isAncestorOf(common), is(true));
-    }
-
-    @Test
-    public void shouldConsiderTwoNotRootSiblingNodesToHaveSameAncestor() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/y/c");
-        assertThat(path1.hasSameAncestor(path2), is(true));
-
-        path1 = pathFactory.create("/a/z");
-        path2 = pathFactory.create("/a/c");
-        assertThat(path1.hasSameAncestor(path2), is(true));
-
-        path1 = pathFactory.create("/z");
-        path2 = pathFactory.create("/c");
-        assertThat(path1.hasSameAncestor(path2), is(true));
-    }
-
-    @Test
-    public void shouldNotConsiderTwoNonSiblingNodesToHaveSameAncestor() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/x/c");
-        assertThat(path1.hasSameAncestor(path2), is(false));
-
-        path1 = pathFactory.create("/a/z");
-        path2 = pathFactory.create("/b/c");
-        assertThat(path1.hasSameAncestor(path2), is(false));
-
-        path1 = pathFactory.create("/z");
-        path2 = pathFactory.create("/a/c");
-        assertThat(path1.hasSameAncestor(path2), is(false));
-    }
-
-    @Test
-    public void shouldConsiderAncestorToBeAtOrAboveTheDecendant() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.getAncestor(i).isAtOrAbove(path1), is(true));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.getAncestor(i).isAtOrAbove(path2), is(true));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.getAncestor(i).isAtOrAbove(path3), is(true));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.getAncestor(i).isAtOrAbove(path4), is(true));
-        }
-    }
-
-    @Test
-    public void shouldConsiderDecendantToBeAtOrBelowTheAncestor() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.isAtOrBelow(path1.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.isAtOrBelow(path2.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.isAtOrBelow(path3.getAncestor(i)), is(true));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.isAtOrBelow(path4.getAncestor(i)), is(true));
-        }
-    }
-
-    @Test
-    public void shouldNotConsiderAncestorToBeAtOrBelowTheDecendant() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.getAncestor(i).isAtOrBelow(path1), is(false));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.getAncestor(i).isAtOrBelow(path2), is(false));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.getAncestor(i).isAtOrBelow(path3), is(false));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.getAncestor(i).isAtOrBelow(path4), is(false));
-        }
-    }
-
-    @Test
-    public void shouldNotConsiderDecendantToBeAtOrAboveTheAncestor() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
-        for (int i = 1; i < path1.size(); ++i) {
-            assertThat(path1.isAtOrAbove(path1.getAncestor(i)), is(false));
-        }
-        for (int i = 1; i < path2.size(); ++i) {
-            assertThat(path2.isAtOrAbove(path2.getAncestor(i)), is(false));
-        }
-        for (int i = 1; i < path3.size(); ++i) {
-            assertThat(path3.isAtOrAbove(path3.getAncestor(i)), is(false));
-        }
-        for (int i = 1; i < path4.size(); ++i) {
-            assertThat(path4.isAtOrAbove(path4.getAncestor(i)), is(false));
-        }
-    }
-
-    @Test
-    public void shouldReturnLastSegmentOfNonRootPath() {
-        Path path1 = pathFactory.create("/a/y/z");
-        Path path2 = pathFactory.create("/a/b/c");
-        Path path3 = pathFactory.create("/x/b/c");
-        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
-        assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
-        assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
-        assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
-        assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
-    }
-
-    @Test
-    public void shouldNormalizePathWithSelfAndParentReferences() {
-        path = pathFactory.create("/a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getNormalizedPath().isAbsolute(), is(true));
-        assertThat(path.getNormalizedPath().isNormalized(), is(true));
-
-        path = pathFactory.create("a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getNormalizedPath().isAbsolute(), is(false));
-        assertThat(path.getNormalizedPath().isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
-        assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
-        assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
-        assertThat(pathFactory.create("a").isNormalized(), is(true));
-        assertThat(pathFactory.create("/a").isNormalized(), is(true));
-        assertThat(ROOT.isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
-        assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(), is(false));
-        assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(), is(false));
-        assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
-        assertThat(pathFactory.create("/a/b/c/../d").isNormalized(), is(false));
-        assertThat(pathFactory.create(".").isNormalized(), is(false));
-        assertThat(pathFactory.create("/.").isNormalized(), is(false));
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
-        path = pathFactory.create("/a/../../../..");
-        assertThat(path.isNormalized(), is(false));
-        path.getNormalizedPath();
-    }
-
-    @Test
-    public void shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
-        // "/a/../b/../c/.." => "/"
-        path = pathFactory.create("/a/../b/../c/../");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), is(ROOT));
-    }
-
-    @Test
-    public void shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
-        // "a/../b/../c/.." => "."
-        path = pathFactory.create("a/../b/../c/../");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath().size(), is(1));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
-    }
-
-    @Test
-    public void shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
-        path = pathFactory.create("/a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getNormalizedPath().isAbsolute(), is(true));
-        assertThat(path.getNormalizedPath().isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
-        path = pathFactory.create("a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getNormalizedPath().isAbsolute(), is(false));
-        assertThat(path.getNormalizedPath().isNormalized(), is(true));
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
-        pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
-    }
-
-    @Test
-    public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
-        path = pathFactory.create("/a/b/c/../d/./e/../..");
-        assertThat(path.isNormalized(), is(false));
-        assertThat(path.isAbsolute(), is(true));
-        assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a", "b"));
-        assertThat(path.getCanonicalPath().isAbsolute(), is(true));
-        assertThat(path.getCanonicalPath().isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
-        testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
-        testSegmentsByIteratorAndListAndArray("/a/b/c", "a", "b", "c");
-        testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
-        testSegmentsByIteratorAndListAndArray("a/b/c", "a", "b", "c");
-        testSegmentsByIteratorAndListAndArray("");
-        testSegmentsByIteratorAndListAndArray(ROOT.getString());
-    }
-
-    public void testSegmentsByIteratorAndListAndArray( String pathStr,
-                                                       String... expectedSegmentStrings ) {
-        path = pathFactory.create(pathStr);
-        assertThat(expectedSegmentStrings.length, is(path.size()));
-        Path.Segment[] segmentArray = path.getSegmentsArray();
-        List<Path.Segment> segmentList = path.getSegmentsList();
-        assertThat(segmentArray.length, is(path.size()));
-        assertThat(segmentList.size(), is(path.size()));
-        Iterator<Path.Segment> iter = path.iterator();
-        Iterator<Path.Segment> listIter = segmentList.iterator();
-        for (int i = 0; i != path.size(); ++i) {
-            Path.Segment expected = pathFactory.createSegment(expectedSegmentStrings[i]);
-            assertThat(path.getSegment(i), is(expected));
-            assertThat(segmentArray[i], is(expected));
-            assertThat(segmentList.get(i), is(expected));
-            assertThat(iter.next(), is(expected));
-            assertThat(listIter.next(), is(expected));
-        }
-        assertThat(iter.hasNext(), is(false));
-        assertThat(listIter.hasNext(), is(false));
-    }
-
-    @Test
-    public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.getString(NO_OP_ENCODER),
-                   is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../{}d/./{http://www.jboss.org/dna}e/../.."));
-    }
-
-    @Test
-    public void shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna:a/b/dna:c/../d/./dna:e/../.."));
-        namespaceRegistry.register("dna2", validNamespaceUri);
-        assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(-1);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(path.size() + 1);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(path.size() + 1, path.size() + 2);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(2, 1);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        path.subpath(2, path.size() + 1);
-    }
-
-    @Test
-    public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.subpath(0, 0), is(ROOT));
-    }
-
-    @Test
-    public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(0), is(path));
-        assertThat(path.subpath(0), is(sameInstance(path)));
-        assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
-        assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
-        assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
-
-        path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(0), is(path));
-        assertThat(path.subpath(0), is(sameInstance(path)));
-        assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
-        assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
-        assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
-    }
-
-    @Test
-    public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
-        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
-        assertThat(path.subpath(0, path.size()), hasSegments(pathFactory,
-                                                             "dna:a",
-                                                             "b",
-                                                             "dna:c",
-                                                             "..",
-                                                             "d",
-                                                             ".",
-                                                             "dna:e",
-                                                             "..",
-                                                             ".."));
-        assertThat(path.subpath(0, path.size()), is(path));
-        assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
-        assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(2, path.size()), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
-        assertThat(path.subpath(6, path.size()), hasSegments(pathFactory, "dna:e", "..", ".."));
-        assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..", ".."));
-        assertThat(path.subpath(8, path.size()), hasSegments(pathFactory, ".."));
-
-        assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a", "b"));
-        assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
-        assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b", "dna:c", "..", "d"));
-        assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c", "..", "d"));
-        assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..", "d"));
-    }
-
-    @Test
-    public void shouldFindRelativePaths() {
-        path = pathFactory.create("/a/b/c/d");
-        assertThat(path.relativeTo(pathFactory.create("/a/e/f")), is(pathFactory.create("../../b/c/d")));
-        assertThat(path.relativeTo(pathFactory.create("/e/f")), is(pathFactory.create("../../a/b/c/d")));
-
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
-        path = pathFactory.create("a/b/c/d");
-        path.relativeTo(pathFactory.create("/e/f"));
-
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotResolveRelativePathToAnotherRelativePath() {
-        path = pathFactory.create("/a/b/c/d");
-        path.relativeTo(pathFactory.create("e/f"));
-
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
-        path = pathFactory.create("/a/b/c/d");
-        path.resolve(pathFactory.create("/e/f"));
-    }
-
-    @Test
-    public void shouldResolveRelativePathToAbsolutePath() {
-        path = pathFactory.create("/a/b/c/d");
-        path2 = path.resolve(pathFactory.create("../../e/f"));
-        assertThat(path2, is(pathFactory.create("/a/b/e/f")));
-        assertThat(path2.isAbsolute(), is(true));
-        assertThat(path2.isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldOrderPathsCorrectly() {
-        List<Path> paths = new ArrayList<Path>();
-        paths.add(pathFactory.create("/a"));
-        paths.add(pathFactory.create("/a/b"));
-        paths.add(pathFactory.create("/a/b/alpha"));
-        paths.add(pathFactory.create("/a/b/beta"));
-        paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
-        paths.add(pathFactory.create("/a/b/dna:name"));
-        paths.add(pathFactory.create("/a/b/dna:primaryType"));
-        paths.add(pathFactory.create("/a/c[1]"));
-        paths.add(pathFactory.create("/a/c[1]/alpha"));
-        paths.add(pathFactory.create("/a/c[1]/beta"));
-        paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
-        paths.add(pathFactory.create("/a/c[1]/dna:name"));
-        paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
-        paths.add(pathFactory.create("/a/c[2]"));
-        paths.add(pathFactory.create("/a/c[2]/alpha"));
-        paths.add(pathFactory.create("/a/c[2]/beta"));
-        paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
-        paths.add(pathFactory.create("/a/c[2]/dna:name"));
-        paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
-
-        // Randomize the list of paths, so we have something to sort ...
-        List<Path> randomizedPaths = new ArrayList<Path>(paths);
-        Collections.shuffle(randomizedPaths);
-        assertThat(randomizedPaths, is(not(paths)));
-
-        // Sort ...
-        Collections.sort(randomizedPaths);
-        assertThat(randomizedPaths, is(paths));
-    }
-
-    @Test
-    public void shouldGetNormalizedPathOfSelfShouldBeSame() {
-        assertThat(pathFactory.create(".").getNormalizedPath(), is(pathFactory.create(".")));
-        assertThat(pathFactory.create("./").getNormalizedPath(), is(pathFactory.create(".")));
-        assertThat(pathFactory.create("./././").getNormalizedPath(), is(pathFactory.create(".")));
-    }
-
-    @Test
-    public void shouldGetNormalizedPathWithParentReferences() {
-        assertThat(pathFactory.create("..").getNormalizedPath(), is(pathFactory.create("..")));
-        assertThat(pathFactory.create("../").getNormalizedPath(), is(pathFactory.create("../")));
-        assertThat(pathFactory.create("../../../../../..").getNormalizedPath(), is(pathFactory.create("../../../../../..")));
-    }
-
-    @Test
-    public void shouldGetRelativePathUsingSelf() {
-        path = pathFactory.create("/a/b/c/d/e/f");
-        assertThat(path.resolve(pathFactory.create(".")), is(sameInstance(path)));
-        assertThat(path.resolve(pathFactory.create("././.")), is(sameInstance(path)));
-    }
-
-    @Test
-    public void shouldResolveRelativePathToParent() {
-        path = pathFactory.create("/a/b/c/d/e/f");
-        assertThat(path.resolve(pathFactory.create("..")), is(path.getParent()));
-        assertThat(path.resolve(pathFactory.create("..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
-    }
-
-    @Test
-    public void shouldResolveRelativePaths() {
-        path = pathFactory.create("/a/b/c/d/e/f");
-        assertThat(path.resolve(pathFactory.create("../../../../../..")), is(ROOT));
-        assertThat(path.resolve(pathFactory.create("../..")), is(path.getParent().getParent()));
-        assertThat(path.resolve(pathFactory.create("../..")), hasSegments(pathFactory, "a", "b", "c", "d"));
-        assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), is(path.getParent()));
-        assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
-        assertThat(path.resolve(pathFactory.create("../x")), hasSegments(pathFactory, "a", "b", "c", "d", "e", "x"));
-    }
-
-    public void shouldResolveNonAbsolutePaths() {
-        path = pathFactory.create("a/b/c");
-        assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
-    }
-
-    @Test
-    public void shouldConvertPathToString() {
-        TextEncoder encoder = new Jsr283Encoder();
-        TextEncoder delimEncoder = new TextEncoder() {
-            public String encode( String text ) {
-                if ("/".equals(text)) return "\\/";
-                if (":".equals(text)) return "\\:";
-                if ("{".equals(text)) return "\\{";
-                if ("}".equals(text)) return "\\}";
-                return text;
-            }
-        };
-        Path path = pathFactory.create("a/b/c");
-        assertThat(path.getString(namespaceRegistry), is("a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder), is("a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("a\\/b\\/c"));
-
-        path = pathFactory.create("/a/b/c");
-        assertThat(path.getString(namespaceRegistry), is("/a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder), is("/a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("\\/a\\/b\\/c"));
-
-        path = pathFactory.create("/dna:a/b/c");
-        assertThat(path.getString(encoder), is("/{" + encoder.encode(DnaLexicon.Namespace.URI) + "}a/{}b/{}c"));
-        assertThat(path.getString(null, encoder, delimEncoder), is("\\/\\{" + encoder.encode(DnaLexicon.Namespace.URI)
-                                                                   + "\\}a\\/\\{\\}b\\/\\{\\}c"));
-        assertThat(path.getString(namespaceRegistry), is("/dna:a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder), is("/dna:a/b/c"));
-        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("\\/dna\\:a\\/b\\/c"));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicPathTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,882 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.jboss.dna.graph.property.basic.IsPathContaining.hasSegments;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.common.text.Jsr283Encoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.BasicPath;
+import org.jboss.dna.graph.property.basic.BasicPathSegment;
+import org.jboss.dna.graph.property.basic.NameValueFactory;
+import org.jboss.dna.graph.property.basic.PathValueFactory;
+import org.jboss.dna.graph.property.basic.RootPath;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class BasicPathTest extends AbstractPathTest {
+
+    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+    public static final Path ROOT = RootPath.INSTANCE;
+
+    private BasicNamespaceRegistry namespaceRegistry;
+    private String validNamespaceUri;
+    private Path path2;
+    private Path.Segment[] validSegments;
+    private List<Path.Segment> validSegmentsList;
+    private Name[] validSegmentNames;
+    private String validNamespacePrefix;
+    private PathValueFactory pathFactory;
+
+    @Before
+    @Override
+    public void beforeEach() {
+        validNamespacePrefix = DnaLexicon.Namespace.PREFIX;
+        validNamespaceUri = DnaLexicon.Namespace.URI;
+        validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"), new BasicName(validNamespaceUri, "b"),
+            new BasicName(validNamespaceUri, "c")};
+        validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]),
+            new BasicPathSegment(validSegmentNames[1]), new BasicPathSegment(validSegmentNames[1])};
+        validSegmentsList = new ArrayList<Path.Segment>();
+        for (Path.Segment segment : validSegments) {
+            validSegmentsList.add(segment);
+        }
+        super.path = new BasicPath(validSegmentsList, true);
+        namespaceRegistry = new BasicNamespaceRegistry();
+        namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
+        StringValueFactory stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
+        NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry, Path.DEFAULT_DECODER, stringValueFactory);
+        pathFactory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameValueFactory);
+    }
+
+    @Test
+    public void shouldCreateAbsolutePathFromListOfValidSegments() {
+        path = new BasicPath(validSegmentsList, true);
+        assertThat(path.isAbsolute(), is(true));
+        assertThat(path.isNormalized(), is(true));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateRelativePathFromListOfValidSegments() {
+        path = new BasicPath(validSegmentsList, false);
+        assertThat(path.isAbsolute(), is(false));
+        assertThat(path.isNormalized(), is(true));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateAbsolutePathWithParentSegment() {
+        validSegmentsList.add(Path.PARENT_SEGMENT);
+        path = new BasicPath(validSegmentsList, true);
+        assertThat(path.isAbsolute(), is(true));
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateRelativePathWithParentSegment() {
+        validSegmentsList.add(Path.PARENT_SEGMENT);
+        path = new BasicPath(validSegmentsList, false);
+        assertThat(path.isAbsolute(), is(false));
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateAbsolutePathWithSelfSegment() {
+        validSegmentsList.add(Path.SELF_SEGMENT);
+        path = new BasicPath(validSegmentsList, true);
+        assertThat(path.isAbsolute(), is(true));
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreateRelativePathWithSelfSegment() {
+        validSegmentsList.add(Path.SELF_SEGMENT);
+        path = new BasicPath(validSegmentsList, false);
+        assertThat(path.isAbsolute(), is(false));
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getSegmentsList(), is(validSegmentsList));
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldCreatePathWithNoNamespacePrefixes() {
+        path = pathFactory.create("/a/b/c/");
+        assertThat(path.size(), is(3));
+        assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
+    }
+
+    @Test
+    public void shouldConstructRelativePath() {
+        assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
+        assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
+        assertThat(pathFactory.create("a/b/c").size(), is(3));
+        assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry), is("a/b/c"));
+    }
+
+    @Test
+    public void shouldConstructRelativePathToSelf() {
+        assertThat(pathFactory.create(".").isAbsolute(), is(false));
+        assertThat(pathFactory.create(".").size(), is(1));
+        assertThat(pathFactory.create("."), hasSegments(pathFactory, Path.SELF));
+
+        assertThat(pathFactory.create("./").isAbsolute(), is(false));
+        assertThat(pathFactory.create("./").size(), is(1));
+        assertThat(pathFactory.create("./"), hasSegments(pathFactory, Path.SELF));
+    }
+
+    @Test
+    public void shouldConstructRelativePathToParent() {
+        assertThat(pathFactory.create("..").isAbsolute(), is(false));
+        assertThat(pathFactory.create("..").size(), is(1));
+        assertThat(pathFactory.create(".."), hasSegments(pathFactory, Path.PARENT));
+
+        assertThat(pathFactory.create("../").isAbsolute(), is(false));
+        assertThat(pathFactory.create("../").size(), is(1));
+        assertThat(pathFactory.create("../"), hasSegments(pathFactory, Path.PARENT));
+    }
+
+    @Test
+    public void shouldConstructRootPathFromStringWithSingleDelimiter() {
+        assertThat(pathFactory.create("/"), is(ROOT));
+        assertThat(pathFactory.create("/").isRoot(), is(true));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotConstructPathWithSuccessiveDelimiters() {
+        pathFactory.create("///a/b///c//d//");
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotConstructPathWithOnlyDelimiters() {
+        pathFactory.create("///");
+    }
+
+    @Test
+    public void shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
+        assertThat(pathFactory.create(" \t /  \t").toString(), is("/"));
+    }
+
+    @Test
+    public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
+        assertThat(pathFactory.create("a"), hasSegments(pathFactory, "a"));
+    }
+
+    @Test
+    public void shouldHaveSizeThatReflectsNumberOfSegments() {
+        assertThat(path.size(), is(validSegmentsList.size()));
+    }
+
+    @Test
+    public void shouldIterateOverAllSegmentsReturnedByList() {
+        Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
+        for (Path.Segment segment : path) {
+            assertThat(segment, is(expectedIter.next()));
+        }
+
+        expectedIter = path.getSegmentsList().iterator();
+        for (Path.Segment segment : path) {
+            assertThat(segment, is(expectedIter.next()));
+        }
+    }
+
+    @Test
+    public void shouldReturnAncestorForNodeOtherThanRoot() {
+        assertThat(path.getParent(), is(pathFactory.create("/dna:a/dna:b")));
+        assertThat(path.getParent().getParent(), is(pathFactory.create("/dna:a")));
+        assertThat(path.getParent().getParent().getParent(), is(ROOT));
+    }
+
+    @Test
+    public void shouldReturnNthDegreeAncestor() {
+        assertThat(path.getAncestor(1), is(pathFactory.create("/dna:a/dna:b")));
+        assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
+        assertThat(path.getAncestor(3), is(ROOT));
+    }
+
+    @Test
+    public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
+        assertThat(path.getCommonAncestor(ROOT), is(ROOT));
+        assertThat(ROOT.getCommonAncestor(path), is(ROOT));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
+        path.getCommonAncestor(null);
+    }
+
+    @Test
+    public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path common = pathFactory.create("/a");
+        assertThat(path1.getCommonAncestor(path2), is(common));
+
+        path1 = pathFactory.create("/a/b/c");
+        path2 = pathFactory.create("/a/b/c/d");
+        common = path1;
+        assertThat(path1.getCommonAncestor(path2), is(common));
+
+        path1 = pathFactory.create("/a/b/c/x/y/");
+        path2 = pathFactory.create("/a/b/c/d/e/f/");
+        common = pathFactory.create("/a/b/c");
+        assertThat(path1.getCommonAncestor(path2), is(common));
+    }
+
+    @Test
+    public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
+        Path path1 = pathFactory.create("/x/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path common = ROOT;
+        assertThat(path1.getCommonAncestor(path2), is(common));
+    }
+
+    @Test
+    public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        Path common = pathFactory.create("/a");
+        assertThat(common.isAncestorOf(path1), is(true));
+        assertThat(common.isAncestorOf(path2), is(true));
+        assertThat(common.isAncestorOf(path3), is(false));
+
+        assertThat(path1.getParent().isAncestorOf(path1), is(true));
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
+        }
+    }
+
+    @Test
+    public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        Path common = pathFactory.create("/a");
+        assertThat(path1.isDecendantOf(common), is(true));
+        assertThat(path2.isDecendantOf(common), is(true));
+        assertThat(path3.isDecendantOf(common), is(false));
+
+        assertThat(path1.getParent().isAncestorOf(path1), is(true));
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
+        }
+    }
+
+    @Override
+    @Test
+    public void shouldNotConsiderNodeToBeAncestorOfItself() {
+        super.shouldNotConsiderNodeToBeAncestorOfItself();
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        assertThat(path1.isAncestorOf(path1), is(false));
+        assertThat(path2.isAncestorOf(path2), is(false));
+        assertThat(path3.isAncestorOf(path3), is(false));
+        assertThat(ROOT.isAncestorOf(ROOT), is(false));
+    }
+
+    @Override
+    @Test
+    public void shouldNotConsiderNodeToBeDecendantOfItself() {
+        super.shouldNotConsiderNodeToBeDecendantOfItself();
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        assertThat(path1.isDecendantOf(path1), is(false));
+        assertThat(path2.isDecendantOf(path2), is(false));
+        assertThat(path3.isDecendantOf(path3), is(false));
+        assertThat(ROOT.isDecendantOf(ROOT), is(false));
+    }
+
+    @Test
+    public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path common = pathFactory.create("/a");
+        assertThat(ROOT.isDecendantOf(path1), is(false));
+        assertThat(ROOT.isDecendantOf(path2), is(false));
+        assertThat(ROOT.isDecendantOf(path3), is(false));
+        assertThat(ROOT.isDecendantOf(common), is(false));
+    }
+
+    @Test
+    public void shouldConsiderRootToBeAncestorOfAnyNode() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path common = pathFactory.create("/a");
+        assertThat(ROOT.isAncestorOf(path1), is(true));
+        assertThat(ROOT.isAncestorOf(path2), is(true));
+        assertThat(ROOT.isAncestorOf(path3), is(true));
+        assertThat(ROOT.isAncestorOf(common), is(true));
+    }
+
+    @Test
+    public void shouldConsiderTwoNotRootSiblingNodesToHaveSameAncestor() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/y/c");
+        assertThat(path1.hasSameAncestor(path2), is(true));
+
+        path1 = pathFactory.create("/a/z");
+        path2 = pathFactory.create("/a/c");
+        assertThat(path1.hasSameAncestor(path2), is(true));
+
+        path1 = pathFactory.create("/z");
+        path2 = pathFactory.create("/c");
+        assertThat(path1.hasSameAncestor(path2), is(true));
+    }
+
+    @Test
+    public void shouldNotConsiderTwoNonSiblingNodesToHaveSameAncestor() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/x/c");
+        assertThat(path1.hasSameAncestor(path2), is(false));
+
+        path1 = pathFactory.create("/a/z");
+        path2 = pathFactory.create("/b/c");
+        assertThat(path1.hasSameAncestor(path2), is(false));
+
+        path1 = pathFactory.create("/z");
+        path2 = pathFactory.create("/a/c");
+        assertThat(path1.hasSameAncestor(path2), is(false));
+    }
+
+    @Test
+    public void shouldConsiderAncestorToBeAtOrAboveTheDecendant() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.getAncestor(i).isAtOrAbove(path1), is(true));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.getAncestor(i).isAtOrAbove(path2), is(true));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.getAncestor(i).isAtOrAbove(path3), is(true));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.getAncestor(i).isAtOrAbove(path4), is(true));
+        }
+    }
+
+    @Test
+    public void shouldConsiderDecendantToBeAtOrBelowTheAncestor() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.isAtOrBelow(path1.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.isAtOrBelow(path2.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.isAtOrBelow(path3.getAncestor(i)), is(true));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.isAtOrBelow(path4.getAncestor(i)), is(true));
+        }
+    }
+
+    @Test
+    public void shouldNotConsiderAncestorToBeAtOrBelowTheDecendant() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.getAncestor(i).isAtOrBelow(path1), is(false));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.getAncestor(i).isAtOrBelow(path2), is(false));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.getAncestor(i).isAtOrBelow(path3), is(false));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.getAncestor(i).isAtOrBelow(path4), is(false));
+        }
+    }
+
+    @Test
+    public void shouldNotConsiderDecendantToBeAtOrAboveTheAncestor() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+        for (int i = 1; i < path1.size(); ++i) {
+            assertThat(path1.isAtOrAbove(path1.getAncestor(i)), is(false));
+        }
+        for (int i = 1; i < path2.size(); ++i) {
+            assertThat(path2.isAtOrAbove(path2.getAncestor(i)), is(false));
+        }
+        for (int i = 1; i < path3.size(); ++i) {
+            assertThat(path3.isAtOrAbove(path3.getAncestor(i)), is(false));
+        }
+        for (int i = 1; i < path4.size(); ++i) {
+            assertThat(path4.isAtOrAbove(path4.getAncestor(i)), is(false));
+        }
+    }
+
+    @Test
+    public void shouldReturnLastSegmentOfNonRootPath() {
+        Path path1 = pathFactory.create("/a/y/z");
+        Path path2 = pathFactory.create("/a/b/c");
+        Path path3 = pathFactory.create("/x/b/c");
+        Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
+        assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
+        assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
+        assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
+        assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
+    }
+
+    @Test
+    public void shouldNormalizePathWithSelfAndParentReferences() {
+        path = pathFactory.create("/a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+        assertThat(path.getNormalizedPath().isNormalized(), is(true));
+
+        path = pathFactory.create("a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+        assertThat(path.getNormalizedPath().isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
+        assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
+        assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
+        assertThat(pathFactory.create("a").isNormalized(), is(true));
+        assertThat(pathFactory.create("/a").isNormalized(), is(true));
+        assertThat(ROOT.isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
+        assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(), is(false));
+        assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(), is(false));
+        assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
+        assertThat(pathFactory.create("/a/b/c/../d").isNormalized(), is(false));
+        assertThat(pathFactory.create(".").isNormalized(), is(false));
+        assertThat(pathFactory.create("/.").isNormalized(), is(false));
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
+        path = pathFactory.create("/a/../../../..");
+        assertThat(path.isNormalized(), is(false));
+        path.getNormalizedPath();
+    }
+
+    @Test
+    public void shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
+        // "/a/../b/../c/.." => "/"
+        path = pathFactory.create("/a/../b/../c/../");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), is(ROOT));
+    }
+
+    @Test
+    public void shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
+        // "a/../b/../c/.." => "."
+        path = pathFactory.create("a/../b/../c/../");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath().size(), is(1));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
+    }
+
+    @Test
+    public void shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
+        path = pathFactory.create("/a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+        assertThat(path.getNormalizedPath().isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
+        path = pathFactory.create("a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+        assertThat(path.getNormalizedPath().isNormalized(), is(true));
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
+        pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
+    }
+
+    @Test
+    public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
+        path = pathFactory.create("/a/b/c/../d/./e/../..");
+        assertThat(path.isNormalized(), is(false));
+        assertThat(path.isAbsolute(), is(true));
+        assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a", "b"));
+        assertThat(path.getCanonicalPath().isAbsolute(), is(true));
+        assertThat(path.getCanonicalPath().isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
+        testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
+        testSegmentsByIteratorAndListAndArray("/a/b/c", "a", "b", "c");
+        testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
+        testSegmentsByIteratorAndListAndArray("a/b/c", "a", "b", "c");
+        testSegmentsByIteratorAndListAndArray("");
+        testSegmentsByIteratorAndListAndArray(ROOT.getString());
+    }
+
+    public void testSegmentsByIteratorAndListAndArray( String pathStr,
+                                                       String... expectedSegmentStrings ) {
+        path = pathFactory.create(pathStr);
+        assertThat(expectedSegmentStrings.length, is(path.size()));
+        Path.Segment[] segmentArray = path.getSegmentsArray();
+        List<Path.Segment> segmentList = path.getSegmentsList();
+        assertThat(segmentArray.length, is(path.size()));
+        assertThat(segmentList.size(), is(path.size()));
+        Iterator<Path.Segment> iter = path.iterator();
+        Iterator<Path.Segment> listIter = segmentList.iterator();
+        for (int i = 0; i != path.size(); ++i) {
+            Path.Segment expected = pathFactory.createSegment(expectedSegmentStrings[i]);
+            assertThat(path.getSegment(i), is(expected));
+            assertThat(segmentArray[i], is(expected));
+            assertThat(segmentList.get(i), is(expected));
+            assertThat(iter.next(), is(expected));
+            assertThat(listIter.next(), is(expected));
+        }
+        assertThat(iter.hasNext(), is(false));
+        assertThat(listIter.hasNext(), is(false));
+    }
+
+    @Test
+    public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.getString(NO_OP_ENCODER),
+                   is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../{}d/./{http://www.jboss.org/dna}e/../.."));
+    }
+
+    @Test
+    public void shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna:a/b/dna:c/../d/./dna:e/../.."));
+        namespaceRegistry.register("dna2", validNamespaceUri);
+        assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(-1);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(path.size() + 1);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(path.size() + 1, path.size() + 2);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(2, 1);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        path.subpath(2, path.size() + 1);
+    }
+
+    @Test
+    public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.subpath(0, 0), is(ROOT));
+    }
+
+    @Test
+    public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(0), is(path));
+        assertThat(path.subpath(0), is(sameInstance(path)));
+        assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
+        assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
+        assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+
+        path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(0), is(path));
+        assertThat(path.subpath(0), is(sameInstance(path)));
+        assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
+        assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
+        assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+    }
+
+    @Test
+    public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
+        path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+        assertThat(path.subpath(0, path.size()), hasSegments(pathFactory,
+                                                             "dna:a",
+                                                             "b",
+                                                             "dna:c",
+                                                             "..",
+                                                             "d",
+                                                             ".",
+                                                             "dna:e",
+                                                             "..",
+                                                             ".."));
+        assertThat(path.subpath(0, path.size()), is(path));
+        assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
+        assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(2, path.size()), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+        assertThat(path.subpath(6, path.size()), hasSegments(pathFactory, "dna:e", "..", ".."));
+        assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..", ".."));
+        assertThat(path.subpath(8, path.size()), hasSegments(pathFactory, ".."));
+
+        assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a", "b"));
+        assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
+        assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b", "dna:c", "..", "d"));
+        assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c", "..", "d"));
+        assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..", "d"));
+    }
+
+    @Test
+    public void shouldFindRelativePaths() {
+        path = pathFactory.create("/a/b/c/d");
+        assertThat(path.relativeTo(pathFactory.create("/a/e/f")), is(pathFactory.create("../../b/c/d")));
+        assertThat(path.relativeTo(pathFactory.create("/e/f")), is(pathFactory.create("../../a/b/c/d")));
+
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
+        path = pathFactory.create("a/b/c/d");
+        path.relativeTo(pathFactory.create("/e/f"));
+
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotResolveRelativePathToAnotherRelativePath() {
+        path = pathFactory.create("/a/b/c/d");
+        path.relativeTo(pathFactory.create("e/f"));
+
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+        path = pathFactory.create("/a/b/c/d");
+        path.resolve(pathFactory.create("/e/f"));
+    }
+
+    @Test
+    public void shouldResolveRelativePathToAbsolutePath() {
+        path = pathFactory.create("/a/b/c/d");
+        path2 = path.resolve(pathFactory.create("../../e/f"));
+        assertThat(path2, is(pathFactory.create("/a/b/e/f")));
+        assertThat(path2.isAbsolute(), is(true));
+        assertThat(path2.isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldOrderPathsCorrectly() {
+        List<Path> paths = new ArrayList<Path>();
+        paths.add(pathFactory.create("/a"));
+        paths.add(pathFactory.create("/a/b"));
+        paths.add(pathFactory.create("/a/b/alpha"));
+        paths.add(pathFactory.create("/a/b/beta"));
+        paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
+        paths.add(pathFactory.create("/a/b/dna:name"));
+        paths.add(pathFactory.create("/a/b/dna:primaryType"));
+        paths.add(pathFactory.create("/a/c[1]"));
+        paths.add(pathFactory.create("/a/c[1]/alpha"));
+        paths.add(pathFactory.create("/a/c[1]/beta"));
+        paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
+        paths.add(pathFactory.create("/a/c[1]/dna:name"));
+        paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
+        paths.add(pathFactory.create("/a/c[2]"));
+        paths.add(pathFactory.create("/a/c[2]/alpha"));
+        paths.add(pathFactory.create("/a/c[2]/beta"));
+        paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
+        paths.add(pathFactory.create("/a/c[2]/dna:name"));
+        paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
+
+        // Randomize the list of paths, so we have something to sort ...
+        List<Path> randomizedPaths = new ArrayList<Path>(paths);
+        Collections.shuffle(randomizedPaths);
+        assertThat(randomizedPaths, is(not(paths)));
+
+        // Sort ...
+        Collections.sort(randomizedPaths);
+        assertThat(randomizedPaths, is(paths));
+    }
+
+    @Test
+    public void shouldGetNormalizedPathOfSelfShouldBeSame() {
+        assertThat(pathFactory.create(".").getNormalizedPath(), is(pathFactory.create(".")));
+        assertThat(pathFactory.create("./").getNormalizedPath(), is(pathFactory.create(".")));
+        assertThat(pathFactory.create("./././").getNormalizedPath(), is(pathFactory.create(".")));
+    }
+
+    @Test
+    public void shouldGetNormalizedPathWithParentReferences() {
+        assertThat(pathFactory.create("..").getNormalizedPath(), is(pathFactory.create("..")));
+        assertThat(pathFactory.create("../").getNormalizedPath(), is(pathFactory.create("../")));
+        assertThat(pathFactory.create("../../../../../..").getNormalizedPath(), is(pathFactory.create("../../../../../..")));
+    }
+
+    @Test
+    public void shouldGetRelativePathUsingSelf() {
+        path = pathFactory.create("/a/b/c/d/e/f");
+        assertThat(path.resolve(pathFactory.create(".")), is(sameInstance(path)));
+        assertThat(path.resolve(pathFactory.create("././.")), is(sameInstance(path)));
+    }
+
+    @Test
+    public void shouldResolveRelativePathToParent() {
+        path = pathFactory.create("/a/b/c/d/e/f");
+        assertThat(path.resolve(pathFactory.create("..")), is(path.getParent()));
+        assertThat(path.resolve(pathFactory.create("..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
+    }
+
+    @Test
+    public void shouldResolveRelativePaths() {
+        path = pathFactory.create("/a/b/c/d/e/f");
+        assertThat(path.resolve(pathFactory.create("../../../../../..")), is(ROOT));
+        assertThat(path.resolve(pathFactory.create("../..")), is(path.getParent().getParent()));
+        assertThat(path.resolve(pathFactory.create("../..")), hasSegments(pathFactory, "a", "b", "c", "d"));
+        assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), is(path.getParent()));
+        assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
+        assertThat(path.resolve(pathFactory.create("../x")), hasSegments(pathFactory, "a", "b", "c", "d", "e", "x"));
+    }
+
+    public void shouldResolveNonAbsolutePaths() {
+        path = pathFactory.create("a/b/c");
+        assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
+    }
+
+    @Test
+    public void shouldConvertPathToString() {
+        TextEncoder encoder = new Jsr283Encoder();
+        TextEncoder delimEncoder = new TextEncoder() {
+            public String encode( String text ) {
+                if ("/".equals(text)) return "\\/";
+                if (":".equals(text)) return "\\:";
+                if ("{".equals(text)) return "\\{";
+                if ("}".equals(text)) return "\\}";
+                return text;
+            }
+        };
+        Path path = pathFactory.create("a/b/c");
+        assertThat(path.getString(namespaceRegistry), is("a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder), is("a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("a\\/b\\/c"));
+
+        path = pathFactory.create("/a/b/c");
+        assertThat(path.getString(namespaceRegistry), is("/a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder), is("/a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("\\/a\\/b\\/c"));
+
+        path = pathFactory.create("/dna:a/b/c");
+        assertThat(path.getString(encoder), is("/{" + encoder.encode(DnaLexicon.Namespace.URI) + "}a/{}b/{}c"));
+        assertThat(path.getString(null, encoder, delimEncoder), is("\\/\\{" + encoder.encode(DnaLexicon.Namespace.URI)
+                                                                   + "\\}a\\/\\{\\}b\\/\\{\\}c"));
+        assertThat(path.getString(namespaceRegistry), is("/dna:a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder), is("/dna:a/b/c"));
+        assertThat(path.getString(namespaceRegistry, encoder, delimEncoder), is("\\/dna\\:a\\/b\\/c"));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BinaryContains.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BinaryContains.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BinaryContains.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,101 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import java.io.UnsupportedEncodingException;
-import org.hamcrest.Description;
-import org.hamcrest.Factory;
-import org.hamcrest.Matcher;
-import org.jboss.dna.graph.properties.Binary;
-import org.junit.matchers.TypeSafeMatcher;
-
-/**
- * @author Randall Hauch
- */
-public class BinaryContains extends TypeSafeMatcher<Binary> {
-
-    private byte[] expectedContent;
-
-    public BinaryContains( byte[] expectedContent ) {
-        this.expectedContent = expectedContent;
-    }
-
-    public BinaryContains( Binary expectedContent ) {
-        try {
-            expectedContent.acquire();
-            this.expectedContent = expectedContent.getBytes();
-        } finally {
-            expectedContent.release();
-        }
-    }
-
-    @Override
-    public boolean matchesSafely( Binary content ) {
-        try {
-            content.acquire();
-            byte[] actualContents = content.getBytes();
-            if (actualContents.length != expectedContent.length) return false;
-            for (int i = 0, len = actualContents.length; i != len; ++i) {
-                if (actualContents[i] != expectedContent[i]) return false;
-            }
-            return true;
-        } finally {
-            content.release();
-        }
-    }
-
-    protected String getDisplayableString( byte[] values ) {
-        StringBuilder sb = new StringBuilder("byte[]: ");
-        sb.append(" len=").append(values.length).append("; [");
-        int len = (int)Math.min(values.length, 20l);
-        for (int i = 0; i != len; ++i) {
-            if (i != 0) sb.append(',');
-            sb.append(values[i]);
-        }
-        return sb.toString();
-    }
-
-    public void describeTo( Description description ) {
-        description.appendText("a binary containing ").appendValue(getDisplayableString(expectedContent));
-    }
-
-    @Factory
-    public static Matcher<Binary> hasContent( Binary expectedContent ) {
-        return new BinaryContains(expectedContent);
-    }
-
-    @Factory
-    public static Matcher<Binary> hasContent( String expectedContent ) throws UnsupportedEncodingException {
-        return new BinaryContains(expectedContent.getBytes("UTF-8"));
-    }
-
-    @Factory
-    public static Matcher<Binary> hasContent( byte[] expectedContent ) {
-        return new BinaryContains(expectedContent);
-    }
-
-    @Factory
-    public static Matcher<Binary> hasNoContent() {
-        return new BinaryContains(new byte[0]);
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BinaryContains.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BinaryContains.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BinaryContains.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BinaryContains.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,101 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import java.io.UnsupportedEncodingException;
+import org.hamcrest.Description;
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+import org.jboss.dna.graph.property.Binary;
+import org.junit.matchers.TypeSafeMatcher;
+
+/**
+ * @author Randall Hauch
+ */
+public class BinaryContains extends TypeSafeMatcher<Binary> {
+
+    private byte[] expectedContent;
+
+    public BinaryContains( byte[] expectedContent ) {
+        this.expectedContent = expectedContent;
+    }
+
+    public BinaryContains( Binary expectedContent ) {
+        try {
+            expectedContent.acquire();
+            this.expectedContent = expectedContent.getBytes();
+        } finally {
+            expectedContent.release();
+        }
+    }
+
+    @Override
+    public boolean matchesSafely( Binary content ) {
+        try {
+            content.acquire();
+            byte[] actualContents = content.getBytes();
+            if (actualContents.length != expectedContent.length) return false;
+            for (int i = 0, len = actualContents.length; i != len; ++i) {
+                if (actualContents[i] != expectedContent[i]) return false;
+            }
+            return true;
+        } finally {
+            content.release();
+        }
+    }
+
+    protected String getDisplayableString( byte[] values ) {
+        StringBuilder sb = new StringBuilder("byte[]: ");
+        sb.append(" len=").append(values.length).append("; [");
+        int len = (int)Math.min(values.length, 20l);
+        for (int i = 0; i != len; ++i) {
+            if (i != 0) sb.append(',');
+            sb.append(values[i]);
+        }
+        return sb.toString();
+    }
+
+    public void describeTo( Description description ) {
+        description.appendText("a binary containing ").appendValue(getDisplayableString(expectedContent));
+    }
+
+    @Factory
+    public static Matcher<Binary> hasContent( Binary expectedContent ) {
+        return new BinaryContains(expectedContent);
+    }
+
+    @Factory
+    public static Matcher<Binary> hasContent( String expectedContent ) throws UnsupportedEncodingException {
+        return new BinaryContains(expectedContent.getBytes("UTF-8"));
+    }
+
+    @Factory
+    public static Matcher<Binary> hasContent( byte[] expectedContent ) {
+        return new BinaryContains(expectedContent);
+    }
+
+    @Factory
+    public static Matcher<Binary> hasNoContent() {
+        return new BinaryContains(new byte[0]);
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BooleanValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BooleanValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BooleanValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,185 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import java.io.ByteArrayInputStream;
-import java.io.StringReader;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.basic.BooleanValueFactory;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class BooleanValueFactoryTest {
-
-    private BooleanValueFactory factory;
-    private StringValueFactory stringFactory;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.DEFAULT_ENCODER);
-        factory = new BooleanValueFactory(Path.URL_DECODER, stringFactory);
-    }
-
-    @Test
-    public void shouldCreateBooleanFromBoolean() {
-        assertThat(factory.create(true), is(true));
-        assertThat(factory.create(false), is(false));
-    }
-
-    @Test
-    public void shouldCreateBooleanFromTrueAndFalseStringRegardlessOfCase() {
-        assertThat(factory.create("true"), is(true));
-        assertThat(factory.create("false"), is(false));
-        assertThat(factory.create("TRUE"), is(true));
-        assertThat(factory.create("FALSE"), is(false));
-    }
-
-    @Test
-    public void shouldCreateBooleanFromTrueAndFalseStringRegardlessOfLeadingAndTrailingWhitespace() {
-        assertThat(factory.create("  true  "), is(true));
-        assertThat(factory.create("  false  "), is(false));
-        assertThat(factory.create("  TRUE  "), is(true));
-        assertThat(factory.create("  FALSE  "), is(false));
-    }
-
-    @Test
-    public void shouldCreateFalseFromStringContainingOneOrZero() {
-        assertThat(factory.create("1"), is(false));
-        assertThat(factory.create("0"), is(false));
-        assertThat(factory.create("  0  "), is(false));
-        assertThat(factory.create("  1  "), is(false));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromIntegerValue() {
-        factory.create(1);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromLongValue() {
-        factory.create(1l);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromFloatValue() {
-        factory.create(1.0f);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromDoubleValue() {
-        factory.create(1.0d);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromBigDecimal() {
-        factory.create(1.0d);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromDate() {
-        factory.create(new Date());
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromCalendar() {
-        factory.create(Calendar.getInstance());
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromName() {
-        factory.create(mock(Name.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromPath() {
-        factory.create(mock(Path.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromReference() {
-        factory.create(mock(Reference.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateBooleanFromUri() throws Exception {
-        factory.create(new URI("http://www.jboss.org"));
-    }
-
-    @Test
-    public void shouldCreateBooleanFromByteArrayContainingUtf8EncodingOfTrueOrFalseStringRegardlessOfCase() throws Exception {
-        assertThat(factory.create("true".getBytes("UTF-8")), is(true));
-        assertThat(factory.create("false".getBytes("UTF-8")), is(false));
-        assertThat(factory.create("TRUE".getBytes("UTF-8")), is(true));
-        assertThat(factory.create("FALSE".getBytes("UTF-8")), is(false));
-        assertThat(factory.create("something else".getBytes("UTF-8")), is(false));
-    }
-
-    @Test
-    public void shouldCreateBooleanFromInputStreamContainingUtf8EncodingOfTrueOrFalseStringRegardlessOfCase() throws Exception {
-        assertThat(factory.create(new ByteArrayInputStream("true".getBytes("UTF-8"))), is(true));
-        assertThat(factory.create(new ByteArrayInputStream("false".getBytes("UTF-8"))), is(false));
-        assertThat(factory.create(new ByteArrayInputStream("TRUE".getBytes("UTF-8"))), is(true));
-        assertThat(factory.create(new ByteArrayInputStream("FALSE".getBytes("UTF-8"))), is(false));
-        assertThat(factory.create(new ByteArrayInputStream("something else".getBytes("UTF-8"))), is(false));
-    }
-
-    @Test
-    public void shouldCreateBooleanFromReaderContainingTrueOrFalseStringRegardlessOfCase() {
-        assertThat(factory.create(new StringReader("true")), is(true));
-        assertThat(factory.create(new StringReader("false")), is(false));
-        assertThat(factory.create(new StringReader("TRUE")), is(true));
-        assertThat(factory.create(new StringReader("FALSE")), is(false));
-        assertThat(factory.create(new StringReader("something else")), is(false));
-    }
-
-    @Test
-    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
-        List<String> values = new ArrayList<String>();
-        for (int i = 0; i != 10; ++i)
-            values.add((i % 2 == 0 ? "true" : "false"));
-        Iterator<Boolean> iter = factory.create(values.iterator());
-        Iterator<String> valueIter = values.iterator();
-        while (iter.hasNext()) {
-            assertThat(iter.next(), is(factory.create(valueIter.next())));
-        }
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BooleanValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BooleanValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BooleanValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BooleanValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,185 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.BooleanValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class BooleanValueFactoryTest {
+
+    private BooleanValueFactory factory;
+    private StringValueFactory stringFactory;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.DEFAULT_ENCODER);
+        factory = new BooleanValueFactory(Path.URL_DECODER, stringFactory);
+    }
+
+    @Test
+    public void shouldCreateBooleanFromBoolean() {
+        assertThat(factory.create(true), is(true));
+        assertThat(factory.create(false), is(false));
+    }
+
+    @Test
+    public void shouldCreateBooleanFromTrueAndFalseStringRegardlessOfCase() {
+        assertThat(factory.create("true"), is(true));
+        assertThat(factory.create("false"), is(false));
+        assertThat(factory.create("TRUE"), is(true));
+        assertThat(factory.create("FALSE"), is(false));
+    }
+
+    @Test
+    public void shouldCreateBooleanFromTrueAndFalseStringRegardlessOfLeadingAndTrailingWhitespace() {
+        assertThat(factory.create("  true  "), is(true));
+        assertThat(factory.create("  false  "), is(false));
+        assertThat(factory.create("  TRUE  "), is(true));
+        assertThat(factory.create("  FALSE  "), is(false));
+    }
+
+    @Test
+    public void shouldCreateFalseFromStringContainingOneOrZero() {
+        assertThat(factory.create("1"), is(false));
+        assertThat(factory.create("0"), is(false));
+        assertThat(factory.create("  0  "), is(false));
+        assertThat(factory.create("  1  "), is(false));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromIntegerValue() {
+        factory.create(1);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromLongValue() {
+        factory.create(1l);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromFloatValue() {
+        factory.create(1.0f);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromDoubleValue() {
+        factory.create(1.0d);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromBigDecimal() {
+        factory.create(1.0d);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromDate() {
+        factory.create(new Date());
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromCalendar() {
+        factory.create(Calendar.getInstance());
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromName() {
+        factory.create(mock(Name.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromPath() {
+        factory.create(mock(Path.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromReference() {
+        factory.create(mock(Reference.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateBooleanFromUri() throws Exception {
+        factory.create(new URI("http://www.jboss.org"));
+    }
+
+    @Test
+    public void shouldCreateBooleanFromByteArrayContainingUtf8EncodingOfTrueOrFalseStringRegardlessOfCase() throws Exception {
+        assertThat(factory.create("true".getBytes("UTF-8")), is(true));
+        assertThat(factory.create("false".getBytes("UTF-8")), is(false));
+        assertThat(factory.create("TRUE".getBytes("UTF-8")), is(true));
+        assertThat(factory.create("FALSE".getBytes("UTF-8")), is(false));
+        assertThat(factory.create("something else".getBytes("UTF-8")), is(false));
+    }
+
+    @Test
+    public void shouldCreateBooleanFromInputStreamContainingUtf8EncodingOfTrueOrFalseStringRegardlessOfCase() throws Exception {
+        assertThat(factory.create(new ByteArrayInputStream("true".getBytes("UTF-8"))), is(true));
+        assertThat(factory.create(new ByteArrayInputStream("false".getBytes("UTF-8"))), is(false));
+        assertThat(factory.create(new ByteArrayInputStream("TRUE".getBytes("UTF-8"))), is(true));
+        assertThat(factory.create(new ByteArrayInputStream("FALSE".getBytes("UTF-8"))), is(false));
+        assertThat(factory.create(new ByteArrayInputStream("something else".getBytes("UTF-8"))), is(false));
+    }
+
+    @Test
+    public void shouldCreateBooleanFromReaderContainingTrueOrFalseStringRegardlessOfCase() {
+        assertThat(factory.create(new StringReader("true")), is(true));
+        assertThat(factory.create(new StringReader("false")), is(false));
+        assertThat(factory.create(new StringReader("TRUE")), is(true));
+        assertThat(factory.create(new StringReader("FALSE")), is(false));
+        assertThat(factory.create(new StringReader("something else")), is(false));
+    }
+
+    @Test
+    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
+        List<String> values = new ArrayList<String>();
+        for (int i = 0; i != 10; ++i)
+            values.add((i % 2 == 0 ? "true" : "false"));
+        Iterator<Boolean> iter = factory.create(values.iterator());
+        Iterator<String> valueIter = values.iterator();
+        while (iter.hasNext()) {
+            assertThat(iter.next(), is(factory.create(valueIter.next())));
+        }
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/ChildPathTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/ChildPathTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/ChildPathTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,352 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import java.util.ArrayList;
-import java.util.List;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicPath;
-import org.jboss.dna.graph.properties.basic.BasicPathSegment;
-import org.jboss.dna.graph.properties.basic.ChildPath;
-import org.jboss.dna.graph.properties.basic.RootPath;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class ChildPathTest extends AbstractPathTest {
-
-    protected Path parent;
-    protected Path root;
-    protected Path.Segment childSegment;
-
-    @Before
-    @Override
-    public void beforeEach() {
-        super.beforeEach();
-        // parent = mock(Path.class);
-        parent = path("/a/b/c");
-        childSegment = segment("d");
-        path = new ChildPath(parent, childSegment);
-        root = RootPath.INSTANCE;
-    }
-
-    protected Path path( String path ) {
-        path = path.trim();
-        if ("/".equals(path)) return RootPath.INSTANCE;
-        boolean absolute = path.startsWith("/");
-        path = path.replaceAll("^/+", "").replaceAll("/+$", ""); // remove leading and trailing slashes
-        String[] segmentStrings = path.split("/");
-        List<Path.Segment> segments = new ArrayList<Path.Segment>(segmentStrings.length);
-        for (String segmentString : segmentStrings) {
-            Name name = new BasicName("", segmentString);
-            Path.Segment segment = new BasicPathSegment(name);
-            segments.add(segment);
-        }
-        return new BasicPath(segments, absolute);
-    }
-
-    protected Path.Segment segment( String segment ) {
-        Name name = new BasicName("", segment);
-        return new BasicPathSegment(name);
-    }
-
-    @Test
-    public void shouldReturnParentForAncestorOfDegreeOne() {
-        assertThat(path.getAncestor(1), is(sameInstance(parent)));
-        assertThat(path.getParent(), is(sameInstance(parent)));
-    }
-
-    @Test
-    public void shouldDelegateToParentForAncestorOfDegreeGreaterThanOne() {
-        parent = mock(Path.class);
-        stub(parent.getAncestor(anyInt())).toReturn(null);
-        path = new ChildPath(parent, segment("d"));
-        for (int i = 2; i != 10; ++i) {
-            path.getAncestor(i);
-            verify(parent).getAncestor(i - 1);
-        }
-    }
-
-    @Test
-    public void shouldConsiderChildPathToBeDecendantOfParent() {
-        assertThat(path.isDecendantOf(parent), is(true));
-    }
-
-    @Test
-    public void shouldConsiderChildPathToNotBeAncestorOfParent() {
-        assertThat(path.isAncestorOf(parent), is(false));
-    }
-
-    @Test
-    public void shouldConsiderParentNotBeDecendantOfChildPath() {
-        assertThat(parent.isDecendantOf(path), is(false));
-    }
-
-    @Test
-    public void shouldConsiderPathDecendantOfOtherPathIfParentIsAtOrBelowOtherPath() {
-        parent = mock(Path.class);
-        path = new ChildPath(parent, segment("d"));
-        Path other = mock(Path.class);
-        stub(parent.isAtOrBelow(other)).toReturn(true);
-        assertThat(path.isDecendantOf(other), is(true));
-        verify(parent).isAtOrBelow(other);
-
-        stub(parent.isAtOrBelow(other)).toReturn(false);
-        assertThat(path.isDecendantOf(other), is(false));
-        verify(parent, times(2)).isAtOrBelow(other);
-    }
-
-    @Test
-    public void shouldConsiderPathDecendantOfOtherParentPath() {
-        assertThat(path.isDecendantOf(parent), is(true));
-    }
-
-    @Test
-    public void shouldReturnChildSegmentFromGetLastSegment() {
-        assertThat(path.getLastSegment(), is(sameInstance(childSegment)));
-    }
-
-    @Test
-    public void shouldReturnChildSegmentFromGetSegmentWithIndexOfSizeMinusOne() {
-        assertThat(path.getSegment(path.size() - 1), is(sameInstance(childSegment)));
-    }
-
-    @Test
-    public void shouldDelegateGetSegmentToParentIfIndexNotEqualToSizeMinusOne() {
-        Path.Segment segment = mock(Path.Segment.class);
-        parent = mock(Path.class);
-        stub(parent.size()).toReturn(10);
-        path = new ChildPath(parent, segment("d"));
-        stub(parent.getSegment(anyInt())).toReturn(segment);
-        for (int i = 0; i < path.size() - 1; ++i) {
-            assertThat(path.getSegment(i), is(sameInstance(segment)));
-        }
-        verify(parent, times(parent.size())).getSegment(anyInt());
-    }
-
-    @Test
-    public void shouldReturnParentInstanceFromGetParent() {
-        assertThat(path.getParent(), is(sameInstance(parent)));
-    }
-
-    // @Test
-    // public void shouldReturnRootForLowestCommonAncestorWithAnyNodePath() {
-    // Path other = mock(Path.class);
-    // stub(other.isRoot()).toReturn(true);
-    // assertThat(root.getCommonAncestor(other).isRoot(), is(true));
-    //
-    // stub(other.isRoot()).toReturn(false);
-    // assertThat(root.getCommonAncestor(other).isRoot(), is(true));
-    // }
-    //
-    // @Test
-    // public void shouldConsiderRootToBeAncestorOfEveryNodeExceptRoot() {
-    // Path other = mock(Path.class);
-    // stub(other.size()).toReturn(1);
-    // assertThat(root.isAncestorOf(other), is(true));
-    // assertThat(root.isAncestorOf(root), is(false));
-    // }
-    //
-    // @Test
-    // public void shouldNotConsiderRootNodeToBeDecendantOfAnyNode() {
-    // Path other = mock(Path.class);
-    // assertThat(root.isDecendantOf(other), is(false));
-    // assertThat(root.isDecendantOf(root), is(false));
-    // }
-    //
-    // @Test
-    // public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
-    // assertThat(root.hasSameAncestor(root), is(true));
-    // }
-    //
-    // @Test
-    // public void shouldBeNormalized() {
-    // assertThat(root.isNormalized(), is(true));
-    // }
-    //
-    // @Test
-    // public void shouldReturnSelfForGetNormalized() {
-    // assertThat(root.getNormalizedPath(), is(sameInstance(root)));
-    // }
-    //
-    // @Test
-    // public void shouldReturnSelfForGetCanonicalPath() {
-    // assertThat(root.getCanonicalPath(), is(sameInstance(root)));
-    // }
-    //
-    // @Test
-    // public void shouldReturnSizeOfZero() {
-    // assertThat(root.size(), is(0));
-    // }
-    //
-    // @Test
-    // public void shouldReturnEmptyIteratorOverSegments() {
-    // assertThat(root.iterator(), is(notNullValue()));
-    // assertThat(root.iterator().hasNext(), is(false));
-    // }
-    //
-    // @Test( expected = IndexOutOfBoundsException.class )
-    // public void shouldFailToReturnSegmentAtIndexZero() {
-    // root.getSegment(0);
-    // }
-    //
-    // @Test( expected = IndexOutOfBoundsException.class )
-    // public void shouldFailToReturnSegmentAtPositiveIndex() {
-    // root.getSegment(1);
-    // }
-    //
-    // @Test
-    // public void shouldReturnEmptySegmentsArray() {
-    // assertThat(root.getSegmentsArray(), is(notNullValue()));
-    // assertThat(root.getSegmentsArray().length, is(0));
-    // }
-    //
-    // @Test
-    // public void shouldReturnEmptySegmentsList() {
-    // assertThat(root.getSegmentsList(), is(notNullValue()));
-    // assertThat(root.getSegmentsList().isEmpty(), is(true));
-    // }
-    //
-    // @Test
-    // public void shouldAlwaysReturnPathWithSingleSlashForGetString() {
-    // NamespaceRegistry registry = mock(NamespaceRegistry.class);
-    // TextEncoder encoder = mock(TextEncoder.class);
-    // stub(encoder.encode("/")).toReturn("/");
-    // assertThat(root.getString(), is("/"));
-    // assertThat(root.getString(registry), is("/"));
-    // assertThat(root.getString(registry, encoder), is("/"));
-    // assertThat(root.getString(registry, encoder, encoder), is("/"));
-    // assertThat(root.getString(encoder), is("/"));
-    // }
-    //
-    // @Test
-    // public void shouldAllowNullNamespaceRegistryWithNonNullTextEncodersSinceRegistryIsNotNeeded() {
-    // TextEncoder encoder = mock(TextEncoder.class);
-    // stub(encoder.encode("/")).toReturn("/");
-    // assertThat(root.getString((NamespaceRegistry)null, encoder, encoder), is("/"));
-    // }
-    //
-    // @Test
-    // public void shouldAllowNullTextEncoder() {
-    // assertThat(root.getString((TextEncoder)null), is("/"));
-    // }
-    //
-    // @Test
-    // public void shouldNotAllowNullTextEncoderWithNonNullNamespaceRegistry() {
-    // NamespaceRegistry registry = mock(NamespaceRegistry.class);
-    // assertThat(root.getString(registry, (TextEncoder)null), is("/"));
-    // }
-    //
-    // @Test
-    // public void shouldNotAllowNullTextEncoderForDelimiterWithNonNullNamespaceRegistry() {
-    // NamespaceRegistry registry = mock(NamespaceRegistry.class);
-    // TextEncoder encoder = mock(TextEncoder.class);
-    // assertThat(root.getString(registry, encoder, (TextEncoder)null), is("/"));
-    // }
-    //
-    // @Test( expected = IndexOutOfBoundsException.class )
-    // public void shouldNotAllowSubpathStartingAtOne() {
-    // root.subpath(1);
-    // }
-    //
-    // @Test( expected = IndexOutOfBoundsException.class )
-    // public void shouldNotAllowSubpathStartingAtMoreThanOne() {
-    // root.subpath(2);
-    // }
-    //
-    // @Test( expected = IndexOutOfBoundsException.class )
-    // public void shouldNotAllowSubpathEndingAtMoreThanZero() {
-    // root.subpath(0, 1);
-    // }
-    //
-    // @Test
-    // public void shouldReturnRelativePathConsistingOfSameNumberOfParentReferencesAsSizeOfSuppliedPath() {
-    // List<Path.Segment> segments = new ArrayList<Path.Segment>();
-    // segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
-    // Path other = new BasicPath(segments, true);
-    //
-    // assertThat(root.relativeTo(other).toString(), is(".."));
-    //
-    // segments.add(new BasicPathSegment(new BasicName("http://example.com", "b")));
-    // other = new BasicPath(segments, true);
-    // assertThat(root.relativeTo(other).toString(), is("../.."));
-    //
-    // String expected = "..";
-    // segments.clear();
-    // for (int i = 1; i != 100; ++i) {
-    // segments.add(new BasicPathSegment(new BasicName("http://example.com", "b" + i)));
-    // other = new BasicPath(segments, true);
-    // assertThat(root.relativeTo(other).toString(), is(expected));
-    // expected = expected + "/..";
-    // }
-    // }
-    //
-    // @Test
-    // public void shouldResolveAllRelativePathsToTheirAbsolutePath() {
-    // List<Path.Segment> segments = new ArrayList<Path.Segment>();
-    // segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
-    // Path other = mock(Path.class);
-    // stub(other.isAbsolute()).toReturn(false);
-    // stub(other.getSegmentsList()).toReturn(segments);
-    // Path resolved = root.resolve(other);
-    // assertThat(resolved.getSegmentsList(), is(segments));
-    // assertThat(resolved.isAbsolute(), is(true));
-    // }
-    //
-    // @Test( expected = InvalidPathException.class )
-    // public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
-    // Path other = mock(Path.class);
-    // stub(other.isAbsolute()).toReturn(true);
-    // root.resolve(other);
-    // }
-    //
-    // @Test
-    // public void shouldAlwaysConsiderRootAsLessThanAnyPathOtherThanRoot() {
-    // Path other = mock(Path.class);
-    // stub(other.isRoot()).toReturn(false);
-    // assertThat(root.compareTo(other), is(-1));
-    // assertThat(root.equals(other), is(false));
-    // }
-    //
-    // @Test
-    // public void shouldAlwaysConsiderRootAsEqualToAnyOtherRoot() {
-    // Path other = mock(Path.class);
-    // stub(other.isRoot()).toReturn(true);
-    // assertThat(root.compareTo(other), is(0));
-    // assertThat(root.equals(other), is(true));
-    // assertThat(root.equals(root), is(true));
-    // }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/ChildPathTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/ChildPathTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/ChildPathTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/ChildPathTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,352 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import java.util.ArrayList;
+import java.util.List;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicPath;
+import org.jboss.dna.graph.property.basic.BasicPathSegment;
+import org.jboss.dna.graph.property.basic.ChildPath;
+import org.jboss.dna.graph.property.basic.RootPath;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class ChildPathTest extends AbstractPathTest {
+
+    protected Path parent;
+    protected Path root;
+    protected Path.Segment childSegment;
+
+    @Before
+    @Override
+    public void beforeEach() {
+        super.beforeEach();
+        // parent = mock(Path.class);
+        parent = path("/a/b/c");
+        childSegment = segment("d");
+        path = new ChildPath(parent, childSegment);
+        root = RootPath.INSTANCE;
+    }
+
+    protected Path path( String path ) {
+        path = path.trim();
+        if ("/".equals(path)) return RootPath.INSTANCE;
+        boolean absolute = path.startsWith("/");
+        path = path.replaceAll("^/+", "").replaceAll("/+$", ""); // remove leading and trailing slashes
+        String[] segmentStrings = path.split("/");
+        List<Path.Segment> segments = new ArrayList<Path.Segment>(segmentStrings.length);
+        for (String segmentString : segmentStrings) {
+            Name name = new BasicName("", segmentString);
+            Path.Segment segment = new BasicPathSegment(name);
+            segments.add(segment);
+        }
+        return new BasicPath(segments, absolute);
+    }
+
+    protected Path.Segment segment( String segment ) {
+        Name name = new BasicName("", segment);
+        return new BasicPathSegment(name);
+    }
+
+    @Test
+    public void shouldReturnParentForAncestorOfDegreeOne() {
+        assertThat(path.getAncestor(1), is(sameInstance(parent)));
+        assertThat(path.getParent(), is(sameInstance(parent)));
+    }
+
+    @Test
+    public void shouldDelegateToParentForAncestorOfDegreeGreaterThanOne() {
+        parent = mock(Path.class);
+        stub(parent.getAncestor(anyInt())).toReturn(null);
+        path = new ChildPath(parent, segment("d"));
+        for (int i = 2; i != 10; ++i) {
+            path.getAncestor(i);
+            verify(parent).getAncestor(i - 1);
+        }
+    }
+
+    @Test
+    public void shouldConsiderChildPathToBeDecendantOfParent() {
+        assertThat(path.isDecendantOf(parent), is(true));
+    }
+
+    @Test
+    public void shouldConsiderChildPathToNotBeAncestorOfParent() {
+        assertThat(path.isAncestorOf(parent), is(false));
+    }
+
+    @Test
+    public void shouldConsiderParentNotBeDecendantOfChildPath() {
+        assertThat(parent.isDecendantOf(path), is(false));
+    }
+
+    @Test
+    public void shouldConsiderPathDecendantOfOtherPathIfParentIsAtOrBelowOtherPath() {
+        parent = mock(Path.class);
+        path = new ChildPath(parent, segment("d"));
+        Path other = mock(Path.class);
+        stub(parent.isAtOrBelow(other)).toReturn(true);
+        assertThat(path.isDecendantOf(other), is(true));
+        verify(parent).isAtOrBelow(other);
+
+        stub(parent.isAtOrBelow(other)).toReturn(false);
+        assertThat(path.isDecendantOf(other), is(false));
+        verify(parent, times(2)).isAtOrBelow(other);
+    }
+
+    @Test
+    public void shouldConsiderPathDecendantOfOtherParentPath() {
+        assertThat(path.isDecendantOf(parent), is(true));
+    }
+
+    @Test
+    public void shouldReturnChildSegmentFromGetLastSegment() {
+        assertThat(path.getLastSegment(), is(sameInstance(childSegment)));
+    }
+
+    @Test
+    public void shouldReturnChildSegmentFromGetSegmentWithIndexOfSizeMinusOne() {
+        assertThat(path.getSegment(path.size() - 1), is(sameInstance(childSegment)));
+    }
+
+    @Test
+    public void shouldDelegateGetSegmentToParentIfIndexNotEqualToSizeMinusOne() {
+        Path.Segment segment = mock(Path.Segment.class);
+        parent = mock(Path.class);
+        stub(parent.size()).toReturn(10);
+        path = new ChildPath(parent, segment("d"));
+        stub(parent.getSegment(anyInt())).toReturn(segment);
+        for (int i = 0; i < path.size() - 1; ++i) {
+            assertThat(path.getSegment(i), is(sameInstance(segment)));
+        }
+        verify(parent, times(parent.size())).getSegment(anyInt());
+    }
+
+    @Test
+    public void shouldReturnParentInstanceFromGetParent() {
+        assertThat(path.getParent(), is(sameInstance(parent)));
+    }
+
+    // @Test
+    // public void shouldReturnRootForLowestCommonAncestorWithAnyNodePath() {
+    // Path other = mock(Path.class);
+    // stub(other.isRoot()).toReturn(true);
+    // assertThat(root.getCommonAncestor(other).isRoot(), is(true));
+    //
+    // stub(other.isRoot()).toReturn(false);
+    // assertThat(root.getCommonAncestor(other).isRoot(), is(true));
+    // }
+    //
+    // @Test
+    // public void shouldConsiderRootToBeAncestorOfEveryNodeExceptRoot() {
+    // Path other = mock(Path.class);
+    // stub(other.size()).toReturn(1);
+    // assertThat(root.isAncestorOf(other), is(true));
+    // assertThat(root.isAncestorOf(root), is(false));
+    // }
+    //
+    // @Test
+    // public void shouldNotConsiderRootNodeToBeDecendantOfAnyNode() {
+    // Path other = mock(Path.class);
+    // assertThat(root.isDecendantOf(other), is(false));
+    // assertThat(root.isDecendantOf(root), is(false));
+    // }
+    //
+    // @Test
+    // public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
+    // assertThat(root.hasSameAncestor(root), is(true));
+    // }
+    //
+    // @Test
+    // public void shouldBeNormalized() {
+    // assertThat(root.isNormalized(), is(true));
+    // }
+    //
+    // @Test
+    // public void shouldReturnSelfForGetNormalized() {
+    // assertThat(root.getNormalizedPath(), is(sameInstance(root)));
+    // }
+    //
+    // @Test
+    // public void shouldReturnSelfForGetCanonicalPath() {
+    // assertThat(root.getCanonicalPath(), is(sameInstance(root)));
+    // }
+    //
+    // @Test
+    // public void shouldReturnSizeOfZero() {
+    // assertThat(root.size(), is(0));
+    // }
+    //
+    // @Test
+    // public void shouldReturnEmptyIteratorOverSegments() {
+    // assertThat(root.iterator(), is(notNullValue()));
+    // assertThat(root.iterator().hasNext(), is(false));
+    // }
+    //
+    // @Test( expected = IndexOutOfBoundsException.class )
+    // public void shouldFailToReturnSegmentAtIndexZero() {
+    // root.getSegment(0);
+    // }
+    //
+    // @Test( expected = IndexOutOfBoundsException.class )
+    // public void shouldFailToReturnSegmentAtPositiveIndex() {
+    // root.getSegment(1);
+    // }
+    //
+    // @Test
+    // public void shouldReturnEmptySegmentsArray() {
+    // assertThat(root.getSegmentsArray(), is(notNullValue()));
+    // assertThat(root.getSegmentsArray().length, is(0));
+    // }
+    //
+    // @Test
+    // public void shouldReturnEmptySegmentsList() {
+    // assertThat(root.getSegmentsList(), is(notNullValue()));
+    // assertThat(root.getSegmentsList().isEmpty(), is(true));
+    // }
+    //
+    // @Test
+    // public void shouldAlwaysReturnPathWithSingleSlashForGetString() {
+    // NamespaceRegistry registry = mock(NamespaceRegistry.class);
+    // TextEncoder encoder = mock(TextEncoder.class);
+    // stub(encoder.encode("/")).toReturn("/");
+    // assertThat(root.getString(), is("/"));
+    // assertThat(root.getString(registry), is("/"));
+    // assertThat(root.getString(registry, encoder), is("/"));
+    // assertThat(root.getString(registry, encoder, encoder), is("/"));
+    // assertThat(root.getString(encoder), is("/"));
+    // }
+    //
+    // @Test
+    // public void shouldAllowNullNamespaceRegistryWithNonNullTextEncodersSinceRegistryIsNotNeeded() {
+    // TextEncoder encoder = mock(TextEncoder.class);
+    // stub(encoder.encode("/")).toReturn("/");
+    // assertThat(root.getString((NamespaceRegistry)null, encoder, encoder), is("/"));
+    // }
+    //
+    // @Test
+    // public void shouldAllowNullTextEncoder() {
+    // assertThat(root.getString((TextEncoder)null), is("/"));
+    // }
+    //
+    // @Test
+    // public void shouldNotAllowNullTextEncoderWithNonNullNamespaceRegistry() {
+    // NamespaceRegistry registry = mock(NamespaceRegistry.class);
+    // assertThat(root.getString(registry, (TextEncoder)null), is("/"));
+    // }
+    //
+    // @Test
+    // public void shouldNotAllowNullTextEncoderForDelimiterWithNonNullNamespaceRegistry() {
+    // NamespaceRegistry registry = mock(NamespaceRegistry.class);
+    // TextEncoder encoder = mock(TextEncoder.class);
+    // assertThat(root.getString(registry, encoder, (TextEncoder)null), is("/"));
+    // }
+    //
+    // @Test( expected = IndexOutOfBoundsException.class )
+    // public void shouldNotAllowSubpathStartingAtOne() {
+    // root.subpath(1);
+    // }
+    //
+    // @Test( expected = IndexOutOfBoundsException.class )
+    // public void shouldNotAllowSubpathStartingAtMoreThanOne() {
+    // root.subpath(2);
+    // }
+    //
+    // @Test( expected = IndexOutOfBoundsException.class )
+    // public void shouldNotAllowSubpathEndingAtMoreThanZero() {
+    // root.subpath(0, 1);
+    // }
+    //
+    // @Test
+    // public void shouldReturnRelativePathConsistingOfSameNumberOfParentReferencesAsSizeOfSuppliedPath() {
+    // List<Path.Segment> segments = new ArrayList<Path.Segment>();
+    // segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
+    // Path other = new BasicPath(segments, true);
+    //
+    // assertThat(root.relativeTo(other).toString(), is(".."));
+    //
+    // segments.add(new BasicPathSegment(new BasicName("http://example.com", "b")));
+    // other = new BasicPath(segments, true);
+    // assertThat(root.relativeTo(other).toString(), is("../.."));
+    //
+    // String expected = "..";
+    // segments.clear();
+    // for (int i = 1; i != 100; ++i) {
+    // segments.add(new BasicPathSegment(new BasicName("http://example.com", "b" + i)));
+    // other = new BasicPath(segments, true);
+    // assertThat(root.relativeTo(other).toString(), is(expected));
+    // expected = expected + "/..";
+    // }
+    // }
+    //
+    // @Test
+    // public void shouldResolveAllRelativePathsToTheirAbsolutePath() {
+    // List<Path.Segment> segments = new ArrayList<Path.Segment>();
+    // segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
+    // Path other = mock(Path.class);
+    // stub(other.isAbsolute()).toReturn(false);
+    // stub(other.getSegmentsList()).toReturn(segments);
+    // Path resolved = root.resolve(other);
+    // assertThat(resolved.getSegmentsList(), is(segments));
+    // assertThat(resolved.isAbsolute(), is(true));
+    // }
+    //
+    // @Test( expected = InvalidPathException.class )
+    // public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+    // Path other = mock(Path.class);
+    // stub(other.isAbsolute()).toReturn(true);
+    // root.resolve(other);
+    // }
+    //
+    // @Test
+    // public void shouldAlwaysConsiderRootAsLessThanAnyPathOtherThanRoot() {
+    // Path other = mock(Path.class);
+    // stub(other.isRoot()).toReturn(false);
+    // assertThat(root.compareTo(other), is(-1));
+    // assertThat(root.equals(other), is(false));
+    // }
+    //
+    // @Test
+    // public void shouldAlwaysConsiderRootAsEqualToAnyOtherRoot() {
+    // Path other = mock(Path.class);
+    // stub(other.isRoot()).toReturn(true);
+    // assertThat(root.compareTo(other), is(0));
+    // assertThat(root.equals(other), is(true));
+    // assertThat(root.equals(root), is(true));
+    // }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DecimalValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/DecimalValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DecimalValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,188 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import java.io.ByteArrayInputStream;
-import java.io.StringReader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.basic.DecimalValueFactory;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class DecimalValueFactoryTest {
-
-    private DecimalValueFactory factory;
-    private StringValueFactory stringFactory;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.DEFAULT_ENCODER);
-        factory = new DecimalValueFactory(Path.URL_DECODER, stringFactory);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDecimalFromBooleanValue() {
-        factory.create(true);
-    }
-
-    @Test
-    public void shouldCreateDecimalFromString() {
-        assertThat(factory.create("1"), is(BigDecimal.valueOf(1)));
-        assertThat(factory.create("-1.0"), is(BigDecimal.valueOf(-1.0d)));
-        assertThat(factory.create("100.000101"), is(BigDecimal.valueOf(100.000101d)));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromStringRegardlessOfLeadingAndTrailingWhitespace() {
-        assertThat(factory.create("  1  "), is(BigDecimal.valueOf(1)));
-        assertThat(factory.create("  -1.0  "), is(BigDecimal.valueOf(-1.0d)));
-        assertThat(factory.create("  100.000101  "), is(BigDecimal.valueOf(100.000101d)));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromIntegerValue() {
-        assertThat(factory.create(1), is(BigDecimal.valueOf(1)));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromLongValue() {
-        assertThat(factory.create(1l), is(BigDecimal.valueOf(1l)));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromFloatValue() {
-        assertThat(factory.create(1.0f), is(BigDecimal.valueOf(1.0f)));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromDoubleValue() {
-        assertThat(factory.create(1.0d), is(BigDecimal.valueOf(1.0d)));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromBigDecimal() {
-        BigDecimal value = new BigDecimal(100);
-        assertThat(factory.create(value), is(value));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromDate() {
-        Date value = new Date();
-        assertThat(factory.create(value), is(BigDecimal.valueOf(value.getTime())));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromCalendar() {
-        Calendar value = Calendar.getInstance();
-        assertThat(factory.create(value), is(BigDecimal.valueOf(value.getTimeInMillis())));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDecimalFromName() {
-        factory.create(mock(Name.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDecimalFromPath() {
-        factory.create(mock(Path.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDecimalFromReference() {
-        factory.create(mock(Reference.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDecimalFromUri() throws Exception {
-        factory.create(new URI("http://www.jboss.org"));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromByteArrayContainingUtf8EncodingOfStringWithDecimal() throws Exception {
-        assertThat(factory.create("1".getBytes("UTF-8")), is(BigDecimal.valueOf(1l)));
-        assertThat(factory.create("-1.0".getBytes("UTF-8")), is(BigDecimal.valueOf(-1.d)));
-        assertThat(factory.create("100.000101".getBytes("UTF-8")), is(BigDecimal.valueOf(100.000101d)));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromInputStreamContainingUtf8EncodingOfStringWithDecimal() throws Exception {
-        assertThat(factory.create(new ByteArrayInputStream("1".getBytes("UTF-8"))), is(BigDecimal.valueOf(1l)));
-        assertThat(factory.create(new ByteArrayInputStream("-1.0".getBytes("UTF-8"))), is(BigDecimal.valueOf(-1.d)));
-        assertThat(factory.create(new ByteArrayInputStream("100.000101".getBytes("UTF-8"))), is(BigDecimal.valueOf(100.000101d)));
-    }
-
-    @Test
-    public void shouldCreateDecimalFromReaderContainingStringWithDecimal() {
-        assertThat(factory.create(new StringReader("1")), is(BigDecimal.valueOf(1l)));
-        assertThat(factory.create(new StringReader("-1.0")), is(BigDecimal.valueOf(-1.d)));
-        assertThat(factory.create(new StringReader("100.000101")), is(BigDecimal.valueOf(100.000101d)));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDecimalFromByteArrayContainingUtf8EncodingOfStringWithContentsOtherThanDecimal() throws Exception {
-        factory.create("something".getBytes("UTF-8"));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDecimalFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanDecimal()
-        throws Exception {
-        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDecimalFromReaderContainingStringWithContentsOtherThanDecimal() {
-        factory.create(new StringReader("something"));
-    }
-
-    @Test
-    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
-        List<String> values = new ArrayList<String>();
-        for (int i = 0; i != 10; ++i)
-            values.add("" + i);
-        Iterator<BigDecimal> iter = factory.create(values.iterator());
-        Iterator<String> valueIter = values.iterator();
-        while (iter.hasNext()) {
-            assertThat(iter.next(), is(factory.create(valueIter.next())));
-        }
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DecimalValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/DecimalValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DecimalValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DecimalValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,188 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.DecimalValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class DecimalValueFactoryTest {
+
+    private DecimalValueFactory factory;
+    private StringValueFactory stringFactory;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.DEFAULT_ENCODER);
+        factory = new DecimalValueFactory(Path.URL_DECODER, stringFactory);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDecimalFromBooleanValue() {
+        factory.create(true);
+    }
+
+    @Test
+    public void shouldCreateDecimalFromString() {
+        assertThat(factory.create("1"), is(BigDecimal.valueOf(1)));
+        assertThat(factory.create("-1.0"), is(BigDecimal.valueOf(-1.0d)));
+        assertThat(factory.create("100.000101"), is(BigDecimal.valueOf(100.000101d)));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromStringRegardlessOfLeadingAndTrailingWhitespace() {
+        assertThat(factory.create("  1  "), is(BigDecimal.valueOf(1)));
+        assertThat(factory.create("  -1.0  "), is(BigDecimal.valueOf(-1.0d)));
+        assertThat(factory.create("  100.000101  "), is(BigDecimal.valueOf(100.000101d)));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromIntegerValue() {
+        assertThat(factory.create(1), is(BigDecimal.valueOf(1)));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromLongValue() {
+        assertThat(factory.create(1l), is(BigDecimal.valueOf(1l)));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromFloatValue() {
+        assertThat(factory.create(1.0f), is(BigDecimal.valueOf(1.0f)));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromDoubleValue() {
+        assertThat(factory.create(1.0d), is(BigDecimal.valueOf(1.0d)));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromBigDecimal() {
+        BigDecimal value = new BigDecimal(100);
+        assertThat(factory.create(value), is(value));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromDate() {
+        Date value = new Date();
+        assertThat(factory.create(value), is(BigDecimal.valueOf(value.getTime())));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromCalendar() {
+        Calendar value = Calendar.getInstance();
+        assertThat(factory.create(value), is(BigDecimal.valueOf(value.getTimeInMillis())));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDecimalFromName() {
+        factory.create(mock(Name.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDecimalFromPath() {
+        factory.create(mock(Path.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDecimalFromReference() {
+        factory.create(mock(Reference.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDecimalFromUri() throws Exception {
+        factory.create(new URI("http://www.jboss.org"));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromByteArrayContainingUtf8EncodingOfStringWithDecimal() throws Exception {
+        assertThat(factory.create("1".getBytes("UTF-8")), is(BigDecimal.valueOf(1l)));
+        assertThat(factory.create("-1.0".getBytes("UTF-8")), is(BigDecimal.valueOf(-1.d)));
+        assertThat(factory.create("100.000101".getBytes("UTF-8")), is(BigDecimal.valueOf(100.000101d)));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromInputStreamContainingUtf8EncodingOfStringWithDecimal() throws Exception {
+        assertThat(factory.create(new ByteArrayInputStream("1".getBytes("UTF-8"))), is(BigDecimal.valueOf(1l)));
+        assertThat(factory.create(new ByteArrayInputStream("-1.0".getBytes("UTF-8"))), is(BigDecimal.valueOf(-1.d)));
+        assertThat(factory.create(new ByteArrayInputStream("100.000101".getBytes("UTF-8"))), is(BigDecimal.valueOf(100.000101d)));
+    }
+
+    @Test
+    public void shouldCreateDecimalFromReaderContainingStringWithDecimal() {
+        assertThat(factory.create(new StringReader("1")), is(BigDecimal.valueOf(1l)));
+        assertThat(factory.create(new StringReader("-1.0")), is(BigDecimal.valueOf(-1.d)));
+        assertThat(factory.create(new StringReader("100.000101")), is(BigDecimal.valueOf(100.000101d)));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDecimalFromByteArrayContainingUtf8EncodingOfStringWithContentsOtherThanDecimal() throws Exception {
+        factory.create("something".getBytes("UTF-8"));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDecimalFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanDecimal()
+        throws Exception {
+        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDecimalFromReaderContainingStringWithContentsOtherThanDecimal() {
+        factory.create(new StringReader("something"));
+    }
+
+    @Test
+    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
+        List<String> values = new ArrayList<String>();
+        for (int i = 0; i != 10; ++i)
+            values.add("" + i);
+        Iterator<BigDecimal> iter = factory.create(values.iterator());
+        Iterator<String> valueIter = values.iterator();
+        while (iter.hasNext()) {
+            assertThat(iter.next(), is(factory.create(valueIter.next())));
+        }
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DoubleValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/DoubleValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DoubleValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,190 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import java.io.ByteArrayInputStream;
-import java.io.StringReader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.basic.DoubleValueFactory;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class DoubleValueFactoryTest {
-
-    private DoubleValueFactory factory;
-    private StringValueFactory stringFactory;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
-        factory = new DoubleValueFactory(Path.URL_DECODER, stringFactory);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromBooleanValue() {
-        factory.create(true);
-    }
-
-    @Test
-    public void shouldCreateDoubleFromString() {
-        assertThat(factory.create("1"), is(Double.valueOf(1)));
-        assertThat(factory.create("-1.0"), is(Double.valueOf(-1.0d)));
-        assertThat(factory.create("100.000101"), is(Double.valueOf(100.000101d)));
-    }
-
-    @Test
-    public void shouldCreateDoubleFromStringRegardlessOfLeadingAndTrailingWhitespace() {
-        assertThat(factory.create("  1  "), is(Double.valueOf(1)));
-        assertThat(factory.create("  -1.0  "), is(Double.valueOf(-1.0d)));
-        assertThat(factory.create("  100.000101  "), is(Double.valueOf(100.000101d)));
-    }
-
-    @Test
-    public void shouldNotCreateDoubleFromIntegerValue() {
-        assertThat(factory.create(1), is(1.0d));
-    }
-
-    @Test
-    public void shouldNotCreateDoubleFromLongValue() {
-        assertThat(factory.create(1l), is(1.0d));
-    }
-
-    @Test
-    public void shouldNotCreateDoubleFromFloatValue() {
-        assertThat(factory.create(1.0f), is(1.0d));
-    }
-
-    @Test
-    public void shouldNotCreateDoubleFromDoubleValue() {
-        assertThat(factory.create(1.0d), is(1.0d));
-    }
-
-    @Test
-    public void shouldCreateDoubleFromBigDecimal() {
-        BigDecimal value = new BigDecimal(100);
-        assertThat(factory.create(value), is(value.doubleValue()));
-    }
-
-    @Test
-    public void shouldCreateDoubleFromDate() {
-        Date value = new Date();
-        assertThat(factory.create(value), is(Double.valueOf(value.getTime())));
-    }
-
-    @Test
-    public void shouldCreateDoubleFromCalendar() {
-        Calendar value = Calendar.getInstance();
-        assertThat(factory.create(value), is(Double.valueOf(value.getTimeInMillis())));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromName() {
-        factory.create(mock(Name.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromPath() {
-        factory.create(mock(Path.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromReference() {
-        factory.create(mock(Reference.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromUri() throws Exception {
-        factory.create(new URI("http://www.jboss.org"));
-    }
-
-    @Test
-    public void shouldCreateDoubleFromByteArrayContainingUtf8EncodingOfStringWithDouble() throws Exception {
-        assertThat(factory.create("0.1".getBytes("UTF-8")), is(0.1d));
-        assertThat(factory.create("1".getBytes("UTF-8")), is(1.0d));
-        assertThat(factory.create("-1.03".getBytes("UTF-8")), is(-1.03));
-        assertThat(factory.create("1003044".getBytes("UTF-8")), is(1003044.d));
-    }
-
-    @Test
-    public void shouldCreateDoubleFromInputStreamContainingUtf8EncodingOfStringWithDouble() throws Exception {
-        assertThat(factory.create(new ByteArrayInputStream("0.1".getBytes("UTF-8"))), is(0.1d));
-        assertThat(factory.create(new ByteArrayInputStream("1".getBytes("UTF-8"))), is(1.0d));
-        assertThat(factory.create(new ByteArrayInputStream("-1.03".getBytes("UTF-8"))), is(-1.03));
-        assertThat(factory.create(new ByteArrayInputStream("1003044".getBytes("UTF-8"))), is(1003044.d));
-    }
-
-    @Test
-    public void shouldCreateDoubleFromReaderContainingStringWithDouble() {
-        assertThat(factory.create(new StringReader("0.1")), is(0.1d));
-        assertThat(factory.create(new StringReader("1")), is(1.0d));
-        assertThat(factory.create(new StringReader("-1.03")), is(-1.03));
-        assertThat(factory.create(new StringReader("1003044")), is(1003044.d));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromByteArrayContainingUtf8EncodingOfStringWithContentsOtherThanDouble() throws Exception {
-        factory.create("something".getBytes("UTF-8"));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanDouble() throws Exception {
-        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromReaderContainingStringWithContentsOtherThanDouble() throws Exception {
-        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
-    }
-
-    @Test
-    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
-        List<String> values = new ArrayList<String>();
-        for (int i = 0; i != 10; ++i)
-            values.add("" + i);
-        Iterator<Double> iter = factory.create(values.iterator());
-        Iterator<String> valueIter = values.iterator();
-        while (iter.hasNext()) {
-            assertThat(iter.next(), is(factory.create(valueIter.next())));
-        }
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DoubleValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/DoubleValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DoubleValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/DoubleValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,190 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.DoubleValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class DoubleValueFactoryTest {
+
+    private DoubleValueFactory factory;
+    private StringValueFactory stringFactory;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
+        factory = new DoubleValueFactory(Path.URL_DECODER, stringFactory);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromBooleanValue() {
+        factory.create(true);
+    }
+
+    @Test
+    public void shouldCreateDoubleFromString() {
+        assertThat(factory.create("1"), is(Double.valueOf(1)));
+        assertThat(factory.create("-1.0"), is(Double.valueOf(-1.0d)));
+        assertThat(factory.create("100.000101"), is(Double.valueOf(100.000101d)));
+    }
+
+    @Test
+    public void shouldCreateDoubleFromStringRegardlessOfLeadingAndTrailingWhitespace() {
+        assertThat(factory.create("  1  "), is(Double.valueOf(1)));
+        assertThat(factory.create("  -1.0  "), is(Double.valueOf(-1.0d)));
+        assertThat(factory.create("  100.000101  "), is(Double.valueOf(100.000101d)));
+    }
+
+    @Test
+    public void shouldNotCreateDoubleFromIntegerValue() {
+        assertThat(factory.create(1), is(1.0d));
+    }
+
+    @Test
+    public void shouldNotCreateDoubleFromLongValue() {
+        assertThat(factory.create(1l), is(1.0d));
+    }
+
+    @Test
+    public void shouldNotCreateDoubleFromFloatValue() {
+        assertThat(factory.create(1.0f), is(1.0d));
+    }
+
+    @Test
+    public void shouldNotCreateDoubleFromDoubleValue() {
+        assertThat(factory.create(1.0d), is(1.0d));
+    }
+
+    @Test
+    public void shouldCreateDoubleFromBigDecimal() {
+        BigDecimal value = new BigDecimal(100);
+        assertThat(factory.create(value), is(value.doubleValue()));
+    }
+
+    @Test
+    public void shouldCreateDoubleFromDate() {
+        Date value = new Date();
+        assertThat(factory.create(value), is(Double.valueOf(value.getTime())));
+    }
+
+    @Test
+    public void shouldCreateDoubleFromCalendar() {
+        Calendar value = Calendar.getInstance();
+        assertThat(factory.create(value), is(Double.valueOf(value.getTimeInMillis())));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromName() {
+        factory.create(mock(Name.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromPath() {
+        factory.create(mock(Path.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromReference() {
+        factory.create(mock(Reference.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromUri() throws Exception {
+        factory.create(new URI("http://www.jboss.org"));
+    }
+
+    @Test
+    public void shouldCreateDoubleFromByteArrayContainingUtf8EncodingOfStringWithDouble() throws Exception {
+        assertThat(factory.create("0.1".getBytes("UTF-8")), is(0.1d));
+        assertThat(factory.create("1".getBytes("UTF-8")), is(1.0d));
+        assertThat(factory.create("-1.03".getBytes("UTF-8")), is(-1.03));
+        assertThat(factory.create("1003044".getBytes("UTF-8")), is(1003044.d));
+    }
+
+    @Test
+    public void shouldCreateDoubleFromInputStreamContainingUtf8EncodingOfStringWithDouble() throws Exception {
+        assertThat(factory.create(new ByteArrayInputStream("0.1".getBytes("UTF-8"))), is(0.1d));
+        assertThat(factory.create(new ByteArrayInputStream("1".getBytes("UTF-8"))), is(1.0d));
+        assertThat(factory.create(new ByteArrayInputStream("-1.03".getBytes("UTF-8"))), is(-1.03));
+        assertThat(factory.create(new ByteArrayInputStream("1003044".getBytes("UTF-8"))), is(1003044.d));
+    }
+
+    @Test
+    public void shouldCreateDoubleFromReaderContainingStringWithDouble() {
+        assertThat(factory.create(new StringReader("0.1")), is(0.1d));
+        assertThat(factory.create(new StringReader("1")), is(1.0d));
+        assertThat(factory.create(new StringReader("-1.03")), is(-1.03));
+        assertThat(factory.create(new StringReader("1003044")), is(1003044.d));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromByteArrayContainingUtf8EncodingOfStringWithContentsOtherThanDouble() throws Exception {
+        factory.create("something".getBytes("UTF-8"));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanDouble() throws Exception {
+        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromReaderContainingStringWithContentsOtherThanDouble() throws Exception {
+        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
+    }
+
+    @Test
+    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
+        List<String> values = new ArrayList<String>();
+        for (int i = 0; i != 10; ++i)
+            values.add("" + i);
+        Iterator<Double> iter = factory.create(values.iterator());
+        Iterator<String> valueIter = values.iterator();
+        while (iter.hasNext()) {
+            assertThat(iter.next(), is(factory.create(valueIter.next())));
+        }
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/InMemoryBinaryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,133 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.jboss.dna.graph.properties.basic.BinaryContains.hasContent;
-import static org.jboss.dna.graph.properties.basic.BinaryContains.hasNoContent;
-import static org.junit.Assert.assertThat;
-import java.io.IOException;
-import java.io.InputStream;
-import org.jboss.dna.common.util.IoUtil;
-import org.jboss.dna.common.util.StringUtil;
-import org.jboss.dna.graph.properties.Binary;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class InMemoryBinaryTest {
-
-    private byte[] validByteArrayContent;
-    private String validStringContent;
-    private InMemoryBinary binary;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        validStringContent = "This is a valid string content";
-        validByteArrayContent = this.validStringContent.getBytes("UTF-8");
-        binary = new InMemoryBinary(validByteArrayContent);
-    }
-
-    @Test
-    public void shouldConstructFromByteArray() {
-        binary = new InMemoryBinary(validByteArrayContent);
-        assertThat(binary.getSize(), is((long)validByteArrayContent.length));
-        assertThat(binary, hasContent(validByteArrayContent));
-    }
-
-    @Test
-    public void shouldConstructFromEmptyByteArray() {
-        validByteArrayContent = new byte[0];
-        binary = new InMemoryBinary(validByteArrayContent);
-        assertThat(binary.getSize(), is(0l));
-        assertThat(binary, hasNoContent());
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotConstructFromNullByteArray() {
-        new InMemoryBinary(null);
-    }
-
-    @Test
-    public void shouldHaveSizeThatMatchesContentLength() {
-        assertThat(binary.getSize(), is((long)validByteArrayContent.length));
-    }
-
-    @Test
-    public void shouldProvideInputStreamToContent() throws IOException {
-        InputStream stream = binary.getStream();
-        byte[] actual = IoUtil.readBytes(stream); // closes the stream
-        assertThat(actual.length, is(validByteArrayContent.length));
-        for (int i = 0, len = actual.length; i != len; ++i) {
-            assertThat(actual[i], is(validByteArrayContent[i]));
-        }
-    }
-
-    @Test
-    public void shouldConsiderEquivalentThoseInstancesWithSameContent() {
-        Binary another = new InMemoryBinary(validByteArrayContent);
-        assertThat(binary.equals(another), is(true));
-        assertThat(binary.compareTo(another), is(0));
-        assertThat(binary, is(another));
-        assertThat(binary, hasContent(validByteArrayContent));
-        assertThat(another, hasContent(validByteArrayContent));
-    }
-
-    @Test
-    public void shouldUseSizeWhenComparing() {
-        byte[] shorterContent = new byte[validByteArrayContent.length - 2];
-        for (int i = 0; i != shorterContent.length; ++i) {
-            shorterContent[i] = validByteArrayContent[i];
-        }
-        Binary another = new InMemoryBinary(shorterContent);
-        assertThat(binary.equals(another), is(false));
-        assertThat(binary.compareTo(another), is(1));
-        assertThat(another.compareTo(binary), is(-1));
-        assertThat(another, hasContent(shorterContent));
-    }
-
-    @Test
-    public void shouldComputeSha1HashOfEmptyContent() throws Exception {
-        validByteArrayContent = new byte[0];
-        binary = new InMemoryBinary(validByteArrayContent);
-        assertThat(binary.getSize(), is(0l));
-        assertThat(binary, hasNoContent());
-        byte[] hash = binary.getHash();
-        assertThat(hash.length, is(20));
-        assertThat(StringUtil.getHexString(hash), is("da39a3ee5e6b4b0d3255bfef95601890afd80709"));
-    }
-
-    @Test
-    public void shouldComputeSha1HashOfNonEmptyContent() throws Exception {
-        binary = new InMemoryBinary(validByteArrayContent);
-        assertThat(binary.getSize(), is((long)validByteArrayContent.length));
-        byte[] hash = binary.getHash();
-        assertThat(hash.length, is(20));
-        assertThat(StringUtil.getHexString(hash), is("14abe696257e85ba18b7c784d6c7855f46ce50ea"));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/InMemoryBinaryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,134 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.jboss.dna.graph.property.basic.BinaryContains.hasContent;
+import static org.jboss.dna.graph.property.basic.BinaryContains.hasNoContent;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.io.IOException;
+import java.io.InputStream;
+import org.jboss.dna.common.util.IoUtil;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.basic.InMemoryBinary;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class InMemoryBinaryTest {
+
+    private byte[] validByteArrayContent;
+    private String validStringContent;
+    private InMemoryBinary binary;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        validStringContent = "This is a valid string content";
+        validByteArrayContent = this.validStringContent.getBytes("UTF-8");
+        binary = new InMemoryBinary(validByteArrayContent);
+    }
+
+    @Test
+    public void shouldConstructFromByteArray() {
+        binary = new InMemoryBinary(validByteArrayContent);
+        assertThat(binary.getSize(), is((long)validByteArrayContent.length));
+        assertThat(binary, hasContent(validByteArrayContent));
+    }
+
+    @Test
+    public void shouldConstructFromEmptyByteArray() {
+        validByteArrayContent = new byte[0];
+        binary = new InMemoryBinary(validByteArrayContent);
+        assertThat(binary.getSize(), is(0l));
+        assertThat(binary, hasNoContent());
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotConstructFromNullByteArray() {
+        new InMemoryBinary(null);
+    }
+
+    @Test
+    public void shouldHaveSizeThatMatchesContentLength() {
+        assertThat(binary.getSize(), is((long)validByteArrayContent.length));
+    }
+
+    @Test
+    public void shouldProvideInputStreamToContent() throws IOException {
+        InputStream stream = binary.getStream();
+        byte[] actual = IoUtil.readBytes(stream); // closes the stream
+        assertThat(actual.length, is(validByteArrayContent.length));
+        for (int i = 0, len = actual.length; i != len; ++i) {
+            assertThat(actual[i], is(validByteArrayContent[i]));
+        }
+    }
+
+    @Test
+    public void shouldConsiderEquivalentThoseInstancesWithSameContent() {
+        Binary another = new InMemoryBinary(validByteArrayContent);
+        assertThat(binary.equals(another), is(true));
+        assertThat(binary.compareTo(another), is(0));
+        assertThat(binary, is(another));
+        assertThat(binary, hasContent(validByteArrayContent));
+        assertThat(another, hasContent(validByteArrayContent));
+    }
+
+    @Test
+    public void shouldUseSizeWhenComparing() {
+        byte[] shorterContent = new byte[validByteArrayContent.length - 2];
+        for (int i = 0; i != shorterContent.length; ++i) {
+            shorterContent[i] = validByteArrayContent[i];
+        }
+        Binary another = new InMemoryBinary(shorterContent);
+        assertThat(binary.equals(another), is(false));
+        assertThat(binary.compareTo(another), is(1));
+        assertThat(another.compareTo(binary), is(-1));
+        assertThat(another, hasContent(shorterContent));
+    }
+
+    @Test
+    public void shouldComputeSha1HashOfEmptyContent() throws Exception {
+        validByteArrayContent = new byte[0];
+        binary = new InMemoryBinary(validByteArrayContent);
+        assertThat(binary.getSize(), is(0l));
+        assertThat(binary, hasNoContent());
+        byte[] hash = binary.getHash();
+        assertThat(hash.length, is(20));
+        assertThat(StringUtil.getHexString(hash), is("da39a3ee5e6b4b0d3255bfef95601890afd80709"));
+    }
+
+    @Test
+    public void shouldComputeSha1HashOfNonEmptyContent() throws Exception {
+        binary = new InMemoryBinary(validByteArrayContent);
+        assertThat(binary.getSize(), is((long)validByteArrayContent.length));
+        byte[] hash = binary.getHash();
+        assertThat(hash.length, is(20));
+        assertThat(StringUtil.getHexString(hash), is("14abe696257e85ba18b7c784d6c7855f46ce50ea"));
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/InMemoryBinaryValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,203 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.jboss.dna.graph.properties.basic.BinaryContains.hasContent;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.io.ByteArrayInputStream;
-import java.io.StringReader;
-import java.io.UnsupportedEncodingException;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.UUID;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
-import org.jboss.dna.graph.properties.basic.InMemoryBinaryValueFactory;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.NameValueFactory;
-import org.jboss.dna.graph.properties.basic.PathValueFactory;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.jboss.dna.graph.properties.basic.UuidReference;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class InMemoryBinaryValueFactoryTest {
-
-    private InMemoryBinaryValueFactory factory;
-    private StringValueFactory stringFactory;
-    private NameValueFactory nameFactory;
-    private BasicNamespaceRegistry namespaceRegistry;
-    private PathValueFactory pathFactory;
-    private TextEncoder encoder;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        encoder = Path.URL_ENCODER;
-        stringFactory = new StringValueFactory(Path.URL_DECODER, encoder);
-        factory = new InMemoryBinaryValueFactory(Path.URL_DECODER, stringFactory);
-        namespaceRegistry = new BasicNamespaceRegistry();
-        namespaceRegistry.register("jboss", "http://www.jboss.org");
-        namespaceRegistry.register("dna", "http://www.jboss.org/dna");
-        nameFactory = new NameValueFactory(namespaceRegistry, Path.URL_DECODER, stringFactory);
-        pathFactory = new PathValueFactory(Path.URL_DECODER, stringFactory, nameFactory);
-    }
-
-    @Test
-    public void shouldCreateBinaryFromBooleanValue() {
-        factory.create(true);
-    }
-
-    @Test
-    public void shouldCreateDecimalFromString() throws UnsupportedEncodingException {
-        assertThat(factory.create("1"), hasContent("1"));
-        assertThat(factory.create("-1.0"), hasContent("-1.0"));
-        assertThat(factory.create("100.000101"), hasContent("100.000101"));
-        assertThat(factory.create("quick brown fox."), hasContent("quick brown fox."));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromStringIncludingfLeadingAndTrailingWhitespace() throws UnsupportedEncodingException {
-        assertThat(factory.create("   1   "), hasContent("   1   "));
-        assertThat(factory.create("   -1.0   "), hasContent("   -1.0   "));
-        assertThat(factory.create("   100.000101   "), hasContent("   100.000101   "));
-        assertThat(factory.create("   quick brown fox.   "), hasContent("   quick brown fox.   "));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromIntegerValue() throws UnsupportedEncodingException {
-        assertThat(factory.create(1), hasContent(Integer.toString(1)));
-        assertThat(factory.create(-1), hasContent(Integer.toString(-1)));
-        assertThat(factory.create(123456), hasContent(Integer.toString(123456)));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromLongValue() throws UnsupportedEncodingException {
-        assertThat(factory.create(1l), hasContent(Long.toString(1)));
-        assertThat(factory.create(-1l), hasContent(Long.toString(-1)));
-        assertThat(factory.create(123456l), hasContent(Long.toString(123456)));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromFloatValue() throws UnsupportedEncodingException {
-        assertThat(factory.create(1.0f), hasContent(Float.toString(1.0f)));
-        assertThat(factory.create(-1.0f), hasContent(Float.toString(-1.0f)));
-        assertThat(factory.create(123456.23f), hasContent(Float.toString(123456.23f)));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromDoubleValue() throws UnsupportedEncodingException {
-        assertThat(factory.create(1.0d), hasContent(Double.toString(1.0d)));
-        assertThat(factory.create(-1.0d), hasContent(Double.toString(-1.0)));
-        assertThat(factory.create(123456.23d), hasContent(Double.toString(123456.23)));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromBigDecimal() throws UnsupportedEncodingException {
-        BigDecimal value = new BigDecimal(100);
-        assertThat(factory.create(value), hasContent(value.toString()));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromDate() throws UnsupportedEncodingException {
-        Date value = new Date();
-        assertThat(factory.create(value), hasContent(new JodaDateTime(value).toString()));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromCalendar() throws UnsupportedEncodingException {
-        Calendar value = Calendar.getInstance();
-        assertThat(factory.create(value), hasContent(new JodaDateTime(value).toString()));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromName() throws UnsupportedEncodingException {
-        Name value = nameFactory.create("jboss:localName");
-        assertThat(factory.create(value), hasContent("{" + encoder.encode("http://www.jboss.org") + "}"
-                                                     + encoder.encode("localName")));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromPath() throws UnsupportedEncodingException {
-        Path value = pathFactory.create("/a/b/c/jboss:localName");
-        assertThat(factory.create(value), hasContent("/{}a/{}b/{}c/{" + encoder.encode("http://www.jboss.org") + "}"
-                                                     + encoder.encode("localName")));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromReference() throws UnsupportedEncodingException {
-        UUID uuid = UUID.randomUUID();
-        Reference value = new UuidReference(uuid);
-        assertThat(factory.create(value), hasContent(uuid.toString()));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromUri() throws Exception {
-        URI value = new URI("http://www.jboss.org");
-        assertThat(factory.create(value), hasContent("http://www.jboss.org"));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromByteArray() throws Exception {
-        byte[] value = "Some byte string".getBytes("UTF-8");
-        assertThat(factory.create(value), hasContent(value));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromInputStream() throws Exception {
-        String value = "Some test string";
-        assertThat(factory.create(new ByteArrayInputStream(value.getBytes("UTF-8"))), hasContent(value));
-    }
-
-    @Test
-    public void shouldCreateBinaryFromReader() throws Exception {
-        String value = "Some test string";
-        assertThat(factory.create(new StringReader(value)), hasContent(value));
-    }
-
-    @Test
-    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
-        List<String> values = new ArrayList<String>();
-        for (int i = 0; i != 10; ++i)
-            values.add("some string" + i);
-        Iterator<Binary> iter = factory.create(values.iterator());
-        Iterator<String> valueIter = values.iterator();
-        while (iter.hasNext()) {
-            assertThat(iter.next(), is(factory.create(valueIter.next())));
-        }
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/InMemoryBinaryValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/InMemoryBinaryValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,203 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.jboss.dna.graph.property.basic.BinaryContains.hasContent;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.InMemoryBinaryValueFactory;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.NameValueFactory;
+import org.jboss.dna.graph.property.basic.PathValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.jboss.dna.graph.property.basic.UuidReference;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class InMemoryBinaryValueFactoryTest {
+
+    private InMemoryBinaryValueFactory factory;
+    private StringValueFactory stringFactory;
+    private NameValueFactory nameFactory;
+    private BasicNamespaceRegistry namespaceRegistry;
+    private PathValueFactory pathFactory;
+    private TextEncoder encoder;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        encoder = Path.URL_ENCODER;
+        stringFactory = new StringValueFactory(Path.URL_DECODER, encoder);
+        factory = new InMemoryBinaryValueFactory(Path.URL_DECODER, stringFactory);
+        namespaceRegistry = new BasicNamespaceRegistry();
+        namespaceRegistry.register("jboss", "http://www.jboss.org");
+        namespaceRegistry.register("dna", "http://www.jboss.org/dna");
+        nameFactory = new NameValueFactory(namespaceRegistry, Path.URL_DECODER, stringFactory);
+        pathFactory = new PathValueFactory(Path.URL_DECODER, stringFactory, nameFactory);
+    }
+
+    @Test
+    public void shouldCreateBinaryFromBooleanValue() {
+        factory.create(true);
+    }
+
+    @Test
+    public void shouldCreateDecimalFromString() throws UnsupportedEncodingException {
+        assertThat(factory.create("1"), hasContent("1"));
+        assertThat(factory.create("-1.0"), hasContent("-1.0"));
+        assertThat(factory.create("100.000101"), hasContent("100.000101"));
+        assertThat(factory.create("quick brown fox."), hasContent("quick brown fox."));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromStringIncludingfLeadingAndTrailingWhitespace() throws UnsupportedEncodingException {
+        assertThat(factory.create("   1   "), hasContent("   1   "));
+        assertThat(factory.create("   -1.0   "), hasContent("   -1.0   "));
+        assertThat(factory.create("   100.000101   "), hasContent("   100.000101   "));
+        assertThat(factory.create("   quick brown fox.   "), hasContent("   quick brown fox.   "));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromIntegerValue() throws UnsupportedEncodingException {
+        assertThat(factory.create(1), hasContent(Integer.toString(1)));
+        assertThat(factory.create(-1), hasContent(Integer.toString(-1)));
+        assertThat(factory.create(123456), hasContent(Integer.toString(123456)));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromLongValue() throws UnsupportedEncodingException {
+        assertThat(factory.create(1l), hasContent(Long.toString(1)));
+        assertThat(factory.create(-1l), hasContent(Long.toString(-1)));
+        assertThat(factory.create(123456l), hasContent(Long.toString(123456)));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromFloatValue() throws UnsupportedEncodingException {
+        assertThat(factory.create(1.0f), hasContent(Float.toString(1.0f)));
+        assertThat(factory.create(-1.0f), hasContent(Float.toString(-1.0f)));
+        assertThat(factory.create(123456.23f), hasContent(Float.toString(123456.23f)));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromDoubleValue() throws UnsupportedEncodingException {
+        assertThat(factory.create(1.0d), hasContent(Double.toString(1.0d)));
+        assertThat(factory.create(-1.0d), hasContent(Double.toString(-1.0)));
+        assertThat(factory.create(123456.23d), hasContent(Double.toString(123456.23)));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromBigDecimal() throws UnsupportedEncodingException {
+        BigDecimal value = new BigDecimal(100);
+        assertThat(factory.create(value), hasContent(value.toString()));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromDate() throws UnsupportedEncodingException {
+        Date value = new Date();
+        assertThat(factory.create(value), hasContent(new JodaDateTime(value).toString()));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromCalendar() throws UnsupportedEncodingException {
+        Calendar value = Calendar.getInstance();
+        assertThat(factory.create(value), hasContent(new JodaDateTime(value).toString()));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromName() throws UnsupportedEncodingException {
+        Name value = nameFactory.create("jboss:localName");
+        assertThat(factory.create(value), hasContent("{" + encoder.encode("http://www.jboss.org") + "}"
+                                                     + encoder.encode("localName")));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromPath() throws UnsupportedEncodingException {
+        Path value = pathFactory.create("/a/b/c/jboss:localName");
+        assertThat(factory.create(value), hasContent("/{}a/{}b/{}c/{" + encoder.encode("http://www.jboss.org") + "}"
+                                                     + encoder.encode("localName")));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromReference() throws UnsupportedEncodingException {
+        UUID uuid = UUID.randomUUID();
+        Reference value = new UuidReference(uuid);
+        assertThat(factory.create(value), hasContent(uuid.toString()));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromUri() throws Exception {
+        URI value = new URI("http://www.jboss.org");
+        assertThat(factory.create(value), hasContent("http://www.jboss.org"));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromByteArray() throws Exception {
+        byte[] value = "Some byte string".getBytes("UTF-8");
+        assertThat(factory.create(value), hasContent(value));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromInputStream() throws Exception {
+        String value = "Some test string";
+        assertThat(factory.create(new ByteArrayInputStream(value.getBytes("UTF-8"))), hasContent(value));
+    }
+
+    @Test
+    public void shouldCreateBinaryFromReader() throws Exception {
+        String value = "Some test string";
+        assertThat(factory.create(new StringReader(value)), hasContent(value));
+    }
+
+    @Test
+    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
+        List<String> values = new ArrayList<String>();
+        for (int i = 0; i != 10; ++i)
+            values.add("some string" + i);
+        Iterator<Binary> iter = factory.create(values.iterator());
+        Iterator<String> valueIter = values.iterator();
+        while (iter.hasNext()) {
+            assertThat(iter.next(), is(factory.create(valueIter.next())));
+        }
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/IsPathContaining.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/IsPathContaining.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/IsPathContaining.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,106 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.AllOf.allOf;
-import static org.hamcrest.core.IsEqual.equalTo;
-import java.util.ArrayList;
-import java.util.Collection;
-import org.hamcrest.Description;
-import org.hamcrest.Factory;
-import org.hamcrest.Matcher;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Path.Segment;
-import org.junit.matchers.TypeSafeMatcher;
-
-/**
- * @author Randall Hauch
- */
-public class IsPathContaining extends TypeSafeMatcher<Iterable<Segment>> {
-
-    private final Matcher<? super Segment> elementMatcher;
-
-    public IsPathContaining( Matcher<? super Segment> elementMatcher ) {
-        this.elementMatcher = elementMatcher;
-    }
-
-    @Override
-    public boolean matchesSafely( Iterable<Segment> collection ) {
-        for (Segment item : collection) {
-            if (elementMatcher.matches(item)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void describeTo( Description description ) {
-        description.appendText("a path containing ").appendDescriptionOf(elementMatcher);
-    }
-
-    @Factory
-    public static Matcher<Iterable<Segment>> hasSegment( Matcher<? super Segment> elementMatcher ) {
-        return new IsPathContaining(elementMatcher);
-    }
-
-    @Factory
-    public static Matcher<Iterable<Segment>> hasSegment( Segment element ) {
-        return hasSegment(equalTo(element));
-    }
-
-    @Factory
-    public static Matcher<Iterable<Segment>> hasSegments( Matcher<Path.Segment>... elementMatchers ) {
-        Collection<Matcher<? extends Iterable<Path.Segment>>> all = new ArrayList<Matcher<? extends Iterable<Path.Segment>>>(elementMatchers.length);
-
-        for (Matcher<Path.Segment> elementMatcher : elementMatchers) {
-            Matcher<Iterable<Path.Segment>> itemMatcher = hasSegment(elementMatcher);
-            all.add(itemMatcher);
-        }
-
-        return allOf(all);
-    }
-
-    @Factory
-    public static Matcher<Iterable<Segment>> hasSegments( Segment... elements ) {
-        Collection<Matcher<? extends Iterable<Segment>>> all = new ArrayList<Matcher<? extends Iterable<Segment>>>(elements.length);
-        for (Segment element : elements) {
-            all.add(hasSegment(element));
-        }
-        return allOf(all);
-    }
-
-    @Factory
-    public static Matcher<Iterable<Segment>> hasSegment( PathFactory pathFactory, String element ) {
-        Path.Segment segment = pathFactory.createSegment(element);
-        return hasSegment(equalTo(segment));
-    }
-
-    @Factory
-    public static Matcher<Iterable<Segment>> hasSegments( PathFactory pathFactory, String... segments ) {
-        Collection<Matcher<? extends Iterable<Segment>>> all = new ArrayList<Matcher<? extends Iterable<Segment>>>(segments.length);
-        for (String element : segments) {
-            all.add(hasSegment(pathFactory, element));
-        }
-        return allOf(all);
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/IsPathContaining.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/IsPathContaining.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/IsPathContaining.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/IsPathContaining.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.AllOf.allOf;
+import static org.hamcrest.core.IsEqual.equalTo;
+import java.util.ArrayList;
+import java.util.Collection;
+import org.hamcrest.Description;
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Path.Segment;
+import org.junit.matchers.TypeSafeMatcher;
+
+/**
+ * @author Randall Hauch
+ */
+public class IsPathContaining extends TypeSafeMatcher<Iterable<Segment>> {
+
+    private final Matcher<? super Segment> elementMatcher;
+
+    public IsPathContaining( Matcher<? super Segment> elementMatcher ) {
+        this.elementMatcher = elementMatcher;
+    }
+
+    @Override
+    public boolean matchesSafely( Iterable<Segment> collection ) {
+        for (Segment item : collection) {
+            if (elementMatcher.matches(item)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void describeTo( Description description ) {
+        description.appendText("a path containing ").appendDescriptionOf(elementMatcher);
+    }
+
+    @Factory
+    public static Matcher<Iterable<Segment>> hasSegment( Matcher<? super Segment> elementMatcher ) {
+        return new IsPathContaining(elementMatcher);
+    }
+
+    @Factory
+    public static Matcher<Iterable<Segment>> hasSegment( Segment element ) {
+        return hasSegment(equalTo(element));
+    }
+
+    @Factory
+    public static Matcher<Iterable<Segment>> hasSegments( Matcher<Path.Segment>... elementMatchers ) {
+        Collection<Matcher<? extends Iterable<Path.Segment>>> all = new ArrayList<Matcher<? extends Iterable<Path.Segment>>>(elementMatchers.length);
+
+        for (Matcher<Path.Segment> elementMatcher : elementMatchers) {
+            Matcher<Iterable<Path.Segment>> itemMatcher = hasSegment(elementMatcher);
+            all.add(itemMatcher);
+        }
+
+        return allOf(all);
+    }
+
+    @Factory
+    public static Matcher<Iterable<Segment>> hasSegments( Segment... elements ) {
+        Collection<Matcher<? extends Iterable<Segment>>> all = new ArrayList<Matcher<? extends Iterable<Segment>>>(elements.length);
+        for (Segment element : elements) {
+            all.add(hasSegment(element));
+        }
+        return allOf(all);
+    }
+
+    @Factory
+    public static Matcher<Iterable<Segment>> hasSegment( PathFactory pathFactory, String element ) {
+        Path.Segment segment = pathFactory.createSegment(element);
+        return hasSegment(equalTo(segment));
+    }
+
+    @Factory
+    public static Matcher<Iterable<Segment>> hasSegments( PathFactory pathFactory, String... segments ) {
+        Collection<Matcher<? extends Iterable<Segment>>> all = new ArrayList<Matcher<? extends Iterable<Segment>>>(segments.length);
+        for (String element : segments) {
+            all.add(hasSegment(pathFactory, element));
+        }
+        return allOf(all);
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/JodaDateTimeTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,83 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.jboss.dna.common.text.StringMatcher.startsWith;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class JodaDateTimeTest {
-
-    private JodaDateTime instant;
-    private String iso8601instance;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        iso8601instance = "2008-05-10T13:22:04.678";
-    }
-
-    @Test
-    public void shouldConstructWithIso8601FormattedStringWithoutZone() {
-        instant = new JodaDateTime(iso8601instance, "UTC");
-        assertThat(instant.getString(), startsWith(iso8601instance));
-        assertThat(instant.getYearOfCentury(), is(8));
-        assertThat(instant.getYear(), is(2008));
-        assertThat(instant.getMonthOfYear(), is(5));
-        assertThat(instant.getDayOfMonth(), is(10));
-        assertThat(instant.getDayOfWeek(), is(6));
-        assertThat(instant.getHourOfDay(), is(13));
-        assertThat(instant.getMinuteOfHour(), is(22));
-        assertThat(instant.getSecondOfMinute(), is(04));
-        assertThat(instant.getMillisOfSecond(), is(678));
-        assertThat(instant.getTimeZoneId(), is("UTC"));
-        assertThat(instant.getTimeZoneOffsetHours(), is(0));
-    }
-
-    @Test
-    public void shouldConstructWithIso8601FormattedString() {
-        iso8601instance = "2008-05-10T13:22:04.678-04:00";
-        instant = new JodaDateTime(iso8601instance);
-        instant = (JodaDateTime)instant.toTimeZone("UTC");
-        assertThat(instant.getString(), is("2008-05-10T17:22:04.678Z"));
-        assertThat(instant.getYearOfCentury(), is(8));
-        assertThat(instant.getYear(), is(2008));
-        assertThat(instant.getMonthOfYear(), is(5));
-        assertThat(instant.getDayOfMonth(), is(10));
-        assertThat(instant.getDayOfWeek(), is(6));
-        assertThat(instant.getHourOfDay(), is(17));
-        assertThat(instant.getMinuteOfHour(), is(22));
-        assertThat(instant.getSecondOfMinute(), is(04));
-        assertThat(instant.getMillisOfSecond(), is(678));
-        assertThat(instant.getTimeZoneId(), is("UTC"));
-        assertThat(instant.getTimeZoneOffsetHours(), is(0));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/JodaDateTimeTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,83 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.jboss.dna.common.text.StringMatcher.startsWith;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class JodaDateTimeTest {
+
+    private JodaDateTime instant;
+    private String iso8601instance;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        iso8601instance = "2008-05-10T13:22:04.678";
+    }
+
+    @Test
+    public void shouldConstructWithIso8601FormattedStringWithoutZone() {
+        instant = new JodaDateTime(iso8601instance, "UTC");
+        assertThat(instant.getString(), startsWith(iso8601instance));
+        assertThat(instant.getYearOfCentury(), is(8));
+        assertThat(instant.getYear(), is(2008));
+        assertThat(instant.getMonthOfYear(), is(5));
+        assertThat(instant.getDayOfMonth(), is(10));
+        assertThat(instant.getDayOfWeek(), is(6));
+        assertThat(instant.getHourOfDay(), is(13));
+        assertThat(instant.getMinuteOfHour(), is(22));
+        assertThat(instant.getSecondOfMinute(), is(04));
+        assertThat(instant.getMillisOfSecond(), is(678));
+        assertThat(instant.getTimeZoneId(), is("UTC"));
+        assertThat(instant.getTimeZoneOffsetHours(), is(0));
+    }
+
+    @Test
+    public void shouldConstructWithIso8601FormattedString() {
+        iso8601instance = "2008-05-10T13:22:04.678-04:00";
+        instant = new JodaDateTime(iso8601instance);
+        instant = (JodaDateTime)instant.toTimeZone("UTC");
+        assertThat(instant.getString(), is("2008-05-10T17:22:04.678Z"));
+        assertThat(instant.getYearOfCentury(), is(8));
+        assertThat(instant.getYear(), is(2008));
+        assertThat(instant.getMonthOfYear(), is(5));
+        assertThat(instant.getDayOfMonth(), is(10));
+        assertThat(instant.getDayOfWeek(), is(6));
+        assertThat(instant.getHourOfDay(), is(17));
+        assertThat(instant.getMinuteOfHour(), is(22));
+        assertThat(instant.getSecondOfMinute(), is(04));
+        assertThat(instant.getMillisOfSecond(), is(678));
+        assertThat(instant.getTimeZoneId(), is("UTC"));
+        assertThat(instant.getTimeZoneOffsetHours(), is(0));
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/JodaDateTimeValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,200 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import java.io.ByteArrayInputStream;
-import java.io.StringReader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.JodaDateTimeValueFactory;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class JodaDateTimeValueFactoryTest {
-
-    public static final DateTime TODAY;
-    public static final DateTime LAST_YEAR;
-
-    static {
-        org.joda.time.DateTime now = new org.joda.time.DateTime();
-        TODAY = new JodaDateTime(now);
-        LAST_YEAR = new JodaDateTime(now.minusYears(1));
-    }
-
-    private JodaDateTimeValueFactory factory;
-    private StringValueFactory stringFactory;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
-        factory = new JodaDateTimeValueFactory(Path.URL_DECODER, stringFactory);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDateFromBoolean() {
-        factory.create(true);
-    }
-
-    @Test
-    public void shouldCreateDateFromString() {
-        assertThat(factory.create(TODAY.getString()), is(TODAY));
-        assertThat(factory.create(LAST_YEAR.getString()), is(LAST_YEAR));
-    }
-
-    @Test
-    public void shouldCreateDateFromStringRegardlessOfLeadingAndTrailingWhitespace() {
-        assertThat(factory.create("  " + TODAY.getString() + "  "), is(TODAY));
-        assertThat(factory.create("  " + LAST_YEAR.getString() + "  "), is(LAST_YEAR));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDateFromStringThatIsNotInTheStandardFormat() {
-        factory.create("something");
-    }
-
-    @Test
-    public void shouldNotCreateDateFromIntegerValue() {
-        assertThat(factory.create(10000), is((DateTime)new JodaDateTime(10000)));
-    }
-
-    @Test
-    public void shouldNotCreateDateFromLongValue() {
-        assertThat(factory.create(10000l), is((DateTime)new JodaDateTime(10000l)));
-    }
-
-    @Test
-    public void shouldNotCreateDateFromFloatValue() {
-        assertThat(factory.create(10000.12345f), is((DateTime)new JodaDateTime(10000)));
-    }
-
-    @Test
-    public void shouldNotCreateDateFromDoubleValue() {
-        assertThat(factory.create(10000.12345d), is((DateTime)new JodaDateTime(10000)));
-    }
-
-    @Test
-    public void shouldCreateDateFromBigDecimal() {
-        assertThat(factory.create(new BigDecimal(10000)), is((DateTime)new JodaDateTime(10000)));
-    }
-
-    @Test
-    public void shouldCreateDateFromDate() {
-        Calendar value = Calendar.getInstance();
-        assertThat(factory.create(value.getTime()), is((DateTime)new JodaDateTime(value.getTime())));
-    }
-
-    @Test
-    public void shouldCreateDateFromCalendar() {
-        Calendar value = Calendar.getInstance();
-        value.setTimeInMillis(10000);
-        assertThat(factory.create(value), is((DateTime)new JodaDateTime(value)));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDateFromName() {
-        factory.create(mock(Name.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDateFromPath() {
-        factory.create(mock(Path.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDateFromReference() {
-        factory.create(mock(Reference.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDateFromUri() throws Exception {
-        factory.create(new URI("http://www.jboss.org"));
-    }
-
-    @Test
-    public void shouldCreateDateFromByteArrayContainingUtf8EncodingOfStringWithWellFormedDate() throws Exception {
-        assertThat(factory.create(TODAY.getString().getBytes("UTF-8")), is(TODAY));
-        assertThat(factory.create(LAST_YEAR.getString().getBytes("UTF-8")), is(LAST_YEAR));
-    }
-
-    @Test
-    public void shouldCreateDateFromInputStreamContainingUtf8EncodingOfStringWithWellFormedDate() throws Exception {
-        assertThat(factory.create(new ByteArrayInputStream(TODAY.getString().getBytes("UTF-8"))), is(TODAY));
-        assertThat(factory.create(new ByteArrayInputStream(LAST_YEAR.getString().getBytes("UTF-8"))), is(LAST_YEAR));
-    }
-
-    @Test
-    public void shouldCreateDateFromReaderContainingStringWithWellFormedDate() {
-        assertThat(factory.create(new StringReader(TODAY.getString())), is(TODAY));
-        assertThat(factory.create(new StringReader(LAST_YEAR.getString())), is(LAST_YEAR));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDateFromByteArrayContainingUtf8EncodingOfStringWithContentThatIsNotWellFormedDate()
-        throws Exception {
-        factory.create("something".getBytes("UTF-8"));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDateFromInputStreamContainingUtf8EncodingOfStringWithContentThatIsNotWellFormedDate()
-        throws Exception {
-        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDateFromReaderContainingStringWithContentThatIsNotWellFormedDate() throws Exception {
-        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
-    }
-
-    @Test
-    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
-        List<String> values = new ArrayList<String>();
-        for (int i = 0; i != 10; ++i) {
-            values.add(new JodaDateTime(10000 + i).toString());
-        }
-        Iterator<DateTime> iter = factory.create(values.iterator());
-        Iterator<String> valueIter = values.iterator();
-        while (iter.hasNext()) {
-            assertThat(iter.next(), is(factory.create(valueIter.next())));
-        }
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/JodaDateTimeValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/JodaDateTimeValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,200 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.JodaDateTimeValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class JodaDateTimeValueFactoryTest {
+
+    public static final DateTime TODAY;
+    public static final DateTime LAST_YEAR;
+
+    static {
+        org.joda.time.DateTime now = new org.joda.time.DateTime();
+        TODAY = new JodaDateTime(now);
+        LAST_YEAR = new JodaDateTime(now.minusYears(1));
+    }
+
+    private JodaDateTimeValueFactory factory;
+    private StringValueFactory stringFactory;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
+        factory = new JodaDateTimeValueFactory(Path.URL_DECODER, stringFactory);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDateFromBoolean() {
+        factory.create(true);
+    }
+
+    @Test
+    public void shouldCreateDateFromString() {
+        assertThat(factory.create(TODAY.getString()), is(TODAY));
+        assertThat(factory.create(LAST_YEAR.getString()), is(LAST_YEAR));
+    }
+
+    @Test
+    public void shouldCreateDateFromStringRegardlessOfLeadingAndTrailingWhitespace() {
+        assertThat(factory.create("  " + TODAY.getString() + "  "), is(TODAY));
+        assertThat(factory.create("  " + LAST_YEAR.getString() + "  "), is(LAST_YEAR));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDateFromStringThatIsNotInTheStandardFormat() {
+        factory.create("something");
+    }
+
+    @Test
+    public void shouldNotCreateDateFromIntegerValue() {
+        assertThat(factory.create(10000), is((DateTime)new JodaDateTime(10000)));
+    }
+
+    @Test
+    public void shouldNotCreateDateFromLongValue() {
+        assertThat(factory.create(10000l), is((DateTime)new JodaDateTime(10000l)));
+    }
+
+    @Test
+    public void shouldNotCreateDateFromFloatValue() {
+        assertThat(factory.create(10000.12345f), is((DateTime)new JodaDateTime(10000)));
+    }
+
+    @Test
+    public void shouldNotCreateDateFromDoubleValue() {
+        assertThat(factory.create(10000.12345d), is((DateTime)new JodaDateTime(10000)));
+    }
+
+    @Test
+    public void shouldCreateDateFromBigDecimal() {
+        assertThat(factory.create(new BigDecimal(10000)), is((DateTime)new JodaDateTime(10000)));
+    }
+
+    @Test
+    public void shouldCreateDateFromDate() {
+        Calendar value = Calendar.getInstance();
+        assertThat(factory.create(value.getTime()), is((DateTime)new JodaDateTime(value.getTime())));
+    }
+
+    @Test
+    public void shouldCreateDateFromCalendar() {
+        Calendar value = Calendar.getInstance();
+        value.setTimeInMillis(10000);
+        assertThat(factory.create(value), is((DateTime)new JodaDateTime(value)));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDateFromName() {
+        factory.create(mock(Name.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDateFromPath() {
+        factory.create(mock(Path.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDateFromReference() {
+        factory.create(mock(Reference.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDateFromUri() throws Exception {
+        factory.create(new URI("http://www.jboss.org"));
+    }
+
+    @Test
+    public void shouldCreateDateFromByteArrayContainingUtf8EncodingOfStringWithWellFormedDate() throws Exception {
+        assertThat(factory.create(TODAY.getString().getBytes("UTF-8")), is(TODAY));
+        assertThat(factory.create(LAST_YEAR.getString().getBytes("UTF-8")), is(LAST_YEAR));
+    }
+
+    @Test
+    public void shouldCreateDateFromInputStreamContainingUtf8EncodingOfStringWithWellFormedDate() throws Exception {
+        assertThat(factory.create(new ByteArrayInputStream(TODAY.getString().getBytes("UTF-8"))), is(TODAY));
+        assertThat(factory.create(new ByteArrayInputStream(LAST_YEAR.getString().getBytes("UTF-8"))), is(LAST_YEAR));
+    }
+
+    @Test
+    public void shouldCreateDateFromReaderContainingStringWithWellFormedDate() {
+        assertThat(factory.create(new StringReader(TODAY.getString())), is(TODAY));
+        assertThat(factory.create(new StringReader(LAST_YEAR.getString())), is(LAST_YEAR));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDateFromByteArrayContainingUtf8EncodingOfStringWithContentThatIsNotWellFormedDate()
+        throws Exception {
+        factory.create("something".getBytes("UTF-8"));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDateFromInputStreamContainingUtf8EncodingOfStringWithContentThatIsNotWellFormedDate()
+        throws Exception {
+        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDateFromReaderContainingStringWithContentThatIsNotWellFormedDate() throws Exception {
+        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
+    }
+
+    @Test
+    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
+        List<String> values = new ArrayList<String>();
+        for (int i = 0; i != 10; ++i) {
+            values.add(new JodaDateTime(10000 + i).toString());
+        }
+        Iterator<DateTime> iter = factory.create(values.iterator());
+        Iterator<String> valueIter = values.iterator();
+        while (iter.hasNext()) {
+            assertThat(iter.next(), is(factory.create(valueIter.next())));
+        }
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/LocalNamespaceRegistryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,92 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.util.HashMap;
-import java.util.Map;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class LocalNamespaceRegistryTest {
-
-    private NamespaceRegistry local;
-    private NamespaceRegistry delegate;
-    private String uri;
-
-    @Before
-    public void beforeEach() {
-        delegate = new BasicNamespaceRegistry();
-        local = new LocalNamespaceRegistry(delegate);
-        uri = "http://www.example.com";
-    }
-
-    @Test
-    public void shouldMirrorDelegateIfLocalIsEmpty() {
-        assertNamespaces(delegate, "");
-        assertNamespaces(local, "");
-    }
-
-    @Test
-    public void shouldAllowLocalRegistryToChangeDefaultNamespace() {
-        local.register("", uri);
-        assertNamespaces(delegate, "");
-        assertNamespaces(local, "=" + uri);
-    }
-
-    protected void assertNamespaces( NamespaceRegistry registry,
-                                     String... namespaces ) {
-        // Create the list of expected namespaces ...
-        Map<String, String> expected = new HashMap<String, String>();
-        for (String str : namespaces) {
-            String[] parts = str.length() != 0 ? str.split("=") : new String[] {"", ""};
-            assertThat("invalid namespace string \"" + str + "\"", parts.length, is(2));
-            expected.put(parts[0], parts[1]);
-        }
-        // Now compare the actual to expected ...
-        for (NamespaceRegistry.Namespace actual : registry.getNamespaces()) {
-            String expectedUri = expected.remove(actual.getPrefix());
-            assertThat("namespace URIs differ", actual.getNamespaceUri(), is(expectedUri));
-            String prefix = actual.getPrefix();
-            String uri = actual.getNamespaceUri();
-            assertThat(registry.isRegisteredNamespaceUri(uri), is(true));
-            assertThat(registry.getPrefixForNamespaceUri(uri, false), is(prefix));
-            assertThat(registry.getNamespaceForPrefix(prefix), is(uri));
-        }
-        // Check that there are no more expected ...
-        if (!expected.isEmpty()) {
-            StringBuilder msg = new StringBuilder("actual is missing namespaces ");
-            boolean first = true;
-            for (Map.Entry<String, String> entry : expected.entrySet()) {
-                if (first) first = false;
-                else msg.append(", ");
-                msg.append(entry.getKey()).append("=").append(entry.getValue());
-            }
-            assertThat(msg.toString(), registry.getNamespaces().isEmpty(), is(true));
-        }
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/LocalNamespaceRegistryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LocalNamespaceRegistryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.util.HashMap;
+import java.util.Map;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.LocalNamespaceRegistry;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class LocalNamespaceRegistryTest {
+
+    private NamespaceRegistry local;
+    private NamespaceRegistry delegate;
+    private String uri;
+
+    @Before
+    public void beforeEach() {
+        delegate = new BasicNamespaceRegistry();
+        local = new LocalNamespaceRegistry(delegate);
+        uri = "http://www.example.com";
+    }
+
+    @Test
+    public void shouldMirrorDelegateIfLocalIsEmpty() {
+        assertNamespaces(delegate, "");
+        assertNamespaces(local, "");
+    }
+
+    @Test
+    public void shouldAllowLocalRegistryToChangeDefaultNamespace() {
+        local.register("", uri);
+        assertNamespaces(delegate, "");
+        assertNamespaces(local, "=" + uri);
+    }
+
+    protected void assertNamespaces( NamespaceRegistry registry,
+                                     String... namespaces ) {
+        // Create the list of expected namespaces ...
+        Map<String, String> expected = new HashMap<String, String>();
+        for (String str : namespaces) {
+            String[] parts = str.length() != 0 ? str.split("=") : new String[] {"", ""};
+            assertThat("invalid namespace string \"" + str + "\"", parts.length, is(2));
+            expected.put(parts[0], parts[1]);
+        }
+        // Now compare the actual to expected ...
+        for (NamespaceRegistry.Namespace actual : registry.getNamespaces()) {
+            String expectedUri = expected.remove(actual.getPrefix());
+            assertThat("namespace URIs differ", actual.getNamespaceUri(), is(expectedUri));
+            String prefix = actual.getPrefix();
+            String uri = actual.getNamespaceUri();
+            assertThat(registry.isRegisteredNamespaceUri(uri), is(true));
+            assertThat(registry.getPrefixForNamespaceUri(uri, false), is(prefix));
+            assertThat(registry.getNamespaceForPrefix(prefix), is(uri));
+        }
+        // Check that there are no more expected ...
+        if (!expected.isEmpty()) {
+            StringBuilder msg = new StringBuilder("actual is missing namespaces ");
+            boolean first = true;
+            for (Map.Entry<String, String> entry : expected.entrySet()) {
+                if (first) first = false;
+                else msg.append(", ");
+                msg.append(entry.getKey()).append("=").append(entry.getValue());
+            }
+            assertThat(msg.toString(), registry.getNamespaces().isEmpty(), is(true));
+        }
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LongValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/LongValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LongValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,192 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import java.io.ByteArrayInputStream;
-import java.io.StringReader;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.basic.LongValueFactory;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class LongValueFactoryTest {
-
-    private LongValueFactory factory;
-    private StringValueFactory stringFactory;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
-        factory = new LongValueFactory(Path.URL_DECODER, stringFactory);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromBooleanValue() {
-        factory.create(true);
-    }
-
-    @Test
-    public void shouldCreateLongFromString() {
-        assertThat(factory.create("1"), is(Long.valueOf(1)));
-        assertThat(factory.create("-10"), is(Long.valueOf(-10)));
-        assertThat(factory.create("100000101"), is(Long.valueOf(100000101)));
-    }
-
-    @Test
-    public void shouldCreateLongFromStringRegardlessOfLeadingAndTrailingWhitespace() {
-        assertThat(factory.create("  1  "), is(Long.valueOf(1)));
-        assertThat(factory.create("  -10  "), is(Long.valueOf(-10)));
-        assertThat(factory.create("  100000101  "), is(Long.valueOf(100000101)));
-    }
-
-    @Test
-    public void shouldNotCreateLongFromIntegerValue() {
-        assertThat(factory.create(1), is(1l));
-    }
-
-    @Test
-    public void shouldNotCreateLongFromLongValue() {
-        assertThat(factory.create(1l), is(1l));
-    }
-
-    @Test
-    public void shouldNotCreateLongFromFloatValue() {
-        assertThat(factory.create(1.0f), is(1l));
-        assertThat(factory.create(1.023f), is(1l));
-        assertThat(factory.create(1.923f), is(1l));
-    }
-
-    @Test
-    public void shouldNotCreateLongFromDoubleValue() {
-        assertThat(factory.create(1.0122d), is(1l));
-    }
-
-    @Test
-    public void shouldCreateLongFromBigDecimal() {
-        BigDecimal value = new BigDecimal(100);
-        assertThat(factory.create(value), is(value.longValue()));
-    }
-
-    @Test
-    public void shouldCreateLongFromDate() {
-        Date value = new Date();
-        assertThat(factory.create(value), is(Long.valueOf(value.getTime())));
-    }
-
-    @Test
-    public void shouldCreateLongFromCalendar() {
-        Calendar value = Calendar.getInstance();
-        assertThat(factory.create(value), is(Long.valueOf(value.getTimeInMillis())));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateLongFromName() {
-        factory.create(mock(Name.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateLongFromPath() {
-        factory.create(mock(Path.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateLongFromReference() {
-        factory.create(mock(Reference.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateLongFromUri() throws Exception {
-        factory.create(new URI("http://www.jboss.org"));
-    }
-
-    @Test
-    public void shouldCreateLongFromByteArrayContainingUtf8EncodingOfStringWithLong() throws Exception {
-        assertThat(factory.create("0".getBytes("UTF-8")), is(0l));
-        assertThat(factory.create("10".getBytes("UTF-8")), is(10l));
-        assertThat(factory.create("-103".getBytes("UTF-8")), is(-103l));
-        assertThat(factory.create("1003044".getBytes("UTF-8")), is(1003044l));
-    }
-
-    @Test
-    public void shouldCreateLongFromInputStreamContainingUtf8EncodingOfStringWithLong() throws Exception {
-        assertThat(factory.create(new ByteArrayInputStream("0".getBytes("UTF-8"))), is(0l));
-        assertThat(factory.create(new ByteArrayInputStream("10".getBytes("UTF-8"))), is(10l));
-        assertThat(factory.create(new ByteArrayInputStream("-103".getBytes("UTF-8"))), is(-103l));
-        assertThat(factory.create(new ByteArrayInputStream("1003044".getBytes("UTF-8"))), is(1003044l));
-    }
-
-    @Test
-    public void shouldCreateLongFromReaderContainingStringWithLong() {
-        assertThat(factory.create(new StringReader("0")), is(0l));
-        assertThat(factory.create(new StringReader("10")), is(10l));
-        assertThat(factory.create(new StringReader("-103")), is(-103l));
-        assertThat(factory.create(new StringReader("1003044")), is(1003044l));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateLongFromByteArrayContainingUtf8EncodingOfStringWithContentsOtherThanLong() throws Exception {
-        factory.create("something".getBytes("UTF-8"));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateLongFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanLong() throws Exception {
-        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateLongFromReaderContainingStringWithContentsOtherThanLong() throws Exception {
-        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
-    }
-
-    @Test
-    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
-        List<String> values = new ArrayList<String>();
-        for (int i = 0; i != 10; ++i)
-            values.add(" " + i);
-        Iterator<Long> iter = factory.create(values.iterator());
-        Iterator<String> valueIter = values.iterator();
-        while (iter.hasNext()) {
-            assertThat(iter.next(), is(factory.create(valueIter.next())));
-        }
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LongValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/LongValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LongValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/LongValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,192 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.LongValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class LongValueFactoryTest {
+
+    private LongValueFactory factory;
+    private StringValueFactory stringFactory;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
+        factory = new LongValueFactory(Path.URL_DECODER, stringFactory);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromBooleanValue() {
+        factory.create(true);
+    }
+
+    @Test
+    public void shouldCreateLongFromString() {
+        assertThat(factory.create("1"), is(Long.valueOf(1)));
+        assertThat(factory.create("-10"), is(Long.valueOf(-10)));
+        assertThat(factory.create("100000101"), is(Long.valueOf(100000101)));
+    }
+
+    @Test
+    public void shouldCreateLongFromStringRegardlessOfLeadingAndTrailingWhitespace() {
+        assertThat(factory.create("  1  "), is(Long.valueOf(1)));
+        assertThat(factory.create("  -10  "), is(Long.valueOf(-10)));
+        assertThat(factory.create("  100000101  "), is(Long.valueOf(100000101)));
+    }
+
+    @Test
+    public void shouldNotCreateLongFromIntegerValue() {
+        assertThat(factory.create(1), is(1l));
+    }
+
+    @Test
+    public void shouldNotCreateLongFromLongValue() {
+        assertThat(factory.create(1l), is(1l));
+    }
+
+    @Test
+    public void shouldNotCreateLongFromFloatValue() {
+        assertThat(factory.create(1.0f), is(1l));
+        assertThat(factory.create(1.023f), is(1l));
+        assertThat(factory.create(1.923f), is(1l));
+    }
+
+    @Test
+    public void shouldNotCreateLongFromDoubleValue() {
+        assertThat(factory.create(1.0122d), is(1l));
+    }
+
+    @Test
+    public void shouldCreateLongFromBigDecimal() {
+        BigDecimal value = new BigDecimal(100);
+        assertThat(factory.create(value), is(value.longValue()));
+    }
+
+    @Test
+    public void shouldCreateLongFromDate() {
+        Date value = new Date();
+        assertThat(factory.create(value), is(Long.valueOf(value.getTime())));
+    }
+
+    @Test
+    public void shouldCreateLongFromCalendar() {
+        Calendar value = Calendar.getInstance();
+        assertThat(factory.create(value), is(Long.valueOf(value.getTimeInMillis())));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateLongFromName() {
+        factory.create(mock(Name.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateLongFromPath() {
+        factory.create(mock(Path.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateLongFromReference() {
+        factory.create(mock(Reference.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateLongFromUri() throws Exception {
+        factory.create(new URI("http://www.jboss.org"));
+    }
+
+    @Test
+    public void shouldCreateLongFromByteArrayContainingUtf8EncodingOfStringWithLong() throws Exception {
+        assertThat(factory.create("0".getBytes("UTF-8")), is(0l));
+        assertThat(factory.create("10".getBytes("UTF-8")), is(10l));
+        assertThat(factory.create("-103".getBytes("UTF-8")), is(-103l));
+        assertThat(factory.create("1003044".getBytes("UTF-8")), is(1003044l));
+    }
+
+    @Test
+    public void shouldCreateLongFromInputStreamContainingUtf8EncodingOfStringWithLong() throws Exception {
+        assertThat(factory.create(new ByteArrayInputStream("0".getBytes("UTF-8"))), is(0l));
+        assertThat(factory.create(new ByteArrayInputStream("10".getBytes("UTF-8"))), is(10l));
+        assertThat(factory.create(new ByteArrayInputStream("-103".getBytes("UTF-8"))), is(-103l));
+        assertThat(factory.create(new ByteArrayInputStream("1003044".getBytes("UTF-8"))), is(1003044l));
+    }
+
+    @Test
+    public void shouldCreateLongFromReaderContainingStringWithLong() {
+        assertThat(factory.create(new StringReader("0")), is(0l));
+        assertThat(factory.create(new StringReader("10")), is(10l));
+        assertThat(factory.create(new StringReader("-103")), is(-103l));
+        assertThat(factory.create(new StringReader("1003044")), is(1003044l));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateLongFromByteArrayContainingUtf8EncodingOfStringWithContentsOtherThanLong() throws Exception {
+        factory.create("something".getBytes("UTF-8"));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateLongFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanLong() throws Exception {
+        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateLongFromReaderContainingStringWithContentsOtherThanLong() throws Exception {
+        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
+    }
+
+    @Test
+    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
+        List<String> values = new ArrayList<String>();
+        for (int i = 0; i != 10; ++i)
+            values.add(" " + i);
+        Iterator<Long> iter = factory.create(values.iterator());
+        Iterator<String> valueIter = values.iterator();
+        while (iter.hasNext()) {
+            assertThat(iter.next(), is(factory.create(valueIter.next())));
+        }
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/NameValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,142 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.common.text.TextDecoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
-import org.jboss.dna.graph.properties.basic.NameValueFactory;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class NameValueFactoryTest {
-
-    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
-
-    private NamespaceRegistry registry;
-    private ValueFactory<String> stringValueFactory;
-    private NameValueFactory factory;
-    private TextEncoder encoder;
-    private TextDecoder decoder;
-    private Name name;
-
-    @Before
-    public void beforeEach() {
-        this.registry = new BasicNamespaceRegistry();
-        this.registry.register("dna", "http://www.jboss.org/dna/namespace");
-        this.encoder = Path.DEFAULT_ENCODER;
-        this.decoder = Path.DEFAULT_DECODER;
-        this.stringValueFactory = new StringValueFactory(decoder, encoder);
-        this.factory = new NameValueFactory(registry, decoder, stringValueFactory);
-    }
-
-    @Test
-    public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormatWithoutPrefix() {
-        name = factory.create("a");
-        assertThat(name.getLocalName(), is("a"));
-        assertThat(name.getNamespaceUri(), is(this.registry.getNamespaceForPrefix("")));
-    }
-
-    @Test
-    public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormat() {
-        name = factory.create("dna:something");
-        assertThat(name.getLocalName(), is("something"));
-        assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
-        assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
-    }
-
-    @Test
-    public void shouldCreateNameFromSingleEncodedStringInPrefixedNamespaceFormat() {
-        name = factory.create(encoder.encode("dna") + ":" + encoder.encode("some/thing"));
-        assertThat(name.getLocalName(), is("some/thing"));
-        assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
-        assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
-    }
-
-    @Test
-    public void shouldCreateNameFromSingleStringInStandardFullNamespaceFormat() {
-        name = factory.create("{http://www.jboss.org/dna/namespace}something");
-        assertThat(name.getLocalName(), is("something"));
-        assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
-        assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
-    }
-
-    @Test
-    public void shouldCreateNameFromSingleEncodedStringInStandardFullNamespaceFormat() {
-        name = factory.create("{" + encoder.encode("http://www.jboss.org/dna/namespace") + "}" + encoder.encode("some/thing"));
-        assertThat(name.getLocalName(), is("some/thing"));
-        assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
-        assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
-    }
-
-    @Test
-    public void shouldProvideAccessToNamespaceRegistryPassedInConstructor() {
-        assertThat(factory.getNamespaceRegistry(), is(registry));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNullLocalName() {
-        factory.create("a", (String)null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNullLocalNameWithEncoder() {
-        factory.create("a", null, decoder);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowEmptyLocalName() {
-        factory.create("a", "");
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowEmptyLocalNameWithEncoder() {
-        factory.create("a", "", decoder);
-    }
-
-    @Test
-    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
-        List<String> values = new ArrayList<String>();
-        for (int i = 0; i != 10; ++i) {
-            values.add("dna:something" + i);
-        }
-        Iterator<Name> iter = factory.create(values.iterator());
-        Iterator<String> valueIter = values.iterator();
-        while (iter.hasNext()) {
-            assertThat(iter.next(), is(factory.create(valueIter.next())));
-        }
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/NameValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,142 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.NameValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class NameValueFactoryTest {
+
+    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+
+    private NamespaceRegistry registry;
+    private ValueFactory<String> stringValueFactory;
+    private NameValueFactory factory;
+    private TextEncoder encoder;
+    private TextDecoder decoder;
+    private Name name;
+
+    @Before
+    public void beforeEach() {
+        this.registry = new BasicNamespaceRegistry();
+        this.registry.register("dna", "http://www.jboss.org/dna/namespace");
+        this.encoder = Path.DEFAULT_ENCODER;
+        this.decoder = Path.DEFAULT_DECODER;
+        this.stringValueFactory = new StringValueFactory(decoder, encoder);
+        this.factory = new NameValueFactory(registry, decoder, stringValueFactory);
+    }
+
+    @Test
+    public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormatWithoutPrefix() {
+        name = factory.create("a");
+        assertThat(name.getLocalName(), is("a"));
+        assertThat(name.getNamespaceUri(), is(this.registry.getNamespaceForPrefix("")));
+    }
+
+    @Test
+    public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormat() {
+        name = factory.create("dna:something");
+        assertThat(name.getLocalName(), is("something"));
+        assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+        assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
+    }
+
+    @Test
+    public void shouldCreateNameFromSingleEncodedStringInPrefixedNamespaceFormat() {
+        name = factory.create(encoder.encode("dna") + ":" + encoder.encode("some/thing"));
+        assertThat(name.getLocalName(), is("some/thing"));
+        assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+        assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
+    }
+
+    @Test
+    public void shouldCreateNameFromSingleStringInStandardFullNamespaceFormat() {
+        name = factory.create("{http://www.jboss.org/dna/namespace}something");
+        assertThat(name.getLocalName(), is("something"));
+        assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+        assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
+    }
+
+    @Test
+    public void shouldCreateNameFromSingleEncodedStringInStandardFullNamespaceFormat() {
+        name = factory.create("{" + encoder.encode("http://www.jboss.org/dna/namespace") + "}" + encoder.encode("some/thing"));
+        assertThat(name.getLocalName(), is("some/thing"));
+        assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+        assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
+    }
+
+    @Test
+    public void shouldProvideAccessToNamespaceRegistryPassedInConstructor() {
+        assertThat(factory.getNamespaceRegistry(), is(registry));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNullLocalName() {
+        factory.create("a", (String)null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNullLocalNameWithEncoder() {
+        factory.create("a", null, decoder);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowEmptyLocalName() {
+        factory.create("a", "");
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowEmptyLocalNameWithEncoder() {
+        factory.create("a", "", decoder);
+    }
+
+    @Test
+    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
+        List<String> values = new ArrayList<String>();
+        for (int i = 0; i != 10; ++i) {
+            values.add("dna:something" + i);
+        }
+        Iterator<Name> iter = factory.create(values.iterator());
+        Iterator<String> valueIter = values.iterator();
+        while (iter.hasNext()) {
+            assertThat(iter.next(), is(factory.create(valueIter.next())));
+        }
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/PathValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/PathValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/PathValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,138 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.jboss.dna.graph.properties.basic.IsPathContaining.hasSegments;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
-import org.jboss.dna.graph.properties.basic.BasicPathSegment;
-import org.jboss.dna.graph.properties.basic.NameValueFactory;
-import org.jboss.dna.graph.properties.basic.PathValueFactory;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class PathValueFactoryTest {
-
-    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
-
-    private BasicNamespaceRegistry registry;
-    private ValueFactory<String> stringValueFactory;
-    private NameValueFactory nameFactory;
-    private PathValueFactory factory;
-    private Path path;
-    private Path path2;
-
-    @Before
-    public void beforeEach() {
-        this.registry = new BasicNamespaceRegistry();
-        this.registry.register("dna", "http://www.jboss.org/dna/namespace");
-        this.stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
-        this.nameFactory = new NameValueFactory(registry, Path.DEFAULT_DECODER, stringValueFactory);
-        this.factory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameFactory);
-    }
-
-    protected List<Path.Segment> getSegments( String... segments ) {
-        List<Path.Segment> result = new ArrayList<Path.Segment>();
-        for (String segmentStr : segments) {
-            Name name = nameFactory.create(segmentStr);
-            BasicPathSegment segment = new BasicPathSegment(name);
-            result.add(segment);
-        }
-        return result;
-    }
-
-    @Test
-    public void shouldCreateFromStringWithAbsolutePathAndNoParentOrSelfReferences() {
-        path = factory.create("/a/b/c/d/dna:e/dna:f");
-        assertThat(path, hasSegments(factory, "a", "b", "c", "d", "dna:e", "dna:f"));
-    }
-
-    @Test
-    public void shouldCreateFromStringWithRelativePathAndNoParentOrSelfReferences() {
-        path = factory.create("a/b/c/d/dna:e/dna:f");
-        assertThat(path, hasSegments(factory, "a", "b", "c", "d", "dna:e", "dna:f"));
-    }
-
-    @Test
-    public void shouldCreateFromStringWithAbsolutePathAndParentReference() {
-        path = factory.create("/a/b/c/../dna:e/dna:f");
-        assertThat(path, hasSegments(factory, "a", "b", "c", "..", "dna:e", "dna:f"));
-    }
-
-    @Test
-    public void shouldCreateFromStringWithRelativePathAndParentReference() {
-        path = factory.create("a/b/c/../dna:e/dna:f");
-        assertThat(path, hasSegments(factory, "a", "b", "c", "..", "dna:e", "dna:f"));
-    }
-
-    @Test
-    public void shouldCreateFromStringWithAbsolutePathAndSelfReference() {
-        path = factory.create("/a/b/c/./dna:e/dna:f");
-        assertThat(path, hasSegments(factory, "a", "b", "c", ".", "dna:e", "dna:f"));
-    }
-
-    @Test
-    public void shouldCreateFromStringWithRelativePathAndSelfReference() {
-        path = factory.create("a/b/c/./dna:e/dna:f");
-        assertThat(path, hasSegments(factory, "a", "b", "c", ".", "dna:e", "dna:f"));
-    }
-
-    @Test
-    public void shouldCreateFromStringWithRelativePathBeginningWithSelfReference() {
-        path = factory.create("./a/b/c/./dna:e/dna:f");
-        assertThat(path, hasSegments(factory, ".", "a", "b", "c", ".", "dna:e", "dna:f"));
-    }
-
-    @Test
-    public void shouldCreateEquivalentPathsWhetherOrNotThereIsATrailingDelimiter() {
-        path = factory.create("/a/b/c/d/dna:e/dna:f");
-        path2 = factory.create("/a/b/c/d/dna:e/dna:f/");
-        assertThat(path.equals(path2), is(true));
-        assertThat(path.compareTo(path2), is(0));
-    }
-
-    @Test
-    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
-        List<String> values = new ArrayList<String>();
-        for (int i = 0; i != 10; ++i) {
-            values.add("/a/b/c/d/dna:e/dna:f" + i);
-        }
-        Iterator<Path> iter = factory.create(values.iterator());
-        Iterator<String> valueIter = values.iterator();
-        while (iter.hasNext()) {
-            assertThat(iter.next(), is(factory.create(valueIter.next())));
-        }
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/PathValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/PathValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/PathValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/PathValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,138 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.jboss.dna.graph.property.basic.IsPathContaining.hasSegments;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.BasicPathSegment;
+import org.jboss.dna.graph.property.basic.NameValueFactory;
+import org.jboss.dna.graph.property.basic.PathValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class PathValueFactoryTest {
+
+    public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+
+    private BasicNamespaceRegistry registry;
+    private ValueFactory<String> stringValueFactory;
+    private NameValueFactory nameFactory;
+    private PathValueFactory factory;
+    private Path path;
+    private Path path2;
+
+    @Before
+    public void beforeEach() {
+        this.registry = new BasicNamespaceRegistry();
+        this.registry.register("dna", "http://www.jboss.org/dna/namespace");
+        this.stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
+        this.nameFactory = new NameValueFactory(registry, Path.DEFAULT_DECODER, stringValueFactory);
+        this.factory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameFactory);
+    }
+
+    protected List<Path.Segment> getSegments( String... segments ) {
+        List<Path.Segment> result = new ArrayList<Path.Segment>();
+        for (String segmentStr : segments) {
+            Name name = nameFactory.create(segmentStr);
+            BasicPathSegment segment = new BasicPathSegment(name);
+            result.add(segment);
+        }
+        return result;
+    }
+
+    @Test
+    public void shouldCreateFromStringWithAbsolutePathAndNoParentOrSelfReferences() {
+        path = factory.create("/a/b/c/d/dna:e/dna:f");
+        assertThat(path, hasSegments(factory, "a", "b", "c", "d", "dna:e", "dna:f"));
+    }
+
+    @Test
+    public void shouldCreateFromStringWithRelativePathAndNoParentOrSelfReferences() {
+        path = factory.create("a/b/c/d/dna:e/dna:f");
+        assertThat(path, hasSegments(factory, "a", "b", "c", "d", "dna:e", "dna:f"));
+    }
+
+    @Test
+    public void shouldCreateFromStringWithAbsolutePathAndParentReference() {
+        path = factory.create("/a/b/c/../dna:e/dna:f");
+        assertThat(path, hasSegments(factory, "a", "b", "c", "..", "dna:e", "dna:f"));
+    }
+
+    @Test
+    public void shouldCreateFromStringWithRelativePathAndParentReference() {
+        path = factory.create("a/b/c/../dna:e/dna:f");
+        assertThat(path, hasSegments(factory, "a", "b", "c", "..", "dna:e", "dna:f"));
+    }
+
+    @Test
+    public void shouldCreateFromStringWithAbsolutePathAndSelfReference() {
+        path = factory.create("/a/b/c/./dna:e/dna:f");
+        assertThat(path, hasSegments(factory, "a", "b", "c", ".", "dna:e", "dna:f"));
+    }
+
+    @Test
+    public void shouldCreateFromStringWithRelativePathAndSelfReference() {
+        path = factory.create("a/b/c/./dna:e/dna:f");
+        assertThat(path, hasSegments(factory, "a", "b", "c", ".", "dna:e", "dna:f"));
+    }
+
+    @Test
+    public void shouldCreateFromStringWithRelativePathBeginningWithSelfReference() {
+        path = factory.create("./a/b/c/./dna:e/dna:f");
+        assertThat(path, hasSegments(factory, ".", "a", "b", "c", ".", "dna:e", "dna:f"));
+    }
+
+    @Test
+    public void shouldCreateEquivalentPathsWhetherOrNotThereIsATrailingDelimiter() {
+        path = factory.create("/a/b/c/d/dna:e/dna:f");
+        path2 = factory.create("/a/b/c/d/dna:e/dna:f/");
+        assertThat(path.equals(path2), is(true));
+        assertThat(path.compareTo(path2), is(0));
+    }
+
+    @Test
+    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
+        List<String> values = new ArrayList<String>();
+        for (int i = 0; i != 10; ++i) {
+            values.add("/a/b/c/d/dna:e/dna:f" + i);
+        }
+        Iterator<Path> iter = factory.create(values.iterator());
+        Iterator<String> valueIter = values.iterator();
+        while (iter.hasNext()) {
+            assertThat(iter.next(), is(factory.create(valueIter.next())));
+        }
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/RootPathTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/RootPathTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/RootPathTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,254 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
-import java.util.ArrayList;
-import java.util.List;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicPath;
-import org.jboss.dna.graph.properties.basic.BasicPathSegment;
-import org.jboss.dna.graph.properties.basic.RootPath;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class RootPathTest extends AbstractPathTest {
-
-    protected Path root;
-
-    @Before
-    @Override
-    public void beforeEach() {
-        super.beforeEach();
-        super.path = RootPath.INSTANCE;
-        root = path;
-    }
-
-    @Test
-    public void shouldReturnRootForLowestCommonAncestorWithAnyNodePath() {
-        Path other = mock(Path.class);
-        stub(other.isRoot()).toReturn(true);
-        assertThat(root.getCommonAncestor(other).isRoot(), is(true));
-
-        stub(other.isRoot()).toReturn(false);
-        assertThat(root.getCommonAncestor(other).isRoot(), is(true));
-    }
-
-    @Test
-    public void shouldConsiderRootToBeAncestorOfEveryNodeExceptRoot() {
-        Path other = mock(Path.class);
-        stub(other.size()).toReturn(1);
-        assertThat(root.isAncestorOf(other), is(true));
-        assertThat(root.isAncestorOf(root), is(false));
-    }
-
-    @Test
-    public void shouldNotConsiderRootNodeToBeDecendantOfAnyNode() {
-        Path other = mock(Path.class);
-        assertThat(root.isDecendantOf(other), is(false));
-        assertThat(root.isDecendantOf(root), is(false));
-    }
-
-    @Test
-    public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
-        assertThat(root.hasSameAncestor(root), is(true));
-    }
-
-    @Test
-    public void shouldBeNormalized() {
-        assertThat(root.isNormalized(), is(true));
-    }
-
-    @Test
-    public void shouldReturnSelfForGetNormalized() {
-        assertThat(root.getNormalizedPath(), is(sameInstance(root)));
-    }
-
-    @Test
-    public void shouldReturnSelfForGetCanonicalPath() {
-        assertThat(root.getCanonicalPath(), is(sameInstance(root)));
-    }
-
-    @Test
-    public void shouldReturnSizeOfZero() {
-        assertThat(root.size(), is(0));
-    }
-
-    @Override
-    @Test( expected = IllegalStateException.class )
-    public void shouldReturnImmutableSegmentsIterator() {
-        root.iterator().remove();
-    }
-
-    @Test
-    public void shouldReturnEmptyIteratorOverSegments() {
-        assertThat(root.iterator(), is(notNullValue()));
-        assertThat(root.iterator().hasNext(), is(false));
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSegmentAtIndexZero() {
-        root.getSegment(0);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldFailToReturnSegmentAtPositiveIndex() {
-        root.getSegment(1);
-    }
-
-    @Test
-    public void shouldReturnEmptySegmentsArray() {
-        assertThat(root.getSegmentsArray(), is(notNullValue()));
-        assertThat(root.getSegmentsArray().length, is(0));
-    }
-
-    @Test
-    public void shouldReturnEmptySegmentsList() {
-        assertThat(root.getSegmentsList(), is(notNullValue()));
-        assertThat(root.getSegmentsList().isEmpty(), is(true));
-    }
-
-    @Test
-    public void shouldAlwaysReturnPathWithSingleSlashForGetString() {
-        NamespaceRegistry registry = mock(NamespaceRegistry.class);
-        TextEncoder encoder = mock(TextEncoder.class);
-        stub(encoder.encode("/")).toReturn("/");
-        assertThat(root.getString(), is("/"));
-        assertThat(root.getString(registry), is("/"));
-        assertThat(root.getString(registry, encoder), is("/"));
-        assertThat(root.getString(registry, encoder, encoder), is("/"));
-        assertThat(root.getString(encoder), is("/"));
-    }
-
-    @Test
-    public void shouldAllowNullNamespaceRegistryWithNonNullTextEncodersSinceRegistryIsNotNeeded() {
-        TextEncoder encoder = mock(TextEncoder.class);
-        stub(encoder.encode("/")).toReturn("/");
-        assertThat(root.getString((NamespaceRegistry)null, encoder, encoder), is("/"));
-    }
-
-    @Test
-    public void shouldAllowNullTextEncoder() {
-        assertThat(root.getString((TextEncoder)null), is("/"));
-    }
-
-    @Test
-    public void shouldNotAllowNullTextEncoderWithNonNullNamespaceRegistry() {
-        NamespaceRegistry registry = mock(NamespaceRegistry.class);
-        assertThat(root.getString(registry, (TextEncoder)null), is("/"));
-    }
-
-    @Test
-    public void shouldNotAllowNullTextEncoderForDelimiterWithNonNullNamespaceRegistry() {
-        NamespaceRegistry registry = mock(NamespaceRegistry.class);
-        TextEncoder encoder = mock(TextEncoder.class);
-        assertThat(root.getString(registry, encoder, (TextEncoder)null), is("/"));
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldNotAllowSubpathStartingAtOne() {
-        root.subpath(1);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldNotAllowSubpathStartingAtMoreThanOne() {
-        root.subpath(2);
-    }
-
-    @Test( expected = IndexOutOfBoundsException.class )
-    public void shouldNotAllowSubpathEndingAtMoreThanZero() {
-        root.subpath(0, 1);
-    }
-
-    @Test
-    public void shouldReturnRelativePathConsistingOfSameNumberOfParentReferencesAsSizeOfSuppliedPath() {
-        List<Path.Segment> segments = new ArrayList<Path.Segment>();
-        segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
-        Path other = new BasicPath(segments, true);
-
-        assertThat(root.relativeTo(other).toString(), is(".."));
-
-        segments.add(new BasicPathSegment(new BasicName("http://example.com", "b")));
-        other = new BasicPath(segments, true);
-        assertThat(root.relativeTo(other).toString(), is("../.."));
-
-        String expected = "..";
-        segments.clear();
-        for (int i = 1; i != 100; ++i) {
-            segments.add(new BasicPathSegment(new BasicName("http://example.com", "b" + i)));
-            other = new BasicPath(segments, true);
-            assertThat(root.relativeTo(other).toString(), is(expected));
-            expected = expected + "/..";
-        }
-    }
-
-    @Test
-    public void shouldResolveAllRelativePathsToTheirAbsolutePath() {
-        List<Path.Segment> segments = new ArrayList<Path.Segment>();
-        segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
-        Path other = mock(Path.class);
-        stub(other.isAbsolute()).toReturn(false);
-        stub(other.getSegmentsList()).toReturn(segments);
-        stub(other.getNormalizedPath()).toReturn(other);
-        Path resolved = root.resolve(other);
-        assertThat(resolved.getSegmentsList(), is(segments));
-        assertThat(resolved.isAbsolute(), is(true));
-    }
-
-    @Test( expected = InvalidPathException.class )
-    public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
-        Path other = mock(Path.class);
-        stub(other.isAbsolute()).toReturn(true);
-        root.resolve(other);
-    }
-
-    @Test
-    public void shouldAlwaysConsiderRootAsLessThanAnyPathOtherThanRoot() {
-        Path other = mock(Path.class);
-        stub(other.isRoot()).toReturn(false);
-        assertThat(root.compareTo(other), is(-1));
-        assertThat(root.equals(other), is(false));
-    }
-
-    @Test
-    public void shouldAlwaysConsiderRootAsEqualToAnyOtherRoot() {
-        Path other = mock(Path.class);
-        stub(other.isRoot()).toReturn(true);
-        assertThat(root.compareTo(other), is(0));
-        assertThat(root.equals(other), is(true));
-        assertThat(root.equals(root), is(true));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/RootPathTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/RootPathTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/RootPathTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/RootPathTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,254 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import java.util.ArrayList;
+import java.util.List;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicPath;
+import org.jboss.dna.graph.property.basic.BasicPathSegment;
+import org.jboss.dna.graph.property.basic.RootPath;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class RootPathTest extends AbstractPathTest {
+
+    protected Path root;
+
+    @Before
+    @Override
+    public void beforeEach() {
+        super.beforeEach();
+        super.path = RootPath.INSTANCE;
+        root = path;
+    }
+
+    @Test
+    public void shouldReturnRootForLowestCommonAncestorWithAnyNodePath() {
+        Path other = mock(Path.class);
+        stub(other.isRoot()).toReturn(true);
+        assertThat(root.getCommonAncestor(other).isRoot(), is(true));
+
+        stub(other.isRoot()).toReturn(false);
+        assertThat(root.getCommonAncestor(other).isRoot(), is(true));
+    }
+
+    @Test
+    public void shouldConsiderRootToBeAncestorOfEveryNodeExceptRoot() {
+        Path other = mock(Path.class);
+        stub(other.size()).toReturn(1);
+        assertThat(root.isAncestorOf(other), is(true));
+        assertThat(root.isAncestorOf(root), is(false));
+    }
+
+    @Test
+    public void shouldNotConsiderRootNodeToBeDecendantOfAnyNode() {
+        Path other = mock(Path.class);
+        assertThat(root.isDecendantOf(other), is(false));
+        assertThat(root.isDecendantOf(root), is(false));
+    }
+
+    @Test
+    public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
+        assertThat(root.hasSameAncestor(root), is(true));
+    }
+
+    @Test
+    public void shouldBeNormalized() {
+        assertThat(root.isNormalized(), is(true));
+    }
+
+    @Test
+    public void shouldReturnSelfForGetNormalized() {
+        assertThat(root.getNormalizedPath(), is(sameInstance(root)));
+    }
+
+    @Test
+    public void shouldReturnSelfForGetCanonicalPath() {
+        assertThat(root.getCanonicalPath(), is(sameInstance(root)));
+    }
+
+    @Test
+    public void shouldReturnSizeOfZero() {
+        assertThat(root.size(), is(0));
+    }
+
+    @Override
+    @Test( expected = IllegalStateException.class )
+    public void shouldReturnImmutableSegmentsIterator() {
+        root.iterator().remove();
+    }
+
+    @Test
+    public void shouldReturnEmptyIteratorOverSegments() {
+        assertThat(root.iterator(), is(notNullValue()));
+        assertThat(root.iterator().hasNext(), is(false));
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSegmentAtIndexZero() {
+        root.getSegment(0);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldFailToReturnSegmentAtPositiveIndex() {
+        root.getSegment(1);
+    }
+
+    @Test
+    public void shouldReturnEmptySegmentsArray() {
+        assertThat(root.getSegmentsArray(), is(notNullValue()));
+        assertThat(root.getSegmentsArray().length, is(0));
+    }
+
+    @Test
+    public void shouldReturnEmptySegmentsList() {
+        assertThat(root.getSegmentsList(), is(notNullValue()));
+        assertThat(root.getSegmentsList().isEmpty(), is(true));
+    }
+
+    @Test
+    public void shouldAlwaysReturnPathWithSingleSlashForGetString() {
+        NamespaceRegistry registry = mock(NamespaceRegistry.class);
+        TextEncoder encoder = mock(TextEncoder.class);
+        stub(encoder.encode("/")).toReturn("/");
+        assertThat(root.getString(), is("/"));
+        assertThat(root.getString(registry), is("/"));
+        assertThat(root.getString(registry, encoder), is("/"));
+        assertThat(root.getString(registry, encoder, encoder), is("/"));
+        assertThat(root.getString(encoder), is("/"));
+    }
+
+    @Test
+    public void shouldAllowNullNamespaceRegistryWithNonNullTextEncodersSinceRegistryIsNotNeeded() {
+        TextEncoder encoder = mock(TextEncoder.class);
+        stub(encoder.encode("/")).toReturn("/");
+        assertThat(root.getString((NamespaceRegistry)null, encoder, encoder), is("/"));
+    }
+
+    @Test
+    public void shouldAllowNullTextEncoder() {
+        assertThat(root.getString((TextEncoder)null), is("/"));
+    }
+
+    @Test
+    public void shouldNotAllowNullTextEncoderWithNonNullNamespaceRegistry() {
+        NamespaceRegistry registry = mock(NamespaceRegistry.class);
+        assertThat(root.getString(registry, (TextEncoder)null), is("/"));
+    }
+
+    @Test
+    public void shouldNotAllowNullTextEncoderForDelimiterWithNonNullNamespaceRegistry() {
+        NamespaceRegistry registry = mock(NamespaceRegistry.class);
+        TextEncoder encoder = mock(TextEncoder.class);
+        assertThat(root.getString(registry, encoder, (TextEncoder)null), is("/"));
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldNotAllowSubpathStartingAtOne() {
+        root.subpath(1);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldNotAllowSubpathStartingAtMoreThanOne() {
+        root.subpath(2);
+    }
+
+    @Test( expected = IndexOutOfBoundsException.class )
+    public void shouldNotAllowSubpathEndingAtMoreThanZero() {
+        root.subpath(0, 1);
+    }
+
+    @Test
+    public void shouldReturnRelativePathConsistingOfSameNumberOfParentReferencesAsSizeOfSuppliedPath() {
+        List<Path.Segment> segments = new ArrayList<Path.Segment>();
+        segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
+        Path other = new BasicPath(segments, true);
+
+        assertThat(root.relativeTo(other).toString(), is(".."));
+
+        segments.add(new BasicPathSegment(new BasicName("http://example.com", "b")));
+        other = new BasicPath(segments, true);
+        assertThat(root.relativeTo(other).toString(), is("../.."));
+
+        String expected = "..";
+        segments.clear();
+        for (int i = 1; i != 100; ++i) {
+            segments.add(new BasicPathSegment(new BasicName("http://example.com", "b" + i)));
+            other = new BasicPath(segments, true);
+            assertThat(root.relativeTo(other).toString(), is(expected));
+            expected = expected + "/..";
+        }
+    }
+
+    @Test
+    public void shouldResolveAllRelativePathsToTheirAbsolutePath() {
+        List<Path.Segment> segments = new ArrayList<Path.Segment>();
+        segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
+        Path other = mock(Path.class);
+        stub(other.isAbsolute()).toReturn(false);
+        stub(other.getSegmentsList()).toReturn(segments);
+        stub(other.getNormalizedPath()).toReturn(other);
+        Path resolved = root.resolve(other);
+        assertThat(resolved.getSegmentsList(), is(segments));
+        assertThat(resolved.isAbsolute(), is(true));
+    }
+
+    @Test( expected = InvalidPathException.class )
+    public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+        Path other = mock(Path.class);
+        stub(other.isAbsolute()).toReturn(true);
+        root.resolve(other);
+    }
+
+    @Test
+    public void shouldAlwaysConsiderRootAsLessThanAnyPathOtherThanRoot() {
+        Path other = mock(Path.class);
+        stub(other.isRoot()).toReturn(false);
+        assertThat(root.compareTo(other), is(-1));
+        assertThat(root.equals(other), is(false));
+    }
+
+    @Test
+    public void shouldAlwaysConsiderRootAsEqualToAnyOtherRoot() {
+        Path other = mock(Path.class);
+        stub(other.isRoot()).toReturn(true);
+        assertThat(root.compareTo(other), is(0));
+        assertThat(root.equals(other), is(true));
+        assertThat(root.equals(root), is(true));
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/UuidValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/UuidValueFactoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/UuidValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,184 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import java.io.ByteArrayInputStream;
-import java.io.StringReader;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Iterator;
-import java.util.List;
-import java.util.UUID;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.basic.StringValueFactory;
-import org.jboss.dna.graph.properties.basic.UuidReference;
-import org.jboss.dna.graph.properties.basic.UuidValueFactory;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class UuidValueFactoryTest {
-
-    private UuidValueFactory factory;
-    private StringValueFactory stringFactory;
-    private UUID uuid;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
-        factory = new UuidValueFactory(Path.URL_DECODER, stringFactory);
-        uuid = UUID.randomUUID();
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateDoubleFromBooleanValue() {
-        factory.create(true);
-    }
-
-    @Test
-    public void shouldReturnUuidWhenCreatingFromUuid() {
-        assertThat(factory.create(uuid), is(sameInstance(uuid)));
-    }
-
-    @Test
-    public void shouldCreateUuidWithNoArguments() {
-        assertThat(factory.create(), is(instanceOf(UUID.class)));
-    }
-
-    @Test
-    public void shouldCreateUuidFromString() {
-        assertThat(factory.create(uuid.toString()), is(uuid));
-    }
-
-    @Test
-    public void shouldCreateUuidFromStringRegardlessOfLeadingAndTrailingWhitespace() {
-        assertThat(factory.create("  " + uuid.toString() + "  "), is(uuid));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromIntegerValue() {
-        factory.create(1);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromLongValue() {
-        factory.create(1L);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromDoubleValue() {
-        factory.create(1.0d);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromFloatValue() {
-        factory.create(1.0f);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromBooleanValue() {
-        factory.create(true);
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromCalendarValue() {
-        factory.create(Calendar.getInstance());
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromName() {
-        factory.create(mock(Name.class));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromPath() {
-        factory.create(mock(Path.class));
-    }
-
-    @Test
-    public void shouldCreateUuidFromReference() {
-        UuidReference ref = new UuidReference(uuid);
-        assertThat(factory.create(ref), is(uuid));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromUri() throws Exception {
-        factory.create(new URI("http://www.jboss.org"));
-    }
-
-    @Test
-    public void shouldCreateUuidFromByteArrayContainingUtf8EncodingOfStringWithUuid() throws Exception {
-        assertThat(factory.create(uuid.toString().getBytes("UTF-8")), is(uuid));
-    }
-
-    @Test
-    public void shouldCreateUuidFromInputStreamContainingUtf8EncodingOfStringWithUuid() throws Exception {
-        assertThat(factory.create(new ByteArrayInputStream(uuid.toString().getBytes("UTF-8"))), is(uuid));
-    }
-
-    @Test
-    public void shouldCreateUuidFromReaderContainingStringWithUuid() {
-        assertThat(factory.create(new StringReader(uuid.toString())), is(uuid));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuidFromByteArrayContainingUtf8EncodingOfStringWithContentsOtherThanUuid() throws Exception {
-        factory.create("something".getBytes("UTF-8"));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuuidFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanUuuid() throws Exception {
-        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
-    }
-
-    @Test( expected = ValueFormatException.class )
-    public void shouldNotCreateUuuidFromReaderContainingStringWithContentsOtherThanUuuid() throws Exception {
-        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
-    }
-
-    @Test
-    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
-        List<String> values = new ArrayList<String>();
-        for (int i = 0; i != 10; ++i) {
-            values.add(" " + UUID.randomUUID());
-        }
-        Iterator<UUID> iter = factory.create(values.iterator());
-        Iterator<String> valueIter = values.iterator();
-        while (iter.hasNext()) {
-            assertThat(iter.next(), is(factory.create(valueIter.next())));
-        }
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/UuidValueFactoryTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/UuidValueFactoryTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/UuidValueFactoryTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/UuidValueFactoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,184 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.property.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.jboss.dna.graph.property.basic.UuidReference;
+import org.jboss.dna.graph.property.basic.UuidValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class UuidValueFactoryTest {
+
+    private UuidValueFactory factory;
+    private StringValueFactory stringFactory;
+    private UUID uuid;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
+        factory = new UuidValueFactory(Path.URL_DECODER, stringFactory);
+        uuid = UUID.randomUUID();
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateDoubleFromBooleanValue() {
+        factory.create(true);
+    }
+
+    @Test
+    public void shouldReturnUuidWhenCreatingFromUuid() {
+        assertThat(factory.create(uuid), is(sameInstance(uuid)));
+    }
+
+    @Test
+    public void shouldCreateUuidWithNoArguments() {
+        assertThat(factory.create(), is(instanceOf(UUID.class)));
+    }
+
+    @Test
+    public void shouldCreateUuidFromString() {
+        assertThat(factory.create(uuid.toString()), is(uuid));
+    }
+
+    @Test
+    public void shouldCreateUuidFromStringRegardlessOfLeadingAndTrailingWhitespace() {
+        assertThat(factory.create("  " + uuid.toString() + "  "), is(uuid));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromIntegerValue() {
+        factory.create(1);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromLongValue() {
+        factory.create(1L);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromDoubleValue() {
+        factory.create(1.0d);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromFloatValue() {
+        factory.create(1.0f);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromBooleanValue() {
+        factory.create(true);
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromCalendarValue() {
+        factory.create(Calendar.getInstance());
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromName() {
+        factory.create(mock(Name.class));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromPath() {
+        factory.create(mock(Path.class));
+    }
+
+    @Test
+    public void shouldCreateUuidFromReference() {
+        UuidReference ref = new UuidReference(uuid);
+        assertThat(factory.create(ref), is(uuid));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromUri() throws Exception {
+        factory.create(new URI("http://www.jboss.org"));
+    }
+
+    @Test
+    public void shouldCreateUuidFromByteArrayContainingUtf8EncodingOfStringWithUuid() throws Exception {
+        assertThat(factory.create(uuid.toString().getBytes("UTF-8")), is(uuid));
+    }
+
+    @Test
+    public void shouldCreateUuidFromInputStreamContainingUtf8EncodingOfStringWithUuid() throws Exception {
+        assertThat(factory.create(new ByteArrayInputStream(uuid.toString().getBytes("UTF-8"))), is(uuid));
+    }
+
+    @Test
+    public void shouldCreateUuidFromReaderContainingStringWithUuid() {
+        assertThat(factory.create(new StringReader(uuid.toString())), is(uuid));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuidFromByteArrayContainingUtf8EncodingOfStringWithContentsOtherThanUuid() throws Exception {
+        factory.create("something".getBytes("UTF-8"));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuuidFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanUuuid() throws Exception {
+        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
+    }
+
+    @Test( expected = ValueFormatException.class )
+    public void shouldNotCreateUuuidFromReaderContainingStringWithContentsOtherThanUuuid() throws Exception {
+        factory.create(new ByteArrayInputStream("something".getBytes("UTF-8")));
+    }
+
+    @Test
+    public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
+        List<String> values = new ArrayList<String>();
+        for (int i = 0; i != 10; ++i) {
+            values.add(" " + UUID.randomUUID());
+        }
+        Iterator<UUID> iter = factory.create(values.iterator());
+        Iterator<String> valueIter = values.iterator();
+        while (iter.hasNext()) {
+            assertThat(iter.next(), is(factory.create(valueIter.next())));
+        }
+    }
+}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests)

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/AbstractRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/AbstractRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/AbstractRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,106 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.util.UUID;
-import org.jboss.dna.graph.BasicExecutionContext;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public abstract class AbstractRequestTest {
-
-    protected ExecutionContext context;
-    protected Location validPathLocation;
-    protected Location validUuidLocation;
-    protected Location validPropsLocation;
-    protected Location validPathLocation1;
-    protected Location validUuidLocation1;
-    protected Location validPropsLocation1;
-    protected Location validPathLocation2;
-    protected Location validUuidLocation2;
-    protected Location validPropsLocation2;
-    protected Property validProperty1;
-    protected Property validProperty2;
-
-    @Before
-    public void beforeEach() {
-        context = new BasicExecutionContext();
-        Path validPath = createPath("/a/b/c");
-        UUID validUuid = UUID.randomUUID();
-        Name idProperty1Name = createName("id1");
-        Name idProperty2Name = createName("id2");
-        Property idProperty1 = context.getPropertyFactory().create(idProperty1Name, "1");
-        Property idProperty2 = context.getPropertyFactory().create(idProperty2Name, "2");
-        validPathLocation = new Location(validPath);
-        validUuidLocation = new Location(validUuid);
-        validPropsLocation = new Location(idProperty1, idProperty2);
-
-        validPathLocation1 = new Location(validPath);
-        validUuidLocation1 = new Location(validUuid);
-        validPropsLocation1 = new Location(idProperty1, idProperty2);
-
-        validPath = createPath("/a/c/d");
-        validUuid = UUID.randomUUID();
-        idProperty1 = context.getPropertyFactory().create(idProperty1Name, "3");
-        idProperty2 = context.getPropertyFactory().create(idProperty2Name, "4");
-        validPathLocation2 = new Location(validPath);
-        validUuidLocation2 = new Location(validUuid);
-        validPropsLocation2 = new Location(idProperty1, idProperty2);
-
-        validProperty1 = context.getPropertyFactory().create(createName("fooProperty"), "foo");
-        validProperty2 = context.getPropertyFactory().create(createName("barProperty"), "bar");
-    }
-
-    protected Path createPath( String path ) {
-        return context.getValueFactories().getPathFactory().create(path);
-    }
-
-    protected Name createName( String name ) {
-        return context.getValueFactories().getNameFactory().create(name);
-    }
-
-    protected abstract Request createRequest();
-
-    @Test
-    public void shouldNotBeCancelledByDefault() {
-        Request request = createRequest();
-        assertThat(request.isCancelled(), is(false));
-    }
-
-    @Test
-    public void shouldBeCancelledAfterCallingCancel() {
-        Request request = createRequest();
-        assertThat(request.isCancelled(), is(false));
-        request.cancel();
-        assertThat(request.isCancelled(), is(true));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/AbstractRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/AbstractRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/AbstractRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/AbstractRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.util.UUID;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public abstract class AbstractRequestTest {
+
+    protected ExecutionContext context;
+    protected Location validPathLocation;
+    protected Location validUuidLocation;
+    protected Location validPropsLocation;
+    protected Location validPathLocation1;
+    protected Location validUuidLocation1;
+    protected Location validPropsLocation1;
+    protected Location validPathLocation2;
+    protected Location validUuidLocation2;
+    protected Location validPropsLocation2;
+    protected Property validProperty1;
+    protected Property validProperty2;
+
+    @Before
+    public void beforeEach() {
+        context = new ExecutionContext();
+        Path validPath = createPath("/a/b/c");
+        UUID validUuid = UUID.randomUUID();
+        Name idProperty1Name = createName("id1");
+        Name idProperty2Name = createName("id2");
+        Property idProperty1 = context.getPropertyFactory().create(idProperty1Name, "1");
+        Property idProperty2 = context.getPropertyFactory().create(idProperty2Name, "2");
+        validPathLocation = new Location(validPath);
+        validUuidLocation = new Location(validUuid);
+        validPropsLocation = new Location(idProperty1, idProperty2);
+
+        validPathLocation1 = new Location(validPath);
+        validUuidLocation1 = new Location(validUuid);
+        validPropsLocation1 = new Location(idProperty1, idProperty2);
+
+        validPath = createPath("/a/c/d");
+        validUuid = UUID.randomUUID();
+        idProperty1 = context.getPropertyFactory().create(idProperty1Name, "3");
+        idProperty2 = context.getPropertyFactory().create(idProperty2Name, "4");
+        validPathLocation2 = new Location(validPath);
+        validUuidLocation2 = new Location(validUuid);
+        validPropsLocation2 = new Location(idProperty1, idProperty2);
+
+        validProperty1 = context.getPropertyFactory().create(createName("fooProperty"), "foo");
+        validProperty2 = context.getPropertyFactory().create(createName("barProperty"), "bar");
+    }
+
+    protected Path createPath( String path ) {
+        return context.getValueFactories().getPathFactory().create(path);
+    }
+
+    protected Name createName( String name ) {
+        return context.getValueFactories().getNameFactory().create(name);
+    }
+
+    protected abstract Request createRequest();
+
+    @Test
+    public void shouldNotBeCancelledByDefault() {
+        Request request = createRequest();
+        assertThat(request.isCancelled(), is(false));
+    }
+
+    @Test
+    public void shouldBeCancelledAfterCallingCancel() {
+        Request request = createRequest();
+        assertThat(request.isCancelled(), is(false));
+        request.cancel();
+        assertThat(request.isCancelled(), is(true));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CompositeRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/CompositeRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CompositeRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,159 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class CompositeRequestTest extends AbstractRequestTest {
-
-    private Request request;
-    private Request[] requests;
-    private List<Request> requestList;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-        Request request1 = new ReadPropertyRequest(validPathLocation1, createName("property"));
-        Request request2 = new ReadPropertyRequest(validPathLocation2, createName("property"));
-        Request request3 = new ReadAllChildrenRequest(validPathLocation);
-        requests = new Request[] {request1, request2, request3};
-        requestList = Arrays.asList(requests);
-    }
-
-    @Override
-    protected Request createRequest() {
-        return CompositeRequest.with(requests);
-    }
-
-    @Test
-    public void shouldCancelAllNestedRequestsAndCompositeAfterCallingCancel() {
-        Request composite = CompositeRequest.with(requests);
-        assertThat(composite.isCancelled(), is(false));
-        for (Request request : requests) {
-            assertThat(request.isCancelled(), is(false));
-        }
-        composite.cancel();
-        assertThat(composite.isCancelled(), is(true));
-        for (Request request : requests) {
-            assertThat(request.isCancelled(), is(true));
-        }
-    }
-
-    @Test
-    public void shouldCancelAllNestedRequestsAndCompositeAfterCallingCancelOnNestedRequest() {
-        Request composite = CompositeRequest.with(requests);
-        assertThat(composite.isCancelled(), is(false));
-        for (Request request : requests) {
-            assertThat(request.isCancelled(), is(false));
-        }
-        requests[0].cancel();
-        assertThat(composite.isCancelled(), is(true));
-        for (Request request : requests) {
-            assertThat(request.isCancelled(), is(true));
-        }
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingCompositeRequestWithNullRequest() {
-        CompositeRequest.with((Request)null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingCompositeRequestWithNullRequestArray() {
-        CompositeRequest.with((Request[])null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingCompositeRequestWithNullRequestIterator() {
-        CompositeRequest.with((Iterator<Request>)null);
-    }
-
-    @Test
-    public void shouldReturnRequestWhenCreatingCompositeFromSingleRequest() {
-        request = CompositeRequest.with(requests[0]);
-        assertThat(request, is(sameInstance(requests[0])));
-    }
-
-    @Test
-    public void shouldReturnRequestWhenCreatingCompositeFromIteratorOverSingleRequest() {
-        requestList = Collections.singletonList(requests[0]);
-        request = CompositeRequest.with(requestList.iterator());
-        assertThat(request, is(sameInstance(requestList.get(0))));
-    }
-
-    @Test
-    public void shouldCreateCompositeFromMultipleRequests() {
-        request = CompositeRequest.with(requests);
-        assertThat(request, is(instanceOf(CompositeRequest.class)));
-        CompositeRequest composite = (CompositeRequest)request;
-        assertThat(composite.size(), is(3));
-        assertThat(composite.size(), is(requests.length));
-        assertThat(composite.getRequests(), hasItems(requests));
-        Iterator<Request> actual = composite.iterator();
-        Iterator<Request> expected = requestList.iterator();
-        while (actual.hasNext() && expected.hasNext()) {
-            assertThat(actual.next(), is(sameInstance(expected.next())));
-        }
-        assertThat(actual.hasNext(), is(expected.hasNext()));
-        assertThat(composite.hasError(), is(false));
-    }
-
-    @Test
-    public void shouldCreateCompositeFromIteratorOverRequests() {
-        request = CompositeRequest.with(requestList.iterator());
-        assertThat(request, is(instanceOf(CompositeRequest.class)));
-        CompositeRequest composite = (CompositeRequest)request;
-        assertThat(composite.size(), is(3));
-        assertThat(composite.size(), is(requestList.size()));
-        assertThat(composite.getRequests(), hasItems(requests));
-        Iterator<Request> actual = composite.iterator();
-        Iterator<Request> expected = requestList.iterator();
-        while (actual.hasNext() && expected.hasNext()) {
-            assertThat(actual.next(), is(sameInstance(expected.next())));
-        }
-        assertThat(actual.hasNext(), is(expected.hasNext()));
-        assertThat(composite.hasError(), is(false));
-    }
-
-    @Test
-    public void shouldConsiderTwoCompositesOfSameRequestsToBeEqual() {
-        request = CompositeRequest.with(requests);
-        Request request2 = CompositeRequest.with(requests);
-        assertThat(request, is(request2));
-        assertThat(request.hasError(), is(false));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CompositeRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/CompositeRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CompositeRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CompositeRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,163 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.graph.request.CompositeRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadPropertyRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class CompositeRequestTest extends AbstractRequestTest {
+
+    private Request request;
+    private Request[] requests;
+    private List<Request> requestList;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+        Request request1 = new ReadPropertyRequest(validPathLocation1, createName("property"));
+        Request request2 = new ReadPropertyRequest(validPathLocation2, createName("property"));
+        Request request3 = new ReadAllChildrenRequest(validPathLocation);
+        requests = new Request[] {request1, request2, request3};
+        requestList = Arrays.asList(requests);
+    }
+
+    @Override
+    protected Request createRequest() {
+        return CompositeRequest.with(requests);
+    }
+
+    @Test
+    public void shouldCancelAllNestedRequestsAndCompositeAfterCallingCancel() {
+        Request composite = CompositeRequest.with(requests);
+        assertThat(composite.isCancelled(), is(false));
+        for (Request request : requests) {
+            assertThat(request.isCancelled(), is(false));
+        }
+        composite.cancel();
+        assertThat(composite.isCancelled(), is(true));
+        for (Request request : requests) {
+            assertThat(request.isCancelled(), is(true));
+        }
+    }
+
+    @Test
+    public void shouldCancelAllNestedRequestsAndCompositeAfterCallingCancelOnNestedRequest() {
+        Request composite = CompositeRequest.with(requests);
+        assertThat(composite.isCancelled(), is(false));
+        for (Request request : requests) {
+            assertThat(request.isCancelled(), is(false));
+        }
+        requests[0].cancel();
+        assertThat(composite.isCancelled(), is(true));
+        for (Request request : requests) {
+            assertThat(request.isCancelled(), is(true));
+        }
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingCompositeRequestWithNullRequest() {
+        CompositeRequest.with((Request)null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingCompositeRequestWithNullRequestArray() {
+        CompositeRequest.with((Request[])null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingCompositeRequestWithNullRequestIterator() {
+        CompositeRequest.with((Iterator<Request>)null);
+    }
+
+    @Test
+    public void shouldReturnRequestWhenCreatingCompositeFromSingleRequest() {
+        request = CompositeRequest.with(requests[0]);
+        assertThat(request, is(sameInstance(requests[0])));
+    }
+
+    @Test
+    public void shouldReturnRequestWhenCreatingCompositeFromIteratorOverSingleRequest() {
+        requestList = Collections.singletonList(requests[0]);
+        request = CompositeRequest.with(requestList.iterator());
+        assertThat(request, is(sameInstance(requestList.get(0))));
+    }
+
+    @Test
+    public void shouldCreateCompositeFromMultipleRequests() {
+        request = CompositeRequest.with(requests);
+        assertThat(request, is(instanceOf(CompositeRequest.class)));
+        CompositeRequest composite = (CompositeRequest)request;
+        assertThat(composite.size(), is(3));
+        assertThat(composite.size(), is(requests.length));
+        assertThat(composite.getRequests(), hasItems(requests));
+        Iterator<Request> actual = composite.iterator();
+        Iterator<Request> expected = requestList.iterator();
+        while (actual.hasNext() && expected.hasNext()) {
+            assertThat(actual.next(), is(sameInstance(expected.next())));
+        }
+        assertThat(actual.hasNext(), is(expected.hasNext()));
+        assertThat(composite.hasError(), is(false));
+    }
+
+    @Test
+    public void shouldCreateCompositeFromIteratorOverRequests() {
+        request = CompositeRequest.with(requestList.iterator());
+        assertThat(request, is(instanceOf(CompositeRequest.class)));
+        CompositeRequest composite = (CompositeRequest)request;
+        assertThat(composite.size(), is(3));
+        assertThat(composite.size(), is(requestList.size()));
+        assertThat(composite.getRequests(), hasItems(requests));
+        Iterator<Request> actual = composite.iterator();
+        Iterator<Request> expected = requestList.iterator();
+        while (actual.hasNext() && expected.hasNext()) {
+            assertThat(actual.next(), is(sameInstance(expected.next())));
+        }
+        assertThat(actual.hasNext(), is(expected.hasNext()));
+        assertThat(composite.hasError(), is(false));
+    }
+
+    @Test
+    public void shouldConsiderTwoCompositesOfSameRequestsToBeEqual() {
+        request = CompositeRequest.with(requests);
+        Request request2 = CompositeRequest.with(requests);
+        assertThat(request, is(request2));
+        assertThat(request.hasError(), is(false));
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CopyBranchRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/CopyBranchRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CopyBranchRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,81 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class CopyBranchRequestTest extends AbstractRequestTest {
-
-    private CopyBranchRequest request;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new CopyBranchRequest(validPathLocation1, validPathLocation2);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new CopyBranchRequest(null, validPathLocation);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullToLocation() {
-        new CopyBranchRequest(validPathLocation, null);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidFromLocationAndValidToLocation() {
-        request = new CopyBranchRequest(validPathLocation1, validPathLocation2);
-        assertThat(request.from(), is(sameInstance(validPathLocation1)));
-        assertThat(request.into(), is(sameInstance(validPathLocation2)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
-        request = new CopyBranchRequest(validPathLocation1, validPathLocation2);
-        CopyBranchRequest request2 = new CopyBranchRequest(validPathLocation1, validPathLocation2);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new CopyBranchRequest(validPathLocation1, validPathLocation2);
-        CopyBranchRequest request2 = new CopyBranchRequest(validPathLocation1, validUuidLocation2);
-        assertThat(request.equals(request2), is(false));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CopyBranchRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/CopyBranchRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CopyBranchRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/CopyBranchRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,83 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class CopyBranchRequestTest extends AbstractRequestTest {
+
+    private CopyBranchRequest request;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new CopyBranchRequest(validPathLocation1, validPathLocation2);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new CopyBranchRequest(null, validPathLocation);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullToLocation() {
+        new CopyBranchRequest(validPathLocation, null);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidFromLocationAndValidToLocation() {
+        request = new CopyBranchRequest(validPathLocation1, validPathLocation2);
+        assertThat(request.from(), is(sameInstance(validPathLocation1)));
+        assertThat(request.into(), is(sameInstance(validPathLocation2)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
+        request = new CopyBranchRequest(validPathLocation1, validPathLocation2);
+        CopyBranchRequest request2 = new CopyBranchRequest(validPathLocation1, validPathLocation2);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new CopyBranchRequest(validPathLocation1, validPathLocation2);
+        CopyBranchRequest request2 = new CopyBranchRequest(validPathLocation1, validUuidLocation2);
+        assertThat(request.equals(request2), is(false));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/DeleteBranchRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/DeleteBranchRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/DeleteBranchRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,75 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class DeleteBranchRequestTest extends AbstractRequestTest {
-
-    private DeleteBranchRequest request;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new DeleteBranchRequest(validPathLocation1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new DeleteBranchRequest(null);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocation() {
-        request = new DeleteBranchRequest(validPathLocation1);
-        assertThat(request.at(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
-        request = new DeleteBranchRequest(validPathLocation1);
-        DeleteBranchRequest request2 = new DeleteBranchRequest(validPathLocation1);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new DeleteBranchRequest(validPathLocation1);
-        DeleteBranchRequest request2 = new DeleteBranchRequest(validPathLocation2);
-        assertThat(request.equals(request2), is(false));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/DeleteBranchRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/DeleteBranchRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/DeleteBranchRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/DeleteBranchRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class DeleteBranchRequestTest extends AbstractRequestTest {
+
+    private DeleteBranchRequest request;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new DeleteBranchRequest(validPathLocation1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new DeleteBranchRequest(null);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocation() {
+        request = new DeleteBranchRequest(validPathLocation1);
+        assertThat(request.at(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
+        request = new DeleteBranchRequest(validPathLocation1);
+        DeleteBranchRequest request2 = new DeleteBranchRequest(validPathLocation1);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new DeleteBranchRequest(validPathLocation1);
+        DeleteBranchRequest request2 = new DeleteBranchRequest(validPathLocation2);
+        assertThat(request.equals(request2), is(false));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/MoveBranchRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/MoveBranchRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/MoveBranchRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,81 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class MoveBranchRequestTest extends AbstractRequestTest {
-
-    private MoveBranchRequest request;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new MoveBranchRequest(validPathLocation1, validPathLocation2);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new MoveBranchRequest(null, validPathLocation);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullToLocation() {
-        new MoveBranchRequest(validPathLocation, null);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidFromLocationAndValidToLocation() {
-        request = new MoveBranchRequest(validPathLocation1, validPathLocation2);
-        assertThat(request.from(), is(sameInstance(validPathLocation1)));
-        assertThat(request.into(), is(sameInstance(validPathLocation2)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
-        request = new MoveBranchRequest(validPathLocation1, validPathLocation2);
-        MoveBranchRequest request2 = new MoveBranchRequest(validPathLocation1, validPathLocation2);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new MoveBranchRequest(validPathLocation1, validPathLocation2);
-        MoveBranchRequest request2 = new MoveBranchRequest(validPathLocation1, validUuidLocation2);
-        assertThat(request.equals(request2), is(false));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/MoveBranchRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/MoveBranchRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/MoveBranchRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/MoveBranchRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,83 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class MoveBranchRequestTest extends AbstractRequestTest {
+
+    private MoveBranchRequest request;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new MoveBranchRequest(validPathLocation1, validPathLocation2);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new MoveBranchRequest(null, validPathLocation);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullToLocation() {
+        new MoveBranchRequest(validPathLocation, null);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidFromLocationAndValidToLocation() {
+        request = new MoveBranchRequest(validPathLocation1, validPathLocation2);
+        assertThat(request.from(), is(sameInstance(validPathLocation1)));
+        assertThat(request.into(), is(sameInstance(validPathLocation2)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
+        request = new MoveBranchRequest(validPathLocation1, validPathLocation2);
+        MoveBranchRequest request2 = new MoveBranchRequest(validPathLocation1, validPathLocation2);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new MoveBranchRequest(validPathLocation1, validPathLocation2);
+        MoveBranchRequest request2 = new MoveBranchRequest(validPathLocation1, validUuidLocation2);
+        assertThat(request.equals(request2), is(false));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllChildrenRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadAllChildrenRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllChildrenRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,85 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class ReadAllChildrenRequestTest extends AbstractRequestTest {
-
-    private ReadAllChildrenRequest request;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new ReadAllChildrenRequest(validPathLocation1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new ReadAllChildrenRequest(null);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocation() {
-        request = new ReadAllChildrenRequest(validPathLocation1);
-        assertThat(request.of(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
-        request = new ReadAllChildrenRequest(validPathLocation1);
-        ReadAllChildrenRequest request2 = new ReadAllChildrenRequest(validPathLocation1);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new ReadAllChildrenRequest(validPathLocation1);
-        ReadAllChildrenRequest request2 = new ReadAllChildrenRequest(validPathLocation2);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldAllowAddingChildren() {
-        request = new ReadAllChildrenRequest(validPathLocation);
-        request.addChild(validPathLocation1);
-        request.addChild(validPathLocation2);
-        assertThat(request.getChildren().size(), is(2));
-        assertThat(request.getChildren(), hasItems(validPathLocation1, validPathLocation2));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllChildrenRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadAllChildrenRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllChildrenRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllChildrenRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,87 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ReadAllChildrenRequestTest extends AbstractRequestTest {
+
+    private ReadAllChildrenRequest request;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new ReadAllChildrenRequest(validPathLocation1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new ReadAllChildrenRequest(null);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocation() {
+        request = new ReadAllChildrenRequest(validPathLocation1);
+        assertThat(request.of(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
+        request = new ReadAllChildrenRequest(validPathLocation1);
+        ReadAllChildrenRequest request2 = new ReadAllChildrenRequest(validPathLocation1);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new ReadAllChildrenRequest(validPathLocation1);
+        ReadAllChildrenRequest request2 = new ReadAllChildrenRequest(validPathLocation2);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldAllowAddingChildren() {
+        request = new ReadAllChildrenRequest(validPathLocation);
+        request.addChild(validPathLocation1);
+        request.addChild(validPathLocation2);
+        assertThat(request.getChildren().size(), is(2));
+        assertThat(request.getChildren(), hasItems(validPathLocation1, validPathLocation2));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllPropertiesRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllPropertiesRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,87 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class ReadAllPropertiesRequestTest extends AbstractRequestTest {
-
-    private ReadAllPropertiesRequest request;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new ReadAllPropertiesRequest(validPathLocation1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new ReadAllPropertiesRequest(null);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocation() {
-        request = new ReadAllPropertiesRequest(validPathLocation1);
-        assertThat(request.at(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
-        request = new ReadAllPropertiesRequest(validPathLocation1);
-        ReadAllPropertiesRequest request2 = new ReadAllPropertiesRequest(validPathLocation1);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new ReadAllPropertiesRequest(validPathLocation1);
-        ReadAllPropertiesRequest request2 = new ReadAllPropertiesRequest(validPathLocation2);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldAllowAddingProperties() {
-        request = new ReadAllPropertiesRequest(validPathLocation);
-        request.addProperty(validProperty1);
-        request.addProperty(validProperty2);
-        assertThat(request.getProperties().size(), is(2));
-        assertThat(request.getProperties(), hasItems(validProperty1, validProperty2));
-        assertThat(request.getPropertiesByName().get(validProperty1.getName()), is(validProperty1));
-        assertThat(request.getPropertiesByName().get(validProperty2.getName()), is(validProperty2));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllPropertiesRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllPropertiesRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadAllPropertiesRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,89 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ReadAllPropertiesRequestTest extends AbstractRequestTest {
+
+    private ReadAllPropertiesRequest request;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new ReadAllPropertiesRequest(validPathLocation1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new ReadAllPropertiesRequest(null);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocation() {
+        request = new ReadAllPropertiesRequest(validPathLocation1);
+        assertThat(request.at(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
+        request = new ReadAllPropertiesRequest(validPathLocation1);
+        ReadAllPropertiesRequest request2 = new ReadAllPropertiesRequest(validPathLocation1);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new ReadAllPropertiesRequest(validPathLocation1);
+        ReadAllPropertiesRequest request2 = new ReadAllPropertiesRequest(validPathLocation2);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldAllowAddingProperties() {
+        request = new ReadAllPropertiesRequest(validPathLocation);
+        request.addProperty(validProperty1);
+        request.addProperty(validProperty2);
+        assertThat(request.getProperties().size(), is(2));
+        assertThat(request.getProperties(), hasItems(validProperty1, validProperty2));
+        assertThat(request.getPropertiesByName().get(validProperty1.getName()), is(validProperty1));
+        assertThat(request.getPropertiesByName().get(validProperty2.getName()), is(validProperty2));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,99 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class ReadBlockOfChildrenRequestTest extends AbstractRequestTest {
-
-    private ReadBlockOfChildrenRequest request;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new ReadBlockOfChildrenRequest(validPathLocation1, 2, 10);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new ReadBlockOfChildrenRequest(null, 0, 1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNegativeStartingIndex() {
-        new ReadBlockOfChildrenRequest(validPathLocation1, -1, 1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNegativeCount() {
-        new ReadBlockOfChildrenRequest(validPathLocation1, 1, -1);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocation() {
-        request = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 10);
-        assertThat(request.of(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
-        request = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 20);
-        ReadBlockOfChildrenRequest request2 = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 20);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new ReadBlockOfChildrenRequest(validPathLocation1, 20, 20);
-        ReadBlockOfChildrenRequest request2 = new ReadBlockOfChildrenRequest(validPathLocation2, 2, 20);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithSameLocationsButDifferentStartingIndexes() {
-        request = new ReadBlockOfChildrenRequest(validPathLocation1, 20, 20);
-        ReadBlockOfChildrenRequest request2 = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 20);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithSameLocationsButDifferentBlockSizes() {
-        request = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 2);
-        ReadBlockOfChildrenRequest request2 = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 20);
-        assertThat(request.equals(request2), is(false));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBlockOfChildrenRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,101 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.request.ReadBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ReadBlockOfChildrenRequestTest extends AbstractRequestTest {
+
+    private ReadBlockOfChildrenRequest request;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new ReadBlockOfChildrenRequest(validPathLocation1, 2, 10);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new ReadBlockOfChildrenRequest(null, 0, 1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNegativeStartingIndex() {
+        new ReadBlockOfChildrenRequest(validPathLocation1, -1, 1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNegativeCount() {
+        new ReadBlockOfChildrenRequest(validPathLocation1, 1, -1);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocation() {
+        request = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 10);
+        assertThat(request.of(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
+        request = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 20);
+        ReadBlockOfChildrenRequest request2 = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 20);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new ReadBlockOfChildrenRequest(validPathLocation1, 20, 20);
+        ReadBlockOfChildrenRequest request2 = new ReadBlockOfChildrenRequest(validPathLocation2, 2, 20);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithSameLocationsButDifferentStartingIndexes() {
+        request = new ReadBlockOfChildrenRequest(validPathLocation1, 20, 20);
+        ReadBlockOfChildrenRequest request2 = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 20);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithSameLocationsButDifferentBlockSizes() {
+        request = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 2);
+        ReadBlockOfChildrenRequest request2 = new ReadBlockOfChildrenRequest(validPathLocation1, 2, 20);
+        assertThat(request.equals(request2), is(false));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBranchRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadBranchRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBranchRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,92 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class ReadBranchRequestTest extends AbstractRequestTest {
-
-    private ReadBranchRequest request;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new ReadBranchRequest(validPathLocation1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new ReadBranchRequest(null);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocation() {
-        request = new ReadBranchRequest(validPathLocation1);
-        assertThat(request.at(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.maximumDepth(), is(ReadBranchRequest.DEFAULT_MAXIMUM_DEPTH));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndMaximumDepth() {
-        request = new ReadBranchRequest(validPathLocation1, 10);
-        assertThat(request.at(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.maximumDepth(), is(10));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
-        request = new ReadBranchRequest(validPathLocation1);
-        ReadBranchRequest request2 = new ReadBranchRequest(validPathLocation1);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new ReadBranchRequest(validPathLocation1, 20);
-        ReadBranchRequest request2 = new ReadBranchRequest(validPathLocation2, 20);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithSameLocationsButDifferentMaximumDepths() {
-        request = new ReadBranchRequest(validPathLocation1, 20);
-        ReadBranchRequest request2 = new ReadBranchRequest(validPathLocation1, 2);
-        assertThat(request.equals(request2), is(false));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBranchRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadBranchRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBranchRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadBranchRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.request.ReadBranchRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ReadBranchRequestTest extends AbstractRequestTest {
+
+    private ReadBranchRequest request;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new ReadBranchRequest(validPathLocation1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new ReadBranchRequest(null);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocation() {
+        request = new ReadBranchRequest(validPathLocation1);
+        assertThat(request.at(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.maximumDepth(), is(ReadBranchRequest.DEFAULT_MAXIMUM_DEPTH));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndMaximumDepth() {
+        request = new ReadBranchRequest(validPathLocation1, 10);
+        assertThat(request.at(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.maximumDepth(), is(10));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
+        request = new ReadBranchRequest(validPathLocation1);
+        ReadBranchRequest request2 = new ReadBranchRequest(validPathLocation1);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new ReadBranchRequest(validPathLocation1, 20);
+        ReadBranchRequest request2 = new ReadBranchRequest(validPathLocation2, 20);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithSameLocationsButDifferentMaximumDepths() {
+        request = new ReadBranchRequest(validPathLocation1, 20);
+        ReadBranchRequest request2 = new ReadBranchRequest(validPathLocation1, 2);
+        assertThat(request.equals(request2), is(false));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadNodeRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadNodeRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadNodeRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,101 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class ReadNodeRequestTest extends AbstractRequestTest {
-
-    private ReadNodeRequest request;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new ReadNodeRequest(validPathLocation1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new CopyBranchRequest(null, validPathLocation);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullToLocation() {
-        new CopyBranchRequest(validPathLocation, null);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocation() {
-        request = new ReadNodeRequest(validPathLocation1);
-        assertThat(request.at(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
-        request = new ReadNodeRequest(validPathLocation1);
-        ReadNodeRequest request2 = new ReadNodeRequest(validPathLocation1);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new ReadNodeRequest(validPathLocation1);
-        ReadNodeRequest request2 = new ReadNodeRequest(validPathLocation2);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldAllowAddingChildren() {
-        request = new ReadNodeRequest(validPathLocation);
-        request.addChild(validPathLocation1);
-        request.addChild(validPathLocation2);
-        assertThat(request.getChildren().size(), is(2));
-        assertThat(request.getChildren(), hasItems(validPathLocation1, validPathLocation2));
-    }
-
-    @Test
-    public void shouldAllowAddingProperties() {
-        request = new ReadNodeRequest(validPathLocation);
-        request.addProperty(validProperty1);
-        request.addProperty(validProperty2);
-        assertThat(request.getProperties().size(), is(2));
-        assertThat(request.getProperties(), hasItems(validProperty1, validProperty2));
-        assertThat(request.getPropertiesByName().get(validProperty1.getName()), is(validProperty1));
-        assertThat(request.getPropertiesByName().get(validProperty2.getName()), is(validProperty2));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadNodeRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadNodeRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadNodeRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadNodeRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,104 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ReadNodeRequestTest extends AbstractRequestTest {
+
+    private ReadNodeRequest request;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new ReadNodeRequest(validPathLocation1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new CopyBranchRequest(null, validPathLocation);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullToLocation() {
+        new CopyBranchRequest(validPathLocation, null);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocation() {
+        request = new ReadNodeRequest(validPathLocation1);
+        assertThat(request.at(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
+        request = new ReadNodeRequest(validPathLocation1);
+        ReadNodeRequest request2 = new ReadNodeRequest(validPathLocation1);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new ReadNodeRequest(validPathLocation1);
+        ReadNodeRequest request2 = new ReadNodeRequest(validPathLocation2);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldAllowAddingChildren() {
+        request = new ReadNodeRequest(validPathLocation);
+        request.addChild(validPathLocation1);
+        request.addChild(validPathLocation2);
+        assertThat(request.getChildren().size(), is(2));
+        assertThat(request.getChildren(), hasItems(validPathLocation1, validPathLocation2));
+    }
+
+    @Test
+    public void shouldAllowAddingProperties() {
+        request = new ReadNodeRequest(validPathLocation);
+        request.addProperty(validProperty1);
+        request.addProperty(validProperty2);
+        assertThat(request.getProperties().size(), is(2));
+        assertThat(request.getProperties(), hasItems(validProperty1, validProperty2));
+        assertThat(request.getPropertiesByName().get(validProperty1.getName()), is(validProperty1));
+        assertThat(request.getPropertiesByName().get(validProperty2.getName()), is(validProperty2));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadPropertyRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadPropertyRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadPropertyRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,105 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class ReadPropertyRequestTest extends AbstractRequestTest {
-
-    private ReadPropertyRequest request;
-    private Property validProperty;
-    private Name validPropertyName;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-        validProperty = validProperty1;
-        validPropertyName = validProperty.getName();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new ReadPropertyRequest(validPathLocation1, validPropertyName);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullLocation() {
-        new ReadPropertyRequest(null, validPropertyName);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullPropertyName() {
-        new CopyBranchRequest(validPathLocation, null);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocation() {
-        request = new ReadPropertyRequest(validPathLocation1, validPropertyName);
-        assertThat(request.on(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocationsAndSamePropertyName() {
-        request = new ReadPropertyRequest(validPathLocation1, validPropertyName);
-        ReadPropertyRequest request2 = new ReadPropertyRequest(validPathLocation1, validPropertyName);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new ReadPropertyRequest(validPathLocation1, validPropertyName);
-        ReadPropertyRequest request2 = new ReadPropertyRequest(validPathLocation2, validPropertyName);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithSameLocationButDifferentPropertyNames() {
-        request = new ReadPropertyRequest(validPathLocation1, validProperty2.getName());
-        ReadPropertyRequest request2 = new ReadPropertyRequest(validPathLocation2, validPropertyName);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldAllowSettingProperties() {
-        request = new ReadPropertyRequest(validPathLocation, validPropertyName);
-        request.setProperty(validProperty1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowSettingPropertyIfNameDoeNotMatch() {
-        request = new ReadPropertyRequest(validPathLocation, validPropertyName);
-        request.setProperty(validProperty2);
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadPropertyRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/ReadPropertyRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadPropertyRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/ReadPropertyRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.ReadPropertyRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ReadPropertyRequestTest extends AbstractRequestTest {
+
+    private ReadPropertyRequest request;
+    private Property validProperty;
+    private Name validPropertyName;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+        validProperty = validProperty1;
+        validPropertyName = validProperty.getName();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new ReadPropertyRequest(validPathLocation1, validPropertyName);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullLocation() {
+        new ReadPropertyRequest(null, validPropertyName);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullPropertyName() {
+        new CopyBranchRequest(validPathLocation, null);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocation() {
+        request = new ReadPropertyRequest(validPathLocation1, validPropertyName);
+        assertThat(request.on(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocationsAndSamePropertyName() {
+        request = new ReadPropertyRequest(validPathLocation1, validPropertyName);
+        ReadPropertyRequest request2 = new ReadPropertyRequest(validPathLocation1, validPropertyName);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new ReadPropertyRequest(validPathLocation1, validPropertyName);
+        ReadPropertyRequest request2 = new ReadPropertyRequest(validPathLocation2, validPropertyName);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithSameLocationButDifferentPropertyNames() {
+        request = new ReadPropertyRequest(validPathLocation1, validProperty2.getName());
+        ReadPropertyRequest request2 = new ReadPropertyRequest(validPathLocation2, validPropertyName);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldAllowSettingProperties() {
+        request = new ReadPropertyRequest(validPathLocation, validPropertyName);
+        request.setProperty(validProperty1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowSettingPropertyIfNameDoeNotMatch() {
+        request = new ReadPropertyRequest(validPathLocation, validPropertyName);
+        request.setProperty(validProperty2);
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/RemovePropertiesRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,171 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.graph.properties.Name;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class RemovePropertiesRequestTest extends AbstractRequestTest {
-
-    private RemovePropertiesRequest request;
-    private Name validPropertyName1;
-    private Name validPropertyName2;
-    private Name validPropertyName3;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-        validPropertyName1 = createName("foo1");
-        validPropertyName2 = createName("foo2");
-        validPropertyName3 = createName("foo3");
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new RemovePropertiesRequest(validPathLocation1, validPropertyName1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new RemovePropertiesRequest(null, validPropertyName1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullPropertyName() {
-        new RemovePropertiesRequest(validPathLocation, (Name[])null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameArray() {
-        new RemovePropertiesRequest(validPathLocation, new Name[] {});
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullPropertyNameIterator() {
-        new RemovePropertiesRequest(validPathLocation, (Iterator<Name>)null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterator() {
-        new RemovePropertiesRequest(validPathLocation, new ArrayList<Name>().iterator());
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullPropertyNameIterable() {
-        new RemovePropertiesRequest(validPathLocation, (Iterable<Name>)null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterable() {
-        new RemovePropertiesRequest(validPathLocation, new ArrayList<Name>());
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndValidPropertyName() {
-        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1);
-        assertThat(request.from(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.propertyNames(), hasItems(validPropertyName1));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndValidPropertyNames() {
-        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
-        assertThat(request.from(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.propertyNames(), hasItems(validPropertyName1, validPropertyName2));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyName() {
-        List<Name> names = new ArrayList<Name>();
-        names.add(validPropertyName1);
-        request = new RemovePropertiesRequest(validPathLocation1, names);
-        assertThat(request.from(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.propertyNames(), hasItems(validPropertyName1));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyNames() {
-        List<Name> names = new ArrayList<Name>();
-        names.add(validPropertyName1);
-        names.add(validPropertyName2);
-        names.add(validPropertyName3);
-        request = new RemovePropertiesRequest(validPathLocation1, names.iterator());
-        assertThat(request.from(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.propertyNames(), hasItems(validPropertyName1, validPropertyName2, validPropertyName3));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndIterableWithValidPropertyNames() {
-        List<Name> names = new ArrayList<Name>();
-        names.add(validPropertyName1);
-        names.add(validPropertyName2);
-        names.add(validPropertyName3);
-        request = new RemovePropertiesRequest(validPathLocation1, names);
-        assertThat(request.from(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.propertyNames(), hasItems(validPropertyName1, validPropertyName2, validPropertyName3));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocationsAndSamePropertyNames() {
-        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
-        RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
-        RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation2, validPropertyName1, validPropertyName2);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithSameLocationButDifferentPropertyNames() {
-        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
-        RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation2, validPropertyName2, validPropertyName3);
-        assertThat(request.equals(request2), is(false));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/RemovePropertiesRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,173 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.request.RemovePropertiesRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class RemovePropertiesRequestTest extends AbstractRequestTest {
+
+    private RemovePropertiesRequest request;
+    private Name validPropertyName1;
+    private Name validPropertyName2;
+    private Name validPropertyName3;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+        validPropertyName1 = createName("foo1");
+        validPropertyName2 = createName("foo2");
+        validPropertyName3 = createName("foo3");
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new RemovePropertiesRequest(validPathLocation1, validPropertyName1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new RemovePropertiesRequest(null, validPropertyName1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullPropertyName() {
+        new RemovePropertiesRequest(validPathLocation, (Name[])null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameArray() {
+        new RemovePropertiesRequest(validPathLocation, new Name[] {});
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullPropertyNameIterator() {
+        new RemovePropertiesRequest(validPathLocation, (Iterator<Name>)null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterator() {
+        new RemovePropertiesRequest(validPathLocation, new ArrayList<Name>().iterator());
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullPropertyNameIterable() {
+        new RemovePropertiesRequest(validPathLocation, (Iterable<Name>)null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterable() {
+        new RemovePropertiesRequest(validPathLocation, new ArrayList<Name>());
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndValidPropertyName() {
+        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1);
+        assertThat(request.from(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.propertyNames(), hasItems(validPropertyName1));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndValidPropertyNames() {
+        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
+        assertThat(request.from(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.propertyNames(), hasItems(validPropertyName1, validPropertyName2));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyName() {
+        List<Name> names = new ArrayList<Name>();
+        names.add(validPropertyName1);
+        request = new RemovePropertiesRequest(validPathLocation1, names);
+        assertThat(request.from(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.propertyNames(), hasItems(validPropertyName1));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyNames() {
+        List<Name> names = new ArrayList<Name>();
+        names.add(validPropertyName1);
+        names.add(validPropertyName2);
+        names.add(validPropertyName3);
+        request = new RemovePropertiesRequest(validPathLocation1, names.iterator());
+        assertThat(request.from(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.propertyNames(), hasItems(validPropertyName1, validPropertyName2, validPropertyName3));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndIterableWithValidPropertyNames() {
+        List<Name> names = new ArrayList<Name>();
+        names.add(validPropertyName1);
+        names.add(validPropertyName2);
+        names.add(validPropertyName3);
+        request = new RemovePropertiesRequest(validPathLocation1, names);
+        assertThat(request.from(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.propertyNames(), hasItems(validPropertyName1, validPropertyName2, validPropertyName3));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocationsAndSamePropertyNames() {
+        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
+        RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
+        RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation2, validPropertyName1, validPropertyName2);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithSameLocationButDifferentPropertyNames() {
+        request = new RemovePropertiesRequest(validPathLocation1, validPropertyName1, validPropertyName2);
+        RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation2, validPropertyName2, validPropertyName3);
+        assertThat(request.equals(request2), is(false));
+    }
+
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RenameNodeRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/RenameNodeRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RenameNodeRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,91 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import org.jboss.dna.graph.properties.Name;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class RenameNodeRequestTest extends AbstractRequestTest {
-
-    private RenameNodeRequest request;
-    private Name newName;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-        newName = createName("SomethingElse");
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new RenameNodeRequest(validPathLocation1, newName);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new RenameNodeRequest(null, newName);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullNewName() {
-        new RenameNodeRequest(validPathLocation1, null);
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidFromLocationAndValidToLocation() {
-        request = new RenameNodeRequest(validPathLocation1, newName);
-        assertThat(request.at(), is(sameInstance(validPathLocation1)));
-        assertThat(request.toName(), is(sameInstance(newName)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
-        request = new RenameNodeRequest(validPathLocation1, newName);
-        RenameNodeRequest request2 = new RenameNodeRequest(validPathLocation1, newName);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new RenameNodeRequest(validPathLocation1, newName);
-        RenameNodeRequest request2 = new RenameNodeRequest(validPathLocation2, newName);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithSameLocationsAndDifferentNames() {
-        request = new RenameNodeRequest(validPathLocation1, newName);
-        RenameNodeRequest request2 = new RenameNodeRequest(validPathLocation1, createName("OtherName"));
-        assertThat(request.equals(request2), is(false));
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RenameNodeRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/RenameNodeRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RenameNodeRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RenameNodeRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,93 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.request.RenameNodeRequest;
+import org.jboss.dna.graph.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class RenameNodeRequestTest extends AbstractRequestTest {
+
+    private RenameNodeRequest request;
+    private Name newName;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+        newName = createName("SomethingElse");
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new RenameNodeRequest(validPathLocation1, newName);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new RenameNodeRequest(null, newName);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullNewName() {
+        new RenameNodeRequest(validPathLocation1, null);
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidFromLocationAndValidToLocation() {
+        request = new RenameNodeRequest(validPathLocation1, newName);
+        assertThat(request.at(), is(sameInstance(validPathLocation1)));
+        assertThat(request.toName(), is(sameInstance(newName)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocations() {
+        request = new RenameNodeRequest(validPathLocation1, newName);
+        RenameNodeRequest request2 = new RenameNodeRequest(validPathLocation1, newName);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new RenameNodeRequest(validPathLocation1, newName);
+        RenameNodeRequest request2 = new RenameNodeRequest(validPathLocation2, newName);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithSameLocationsAndDifferentNames() {
+        request = new RenameNodeRequest(validPathLocation1, newName);
+        RenameNodeRequest request2 = new RenameNodeRequest(validPathLocation1, createName("OtherName"));
+        assertThat(request.equals(request2), is(false));
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/UpdatePropertiesRequestTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,174 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.requests;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.graph.properties.Property;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class UpdatePropertiesRequestTest extends AbstractRequestTest {
-
-    private UpdatePropertiesRequest request;
-
-    @Override
-    @Before
-    public void beforeEach() {
-        super.beforeEach();
-    }
-
-    @Override
-    protected Request createRequest() {
-        return new UpdatePropertiesRequest(validPathLocation1, validProperty1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
-        new UpdatePropertiesRequest(null, validProperty1);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullPropertyName() {
-        new UpdatePropertiesRequest(validPathLocation, (Property[])null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameArray() {
-        new UpdatePropertiesRequest(validPathLocation, new Property[] {});
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullPropertyNameIterator() {
-        new UpdatePropertiesRequest(validPathLocation, (Iterator<Property>)null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterator() {
-        new UpdatePropertiesRequest(validPathLocation, new ArrayList<Property>().iterator());
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithNullPropertyNameIterable() {
-        new UpdatePropertiesRequest(validPathLocation, (Iterable<Property>)null);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterable() {
-        new UpdatePropertiesRequest(validPathLocation, new ArrayList<Property>());
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndValidProperty() {
-        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1);
-        assertThat(request.on(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.properties(), hasItems(validProperty1));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndValidPropertyNames() {
-        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
-        assertThat(request.on(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.properties(), hasItems(validProperty1, validProperty2));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyName() {
-        List<Property> properties = new ArrayList<Property>();
-        properties.add(validProperty1);
-        request = new UpdatePropertiesRequest(validPathLocation1, properties.iterator());
-        assertThat(request.on(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.properties(), hasItems(validProperty1));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyNames() {
-        List<Property> properties = new ArrayList<Property>();
-        properties.add(validProperty1);
-        properties.add(validProperty2);
-        request = new UpdatePropertiesRequest(validPathLocation1, properties.iterator());
-        assertThat(request.on(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.properties(), hasItems(validProperty1, validProperty2));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndIterableWithValidPropertyName() {
-        List<Property> properties = new ArrayList<Property>();
-        properties.add(validProperty1);
-        request = new UpdatePropertiesRequest(validPathLocation1, properties);
-        assertThat(request.on(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.properties(), hasItems(validProperty1));
-    }
-
-    @Test
-    public void shouldCreateValidRequestWithValidLocationAndIterableWithValidPropertyNames() {
-        List<Property> properties = new ArrayList<Property>();
-        properties.add(validProperty1);
-        properties.add(validProperty2);
-        request = new UpdatePropertiesRequest(validPathLocation1, properties);
-        assertThat(request.on(), is(sameInstance(validPathLocation1)));
-        assertThat(request.hasError(), is(false));
-        assertThat(request.getError(), is(nullValue()));
-        assertThat(request.properties(), hasItems(validProperty1, validProperty2));
-    }
-
-    @Test
-    public void shouldConsiderEqualTwoRequestsWithSameLocationsAndSamePropertyNames() {
-        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
-        UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
-        assertThat(request, is(request2));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
-        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
-        UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation2, validProperty1, validProperty2);
-        assertThat(request.equals(request2), is(false));
-    }
-
-    @Test
-    public void shouldConsiderNotEqualTwoRequestsWithSameLocationButDifferentPropertyNames() {
-        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
-        UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation2, validProperty1);
-        assertThat(request.equals(request2), is(false));
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/UpdatePropertiesRequestTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,176 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class UpdatePropertiesRequestTest extends AbstractRequestTest {
+
+    private UpdatePropertiesRequest request;
+
+    @Override
+    @Before
+    public void beforeEach() {
+        super.beforeEach();
+    }
+
+    @Override
+    protected Request createRequest() {
+        return new UpdatePropertiesRequest(validPathLocation1, validProperty1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullFromLocation() {
+        new UpdatePropertiesRequest(null, validProperty1);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullPropertyName() {
+        new UpdatePropertiesRequest(validPathLocation, (Property[])null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameArray() {
+        new UpdatePropertiesRequest(validPathLocation, new Property[] {});
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullPropertyNameIterator() {
+        new UpdatePropertiesRequest(validPathLocation, (Iterator<Property>)null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterator() {
+        new UpdatePropertiesRequest(validPathLocation, new ArrayList<Property>().iterator());
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithNullPropertyNameIterable() {
+        new UpdatePropertiesRequest(validPathLocation, (Iterable<Property>)null);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterable() {
+        new UpdatePropertiesRequest(validPathLocation, new ArrayList<Property>());
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndValidProperty() {
+        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1);
+        assertThat(request.on(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.properties(), hasItems(validProperty1));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndValidPropertyNames() {
+        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
+        assertThat(request.on(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.properties(), hasItems(validProperty1, validProperty2));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyName() {
+        List<Property> properties = new ArrayList<Property>();
+        properties.add(validProperty1);
+        request = new UpdatePropertiesRequest(validPathLocation1, properties.iterator());
+        assertThat(request.on(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.properties(), hasItems(validProperty1));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyNames() {
+        List<Property> properties = new ArrayList<Property>();
+        properties.add(validProperty1);
+        properties.add(validProperty2);
+        request = new UpdatePropertiesRequest(validPathLocation1, properties.iterator());
+        assertThat(request.on(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.properties(), hasItems(validProperty1, validProperty2));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndIterableWithValidPropertyName() {
+        List<Property> properties = new ArrayList<Property>();
+        properties.add(validProperty1);
+        request = new UpdatePropertiesRequest(validPathLocation1, properties);
+        assertThat(request.on(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.properties(), hasItems(validProperty1));
+    }
+
+    @Test
+    public void shouldCreateValidRequestWithValidLocationAndIterableWithValidPropertyNames() {
+        List<Property> properties = new ArrayList<Property>();
+        properties.add(validProperty1);
+        properties.add(validProperty2);
+        request = new UpdatePropertiesRequest(validPathLocation1, properties);
+        assertThat(request.on(), is(sameInstance(validPathLocation1)));
+        assertThat(request.hasError(), is(false));
+        assertThat(request.getError(), is(nullValue()));
+        assertThat(request.properties(), hasItems(validProperty1, validProperty2));
+    }
+
+    @Test
+    public void shouldConsiderEqualTwoRequestsWithSameLocationsAndSamePropertyNames() {
+        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
+        UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
+        assertThat(request, is(request2));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
+        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
+        UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation2, validProperty1, validProperty2);
+        assertThat(request.equals(request2), is(false));
+    }
+
+    @Test
+    public void shouldConsiderNotEqualTwoRequestsWithSameLocationButDifferentPropertyNames() {
+        request = new UpdatePropertiesRequest(validPathLocation1, validProperty1, validProperty2);
+        UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation2, validProperty1);
+        assertThat(request.equals(request2), is(false));
+    }
+
+}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer (from rev 705, trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers)

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerContext.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerContext.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerContext.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,196 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.sequencers;
-
-import java.security.AccessControlContext;
-import java.util.Set;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.collection.Problems;
-import org.jboss.dna.common.collection.SimpleProblems;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.graph.BasicExecutionContext;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.mimetype.MimeTypeDetector;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
-
-/**
- * @author John Verhaeg
- */
- at Immutable
-public class MockSequencerContext implements SequencerContext {
-
-    private final ExecutionContext context = new BasicExecutionContext();
-    private final Problems problems = new SimpleProblems();
-
-    public MockSequencerContext() {
-        NamespaceRegistry registry = context.getNamespaceRegistry();
-        registry.register("jcr", "http://www.jcp.org/jcr/1.0");
-        registry.register("mix", "http://www.jcp.org/jcr/mix/1.0");
-        registry.register("nt", "http://www.jcp.org/jcr/nt/1.0");
-        registry.register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
-        registry.register("dnadtd", "http://www.jboss.org/dna/dtd/1.0");
-        registry.register("dnaxml", "http://www.jboss.org/dna/xml/1.0");
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.common.component.ClassLoaderFactory#getClassLoader(java.lang.String[])
-     */
-    public ClassLoader getClassLoader( String... classpath ) {
-        return context.getClassLoader(classpath);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getMimeTypeDetector()
-     */
-    public MimeTypeDetector getMimeTypeDetector() {
-        return context.getMimeTypeDetector();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getInputPath()
-     */
-    public Path getInputPath() {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getInputProperties()
-     */
-    public Set<Property> getInputProperties() {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getInputProperty(org.jboss.dna.graph.properties.Name)
-     */
-    public Property getInputProperty( Name name ) {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getMimeType()
-     */
-    public String getMimeType() {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getProblems()
-     */
-    public Problems getProblems() {
-        return problems;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getAccessControlContext()
-     */
-    public AccessControlContext getAccessControlContext() {
-        return context.getAccessControlContext();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getLogger(java.lang.Class)
-     */
-    public Logger getLogger( Class<?> clazz ) {
-        return context.getLogger(clazz);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getLogger(java.lang.String)
-     */
-    public Logger getLogger( String name ) {
-        return context.getLogger(name);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getLoginContext()
-     */
-    public LoginContext getLoginContext() {
-        return context.getLoginContext();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getNamespaceRegistry()
-     */
-    public NamespaceRegistry getNamespaceRegistry() {
-        return context.getNamespaceRegistry();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getPropertyFactory()
-     */
-    public PropertyFactory getPropertyFactory() {
-        return context.getPropertyFactory();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getSubject()
-     */
-    public Subject getSubject() {
-        return context.getSubject();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getValueFactories()
-     */
-    public ValueFactories getValueFactories() {
-        return context.getValueFactories();
-    }
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerContext.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerContext.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerContext.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerContext.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.sequencer;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.collection.SimpleProblems;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+
+/**
+ * @author John Verhaeg
+ */
+ at Immutable
+public class MockSequencerContext extends SequencerContext {
+
+    public MockSequencerContext() {
+        super(new ExecutionContext(), null, null, null, new SimpleProblems());
+        getNamespaceRegistry().register("dnadtd", "http://www.jboss.org/dna/dtd/1.0");
+        getNamespaceRegistry().register("dnaxml", "http://www.jboss.org/dna/xml/1.0");
+    }
+}

Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerOutput.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerOutput.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerOutput.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,167 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.sequencers;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Map;
-import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Property;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at NotThreadSafe
-public class MockSequencerOutput implements SequencerOutput {
-
-    private final Map<Path, Map<Name, Property>> propertiesByPath;
-    private final SequencerContext context;
-    private final LinkedList<Path> nodePathsInCreationOrder;
-
-    public MockSequencerOutput( SequencerContext context ) {
-        this(context, false);
-    }
-
-    public MockSequencerOutput( SequencerContext context,
-                                boolean recordOrderOfNodeCreation ) {
-        this.context = context;
-        this.propertiesByPath = new HashMap<Path, Map<Name, Property>>();
-        this.nodePathsInCreationOrder = recordOrderOfNodeCreation ? new LinkedList<Path>() : null;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setProperty( Path nodePath,
-                             Name propertyName,
-                             Object... values ) {
-        Map<Name, Property> properties = propertiesByPath.get(nodePath);
-        if (values == null || values.length == 0) {
-            // remove the property ...
-            if (properties != null) {
-                properties.remove(propertyName);
-                if (properties.isEmpty()) {
-                    propertiesByPath.remove(nodePath);
-                    if (nodePathsInCreationOrder != null) nodePathsInCreationOrder.remove(nodePath);
-                }
-            }
-        } else {
-            if (properties == null) {
-                properties = new HashMap<Name, Property>();
-                propertiesByPath.put(nodePath, properties);
-                if (nodePathsInCreationOrder != null) nodePathsInCreationOrder.add(nodePath);
-            }
-            Property property = context.getPropertyFactory().create(propertyName, values);
-            properties.put(propertyName, property);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setProperty( String nodePath,
-                             String propertyName,
-                             Object... values ) {
-        Path path = context.getValueFactories().getPathFactory().create(nodePath);
-        Name name = context.getValueFactories().getNameFactory().create(propertyName);
-        setProperty(path, name, values);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setReference( String nodePath,
-                              String propertyName,
-                              String... paths ) {
-        PathFactory pathFactory = context.getValueFactories().getPathFactory();
-        Path path = pathFactory.create(nodePath);
-        Name name = context.getValueFactories().getNameFactory().create(propertyName);
-        Object[] values = null;
-        if (paths != null && paths.length != 0) {
-            values = new Path[paths.length];
-            for (int i = 0, len = paths.length; i != len; ++i) {
-                String pathValue = paths[i];
-                values[i] = pathFactory.create(pathValue);
-            }
-        }
-        setProperty(path, name, values);
-    }
-
-    public LinkedList<Path> getOrderOfCreation() {
-        return nodePathsInCreationOrder;
-    }
-
-    public boolean exists( Path nodePath ) {
-        return this.propertiesByPath.containsKey(nodePath);
-    }
-
-    public Map<Name, Property> getProperties( Path nodePath ) {
-        Map<Name, Property> properties = this.propertiesByPath.get(nodePath);
-        if (properties == null) return null;
-        return Collections.unmodifiableMap(properties);
-    }
-
-    public Property getProperty( String nodePath,
-                                 String propertyName ) {
-        Path path = context.getValueFactories().getPathFactory().create(nodePath);
-        Name name = context.getValueFactories().getNameFactory().create(propertyName);
-        return getProperty(path, name);
-    }
-
-    public Property getProperty( Path nodePath,
-                                 Name propertyName ) {
-        Map<Name, Property> properties = this.propertiesByPath.get(nodePath);
-        if (properties == null) return null;
-        return properties.get(propertyName);
-    }
-
-    public Object[] getPropertyValues( String nodePath,
-                                       String propertyName ) {
-        Path path = context.getValueFactories().getPathFactory().create(nodePath);
-        return getPropertyValues(path, propertyName);
-    }
-
-    public Object[] getPropertyValues( Path path,
-                                       String propertyName ) {
-        Name name = context.getValueFactories().getNameFactory().create(propertyName);
-        Property prop = getProperty(path, name);
-        if (prop != null) {
-            return prop.getValuesAsArray();
-        }
-        return null;
-    }
-
-    public boolean hasProperty( String nodePath,
-                                String property ) {
-        return getProperty(nodePath, property) != null;
-    }
-
-    public boolean hasProperties() {
-        return this.propertiesByPath.size() > 0;
-    }
-
-}

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerOutput.java (from rev 706, trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerOutput.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerOutput.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencer/MockSequencerOutput.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,169 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.sequencer;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at NotThreadSafe
+public class MockSequencerOutput implements SequencerOutput {
+
+    private final Map<Path, Map<Name, Property>> propertiesByPath;
+    private final SequencerContext context;
+    private final LinkedList<Path> nodePathsInCreationOrder;
+
+    public MockSequencerOutput( SequencerContext context ) {
+        this(context, false);
+    }
+
+    public MockSequencerOutput( SequencerContext context,
+                                boolean recordOrderOfNodeCreation ) {
+        this.context = context;
+        this.propertiesByPath = new HashMap<Path, Map<Name, Property>>();
+        this.nodePathsInCreationOrder = recordOrderOfNodeCreation ? new LinkedList<Path>() : null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setProperty( Path nodePath,
+                             Name propertyName,
+                             Object... values ) {
+        Map<Name, Property> properties = propertiesByPath.get(nodePath);
+        if (values == null || values.length == 0) {
+            // remove the property ...
+            if (properties != null) {
+                properties.remove(propertyName);
+                if (properties.isEmpty()) {
+                    propertiesByPath.remove(nodePath);
+                    if (nodePathsInCreationOrder != null) nodePathsInCreationOrder.remove(nodePath);
+                }
+            }
+        } else {
+            if (properties == null) {
+                properties = new HashMap<Name, Property>();
+                propertiesByPath.put(nodePath, properties);
+                if (nodePathsInCreationOrder != null) nodePathsInCreationOrder.add(nodePath);
+            }
+            Property property = context.getPropertyFactory().create(propertyName, values);
+            properties.put(propertyName, property);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setProperty( String nodePath,
+                             String propertyName,
+                             Object... values ) {
+        Path path = context.getValueFactories().getPathFactory().create(nodePath);
+        Name name = context.getValueFactories().getNameFactory().create(propertyName);
+        setProperty(path, name, values);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setReference( String nodePath,
+                              String propertyName,
+                              String... paths ) {
+        PathFactory pathFactory = context.getValueFactories().getPathFactory();
+        Path path = pathFactory.create(nodePath);
+        Name name = context.getValueFactories().getNameFactory().create(propertyName);
+        Object[] values = null;
+        if (paths != null && paths.length != 0) {
+            values = new Path[paths.length];
+            for (int i = 0, len = paths.length; i != len; ++i) {
+                String pathValue = paths[i];
+                values[i] = pathFactory.create(pathValue);
+            }
+        }
+        setProperty(path, name, values);
+    }
+
+    public LinkedList<Path> getOrderOfCreation() {
+        return nodePathsInCreationOrder;
+    }
+
+    public boolean exists( Path nodePath ) {
+        return this.propertiesByPath.containsKey(nodePath);
+    }
+
+    public Map<Name, Property> getProperties( Path nodePath ) {
+        Map<Name, Property> properties = this.propertiesByPath.get(nodePath);
+        if (properties == null) return null;
+        return Collections.unmodifiableMap(properties);
+    }
+
+    public Property getProperty( String nodePath,
+                                 String propertyName ) {
+        Path path = context.getValueFactories().getPathFactory().create(nodePath);
+        Name name = context.getValueFactories().getNameFactory().create(propertyName);
+        return getProperty(path, name);
+    }
+
+    public Property getProperty( Path nodePath,
+                                 Name propertyName ) {
+        Map<Name, Property> properties = this.propertiesByPath.get(nodePath);
+        if (properties == null) return null;
+        return properties.get(propertyName);
+    }
+
+    public Object[] getPropertyValues( String nodePath,
+                                       String propertyName ) {
+        Path path = context.getValueFactories().getPathFactory().create(nodePath);
+        return getPropertyValues(path, propertyName);
+    }
+
+    public Object[] getPropertyValues( Path path,
+                                       String propertyName ) {
+        Name name = context.getValueFactories().getNameFactory().create(propertyName);
+        Property prop = getProperty(path, name);
+        if (prop != null) {
+            return prop.getValuesAsArray();
+        }
+        return null;
+    }
+
+    public boolean hasProperty( String nodePath,
+                                String property ) {
+        return getProperty(nodePath, property) != null;
+    }
+
+    public boolean hasProperties() {
+        return this.propertiesByPath.size() > 0;
+    }
+
+}

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -38,12 +38,12 @@
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CreateNodeRequest;
 import org.junit.Before;
 import org.junit.Test;
 import org.xml.sax.InputSource;

Modified: trunk/dna-integration-tests/.classpath
===================================================================
--- trunk/dna-integration-tests/.classpath	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-integration-tests/.classpath	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,7 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="src" path="src/main/java"/>
-    <classpathentry kind="src" path="src/main/resources"/>
 	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
 	<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>

Copied: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit (from rev 705, trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit)

Deleted: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitBasicFunctionTest.java
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit/JackrabbitBasicFunctionTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitBasicFunctionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,214 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.tests.integration.jackrabbit;
-
-import static org.junit.Assert.assertNotNull;
-import java.io.FileInputStream;
-import java.util.ArrayList;
-import java.util.List;
-import javax.jcr.ImportUUIDBehavior;
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import org.apache.jackrabbit.core.TransientRepository;
-import org.jboss.dna.common.i18n.MockI18n;
-import org.jboss.dna.common.util.FileUtil;
-import org.jboss.dna.common.util.Logger;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class JackrabbitBasicFunctionTest {
-
-    public static final String TESTATA_PATH = "./src/test/resources/";
-    public static final String JACKRABBIT_DATA_PATH = "./target/testdata/jackrabbittest/";
-    public static final String REPOSITORY_DIRECTORY_PATH = JACKRABBIT_DATA_PATH + "repository";
-    public static final String REPOSITORY_CONFIG_PATH = TESTATA_PATH + "jackrabbitDerbyTestRepositoryConfig.xml";
-    public static final String DERBY_SYSTEM_HOME = JACKRABBIT_DATA_PATH + "/derby";
-
-    private Logger logger;
-    private Repository repository;
-
-    @Before
-    public void beforeEach() throws Exception {
-        // Clean up the test data ...
-        FileUtil.delete(JACKRABBIT_DATA_PATH);
-
-        // Set up Derby and the logger ...
-        System.setProperty("derby.system.home", DERBY_SYSTEM_HOME);
-        logger = Logger.getLogger(JackrabbitBasicFunctionTest.class);
-
-        // Set up the transient repository ...
-        this.repository = new TransientRepository(REPOSITORY_CONFIG_PATH, REPOSITORY_DIRECTORY_PATH);
-    }
-
-    @After
-    public void afterEach() {
-        // Clean up the test data ...
-        FileUtil.delete(JACKRABBIT_DATA_PATH);
-    }
-
-    @Test
-    public void shouldConnectWithAnonymous() throws Exception {
-        Session session = null;
-        try {
-            session = this.repository.login();
-            assertNotNull(session);
-            String username = session.getUserID();
-            String name = repository.getDescriptor(Repository.REP_NAME_DESC);
-            logger.info(MockI18n.passthrough, "Logged in as " + username + " to a " + name + " repository");
-        } finally {
-            if (session != null) session.logout();
-        }
-    }
-
-    @Test
-    public void shouldConnectWithSimpleCredentials() throws Exception {
-        Session session = null;
-        try {
-            SimpleCredentials creds = new SimpleCredentials("jsmith", "password".toCharArray());
-            session = this.repository.login(creds);
-            assertNotNull(session);
-            String username = session.getUserID();
-            String name = repository.getDescriptor(Repository.REP_NAME_DESC);
-            logger.info(MockI18n.passthrough, "Logged in as " + username + " to a " + name + " repository");
-        } finally {
-            if (session != null) session.logout();
-        }
-    }
-
-    @Test
-    public void shouldSupportConcurrentSessionsForDifferentUsers() throws Exception {
-        List<Session> sessions = new ArrayList<Session>();
-        try {
-            for (int i = 0; i != 10; ++i) {
-                SimpleCredentials creds = new SimpleCredentials("user" + i, ("secret" + i).toCharArray());
-                Session session = this.repository.login(creds);
-                assertNotNull(session);
-                sessions.add(session);
-                logger.info(MockI18n.passthrough, "Logged in as " + session.getUserID());
-            }
-        } finally {
-            while (!sessions.isEmpty()) {
-                sessions.remove(0).logout();
-            }
-        }
-    }
-
-    @Test( expected = javax.jcr.AccessDeniedException.class )
-    public void shouldNotAllowAnonymousUserToCreateContent() throws Exception {
-        Session session = null;
-        try {
-            session = this.repository.login();
-            assertNotNull(session);
-            Node root = session.getRootNode();
-
-            // Store content
-            Node hello = root.addNode("hello");
-            Node world = hello.addNode("world");
-            world.setProperty("message", "Hello, World!");
-            session.save(); // Should fail
-        } finally {
-            if (session != null) session.logout();
-        }
-    }
-
-    @Test
-    public void shouldAllowAuthenticatedUserToCreateAndManipulateContent() throws Exception {
-        SimpleCredentials creds = new SimpleCredentials("user", "secret".toCharArray());
-        Session session = null;
-        try {
-            session = this.repository.login(creds);
-            assertNotNull(session);
-            Node root = session.getRootNode();
-
-            // Store content
-            Node hello = root.addNode("hello");
-            Node world = hello.addNode("world");
-            world.setProperty("message", "Hello, World!");
-            session.save();
-
-            // Retrieve content ...
-            Node node = root.getNode("hello/world");
-            this.logger.info(MockI18n.passthrough, "Node 'hello/world' has path: " + node.getPath());
-            this.logger.info(MockI18n.passthrough, "Node 'hello/world' has 'message' property: "
-                                                   + node.getProperty("message").getString());
-        } finally {
-            if (session != null) session.logout();
-        }
-
-        try {
-            session = this.repository.login(creds);
-            assertNotNull(session);
-            Node root = session.getRootNode();
-
-            // Retrieve content
-            Node node = root.getNode("hello/world");
-            this.logger.info(MockI18n.passthrough, "Node 'hello/world' has path: " + node.getPath());
-            this.logger.info(MockI18n.passthrough, "Node 'hello/world' has 'message' property: "
-                                                   + node.getProperty("message").getString());
-
-            // Remove content
-            this.logger.info(MockI18n.passthrough, "Node 'hello' is being removed");
-            root.getNode("hello").remove();
-            session.save();
-        } finally {
-            if (session != null) session.logout();
-        }
-    }
-
-    @Test
-    public void shouldImportFile() throws Exception {
-        SimpleCredentials creds = new SimpleCredentials("user", "secret".toCharArray());
-        Session session = null;
-        try {
-            session = this.repository.login(creds);
-            assertNotNull(session);
-
-            // Use the root node as a starting point
-            Node root = session.getRootNode();
-
-            // Import the XML file unless already imported
-            if (!root.hasNode("importxml")) {
-                System.out.print("Importing xml... ");
-                // Create an unstructured node under which to import the XML
-                Node node = root.addNode("importxml", "nt:unstructured");
-                // Import the file "test.xml" under the created node
-                FileInputStream xml = new FileInputStream(TESTATA_PATH + "jcr-import-test.xml");
-                try {
-                    session.importXML(node.getPath(), xml, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
-                } finally {
-                    xml.close();
-                }
-                // Save the changes to the repository
-                session.save();
-                System.out.println("done.");
-            }
-
-            JackrabbitTestUtil.dumpNode(root, System.out, true);
-        } finally {
-            if (session != null) session.logout();
-        }
-    }
-
-}

Copied: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitBasicFunctionTest.java (from rev 706, trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit/JackrabbitBasicFunctionTest.java)
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitBasicFunctionTest.java	                        (rev 0)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitBasicFunctionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,214 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.test.integration.jackrabbit;
+
+import static org.junit.Assert.assertNotNull;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.List;
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import org.apache.jackrabbit.core.TransientRepository;
+import org.jboss.dna.common.i18n.MockI18n;
+import org.jboss.dna.common.util.FileUtil;
+import org.jboss.dna.common.util.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JackrabbitBasicFunctionTest {
+
+    public static final String TESTATA_PATH = "./src/test/resources/";
+    public static final String JACKRABBIT_DATA_PATH = "./target/testdata/jackrabbittest/";
+    public static final String REPOSITORY_DIRECTORY_PATH = JACKRABBIT_DATA_PATH + "repository";
+    public static final String REPOSITORY_CONFIG_PATH = TESTATA_PATH + "jackrabbitDerbyTestRepositoryConfig.xml";
+    public static final String DERBY_SYSTEM_HOME = JACKRABBIT_DATA_PATH + "/derby";
+
+    private Logger logger;
+    private Repository repository;
+
+    @Before
+    public void beforeEach() throws Exception {
+        // Clean up the test data ...
+        FileUtil.delete(JACKRABBIT_DATA_PATH);
+
+        // Set up Derby and the logger ...
+        System.setProperty("derby.system.home", DERBY_SYSTEM_HOME);
+        logger = Logger.getLogger(JackrabbitBasicFunctionTest.class);
+
+        // Set up the transient repository ...
+        this.repository = new TransientRepository(REPOSITORY_CONFIG_PATH, REPOSITORY_DIRECTORY_PATH);
+    }
+
+    @After
+    public void afterEach() {
+        // Clean up the test data ...
+        FileUtil.delete(JACKRABBIT_DATA_PATH);
+    }
+
+    @Test
+    public void shouldConnectWithAnonymous() throws Exception {
+        Session session = null;
+        try {
+            session = this.repository.login();
+            assertNotNull(session);
+            String username = session.getUserID();
+            String name = repository.getDescriptor(Repository.REP_NAME_DESC);
+            logger.info(MockI18n.passthrough, "Logged in as " + username + " to a " + name + " repository");
+        } finally {
+            if (session != null) session.logout();
+        }
+    }
+
+    @Test
+    public void shouldConnectWithSimpleCredentials() throws Exception {
+        Session session = null;
+        try {
+            SimpleCredentials creds = new SimpleCredentials("jsmith", "password".toCharArray());
+            session = this.repository.login(creds);
+            assertNotNull(session);
+            String username = session.getUserID();
+            String name = repository.getDescriptor(Repository.REP_NAME_DESC);
+            logger.info(MockI18n.passthrough, "Logged in as " + username + " to a " + name + " repository");
+        } finally {
+            if (session != null) session.logout();
+        }
+    }
+
+    @Test
+    public void shouldSupportConcurrentSessionsForDifferentUsers() throws Exception {
+        List<Session> sessions = new ArrayList<Session>();
+        try {
+            for (int i = 0; i != 10; ++i) {
+                SimpleCredentials creds = new SimpleCredentials("user" + i, ("secret" + i).toCharArray());
+                Session session = this.repository.login(creds);
+                assertNotNull(session);
+                sessions.add(session);
+                logger.info(MockI18n.passthrough, "Logged in as " + session.getUserID());
+            }
+        } finally {
+            while (!sessions.isEmpty()) {
+                sessions.remove(0).logout();
+            }
+        }
+    }
+
+    @Test( expected = javax.jcr.AccessDeniedException.class )
+    public void shouldNotAllowAnonymousUserToCreateContent() throws Exception {
+        Session session = null;
+        try {
+            session = this.repository.login();
+            assertNotNull(session);
+            Node root = session.getRootNode();
+
+            // Store content
+            Node hello = root.addNode("hello");
+            Node world = hello.addNode("world");
+            world.setProperty("message", "Hello, World!");
+            session.save(); // Should fail
+        } finally {
+            if (session != null) session.logout();
+        }
+    }
+
+    @Test
+    public void shouldAllowAuthenticatedUserToCreateAndManipulateContent() throws Exception {
+        SimpleCredentials creds = new SimpleCredentials("user", "secret".toCharArray());
+        Session session = null;
+        try {
+            session = this.repository.login(creds);
+            assertNotNull(session);
+            Node root = session.getRootNode();
+
+            // Store content
+            Node hello = root.addNode("hello");
+            Node world = hello.addNode("world");
+            world.setProperty("message", "Hello, World!");
+            session.save();
+
+            // Retrieve content ...
+            Node node = root.getNode("hello/world");
+            this.logger.info(MockI18n.passthrough, "Node 'hello/world' has path: " + node.getPath());
+            this.logger.info(MockI18n.passthrough, "Node 'hello/world' has 'message' property: "
+                                                   + node.getProperty("message").getString());
+        } finally {
+            if (session != null) session.logout();
+        }
+
+        try {
+            session = this.repository.login(creds);
+            assertNotNull(session);
+            Node root = session.getRootNode();
+
+            // Retrieve content
+            Node node = root.getNode("hello/world");
+            this.logger.info(MockI18n.passthrough, "Node 'hello/world' has path: " + node.getPath());
+            this.logger.info(MockI18n.passthrough, "Node 'hello/world' has 'message' property: "
+                                                   + node.getProperty("message").getString());
+
+            // Remove content
+            this.logger.info(MockI18n.passthrough, "Node 'hello' is being removed");
+            root.getNode("hello").remove();
+            session.save();
+        } finally {
+            if (session != null) session.logout();
+        }
+    }
+
+    @Test
+    public void shouldImportFile() throws Exception {
+        SimpleCredentials creds = new SimpleCredentials("user", "secret".toCharArray());
+        Session session = null;
+        try {
+            session = this.repository.login(creds);
+            assertNotNull(session);
+
+            // Use the root node as a starting point
+            Node root = session.getRootNode();
+
+            // Import the XML file unless already imported
+            if (!root.hasNode("importxml")) {
+                System.out.print("Importing xml... ");
+                // Create an unstructured node under which to import the XML
+                Node node = root.addNode("importxml", "nt:unstructured");
+                // Import the file "test.xml" under the created node
+                FileInputStream xml = new FileInputStream(TESTATA_PATH + "jcr-import-test.xml");
+                try {
+                    session.importXML(node.getPath(), xml, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
+                } finally {
+                    xml.close();
+                }
+                // Save the changes to the repository
+                session.save();
+                System.out.println("done.");
+            }
+
+            JackrabbitTestUtil.dumpNode(root, System.out, true);
+        } finally {
+            if (session != null) session.logout();
+        }
+    }
+
+}

Deleted: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitDerbyStressTest.java
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit/JackrabbitDerbyStressTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitDerbyStressTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,230 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.tests.integration.jackrabbit;
-
-import static org.junit.Assert.assertNotNull;
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import org.apache.jackrabbit.core.TransientRepository;
-import org.jboss.dna.common.i18n.MockI18n;
-import org.jboss.dna.common.stats.HistogramTest;
-import org.jboss.dna.common.stats.Stopwatch;
-import org.jboss.dna.common.util.FileUtil;
-import org.jboss.dna.common.util.Logger;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * These tests are designed to stress Jackrabbit in a variety of ways. Each test are independent of each other, and therefore each
- * test sets up a brand-new repository.
- */
-public class JackrabbitDerbyStressTest {
-
-    public static final String TESTATA_PATH = "./src/test/resources/";
-    public static final String JACKRABBIT_DATA_PATH = "./target/testdata/jackrabbittest/";
-    public static final String REPOSITORY_DIRECTORY_PATH = JACKRABBIT_DATA_PATH + "repository";
-    public static final String REPOSITORY_CONFIG_PATH = TESTATA_PATH + "jackrabbitDerbyTestRepositoryConfig.xml";
-    public static final String DERBY_SYSTEM_HOME = JACKRABBIT_DATA_PATH + "/derby";
-    public static final String USERNAME = "jsmith";
-    public static final char[] PASSWORD = "secret".toCharArray();
-
-    private Logger logger;
-    private Repository repository;
-    private Session session;
-    private Stopwatch stopwatch = new Stopwatch();
-
-    @Before
-    public void beforeEach() throws Exception {
-        // Clean up the test data ...
-        FileUtil.delete(JACKRABBIT_DATA_PATH);
-
-        // Set up Derby and the logger ...
-        System.setProperty("derby.system.home", DERBY_SYSTEM_HOME);
-        logger = Logger.getLogger(JackrabbitDerbyStressTest.class);
-
-        // Set up the transient repository ...
-        logger.info(MockI18n.passthrough, "Creating test repository for stress test and logging in with user " + USERNAME);
-        this.repository = new TransientRepository(REPOSITORY_CONFIG_PATH, REPOSITORY_DIRECTORY_PATH);
-
-        SimpleCredentials creds = new SimpleCredentials(USERNAME, PASSWORD);
-        session = this.repository.login(creds);
-        assertNotNull(session);
-    }
-
-    @After
-    public void afterEach() {
-        try {
-            if (session != null) session.logout();
-        } finally {
-            session = null;
-            // No matter what, clean up the test data ...
-            FileUtil.delete(JACKRABBIT_DATA_PATH);
-        }
-    }
-
-    @Test
-    public void shouldCreate100NodesWithNoChildrenAndNoProperties() throws Exception {
-        Node rootNode = this.session.getRootNode();
-        rootNode.addNode("node"); // don't measure the first one
-        for (int i = 0; i != 100; ++i) {
-            stopwatch.start();
-            rootNode.addNode("node" + i);
-            stopwatch.stop();
-        }
-        rootNode.save();
-        HistogramTest.writeHistogramToLog(logger,
-                                          stopwatch.getHistogram(3).setBucketCount(50),
-                                          80,
-                                          "create 100 nodes with no children and no properties");
-        this.logger.info(MockI18n.passthrough, stopwatch.toString());
-    }
-
-    @Test
-    public void shouldCreate1000NodesWithNoChildrenAndNoProperties() throws Exception {
-        Node rootNode = this.session.getRootNode();
-        rootNode.addNode("node"); // don't measure the first one
-        for (int i = 0; i != 1000; ++i) {
-            stopwatch.start();
-            rootNode.addNode("node" + i);
-            stopwatch.stop();
-        }
-        rootNode.save();
-        HistogramTest.writeHistogramToLog(logger,
-                                          stopwatch.getHistogram(1).setBucketCount(50),
-                                          80,
-                                          "create 1000 nodes with no children and no properties");
-        this.logger.info(MockI18n.passthrough, stopwatch.toString());
-    }
-
-    @Test
-    public void shouldCreate5000NodesWithNoChildrenAndNoProperties() throws Exception {
-        Node rootNode = this.session.getRootNode();
-        rootNode.addNode("node"); // don't measure the first one
-        for (int i = 0; i != 5000; ++i) {
-            stopwatch.start();
-            rootNode.addNode("node" + i);
-            stopwatch.stop();
-        }
-        rootNode.save();
-        HistogramTest.writeHistogramToLog(logger,
-                                          stopwatch.getHistogram(1).setBucketCount(50),
-                                          80,
-                                          "create 5000 nodes with no children and no properties");
-        this.logger.info(MockI18n.passthrough, stopwatch.toString());
-    }
-
-    @Test
-    public void shouldCreate10000NodesWithNoChildrenAndNoProperties() throws Exception {
-        Node rootNode = this.session.getRootNode();
-        rootNode.addNode("node"); // don't measure the first one
-        for (int i = 0; i != 10000; ++i) {
-            stopwatch.start();
-            rootNode.addNode("node" + i);
-            stopwatch.stop();
-        }
-        rootNode.save();
-        HistogramTest.writeHistogramToLog(logger,
-                                          stopwatch.getHistogram(1).setBucketCount(50),
-                                          80,
-                                          "create 10000 nodes with no children and no properties");
-        this.logger.info(MockI18n.passthrough, stopwatch.toString());
-    }
-
-    @Test
-    public void shouldCreate100NodesWithNoChildrenAndSeveralProperties() throws Exception {
-        Node rootNode = this.session.getRootNode();
-        rootNode.addNode("node"); // don't measure the first one
-        for (int i = 0; i != 100; ++i) {
-            stopwatch.start();
-            Node child = rootNode.addNode("node" + i);
-            child.setProperty("jcr:name", "This is the name of node " + i);
-            child.setProperty("jcr:description", "This is the description of node " + i);
-            stopwatch.stop();
-        }
-        rootNode.save();
-        HistogramTest.writeHistogramToLog(logger,
-                                          stopwatch.getHistogram(3).setBucketCount(50),
-                                          80,
-                                          "create 100 nodes with no children and several properties");
-        this.logger.info(MockI18n.passthrough, stopwatch.toString());
-    }
-    //	
-    // @Test
-    // public void shouldCreate10000NodesWithNoChildrenAndSeveralProperties() throws Exception {
-    // Node rootNode = this.session.getRootNode();
-    // rootNode.addNode("node"); // don't measure the first one
-    // for(int i=0; i!=10000; ++i ) {
-    // stopwatch.start();
-    // Node child = rootNode.addNode("node" + i);
-    // child.setProperty("jcr:name", "This is the name of node " + i );
-    // child.setProperty("jcr:description", "This is the description of node " + i );
-    // stopwatch.stop();
-    // }
-    // rootNode.save();
-    // HistogramTest.writeHistogramToLog(logger, stopwatch.getHistogram(3).setBucketCount(50), 80, "create 10000 nodes with no
-    // children and several properties");
-    // this.logger.info( stopwatch.toString() );
-    // }
-    //	
-    // // @Test
-    // // public void shouldCreate50000NodesWithNoChildrenAndSeveralProperties() throws Exception {
-    // // Node rootNode = this.session.getRootNode();
-    // // rootNode.addNode("node"); // don't measure the first one
-    // // for(int i=0; i!=50000; ++i ) {
-    // // stopwatch.start();
-    // // Node child = rootNode.addNode("node" + i);
-    // // child.setProperty("jcr:name", "This is the name of node " + i );
-    // // child.setProperty("jcr:description", "This is the description of node " + i );
-    // // stopwatch.stop();
-    // // }
-    // // rootNode.save();
-    // // HistogramTest.writeHistogramToLog(logger, stopwatch.getHistogram(3).setBucketCount(50), 80, "create 50000 nodes with no
-    // children and several properties");
-    // // this.logger.info( stopwatch.toString() );
-    // // }
-    //	
-    // @Test
-    // public void shouldCreate100000NodesWithNoChildrenAndSeveralProperties() throws Exception {
-    // Node rootNode = this.session.getRootNode();
-    // rootNode.addNode("node"); // don't measure the first one
-    // int index = 0;
-    // stopwatch.start();
-    // for(int j=0; j!=100; ++j ) {
-    // for(int i=0; i!=1000; ++i ) {
-    // ++index;
-    // // stopwatch.start();
-    // Node child = rootNode.addNode("node" + index);
-    // child.setProperty("jcr:name", "This is the name of node " + index );
-    // child.setProperty("jcr:description", "This is the description of node " + index );
-    // // stopwatch.stop();
-    // }
-    // rootNode.save();
-    // }
-    // stopwatch.stop();
-    // HistogramTest.writeHistogramToLog(logger, stopwatch.getHistogram(3).setBucketCount(50), 80, "create 100000 nodes (in 100
-    // batches) with no children and several properties");
-    // this.logger.info( stopwatch.toString() );
-    // }
-}

Copied: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitDerbyStressTest.java (from rev 706, trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit/JackrabbitDerbyStressTest.java)
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitDerbyStressTest.java	                        (rev 0)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitDerbyStressTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,230 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.test.integration.jackrabbit;
+
+import static org.junit.Assert.assertNotNull;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import org.apache.jackrabbit.core.TransientRepository;
+import org.jboss.dna.common.i18n.MockI18n;
+import org.jboss.dna.common.statistic.HistogramTest;
+import org.jboss.dna.common.statistic.Stopwatch;
+import org.jboss.dna.common.util.FileUtil;
+import org.jboss.dna.common.util.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * These tests are designed to stress Jackrabbit in a variety of ways. Each test are independent of each other, and therefore each
+ * test sets up a brand-new repository.
+ */
+public class JackrabbitDerbyStressTest {
+
+    public static final String TESTATA_PATH = "./src/test/resources/";
+    public static final String JACKRABBIT_DATA_PATH = "./target/testdata/jackrabbittest/";
+    public static final String REPOSITORY_DIRECTORY_PATH = JACKRABBIT_DATA_PATH + "repository";
+    public static final String REPOSITORY_CONFIG_PATH = TESTATA_PATH + "jackrabbitDerbyTestRepositoryConfig.xml";
+    public static final String DERBY_SYSTEM_HOME = JACKRABBIT_DATA_PATH + "/derby";
+    public static final String USERNAME = "jsmith";
+    public static final char[] PASSWORD = "secret".toCharArray();
+
+    private Logger logger;
+    private Repository repository;
+    private Session session;
+    private Stopwatch stopwatch = new Stopwatch();
+
+    @Before
+    public void beforeEach() throws Exception {
+        // Clean up the test data ...
+        FileUtil.delete(JACKRABBIT_DATA_PATH);
+
+        // Set up Derby and the logger ...
+        System.setProperty("derby.system.home", DERBY_SYSTEM_HOME);
+        logger = Logger.getLogger(JackrabbitDerbyStressTest.class);
+
+        // Set up the transient repository ...
+        logger.info(MockI18n.passthrough, "Creating test repository for stress test and logging in with user " + USERNAME);
+        this.repository = new TransientRepository(REPOSITORY_CONFIG_PATH, REPOSITORY_DIRECTORY_PATH);
+
+        SimpleCredentials creds = new SimpleCredentials(USERNAME, PASSWORD);
+        session = this.repository.login(creds);
+        assertNotNull(session);
+    }
+
+    @After
+    public void afterEach() {
+        try {
+            if (session != null) session.logout();
+        } finally {
+            session = null;
+            // No matter what, clean up the test data ...
+            FileUtil.delete(JACKRABBIT_DATA_PATH);
+        }
+    }
+
+    @Test
+    public void shouldCreate100NodesWithNoChildrenAndNoProperties() throws Exception {
+        Node rootNode = this.session.getRootNode();
+        rootNode.addNode("node"); // don't measure the first one
+        for (int i = 0; i != 100; ++i) {
+            stopwatch.start();
+            rootNode.addNode("node" + i);
+            stopwatch.stop();
+        }
+        rootNode.save();
+        HistogramTest.writeHistogramToLog(logger,
+                                          stopwatch.getHistogram(3).setBucketCount(50),
+                                          80,
+                                          "create 100 nodes with no children and no properties");
+        this.logger.info(MockI18n.passthrough, stopwatch.toString());
+    }
+
+    @Test
+    public void shouldCreate1000NodesWithNoChildrenAndNoProperties() throws Exception {
+        Node rootNode = this.session.getRootNode();
+        rootNode.addNode("node"); // don't measure the first one
+        for (int i = 0; i != 1000; ++i) {
+            stopwatch.start();
+            rootNode.addNode("node" + i);
+            stopwatch.stop();
+        }
+        rootNode.save();
+        HistogramTest.writeHistogramToLog(logger,
+                                          stopwatch.getHistogram(1).setBucketCount(50),
+                                          80,
+                                          "create 1000 nodes with no children and no properties");
+        this.logger.info(MockI18n.passthrough, stopwatch.toString());
+    }
+
+    @Test
+    public void shouldCreate5000NodesWithNoChildrenAndNoProperties() throws Exception {
+        Node rootNode = this.session.getRootNode();
+        rootNode.addNode("node"); // don't measure the first one
+        for (int i = 0; i != 5000; ++i) {
+            stopwatch.start();
+            rootNode.addNode("node" + i);
+            stopwatch.stop();
+        }
+        rootNode.save();
+        HistogramTest.writeHistogramToLog(logger,
+                                          stopwatch.getHistogram(1).setBucketCount(50),
+                                          80,
+                                          "create 5000 nodes with no children and no properties");
+        this.logger.info(MockI18n.passthrough, stopwatch.toString());
+    }
+
+    @Test
+    public void shouldCreate10000NodesWithNoChildrenAndNoProperties() throws Exception {
+        Node rootNode = this.session.getRootNode();
+        rootNode.addNode("node"); // don't measure the first one
+        for (int i = 0; i != 10000; ++i) {
+            stopwatch.start();
+            rootNode.addNode("node" + i);
+            stopwatch.stop();
+        }
+        rootNode.save();
+        HistogramTest.writeHistogramToLog(logger,
+                                          stopwatch.getHistogram(1).setBucketCount(50),
+                                          80,
+                                          "create 10000 nodes with no children and no properties");
+        this.logger.info(MockI18n.passthrough, stopwatch.toString());
+    }
+
+    @Test
+    public void shouldCreate100NodesWithNoChildrenAndSeveralProperties() throws Exception {
+        Node rootNode = this.session.getRootNode();
+        rootNode.addNode("node"); // don't measure the first one
+        for (int i = 0; i != 100; ++i) {
+            stopwatch.start();
+            Node child = rootNode.addNode("node" + i);
+            child.setProperty("jcr:name", "This is the name of node " + i);
+            child.setProperty("jcr:description", "This is the description of node " + i);
+            stopwatch.stop();
+        }
+        rootNode.save();
+        HistogramTest.writeHistogramToLog(logger,
+                                          stopwatch.getHistogram(3).setBucketCount(50),
+                                          80,
+                                          "create 100 nodes with no children and several properties");
+        this.logger.info(MockI18n.passthrough, stopwatch.toString());
+    }
+    //	
+    // @Test
+    // public void shouldCreate10000NodesWithNoChildrenAndSeveralProperties() throws Exception {
+    // Node rootNode = this.session.getRootNode();
+    // rootNode.addNode("node"); // don't measure the first one
+    // for(int i=0; i!=10000; ++i ) {
+    // stopwatch.start();
+    // Node child = rootNode.addNode("node" + i);
+    // child.setProperty("jcr:name", "This is the name of node " + i );
+    // child.setProperty("jcr:description", "This is the description of node " + i );
+    // stopwatch.stop();
+    // }
+    // rootNode.save();
+    // HistogramTest.writeHistogramToLog(logger, stopwatch.getHistogram(3).setBucketCount(50), 80, "create 10000 nodes with no
+    // children and several properties");
+    // this.logger.info( stopwatch.toString() );
+    // }
+    //	
+    // // @Test
+    // // public void shouldCreate50000NodesWithNoChildrenAndSeveralProperties() throws Exception {
+    // // Node rootNode = this.session.getRootNode();
+    // // rootNode.addNode("node"); // don't measure the first one
+    // // for(int i=0; i!=50000; ++i ) {
+    // // stopwatch.start();
+    // // Node child = rootNode.addNode("node" + i);
+    // // child.setProperty("jcr:name", "This is the name of node " + i );
+    // // child.setProperty("jcr:description", "This is the description of node " + i );
+    // // stopwatch.stop();
+    // // }
+    // // rootNode.save();
+    // // HistogramTest.writeHistogramToLog(logger, stopwatch.getHistogram(3).setBucketCount(50), 80, "create 50000 nodes with no
+    // children and several properties");
+    // // this.logger.info( stopwatch.toString() );
+    // // }
+    //	
+    // @Test
+    // public void shouldCreate100000NodesWithNoChildrenAndSeveralProperties() throws Exception {
+    // Node rootNode = this.session.getRootNode();
+    // rootNode.addNode("node"); // don't measure the first one
+    // int index = 0;
+    // stopwatch.start();
+    // for(int j=0; j!=100; ++j ) {
+    // for(int i=0; i!=1000; ++i ) {
+    // ++index;
+    // // stopwatch.start();
+    // Node child = rootNode.addNode("node" + index);
+    // child.setProperty("jcr:name", "This is the name of node " + index );
+    // child.setProperty("jcr:description", "This is the description of node " + index );
+    // // stopwatch.stop();
+    // }
+    // rootNode.save();
+    // }
+    // stopwatch.stop();
+    // HistogramTest.writeHistogramToLog(logger, stopwatch.getHistogram(3).setBucketCount(50), 80, "create 100000 nodes (in 100
+    // batches) with no children and several properties");
+    // this.logger.info( stopwatch.toString() );
+    // }
+}

Deleted: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitInMemoryTest.java
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit/JackrabbitInMemoryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitInMemoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,184 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.tests.integration.jackrabbit;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import org.apache.jackrabbit.core.TransientRepository;
-import org.jboss.dna.common.i18n.MockI18n;
-import org.jboss.dna.common.stats.HistogramTest;
-import org.jboss.dna.common.stats.Stopwatch;
-import org.jboss.dna.common.util.FileUtil;
-import org.jboss.dna.common.util.Logger;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * These tests are designed to stress Jackrabbit in a variety of ways, using the in-memory persistence manager. Each test are
- * independent of each other, and therefore each test sets up a brand-new repository.
- */
-public class JackrabbitInMemoryTest {
-
-    public static final String TESTATA_PATH = "./src/test/resources/";
-    public static final String JACKRABBIT_DATA_PATH = "./target/testdata/jackrabbittest/";
-    public static final String REPOSITORY_DIRECTORY_PATH = JACKRABBIT_DATA_PATH + "repository";
-    public static final String REPOSITORY_CONFIG_PATH = TESTATA_PATH + "jackrabbitInMemoryTestRepositoryConfig.xml";
-    public static final String USERNAME = "jsmith";
-    public static final char[] PASSWORD = "secret".toCharArray();
-
-    private Logger logger;
-    private Repository repository;
-    private Session session;
-    private Stopwatch nodeStopwatch = new Stopwatch();
-    private Stopwatch saveStopwatch = new Stopwatch();
-
-    @Before
-    public void beforeEach() throws Exception {
-        // Clean up the test data ...
-        FileUtil.delete(JACKRABBIT_DATA_PATH);
-
-        // Set up the logger ...
-        logger = Logger.getLogger(JackrabbitInMemoryTest.class);
-
-        // Set up the transient repository ...
-        logger.info(MockI18n.passthrough, "Creating test repository for stress test and logging in with user " + USERNAME);
-        this.repository = new TransientRepository(REPOSITORY_CONFIG_PATH, REPOSITORY_DIRECTORY_PATH);
-
-        SimpleCredentials creds = new SimpleCredentials(USERNAME, PASSWORD);
-        session = this.repository.login(creds);
-        assertNotNull(session);
-    }
-
-    @After
-    public void afterEach() {
-        try {
-            if (session != null) session.logout();
-        } finally {
-            session = null;
-            // No matter what, clean up the test data ...
-            FileUtil.delete(JACKRABBIT_DATA_PATH);
-        }
-    }
-
-    /**
-     * Create an evenly distributed tree of nodes, starting with the supplied parent.
-     * 
-     * @param parentNode the parent node of the tree; may not be null
-     * @param numberOfChildNodes the number of child nodes to create under the parent
-     * @param levelsToCreate the total number of levels in the tree to create
-     * @return the total number of child nodes created
-     * @throws Exception
-     */
-    public int createNodes( Node parentNode,
-                            int numberOfChildNodes,
-                            int levelsToCreate ) throws Exception {
-        int numberCreated = 0;
-        for (int i = 0; i < numberOfChildNodes; ++i) {
-            nodeStopwatch.start();
-            Node child = parentNode.addNode("node" + i);
-            child.setProperty("jcr:name", "This is the name of node " + i);
-            child.setProperty("jcr:description", "This is the description of node " + i);
-            nodeStopwatch.stop();
-            // this.logger.debug(" - " + child.getPath());
-            ++numberCreated;
-            if (levelsToCreate > 1) {
-                numberCreated += createNodes(child, numberOfChildNodes, levelsToCreate - 1);
-            }
-        }
-        return numberCreated;
-    }
-
-    @Test
-    public void shouldCreate10NodesWithNoChildrenAndNoProperties() throws Exception {
-        Node rootNode = this.session.getRootNode();
-        rootNode.addNode("node"); // don't measure the first one
-        for (int i = 0; i != 10; ++i) {
-            nodeStopwatch.start();
-            rootNode.addNode("node" + i);
-            nodeStopwatch.stop();
-        }
-        rootNode.save();
-        HistogramTest.writeHistogramToLog(logger,
-                                          nodeStopwatch.getHistogram(3).setBucketCount(50),
-                                          80,
-                                          "create 100 nodes with no children and no properties");
-        this.logger.info(MockI18n.passthrough, nodeStopwatch.toString());
-    }
-
-    @Test
-    public void shouldCreateTreeOfNodes2LevelsDeepWith10ChildrenAtEachNode() throws Exception {
-        Node rootNode = this.session.getRootNode();
-        Node parent = rootNode.addNode("node"); // don't measure the first one
-        int numNodes = this.createNodes(parent, 10, 2);
-        saveStopwatch.start();
-        rootNode.save();
-        saveStopwatch.stop();
-
-        HistogramTest.writeHistogramToLog(logger,
-                                          nodeStopwatch.getHistogram(3).setBucketCount(50),
-                                          80,
-                                          "create tree of " + numNodes + " nodes (2 deep, 10 children at every node)");
-        HistogramTest.writeHistogramToLog(logger, saveStopwatch.getHistogram(3).setBucketCount(50), 80, "1 save of 2x10 tree of "
-                                                                                                        + numNodes + " nodes");
-        this.logger.info(MockI18n.passthrough, "Node operation times: " + nodeStopwatch.toString());
-        this.logger.info(MockI18n.passthrough, "Save times: " + saveStopwatch.toString());
-    }
-
-    @Test
-    public void shouldExportSystemBranchToSystemView() throws Exception {
-        this.session.exportSystemView("/jcr:system", System.out, true, false);
-    }
-
-    @Test
-    public void shouldExportSystemBranchToDocumentView() throws Exception {
-        this.session.exportDocumentView("/jcr:system", System.out, true, false);
-    }
-
-    @Test
-    public void shouldNotHaveNamePropertyForNodes() throws Exception {
-        Node node = session.getRootNode().addNode("test");
-        assertThat(node, notNullValue());
-        assertThat(node.hasProperty("jcr:name"), is(false));
-    }
-
-    @Test
-    public void shouldNotHaveUuidPropertyForNonReferenceableNodes() throws Exception {
-        Node node = session.getRootNode().addNode("test");
-        assertThat(node, notNullValue());
-        assertThat(node.hasProperty("jcr:uuid"), is(false));
-    }
-
-    @Test
-    public void shouldHaveUuidPropertyForReferenceableNodes() throws Exception {
-        Node node = session.getRootNode().addNode("test");
-        node.addMixin("mix:referenceable");
-        assertThat(node, notNullValue());
-        assertThat(node.hasProperty("jcr:uuid"), is(true));
-    }
-}

Copied: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitInMemoryTest.java (from rev 706, trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit/JackrabbitInMemoryTest.java)
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitInMemoryTest.java	                        (rev 0)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitInMemoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,184 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.test.integration.jackrabbit;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import org.apache.jackrabbit.core.TransientRepository;
+import org.jboss.dna.common.i18n.MockI18n;
+import org.jboss.dna.common.statistic.HistogramTest;
+import org.jboss.dna.common.statistic.Stopwatch;
+import org.jboss.dna.common.util.FileUtil;
+import org.jboss.dna.common.util.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * These tests are designed to stress Jackrabbit in a variety of ways, using the in-memory persistence manager. Each test are
+ * independent of each other, and therefore each test sets up a brand-new repository.
+ */
+public class JackrabbitInMemoryTest {
+
+    public static final String TESTATA_PATH = "./src/test/resources/";
+    public static final String JACKRABBIT_DATA_PATH = "./target/testdata/jackrabbittest/";
+    public static final String REPOSITORY_DIRECTORY_PATH = JACKRABBIT_DATA_PATH + "repository";
+    public static final String REPOSITORY_CONFIG_PATH = TESTATA_PATH + "jackrabbitInMemoryTestRepositoryConfig.xml";
+    public static final String USERNAME = "jsmith";
+    public static final char[] PASSWORD = "secret".toCharArray();
+
+    private Logger logger;
+    private Repository repository;
+    private Session session;
+    private Stopwatch nodeStopwatch = new Stopwatch();
+    private Stopwatch saveStopwatch = new Stopwatch();
+
+    @Before
+    public void beforeEach() throws Exception {
+        // Clean up the test data ...
+        FileUtil.delete(JACKRABBIT_DATA_PATH);
+
+        // Set up the logger ...
+        logger = Logger.getLogger(JackrabbitInMemoryTest.class);
+
+        // Set up the transient repository ...
+        logger.info(MockI18n.passthrough, "Creating test repository for stress test and logging in with user " + USERNAME);
+        this.repository = new TransientRepository(REPOSITORY_CONFIG_PATH, REPOSITORY_DIRECTORY_PATH);
+
+        SimpleCredentials creds = new SimpleCredentials(USERNAME, PASSWORD);
+        session = this.repository.login(creds);
+        assertNotNull(session);
+    }
+
+    @After
+    public void afterEach() {
+        try {
+            if (session != null) session.logout();
+        } finally {
+            session = null;
+            // No matter what, clean up the test data ...
+            FileUtil.delete(JACKRABBIT_DATA_PATH);
+        }
+    }
+
+    /**
+     * Create an evenly distributed tree of nodes, starting with the supplied parent.
+     * 
+     * @param parentNode the parent node of the tree; may not be null
+     * @param numberOfChildNodes the number of child nodes to create under the parent
+     * @param levelsToCreate the total number of levels in the tree to create
+     * @return the total number of child nodes created
+     * @throws Exception
+     */
+    public int createNodes( Node parentNode,
+                            int numberOfChildNodes,
+                            int levelsToCreate ) throws Exception {
+        int numberCreated = 0;
+        for (int i = 0; i < numberOfChildNodes; ++i) {
+            nodeStopwatch.start();
+            Node child = parentNode.addNode("node" + i);
+            child.setProperty("jcr:name", "This is the name of node " + i);
+            child.setProperty("jcr:description", "This is the description of node " + i);
+            nodeStopwatch.stop();
+            // this.logger.debug(" - " + child.getPath());
+            ++numberCreated;
+            if (levelsToCreate > 1) {
+                numberCreated += createNodes(child, numberOfChildNodes, levelsToCreate - 1);
+            }
+        }
+        return numberCreated;
+    }
+
+    @Test
+    public void shouldCreate10NodesWithNoChildrenAndNoProperties() throws Exception {
+        Node rootNode = this.session.getRootNode();
+        rootNode.addNode("node"); // don't measure the first one
+        for (int i = 0; i != 10; ++i) {
+            nodeStopwatch.start();
+            rootNode.addNode("node" + i);
+            nodeStopwatch.stop();
+        }
+        rootNode.save();
+        HistogramTest.writeHistogramToLog(logger,
+                                          nodeStopwatch.getHistogram(3).setBucketCount(50),
+                                          80,
+                                          "create 100 nodes with no children and no properties");
+        this.logger.info(MockI18n.passthrough, nodeStopwatch.toString());
+    }
+
+    @Test
+    public void shouldCreateTreeOfNodes2LevelsDeepWith10ChildrenAtEachNode() throws Exception {
+        Node rootNode = this.session.getRootNode();
+        Node parent = rootNode.addNode("node"); // don't measure the first one
+        int numNodes = this.createNodes(parent, 10, 2);
+        saveStopwatch.start();
+        rootNode.save();
+        saveStopwatch.stop();
+
+        HistogramTest.writeHistogramToLog(logger,
+                                          nodeStopwatch.getHistogram(3).setBucketCount(50),
+                                          80,
+                                          "create tree of " + numNodes + " nodes (2 deep, 10 children at every node)");
+        HistogramTest.writeHistogramToLog(logger, saveStopwatch.getHistogram(3).setBucketCount(50), 80, "1 save of 2x10 tree of "
+                                                                                                        + numNodes + " nodes");
+        this.logger.info(MockI18n.passthrough, "Node operation times: " + nodeStopwatch.toString());
+        this.logger.info(MockI18n.passthrough, "Save times: " + saveStopwatch.toString());
+    }
+
+    @Test
+    public void shouldExportSystemBranchToSystemView() throws Exception {
+        this.session.exportSystemView("/jcr:system", System.out, true, false);
+    }
+
+    @Test
+    public void shouldExportSystemBranchToDocumentView() throws Exception {
+        this.session.exportDocumentView("/jcr:system", System.out, true, false);
+    }
+
+    @Test
+    public void shouldNotHaveNamePropertyForNodes() throws Exception {
+        Node node = session.getRootNode().addNode("test");
+        assertThat(node, notNullValue());
+        assertThat(node.hasProperty("jcr:name"), is(false));
+    }
+
+    @Test
+    public void shouldNotHaveUuidPropertyForNonReferenceableNodes() throws Exception {
+        Node node = session.getRootNode().addNode("test");
+        assertThat(node, notNullValue());
+        assertThat(node.hasProperty("jcr:uuid"), is(false));
+    }
+
+    @Test
+    public void shouldHaveUuidPropertyForReferenceableNodes() throws Exception {
+        Node node = session.getRootNode().addNode("test");
+        node.addMixin("mix:referenceable");
+        assertThat(node, notNullValue());
+        assertThat(node.hasProperty("jcr:uuid"), is(true));
+    }
+}

Deleted: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitTestUtil.java
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit/JackrabbitTestUtil.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitTestUtil.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,74 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.tests.integration.jackrabbit;
-
-import java.io.PrintStream;
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-
-public class JackrabbitTestUtil {
-
-    /**
-     * Recursively outputs the contents of the given node.
-     * @param node
-     * @param stream
-     * @param recursive
-     * @throws RepositoryException
-     */
-    public static void dumpNode( Node node, PrintStream stream, boolean recursive ) throws RepositoryException {
-        // First output the node path
-        System.out.println(node.getPath());
-        // Skip the virtual (and large!) jcr:system subtree
-        if (node.getName().equals("jcr:system")) {
-            return;
-        }
-
-        // Then output the properties
-        PropertyIterator properties = node.getProperties();
-        while (properties.hasNext()) {
-            Property property = properties.nextProperty();
-            if (property.getDefinition().isMultiple()) {
-                // A multi-valued property, print all values
-                Value[] values = property.getValues();
-                for (int i = 0; i < values.length; i++) {
-                    stream.println(property.getPath() + " = " + values[i].getString());
-                }
-            } else {
-                // A single-valued property
-                stream.println(property.getPath() + " = " + property.getString());
-            }
-        }
-
-        if (recursive) {
-            // Finally output all the child nodes recursively
-            NodeIterator nodes = node.getNodes();
-            while (nodes.hasNext()) {
-                dumpNode(nodes.nextNode(), stream, true);
-            }
-        }
-    }
-
-}

Copied: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitTestUtil.java (from rev 706, trunk/dna-integration-tests/src/test/java/org/jboss/dna/tests/integration/jackrabbit/JackrabbitTestUtil.java)
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitTestUtil.java	                        (rev 0)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/jackrabbit/JackrabbitTestUtil.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,74 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.test.integration.jackrabbit;
+
+import java.io.PrintStream;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
+public class JackrabbitTestUtil {
+
+    /**
+     * Recursively outputs the contents of the given node.
+     * @param node
+     * @param stream
+     * @param recursive
+     * @throws RepositoryException
+     */
+    public static void dumpNode( Node node, PrintStream stream, boolean recursive ) throws RepositoryException {
+        // First output the node path
+        System.out.println(node.getPath());
+        // Skip the virtual (and large!) jcr:system subtree
+        if (node.getName().equals("jcr:system")) {
+            return;
+        }
+
+        // Then output the properties
+        PropertyIterator properties = node.getProperties();
+        while (properties.hasNext()) {
+            Property property = properties.nextProperty();
+            if (property.getDefinition().isMultiple()) {
+                // A multi-valued property, print all values
+                Value[] values = property.getValues();
+                for (int i = 0; i < values.length; i++) {
+                    stream.println(property.getPath() + " = " + values[i].getString());
+                }
+            } else {
+                // A single-valued property
+                stream.println(property.getPath() + " = " + property.getString());
+            }
+        }
+
+        if (recursive) {
+            // Finally output all the child nodes recursively
+            NodeIterator nodes = node.getNodes();
+            while (nodes.hasNext()) {
+                dumpNode(nodes.nextNode(), stream, true);
+            }
+        }
+    }
+
+}

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -46,8 +46,8 @@
 import javax.jcr.version.VersionHistory;
 import net.jcip.annotations.NotThreadSafe;
 import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path.Segment;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path.Segment;
 
 /**
  * @author jverhaeg

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -37,9 +37,9 @@
 import net.jcip.annotations.NotThreadSafe;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.ValueFactories;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFactories;
 
 /**
  * @author jverhaeg

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -33,8 +33,8 @@
 import javax.jcr.nodetype.PropertyDefinition;
 import net.jcip.annotations.NotThreadSafe;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.ValueFactories;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.ValueFactories;
 
 /**
  * @author jverhaeg

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -34,9 +34,9 @@
  */
 final class JcrNamespaceRegistry implements NamespaceRegistry {
 
-    private org.jboss.dna.graph.properties.NamespaceRegistry dnaNamespaceRegistry;
+    private org.jboss.dna.graph.property.NamespaceRegistry dnaNamespaceRegistry;
 
-    JcrNamespaceRegistry( org.jboss.dna.graph.properties.NamespaceRegistry dnaNamespaceRegistry ) {
+    JcrNamespaceRegistry( org.jboss.dna.graph.property.NamespaceRegistry dnaNamespaceRegistry ) {
         this.dnaNamespaceRegistry = dnaNamespaceRegistry;
     }
 

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -26,7 +26,7 @@
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.graph.properties.Path.Segment;
+import org.jboss.dna.graph.property.Path.Segment;
 
 /**
  * @author jverhaeg

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeIterator.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeIterator.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeIterator.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,7 +28,7 @@
 import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
 import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.property.Name;
 
 /**
  * @author jverhaeg

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrProperty.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrProperty.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -29,8 +29,8 @@
 import javax.jcr.ValueFormatException;
 import javax.jcr.nodetype.PropertyDefinition;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.ValueFactories;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.ValueFactories;
 
 /**
  * @author jverhaeg

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -40,7 +40,7 @@
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.ExecutionContextFactory;
 import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import com.google.common.base.ReferenceType;
 import com.google.common.collect.ReferenceMap;
 

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -50,10 +50,10 @@
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.UuidFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.UuidFactory;
+import org.jboss.dna.graph.property.ValueFactories;
 import org.xml.sax.ContentHandler;
 import com.google.common.base.ReferenceType;
 import com.google.common.collect.ReferenceMap;
@@ -222,7 +222,7 @@
         if (path.getLastSegment().hasIndex()) {
             try {
                 return getNode(path);
-            } catch (org.jboss.dna.graph.properties.PathNotFoundException e) {
+            } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
                 // If the node isn't found, throw a PathNotFoundException
                 throw new PathNotFoundException(JcrI18n.pathNotFound.text(path));
             }
@@ -230,13 +230,13 @@
         // We can't tell from the name, so try a node first ...
         try {
             return getNode(path);
-        } catch (org.jboss.dna.graph.properties.PathNotFoundException e) {
+        } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
             // A node was not found, so treat look for a node using the parent as the node's path ...
             Path parentPath = path.getParent();
             Name propertyName = path.getLastSegment().getName();
             try {
                 return getNode(parentPath).getProperty(propertyName.getString(executionContext.getNamespaceRegistry()));
-            } catch (org.jboss.dna.graph.properties.PathNotFoundException e2) {
+            } catch (org.jboss.dna.graph.property.PathNotFoundException e2) {
                 // If the node isn't found, throw a PathNotFoundException
                 throw new PathNotFoundException(JcrI18n.pathNotFound.text(path));
             }
@@ -284,7 +284,7 @@
         // Get node from source
         org.jboss.dna.graph.Node graphNode = graph.getNodeAt(path);
         // First check if node already exists. We don't need to check for changes since that will be handled by an observer
-        org.jboss.dna.graph.properties.Property dnaUuidProp = graphNode.getPropertiesByName().get(JcrLexicon.UUID);
+        org.jboss.dna.graph.property.Property dnaUuidProp = graphNode.getPropertiesByName().get(JcrLexicon.UUID);
         if (dnaUuidProp == null) dnaUuidProp = graphNode.getPropertiesByName().get(DnaLexicon.UUID);
         if (dnaUuidProp != null) {
             UUID uuid = executionContext.getValueFactories().getUuidFactory().create(dnaUuidProp.getValues()).next();
@@ -510,16 +510,16 @@
         Name jcrUuidName = executionContext.getValueFactories().getNameFactory().create("jcr:uuid");
         Name jcrMixinTypesName = executionContext.getValueFactories().getNameFactory().create("jcr:mixinTypes");
         UuidFactory uuidFactory = executionContext.getValueFactories().getUuidFactory();
-        org.jboss.dna.graph.properties.Property dnaUuidProp = null;
+        org.jboss.dna.graph.property.Property dnaUuidProp = null;
         boolean referenceable = false;
-        for (org.jboss.dna.graph.properties.Property dnaProp : graphNode.getProperties()) {
+        for (org.jboss.dna.graph.property.Property dnaProp : graphNode.getProperties()) {
             Name name = dnaProp.getName();
             if (dnaProp.isMultiple()) properties.add(new JcrMultiValueProperty(node, executionContext, name, dnaProp));
             else {
                 if (uuid == null && DnaLexicon.UUID.equals(name)) uuid = uuidFactory.create(dnaProp.getValues()).next();
                 else if (jcrUuidName.equals(name)) dnaUuidProp = dnaProp;
                 else if (jcrMixinTypesName.equals(name)) {
-                    org.jboss.dna.graph.properties.ValueFactory<String> stringFactory = executionContext.getValueFactories().getStringFactory();
+                    org.jboss.dna.graph.property.ValueFactory<String> stringFactory = executionContext.getValueFactories().getStringFactory();
                     for (String mixin : stringFactory.create(dnaProp)) {
                         if ("mix:referenceable".equals(mixin)) referenceable = true;
                     }

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,7 +28,7 @@
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
 import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.graph.properties.ValueFactories;
+import org.jboss.dna.graph.property.ValueFactories;
 
 /**
  * @param <T> the type of value to create.

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -44,9 +44,9 @@
 import javax.jcr.Workspace;
 import javax.jcr.version.Version;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path.Segment;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path.Segment;
+import org.jboss.dna.graph.property.basic.BasicName;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -36,8 +36,8 @@
 import javax.jcr.nodetype.PropertyDefinition;
 import org.jboss.dna.common.util.StringUtil;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -36,8 +36,8 @@
 import javax.jcr.ValueFormatException;
 import javax.jcr.nodetype.PropertyDefinition;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeIteratorTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeIteratorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeIteratorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -30,8 +30,8 @@
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path.Segment;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path.Segment;
 import org.jboss.dna.jcr.AbstractJcrNodeTest.MockAbstractJcrNode;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -32,9 +32,9 @@
 import javax.jcr.Node;
 import javax.jcr.Property;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path.Segment;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path.Segment;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -35,8 +35,8 @@
 import javax.jcr.ValueFormatException;
 import javax.jcr.nodetype.PropertyDefinition;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -37,8 +37,8 @@
 import javax.security.auth.login.LoginException;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.ExecutionContextFactory;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -47,9 +47,9 @@
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.ExecutionContextFactory;
 import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.SimpleRepository;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.SimpleRepository;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrValueTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrValueTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrValueTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -30,9 +30,9 @@
 import java.util.UUID;
 import javax.jcr.PropertyType;
 import javax.jcr.ValueFormatException;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.basic.StandardValueFactories;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.basic.StandardValueFactories;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -27,7 +27,7 @@
 import javax.jcr.Session;
 import javax.jcr.Workspace;
 import org.jboss.dna.graph.ExecutionContextFactory;
-import org.jboss.dna.graph.connectors.SimpleRepository;
+import org.jboss.dna.graph.connector.SimpleRepository;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestUtil.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestUtil.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestUtil.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,11 +28,11 @@
 import net.jcip.annotations.NotThreadSafe;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.ExecutionContextFactory;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.SimpleRepository;
-import org.jboss.dna.graph.connectors.SimpleRepositorySource;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.SimpleRepository;
+import org.jboss.dna.graph.connector.SimpleRepositorySource;
+import org.jboss.dna.graph.property.NamespaceRegistry;
 import org.mockito.Mockito;
 
 /**

Added: trunk/dna-jcr/src/test/resources/log4j.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/log4j.properties	                        (rev 0)
+++ trunk/dna-jcr/src/test/resources/log4j.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,12 @@
+# 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 %m%n
+
+# Root logger option
+log4j.rootLogger=INFO, stdout
+
+# Set up the default logging to be INFO level, then override specific units
+log4j.logger.org.jboss.dna=INFO
+


Property changes on: trunk/dna-jcr/src/test/resources/log4j.properties
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryLibrary.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryLibrary.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryLibrary.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -35,14 +35,14 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.ExecutionContextFactory;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositoryConnectionPool;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositoryConnectionPool;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
 import org.jboss.dna.repository.mimetype.MimeTypeDetectors;
-import org.jboss.dna.repository.services.AbstractServiceAdministrator;
-import org.jboss.dna.repository.services.ServiceAdministrator;
+import org.jboss.dna.repository.service.AbstractServiceAdministrator;
+import org.jboss.dna.repository.service.ServiceAdministrator;
 
 /**
  * A library of {@link RepositorySource} instances and the {@link RepositoryConnectionPool} used to manage the connections for
@@ -152,7 +152,7 @@
             /**
              * {@inheritDoc}
              * 
-             * @see org.jboss.dna.graph.connectors.RepositoryContext#getExecutionContextFactory()
+             * @see org.jboss.dna.graph.connector.RepositoryContext#getExecutionContextFactory()
              */
             public ExecutionContextFactory getExecutionContextFactory() {
                 return RepositoryLibrary.this.getExecutionContextFactory();
@@ -161,7 +161,7 @@
             /**
              * {@inheritDoc}
              * 
-             * @see org.jboss.dna.graph.connectors.RepositoryContext#getRepositoryConnectionFactory()
+             * @see org.jboss.dna.graph.connector.RepositoryContext#getRepositoryConnectionFactory()
              */
             public RepositoryConnectionFactory getRepositoryConnectionFactory() {
                 return RepositoryLibrary.this;
@@ -441,7 +441,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnectionFactory#createConnection(java.lang.String)
+     * @see org.jboss.dna.graph.connector.RepositoryConnectionFactory#createConnection(java.lang.String)
      */
     public RepositoryConnection createConnection( String sourceName ) {
         try {

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -37,16 +37,16 @@
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.Node;
 import org.jboss.dna.graph.Subgraph;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.repository.services.AbstractServiceAdministrator;
-import org.jboss.dna.repository.services.AdministeredService;
-import org.jboss.dna.repository.services.ServiceAdministrator;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.repository.service.AbstractServiceAdministrator;
+import org.jboss.dna.repository.service.AdministeredService;
+import org.jboss.dna.repository.service.ServiceAdministrator;
 
 /**
  * @author Randall Hauch
@@ -85,7 +85,7 @@
         /**
          * {@inheritDoc}
          * 
-         * @see org.jboss.dna.repository.services.ServiceAdministrator#awaitTermination(long, java.util.concurrent.TimeUnit)
+         * @see org.jboss.dna.repository.service.ServiceAdministrator#awaitTermination(long, java.util.concurrent.TimeUnit)
          */
         public boolean awaitTermination( long timeout,
                                          TimeUnit unit ) {

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -44,9 +44,9 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.common.util.Logger;
 import org.jboss.dna.repository.RepositoryI18n;
-import org.jboss.dna.repository.services.AbstractServiceAdministrator;
-import org.jboss.dna.repository.services.AdministeredService;
-import org.jboss.dna.repository.services.ServiceAdministrator;
+import org.jboss.dna.repository.service.AbstractServiceAdministrator;
+import org.jboss.dna.repository.service.AdministeredService;
+import org.jboss.dna.repository.service.ServiceAdministrator;
 import org.jboss.dna.repository.util.SessionFactory;
 
 /**

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleService.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleService.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -55,9 +55,9 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.common.util.Logger;
 import org.jboss.dna.repository.RepositoryI18n;
-import org.jboss.dna.repository.services.AbstractServiceAdministrator;
-import org.jboss.dna.repository.services.AdministeredService;
-import org.jboss.dna.repository.services.ServiceAdministrator;
+import org.jboss.dna.repository.service.AbstractServiceAdministrator;
+import org.jboss.dna.repository.service.AdministeredService;
+import org.jboss.dna.repository.service.ServiceAdministrator;
 
 /**
  * A rule service that is capable of executing rule sets using one or more JSR-94 rule engines. Sets of rules are

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer (from rev 705, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers)

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/InvalidSequencerPathExpression.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/InvalidSequencerPathExpression.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/InvalidSequencerPathExpression.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,66 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-
-/**
- * 
- * @author Randall Hauch
- */
-public class InvalidSequencerPathExpression extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = -2814638971450551156L;
-
-    /**
-     * 
-     */
-    public InvalidSequencerPathExpression() {
-    }
-
-    /**
-     * @param message
-     */
-    public InvalidSequencerPathExpression( String message ) {
-        super(message);
-
-    }
-
-    /**
-     * @param cause
-     */
-    public InvalidSequencerPathExpression( Throwable cause ) {
-        super(cause);
-
-    }
-
-    /**
-     * @param message
-     * @param cause
-     */
-    public InvalidSequencerPathExpression( String message, Throwable cause ) {
-        super(message, cause);
-
-    }
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/InvalidSequencerPathExpression.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/InvalidSequencerPathExpression.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/InvalidSequencerPathExpression.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/InvalidSequencerPathExpression.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+
+/**
+ * 
+ * @author Randall Hauch
+ */
+public class InvalidSequencerPathExpression extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = -2814638971450551156L;
+
+    /**
+     * 
+     */
+    public InvalidSequencerPathExpression() {
+    }
+
+    /**
+     * @param message
+     */
+    public InvalidSequencerPathExpression( String message ) {
+        super(message);
+
+    }
+
+    /**
+     * @param cause
+     */
+    public InvalidSequencerPathExpression( Throwable cause ) {
+        super(cause);
+
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public InvalidSequencerPathExpression( String message, Throwable cause ) {
+        super(message, cause);
+
+    }
+
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/Sequencer.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/Sequencer.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/Sequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,90 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import java.util.Set;
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.collection.Problems;
-import org.jboss.dna.common.component.Component;
-import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.observation.NodeChangeListener;
-import org.jboss.dna.repository.observation.NodeChanges;
-import org.jboss.dna.repository.observation.ObservationService;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-import org.jboss.dna.repository.util.RepositoryNodePath;
-
-/**
- * The interface for a DNA sequencer, which sequences nodes and their content to extract additional information from the
- * information.
- * <p>
- * Implementations must provide a no-argument constructor.
- * </p>
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at ThreadSafe
-public interface Sequencer extends Component<SequencerConfig> {
-
-    /**
-     * Execute the sequencing operation on the supplied node, which has recently been created or changed. The implementation of
-     * this method is responsible for {@link JcrExecutionContext#getSessionFactory() getting sessions}, modifying the appropriate
-     * nodes, {@link Session#save() saving} any changes made by this sequencer, and {@link Session#logout() closing} all sessions
-     * (and any other acquired resources), even in the case of exceptions.
-     * <p>
-     * The {@link SequencingService} determines the sequencers that should be executed by monitoring the changes to one or more
-     * workspaces (it is a {@link NodeChangeListener} registered with the {@link ObservationService}). Changes in those workspaces
-     * are aggregated for each transaction, and organized into {@link NodeChanges changes for each node}. The SequencingService
-     * then determines for each {@link NodeChange set of changes to a node} the set of full paths to the properties that have
-     * changed and whether those paths {@link SequencerPathExpression#matcher(String) match} the sequencer's
-     * {@link SequencerConfig#getPathExpressions() path expressions}. Each path expression produces the path to the output node,
-     * and these output paths are accumulated and (with the original node that changed, the node change summary, and other
-     * information) supplied to the sequencer via this method.
-     * <p>
-     * It is possible that a sequencer is configured to apply to multiple properties on a node. So, in cases where multiple
-     * properties are changed on a single node (within a single repository transaction), the sequencer will only be executed once.
-     * Also, in such cases the sequencer's configuration may imply multiple output nodes, so it is left to the sequencer to define
-     * the behavior in such cases.
-     * </p>
-     * 
-     * @param input the node that has recently been created or changed; never null
-     * @param sequencedPropertyName the name of the property that caused this sequencer to be executed; never null and never empty
-     * @param changes the immutable summary of changes that occurred on the <code>input</code> node within the transaction; never
-     *        null
-     * @param outputPaths the paths to the nodes where the sequencing content should be placed; never null and never empty, but
-     *        the set may contain paths for non-existant nodes or may reference the <code>input</code> node
-     * @param context the context in which this sequencer is executing; never null
-     * @param problems the interface used for recording problems; never null
-     * @throws RepositoryException if there is a problem while working with the repository
-     * @throws SequencerException if there is an error in this sequencer
-     */
-    void execute( Node input,
-                  String sequencedPropertyName,
-                  NodeChange changes,
-                  Set<RepositoryNodePath> outputPaths,
-                  JcrExecutionContext context,
-                  Problems problems ) throws RepositoryException, SequencerException;
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/Sequencer.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/Sequencer.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/Sequencer.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/Sequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+import java.util.Set;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.common.component.Component;
+import org.jboss.dna.repository.observation.NodeChange;
+import org.jboss.dna.repository.observation.NodeChangeListener;
+import org.jboss.dna.repository.observation.NodeChanges;
+import org.jboss.dna.repository.observation.ObservationService;
+import org.jboss.dna.repository.util.JcrExecutionContext;
+import org.jboss.dna.repository.util.RepositoryNodePath;
+
+/**
+ * The interface for a DNA sequencer, which sequences nodes and their content to extract additional information from the
+ * information.
+ * <p>
+ * Implementations must provide a no-argument constructor.
+ * </p>
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at ThreadSafe
+public interface Sequencer extends Component<SequencerConfig> {
+
+    /**
+     * Execute the sequencing operation on the supplied node, which has recently been created or changed. The implementation of
+     * this method is responsible for {@link JcrExecutionContext#getSessionFactory() getting sessions}, modifying the appropriate
+     * nodes, {@link Session#save() saving} any changes made by this sequencer, and {@link Session#logout() closing} all sessions
+     * (and any other acquired resources), even in the case of exceptions.
+     * <p>
+     * The {@link SequencingService} determines the sequencers that should be executed by monitoring the changes to one or more
+     * workspaces (it is a {@link NodeChangeListener} registered with the {@link ObservationService}). Changes in those workspaces
+     * are aggregated for each transaction, and organized into {@link NodeChanges changes for each node}. The SequencingService
+     * then determines for each {@link NodeChange set of changes to a node} the set of full paths to the properties that have
+     * changed and whether those paths {@link SequencerPathExpression#matcher(String) match} the sequencer's
+     * {@link SequencerConfig#getPathExpressions() path expressions}. Each path expression produces the path to the output node,
+     * and these output paths are accumulated and (with the original node that changed, the node change summary, and other
+     * information) supplied to the sequencer via this method.
+     * <p>
+     * It is possible that a sequencer is configured to apply to multiple properties on a node. So, in cases where multiple
+     * properties are changed on a single node (within a single repository transaction), the sequencer will only be executed once.
+     * Also, in such cases the sequencer's configuration may imply multiple output nodes, so it is left to the sequencer to define
+     * the behavior in such cases.
+     * </p>
+     * 
+     * @param input the node that has recently been created or changed; never null
+     * @param sequencedPropertyName the name of the property that caused this sequencer to be executed; never null and never empty
+     * @param changes the immutable summary of changes that occurred on the <code>input</code> node within the transaction; never
+     *        null
+     * @param outputPaths the paths to the nodes where the sequencing content should be placed; never null and never empty, but
+     *        the set may contain paths for non-existant nodes or may reference the <code>input</code> node
+     * @param context the context in which this sequencer is executing; never null
+     * @param problems the interface used for recording problems; never null
+     * @throws RepositoryException if there is a problem while working with the repository
+     * @throws SequencerException if there is an error in this sequencer
+     */
+    void execute( Node input,
+                  String sequencedPropertyName,
+                  NodeChange changes,
+                  Set<RepositoryNodePath> outputPaths,
+                  JcrExecutionContext context,
+                  Problems problems ) throws RepositoryException, SequencerException;
+
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerConfig.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerConfig.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerConfig.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,75 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.component.ComponentConfig;
-
-/**
- * @author Randall Hauch
- */
- at Immutable
-public class SequencerConfig extends ComponentConfig {
-
-    private final Set<SequencerPathExpression> pathExpressions;
-
-    public SequencerConfig( String name, String description, String classname, String[] classpath, String... pathExpressions ) {
-        this(name, description, System.currentTimeMillis(), classname, classpath, pathExpressions);
-    }
-
-    public SequencerConfig( String name, String description, long timestamp, String classname, String[] classpath, String... pathExpressions ) {
-        super(name, description, timestamp, classname, classpath);
-        this.pathExpressions = buildPathExpressionSet(pathExpressions);
-    }
-
-    /* package */static Set<SequencerPathExpression> buildPathExpressionSet( String... pathExpressions ) {
-        Set<SequencerPathExpression> result = null;
-        if (pathExpressions != null) {
-            result = new LinkedHashSet<SequencerPathExpression>();
-            for (String pathExpression : pathExpressions) {
-                if (pathExpression == null) continue;
-                pathExpression = pathExpression.trim();
-                if (pathExpression.length() == 0) continue;
-                result.add(SequencerPathExpression.compile(pathExpression));
-            }
-            result = Collections.unmodifiableSet(result);
-        } else {
-            result = Collections.emptySet(); // already immutable
-        }
-        return result;
-    }
-
-    public Collection<SequencerPathExpression> getPathExpressions() {
-        return Collections.unmodifiableSet(this.pathExpressions);
-    }
-
-    public boolean hasChanged( SequencerConfig that ) {
-        if (super.hasChanged(that)) return true;
-        if (!this.getPathExpressions().equals(that.getPathExpressions())) return true;
-        return false;
-    }
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerConfig.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerConfig.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerConfig.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerConfig.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,75 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.component.ComponentConfig;
+
+/**
+ * @author Randall Hauch
+ */
+ at Immutable
+public class SequencerConfig extends ComponentConfig {
+
+    private final Set<SequencerPathExpression> pathExpressions;
+
+    public SequencerConfig( String name, String description, String classname, String[] classpath, String... pathExpressions ) {
+        this(name, description, System.currentTimeMillis(), classname, classpath, pathExpressions);
+    }
+
+    public SequencerConfig( String name, String description, long timestamp, String classname, String[] classpath, String... pathExpressions ) {
+        super(name, description, timestamp, classname, classpath);
+        this.pathExpressions = buildPathExpressionSet(pathExpressions);
+    }
+
+    /* package */static Set<SequencerPathExpression> buildPathExpressionSet( String... pathExpressions ) {
+        Set<SequencerPathExpression> result = null;
+        if (pathExpressions != null) {
+            result = new LinkedHashSet<SequencerPathExpression>();
+            for (String pathExpression : pathExpressions) {
+                if (pathExpression == null) continue;
+                pathExpression = pathExpression.trim();
+                if (pathExpression.length() == 0) continue;
+                result.add(SequencerPathExpression.compile(pathExpression));
+            }
+            result = Collections.unmodifiableSet(result);
+        } else {
+            result = Collections.emptySet(); // already immutable
+        }
+        return result;
+    }
+
+    public Collection<SequencerPathExpression> getPathExpressions() {
+        return Collections.unmodifiableSet(this.pathExpressions);
+    }
+
+    public boolean hasChanged( SequencerConfig that ) {
+        if (super.hasChanged(that)) return true;
+        if (!this.getPathExpressions().equals(that.getPathExpressions())) return true;
+        return false;
+    }
+
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerException.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerException.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,60 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-/**
- * @author Randall Hauch
- */
-public class SequencerException extends RuntimeException {
-
-    /**
-     */
-    private static final long serialVersionUID = -7610898771539657335L;
-
-    /**
-     */
-    public SequencerException() {
-    }
-
-    /**
-     * @param message
-     */
-    public SequencerException( String message ) {
-        super(message);
-    }
-
-    /**
-     * @param cause
-     */
-    public SequencerException( Throwable cause ) {
-        super(cause);
-    }
-
-    /**
-     * @param message
-     * @param cause
-     */
-    public SequencerException( String message, Throwable cause ) {
-        super(message, cause);
-    }
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerException.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerException.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerException.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerException.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+/**
+ * @author Randall Hauch
+ */
+public class SequencerException extends RuntimeException {
+
+    /**
+     */
+    private static final long serialVersionUID = -7610898771539657335L;
+
+    /**
+     */
+    public SequencerException() {
+    }
+
+    /**
+     * @param message
+     */
+    public SequencerException( String message ) {
+        super(message);
+    }
+
+    /**
+     * @param cause
+     */
+    public SequencerException( Throwable cause ) {
+        super(cause);
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public SequencerException( String message, Throwable cause ) {
+        super(message, cause);
+    }
+
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerLibrary.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerLibrary.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerLibrary.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,51 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import org.jboss.dna.common.component.ComponentLibrary;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
-
-/**
- * @author Randall Hauch
- */
-public class SequencerLibrary extends ComponentLibrary<Sequencer, SequencerConfig> {
-
-    /**
-     * 
-     */
-    public SequencerLibrary() {
-        super();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Sequencer doCreateInstance( Class<?> componentClass ) throws InstantiationException, IllegalAccessException {
-        Object sequencerImpl = componentClass.newInstance();
-        if (sequencerImpl instanceof StreamSequencer) {
-            sequencerImpl = new StreamSequencerAdapter((StreamSequencer)sequencerImpl);
-        }
-        return (Sequencer)sequencerImpl;
-    }
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerLibrary.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerLibrary.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerLibrary.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerLibrary.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+import org.jboss.dna.common.component.ComponentLibrary;
+import org.jboss.dna.graph.sequencer.StreamSequencer;
+
+/**
+ * @author Randall Hauch
+ */
+public class SequencerLibrary extends ComponentLibrary<Sequencer, SequencerConfig> {
+
+    /**
+     * 
+     */
+    public SequencerLibrary() {
+        super();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Sequencer doCreateInstance( Class<?> componentClass ) throws InstantiationException, IllegalAccessException {
+        Object sequencerImpl = componentClass.newInstance();
+        if (sequencerImpl instanceof StreamSequencer) {
+            sequencerImpl = new StreamSequencerAdapter((StreamSequencer)sequencerImpl);
+        }
+        return (Sequencer)sequencerImpl;
+    }
+
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerNodeContext.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerNodeContext.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerNodeContext.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,304 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.AccessControlContext;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import javax.jcr.Node;
-import javax.jcr.PropertyIterator;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.collection.Problems;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.graph.mimetype.MimeTypeDetector;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
-import org.jboss.dna.repository.RepositoryI18n;
-import org.jboss.dna.repository.mimetype.MimeType;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-
-/**
- * Contains context information that is passed to {@link StreamSequencer stream sequencers}, including information about the input
- * node containing the data being sequenced.
- * 
- * @author John Verhaeg
- */
- at Immutable
-public class SequencerNodeContext implements SequencerContext {
-
-    private final javax.jcr.Property sequencedProperty;
-    private final ValueFactories factories;
-    private final Path path;
-    private final Set<Property> props;
-    private final JcrExecutionContext context;
-    private final Problems problems;
-
-    SequencerNodeContext( Node input,
-                          javax.jcr.Property sequencedProperty,
-                          JcrExecutionContext context,
-                          Problems problems ) throws RepositoryException {
-        assert input != null;
-        assert sequencedProperty != null;
-        assert context != null;
-        assert problems != null;
-        this.context = context;
-        this.sequencedProperty = sequencedProperty;
-        this.problems = problems;
-        this.factories = context.getValueFactories();
-        // Translate JCR path and property values to DNA constructs and cache them to improve performance and prevent
-        // RepositoryException from being thrown by getters
-        // Note: getMimeType() will still operate lazily, and thus throw a SequencerException, since it is very intrusive and
-        // potentially slow-running.
-        path = factories.getPathFactory().create(input.getPath());
-        Set<Property> props = new HashSet<Property>();
-        for (PropertyIterator iter = input.getProperties(); iter.hasNext();) {
-            javax.jcr.Property jcrProp = iter.nextProperty();
-            Property prop;
-            if (jcrProp.getDefinition().isMultiple()) {
-                Value[] jcrVals = jcrProp.getValues();
-                Object[] vals = new Object[jcrVals.length];
-                int ndx = 0;
-                for (Value jcrVal : jcrVals) {
-                    vals[ndx++] = convert(factories, jcrProp.getName(), jcrVal);
-                }
-                prop = context.getPropertyFactory().create(factories.getNameFactory().create(jcrProp.getName()), vals);
-            } else {
-                Value jcrVal = jcrProp.getValue();
-                Object val = convert(factories, jcrProp.getName(), jcrVal);
-                prop = context.getPropertyFactory().create(factories.getNameFactory().create(jcrProp.getName()), val);
-            }
-            props.add(prop);
-        }
-        this.props = Collections.unmodifiableSet(props);
-    }
-
-    private Object convert( ValueFactories factories,
-                            String name,
-                            Value jcrValue ) throws RepositoryException {
-        switch (jcrValue.getType()) {
-            case PropertyType.BINARY: {
-                return factories.getBinaryFactory().create(jcrValue.getStream());
-            }
-            case PropertyType.BOOLEAN: {
-                return factories.getBooleanFactory().create(jcrValue.getBoolean());
-            }
-            case PropertyType.DATE: {
-                return factories.getDateFactory().create(jcrValue.getDate());
-            }
-            case PropertyType.DOUBLE: {
-                return factories.getDoubleFactory().create(jcrValue.getDouble());
-            }
-            case PropertyType.LONG: {
-                return factories.getLongFactory().create(jcrValue.getLong());
-            }
-            case PropertyType.NAME: {
-                return factories.getNameFactory().create(jcrValue.getString());
-            }
-            case PropertyType.PATH: {
-                return factories.getPathFactory().create(jcrValue.getString());
-            }
-            case PropertyType.REFERENCE: {
-                return factories.getReferenceFactory().create(jcrValue.getString());
-            }
-            case PropertyType.STRING: {
-                return factories.getStringFactory().create(jcrValue.getString());
-            }
-            default: {
-                throw new RepositoryException(RepositoryI18n.unknownPropertyValueType.text(name, jcrValue.getType()));
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getAccessControlContext()
-     */
-    public AccessControlContext getAccessControlContext() {
-        return context.getAccessControlContext();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.common.component.ClassLoaderFactory#getClassLoader(java.lang.String[])
-     */
-    public ClassLoader getClassLoader( String... classpath ) {
-        return context.getClassLoader(classpath);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getMimeTypeDetector()
-     */
-    public MimeTypeDetector getMimeTypeDetector() {
-        return context.getMimeTypeDetector();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ValueFactories getValueFactories() {
-        return factories;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getInputPath()
-     */
-    public Path getInputPath() {
-        return path;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getInputProperties()
-     */
-    public Set<Property> getInputProperties() {
-        return props;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getInputProperty(org.jboss.dna.graph.properties.Name)
-     */
-    public Property getInputProperty( Name name ) {
-        CheckArg.isNotNull(name, "name");
-        for (Property prop : props) {
-            if (name.equals(prop.getName())) {
-                return prop;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getProblems()
-     */
-    public Problems getProblems() {
-        return problems;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getMimeType()
-     */
-    @SuppressWarnings( "null" )
-    // The need for the SuppressWarnings looks like an Eclipse bug
-    public String getMimeType() {
-        SequencerException err = null;
-        String mimeType = null;
-        InputStream stream = null;
-        try {
-            stream = sequencedProperty.getStream();
-            mimeType = MimeType.of(path.getLastSegment().getName().getLocalName(), stream);
-            return mimeType;
-        } catch (Exception error) {
-            err = new SequencerException(error);
-        } finally {
-            if (stream != null) {
-                try {
-                    stream.close();
-                } catch (IOException error) {
-                    // Only throw exception if an exception was not already thrown
-                    if (err == null) err = new SequencerException(error);
-                }
-            }
-        }
-        if (err != null) throw err;
-        return mimeType;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getLogger(java.lang.Class)
-     */
-    public Logger getLogger( Class<?> clazz ) {
-        return context.getLogger(clazz);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.sequencers.SequencerContext#getLogger(java.lang.String)
-     */
-    public Logger getLogger( String name ) {
-        return context.getLogger(name);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getLoginContext()
-     */
-    public LoginContext getLoginContext() {
-        return context.getLoginContext();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public NamespaceRegistry getNamespaceRegistry() {
-        return factories.getNameFactory().getNamespaceRegistry();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getPropertyFactory()
-     */
-    public PropertyFactory getPropertyFactory() {
-        return context.getPropertyFactory();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.ExecutionContext#getSubject()
-     */
-    public Subject getSubject() {
-        return context.getSubject();
-    }
-}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerOutputMap.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerOutputMap.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerOutputMap.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,358 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import net.jcip.annotations.Immutable;
-import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.JcrLexicon;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
-
-/**
- * A basic {@link SequencerOutput} that records all information in-memory and which organizes the properties by {@link Path node
- * paths} and provides access to the nodes in a natural path-order.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at NotThreadSafe
-public class SequencerOutputMap implements SequencerOutput, Iterable<SequencerOutputMap.Entry> {
-
-    private static final String JCR_NAME_PROPERTY_NAME = "jcr:name";
-
-    private final Map<Path, List<PropertyValue>> data;
-    private transient boolean valuesSorted = true;
-    private final ValueFactories factories;
-    private final Name jcrName;
-
-    public SequencerOutputMap( ValueFactories factories ) {
-        CheckArg.isNotNull(factories, "factories");
-        this.data = new HashMap<Path, List<PropertyValue>>();
-        this.factories = factories;
-        this.jcrName = this.factories.getNameFactory().create(JCR_NAME_PROPERTY_NAME);
-    }
-
-    ValueFactories getFactories() {
-        return this.factories;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setProperty( Path nodePath,
-                             Name propertyName,
-                             Object... values ) {
-        CheckArg.isNotNull(nodePath, "nodePath");
-        CheckArg.isNotNull(propertyName, "property");
-        // Ignore the "jcr:name" property, as that's handled by the path ...
-        if (this.jcrName.equals(propertyName)) return;
-
-        // Find or create the entry for this node ...
-        List<PropertyValue> properties = this.data.get(nodePath);
-        if (properties == null) {
-            if (values == null || values.length == 0) return; // do nothing
-            properties = new ArrayList<PropertyValue>();
-            this.data.put(nodePath, properties);
-        }
-        if (values == null || values.length == 0) {
-            properties.remove(new PropertyValue(propertyName, null));
-        } else {
-            Object propValue = values.length == 1 ? values[0] : values;
-            PropertyValue value = new PropertyValue(propertyName, propValue);
-            properties.add(value);
-            valuesSorted = false;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setProperty( String nodePath,
-                             String property,
-                             Object... values ) {
-        CheckArg.isNotEmpty(nodePath, "nodePath");
-        CheckArg.isNotEmpty(property, "property");
-        Path path = this.factories.getPathFactory().create(nodePath);
-        Name propertyName = this.factories.getNameFactory().create(property);
-        setProperty(path, propertyName, values);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setReference( String nodePath,
-                              String propertyName,
-                              String... paths ) {
-        PathFactory pathFactory = this.factories.getPathFactory();
-        Path path = pathFactory.create(nodePath);
-        Name name = this.factories.getNameFactory().create(propertyName);
-        Object[] values = null;
-        if (paths != null && paths.length != 0) {
-            values = new Path[paths.length];
-            for (int i = 0, len = paths.length; i != len; ++i) {
-                String pathValue = paths[i];
-                values[i] = pathFactory.create(pathValue);
-            }
-        }
-        setProperty(path, name, values);
-    }
-
-    /**
-     * Return the number of node entries in this map.
-     * 
-     * @return the number of entries
-     */
-    public int size() {
-        return this.data.size();
-    }
-
-    /**
-     * Return whether there are no entries
-     * 
-     * @return true if this container is empty, or false otherwise
-     */
-    public boolean isEmpty() {
-        return this.data.isEmpty();
-    }
-
-    protected List<PropertyValue> removeProperties( Path nodePath ) {
-        return this.data.remove(nodePath);
-    }
-
-    /**
-     * Get the properties for the node given by the supplied path.
-     * 
-     * @param nodePath the path to the node
-     * @return the property values, or null if there are none
-     */
-    protected List<PropertyValue> getProperties( Path nodePath ) {
-        return data.get(nodePath);
-    }
-
-    /**
-     * Return the entries in this output in an order with shorter paths first.
-     * <p>
-     * {@inheritDoc}
-     */
-    public Iterator<Entry> iterator() {
-        LinkedList<Path> paths = new LinkedList<Path>(data.keySet());
-        Collections.sort(paths);
-        sortValues();
-        return new EntryIterator(paths.iterator());
-    }
-
-    protected void sortValues() {
-        if (!valuesSorted) {
-            for (List<PropertyValue> values : this.data.values()) {
-                if (values.size() > 1) Collections.sort(values);
-            }
-            valuesSorted = true;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return this.data.toString();
-    }
-
-    /**
-     * A property name and value pair. PropertyValue instances have a natural order where the <code>jcr:primaryType</code> is
-     * first, followed by all other properties in ascending lexicographical order according to the {@link #getName() name}.
-     * 
-     * @author Randall Hauch
-     */
-    @Immutable
-    public class PropertyValue implements Comparable<PropertyValue> {
-
-        private final Name name;
-        private final Object value;
-
-        protected PropertyValue( Name propertyName,
-                                 Object value ) {
-            this.name = propertyName;
-            this.value = value;
-        }
-
-        /**
-         * Get the property name.
-         * 
-         * @return the property name; never null
-         */
-        public Name getName() {
-            return this.name;
-        }
-
-        /**
-         * Get the property value, which is either a single value or an array of values.
-         * 
-         * @return the property value
-         */
-        public Object getValue() {
-            return this.value;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public int compareTo( PropertyValue that ) {
-            if (this == that) return 0;
-            if (this.name.equals(JcrLexicon.PRIMARY_TYPE)) return -1;
-            if (that.name.equals(JcrLexicon.PRIMARY_TYPE)) return 1;
-            return this.name.compareTo(that.name);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public int hashCode() {
-            return this.name.hashCode();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public boolean equals( Object obj ) {
-            if (obj == this) return true;
-            if (obj instanceof PropertyValue) {
-                PropertyValue that = (PropertyValue)obj;
-                if (!this.getName().equals(that.getName())) return false;
-                return true;
-            }
-            return false;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public String toString() {
-            return "[" + this.name + "=" + value + "]";
-        }
-    }
-
-    /**
-     * An entry in a SequencerOutputMap, which contains the path of the node and the {@link #getPropertyValues() property values}
-     * on the node.
-     * 
-     * @author Randall Hauch
-     */
-    @Immutable
-    public class Entry {
-
-        private final Path path;
-        private final Name primaryType;
-        private final List<PropertyValue> properties;
-
-        protected Entry( Path path,
-                         List<PropertyValue> properties ) {
-            assert path != null;
-            assert properties != null;
-            this.path = path;
-            this.properties = properties;
-            if (this.properties.size() > 0 && this.properties.get(0).getName().equals("jcr:primaryType")) {
-                PropertyValue primaryTypeProperty = this.properties.remove(0);
-                this.primaryType = getFactories().getNameFactory().create(primaryTypeProperty.getValue());
-            } else {
-                this.primaryType = null;
-            }
-        }
-
-        /**
-         * @return path
-         */
-        public Path getPath() {
-            return this.path;
-        }
-
-        /**
-         * Get the primary type specified for this node, or null if the type was not specified
-         * 
-         * @return the primary type, or null
-         */
-        public Name getPrimaryTypeValue() {
-            return this.primaryType;
-        }
-
-        /**
-         * Get the property values, which may be empty
-         * 
-         * @return value
-         */
-        public List<PropertyValue> getPropertyValues() {
-            return getProperties(path);
-        }
-    }
-
-    protected class EntryIterator implements Iterator<Entry> {
-
-        private Path last;
-        private final Iterator<Path> iter;
-
-        protected EntryIterator( Iterator<Path> iter ) {
-            this.iter = iter;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean hasNext() {
-            return iter.hasNext();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Entry next() {
-            this.last = iter.next();
-            return new Entry(last, getProperties(last));
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void remove() {
-            if (last == null) throw new IllegalStateException();
-            try {
-                removeProperties(last);
-            } finally {
-                last = null;
-            }
-        }
-    }
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerOutputMap.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerOutputMap.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerOutputMap.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerOutputMap.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,358 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import net.jcip.annotations.Immutable;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.JcrLexicon;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
+
+/**
+ * A basic {@link SequencerOutput} that records all information in-memory and which organizes the properties by {@link Path node
+ * paths} and provides access to the nodes in a natural path-order.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at NotThreadSafe
+public class SequencerOutputMap implements SequencerOutput, Iterable<SequencerOutputMap.Entry> {
+
+    private static final String JCR_NAME_PROPERTY_NAME = "jcr:name";
+
+    private final Map<Path, List<PropertyValue>> data;
+    private transient boolean valuesSorted = true;
+    private final ValueFactories factories;
+    private final Name jcrName;
+
+    public SequencerOutputMap( ValueFactories factories ) {
+        CheckArg.isNotNull(factories, "factories");
+        this.data = new HashMap<Path, List<PropertyValue>>();
+        this.factories = factories;
+        this.jcrName = this.factories.getNameFactory().create(JCR_NAME_PROPERTY_NAME);
+    }
+
+    ValueFactories getFactories() {
+        return this.factories;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setProperty( Path nodePath,
+                             Name propertyName,
+                             Object... values ) {
+        CheckArg.isNotNull(nodePath, "nodePath");
+        CheckArg.isNotNull(propertyName, "property");
+        // Ignore the "jcr:name" property, as that's handled by the path ...
+        if (this.jcrName.equals(propertyName)) return;
+
+        // Find or create the entry for this node ...
+        List<PropertyValue> properties = this.data.get(nodePath);
+        if (properties == null) {
+            if (values == null || values.length == 0) return; // do nothing
+            properties = new ArrayList<PropertyValue>();
+            this.data.put(nodePath, properties);
+        }
+        if (values == null || values.length == 0) {
+            properties.remove(new PropertyValue(propertyName, null));
+        } else {
+            Object propValue = values.length == 1 ? values[0] : values;
+            PropertyValue value = new PropertyValue(propertyName, propValue);
+            properties.add(value);
+            valuesSorted = false;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setProperty( String nodePath,
+                             String property,
+                             Object... values ) {
+        CheckArg.isNotEmpty(nodePath, "nodePath");
+        CheckArg.isNotEmpty(property, "property");
+        Path path = this.factories.getPathFactory().create(nodePath);
+        Name propertyName = this.factories.getNameFactory().create(property);
+        setProperty(path, propertyName, values);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setReference( String nodePath,
+                              String propertyName,
+                              String... paths ) {
+        PathFactory pathFactory = this.factories.getPathFactory();
+        Path path = pathFactory.create(nodePath);
+        Name name = this.factories.getNameFactory().create(propertyName);
+        Object[] values = null;
+        if (paths != null && paths.length != 0) {
+            values = new Path[paths.length];
+            for (int i = 0, len = paths.length; i != len; ++i) {
+                String pathValue = paths[i];
+                values[i] = pathFactory.create(pathValue);
+            }
+        }
+        setProperty(path, name, values);
+    }
+
+    /**
+     * Return the number of node entries in this map.
+     * 
+     * @return the number of entries
+     */
+    public int size() {
+        return this.data.size();
+    }
+
+    /**
+     * Return whether there are no entries
+     * 
+     * @return true if this container is empty, or false otherwise
+     */
+    public boolean isEmpty() {
+        return this.data.isEmpty();
+    }
+
+    protected List<PropertyValue> removeProperties( Path nodePath ) {
+        return this.data.remove(nodePath);
+    }
+
+    /**
+     * Get the properties for the node given by the supplied path.
+     * 
+     * @param nodePath the path to the node
+     * @return the property values, or null if there are none
+     */
+    protected List<PropertyValue> getProperties( Path nodePath ) {
+        return data.get(nodePath);
+    }
+
+    /**
+     * Return the entries in this output in an order with shorter paths first.
+     * <p>
+     * {@inheritDoc}
+     */
+    public Iterator<Entry> iterator() {
+        LinkedList<Path> paths = new LinkedList<Path>(data.keySet());
+        Collections.sort(paths);
+        sortValues();
+        return new EntryIterator(paths.iterator());
+    }
+
+    protected void sortValues() {
+        if (!valuesSorted) {
+            for (List<PropertyValue> values : this.data.values()) {
+                if (values.size() > 1) Collections.sort(values);
+            }
+            valuesSorted = true;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return this.data.toString();
+    }
+
+    /**
+     * A property name and value pair. PropertyValue instances have a natural order where the <code>jcr:primaryType</code> is
+     * first, followed by all other properties in ascending lexicographical order according to the {@link #getName() name}.
+     * 
+     * @author Randall Hauch
+     */
+    @Immutable
+    public class PropertyValue implements Comparable<PropertyValue> {
+
+        private final Name name;
+        private final Object value;
+
+        protected PropertyValue( Name propertyName,
+                                 Object value ) {
+            this.name = propertyName;
+            this.value = value;
+        }
+
+        /**
+         * Get the property name.
+         * 
+         * @return the property name; never null
+         */
+        public Name getName() {
+            return this.name;
+        }
+
+        /**
+         * Get the property value, which is either a single value or an array of values.
+         * 
+         * @return the property value
+         */
+        public Object getValue() {
+            return this.value;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public int compareTo( PropertyValue that ) {
+            if (this == that) return 0;
+            if (this.name.equals(JcrLexicon.PRIMARY_TYPE)) return -1;
+            if (that.name.equals(JcrLexicon.PRIMARY_TYPE)) return 1;
+            return this.name.compareTo(that.name);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int hashCode() {
+            return this.name.hashCode();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean equals( Object obj ) {
+            if (obj == this) return true;
+            if (obj instanceof PropertyValue) {
+                PropertyValue that = (PropertyValue)obj;
+                if (!this.getName().equals(that.getName())) return false;
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public String toString() {
+            return "[" + this.name + "=" + value + "]";
+        }
+    }
+
+    /**
+     * An entry in a SequencerOutputMap, which contains the path of the node and the {@link #getPropertyValues() property values}
+     * on the node.
+     * 
+     * @author Randall Hauch
+     */
+    @Immutable
+    public class Entry {
+
+        private final Path path;
+        private final Name primaryType;
+        private final List<PropertyValue> properties;
+
+        protected Entry( Path path,
+                         List<PropertyValue> properties ) {
+            assert path != null;
+            assert properties != null;
+            this.path = path;
+            this.properties = properties;
+            if (this.properties.size() > 0 && this.properties.get(0).getName().equals("jcr:primaryType")) {
+                PropertyValue primaryTypeProperty = this.properties.remove(0);
+                this.primaryType = getFactories().getNameFactory().create(primaryTypeProperty.getValue());
+            } else {
+                this.primaryType = null;
+            }
+        }
+
+        /**
+         * @return path
+         */
+        public Path getPath() {
+            return this.path;
+        }
+
+        /**
+         * Get the primary type specified for this node, or null if the type was not specified
+         * 
+         * @return the primary type, or null
+         */
+        public Name getPrimaryTypeValue() {
+            return this.primaryType;
+        }
+
+        /**
+         * Get the property values, which may be empty
+         * 
+         * @return value
+         */
+        public List<PropertyValue> getPropertyValues() {
+            return getProperties(path);
+        }
+    }
+
+    protected class EntryIterator implements Iterator<Entry> {
+
+        private Path last;
+        private final Iterator<Path> iter;
+
+        protected EntryIterator( Iterator<Path> iter ) {
+            this.iter = iter;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean hasNext() {
+            return iter.hasNext();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Entry next() {
+            this.last = iter.next();
+            return new Entry(last, getProperties(last));
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void remove() {
+            if (last == null) throw new IllegalStateException();
+            try {
+                removeProperties(last);
+            } finally {
+                last = null;
+            }
+        }
+    }
+
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerPathExpression.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerPathExpression.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerPathExpression.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,294 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Pattern;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.HashCode;
-import org.jboss.dna.graph.properties.PathExpression;
-import org.jboss.dna.repository.RepositoryI18n;
-
-/**
- * An expression that defines a selection of some change in the repository that signals a sequencing operation should be run, and
- * the location where the sequencing output should be placed. Sequencer path expressions are used within the
- * {@link SequencerConfig sequencer configurations} and used to determine whether information in the repository needs to be
- * sequenced.
- * <p>
- * A simple example is the following:
- * 
- * <pre>
- *     /a/b/c at title =&gt; /d/e/f
- * </pre>
- * 
- * which means that a sequencer (that uses this expression in its configuration) should be run any time there is a new or modified
- * <code>title</code> property on the <code>/a/b/c</code> node, and that the output of the sequencing should be placed at
- * <code>/d/e/f</code>.
- * </p>
- * 
- * @author Randall Hauch
- */
- at Immutable
-public class SequencerPathExpression implements Serializable {
-
-    /**
-     */
-    private static final long serialVersionUID = 229464314137494765L;
-
-    /**
-     * The pattern used to break the initial input string into the two major parts, the selection and output expressions. Group 1
-     * contains the selection expression, and group 2 contains the output expression.
-     */
-    private static final Pattern TWO_PART_PATTERN = Pattern.compile("((?:[^=]|=(?!>))+)(?:=>(.+))?");
-
-    protected static final String DEFAULT_OUTPUT_EXPRESSION = ".";
-
-    private static final String PARENT_PATTERN_STRING = "[^/]+/\\.\\./"; // [^/]+/\.\./
-    private static final Pattern PARENT_PATTERN = Pattern.compile(PARENT_PATTERN_STRING);
-
-    private static final String REPLACEMENT_VARIABLE_PATTERN_STRING = "(?<!\\\\)\\$(\\d+)"; // (?<!\\)\$(\d+)
-    private static final Pattern REPLACEMENT_VARIABLE_PATTERN = Pattern.compile(REPLACEMENT_VARIABLE_PATTERN_STRING);
-
-    /**
-     * Compile the supplied expression and return the resulting SequencerPathExpression instance.
-     * 
-     * @param expression the expression
-     * @return the path expression; never null
-     * @throws IllegalArgumentException if the expression is null
-     * @throws InvalidSequencerPathExpression if the expression is blank or is not a valid expression
-     */
-    public static final SequencerPathExpression compile( String expression ) throws InvalidSequencerPathExpression {
-        CheckArg.isNotNull(expression, "sequencer path expression");
-        expression = expression.trim();
-        if (expression.length() == 0) {
-            throw new InvalidSequencerPathExpression(RepositoryI18n.pathExpressionMayNotBeBlank.text());
-        }
-        java.util.regex.Matcher matcher = TWO_PART_PATTERN.matcher(expression);
-        if (!matcher.matches()) {
-            throw new InvalidSequencerPathExpression(RepositoryI18n.pathExpressionIsInvalid.text(expression));
-        }
-        String selectExpression = matcher.group(1);
-        String outputExpression = matcher.group(2);
-        return new SequencerPathExpression(PathExpression.compile(selectExpression), outputExpression);
-    }
-
-    private final PathExpression selectExpression;
-    private final String outputExpression;
-    private final int hc;
-
-    protected SequencerPathExpression( PathExpression selectExpression,
-                                       String outputExpression ) throws InvalidSequencerPathExpression {
-        CheckArg.isNotNull(selectExpression, "select expression");
-        this.selectExpression = selectExpression;
-        this.outputExpression = outputExpression != null ? outputExpression.trim() : DEFAULT_OUTPUT_EXPRESSION;
-        this.hc = HashCode.compute(this.selectExpression, this.outputExpression);
-    }
-
-    /**
-     * @return selectExpression
-     */
-    public String getSelectExpression() {
-        return this.selectExpression.getSelectExpression();
-    }
-
-    /**
-     * @return outputExpression
-     */
-    public String getOutputExpression() {
-        return this.outputExpression;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return this.hc;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof SequencerPathExpression) {
-            SequencerPathExpression that = (SequencerPathExpression)obj;
-            if (!this.selectExpression.equals(that.selectExpression)) return false;
-            if (!this.outputExpression.equalsIgnoreCase(that.outputExpression)) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return this.selectExpression + "=>" + this.outputExpression;
-    }
-
-    /**
-     * @param absolutePath
-     * @return the matcher
-     */
-    public Matcher matcher( String absolutePath ) {
-        PathExpression.Matcher inputMatcher = selectExpression.matcher(absolutePath);
-        String outputPath = null;
-        if (inputMatcher.matches()) {
-            // Grab the named groups ...
-            Map<Integer, String> replacements = new HashMap<Integer, String>();
-            for (int i = 0, count = inputMatcher.groupCount(); i <= count; ++i) {
-                replacements.put(i, inputMatcher.group(i));
-            }
-
-            // Grab the selected path ...
-            String selectedPath = inputMatcher.getSelectedNodePath();
-
-            // Find the output path using the groups from the match pattern ...
-            outputPath = this.outputExpression;
-            if (!DEFAULT_OUTPUT_EXPRESSION.equals(outputPath)) {
-                java.util.regex.Matcher replacementMatcher = REPLACEMENT_VARIABLE_PATTERN.matcher(outputPath);
-                StringBuffer sb = new StringBuffer();
-                if (replacementMatcher.find()) {
-                    do {
-                        String variable = replacementMatcher.group(1);
-                        String replacement = replacements.get(Integer.valueOf(variable));
-                        if (replacement == null) replacement = replacementMatcher.group(0);
-                        replacementMatcher.appendReplacement(sb, replacement);
-                    } while (replacementMatcher.find());
-                    replacementMatcher.appendTail(sb);
-                    outputPath = sb.toString();
-                }
-                // Make sure there is a trailing '/' ...
-                if (!outputPath.endsWith("/")) outputPath = outputPath + "/";
-
-                // Replace all references to "/./" with "/" ...
-                outputPath = outputPath.replaceAll("/\\./", "/");
-
-                // Remove any path segment followed by a parent reference ...
-                java.util.regex.Matcher parentMatcher = PARENT_PATTERN.matcher(outputPath);
-                while (parentMatcher.find()) {
-                    outputPath = parentMatcher.replaceAll("");
-                    // Make sure there is a trailing '/' ...
-                    if (!outputPath.endsWith("/")) outputPath = outputPath + "/";
-                    parentMatcher = PARENT_PATTERN.matcher(outputPath);
-                }
-
-                // Remove all multiple occurrences of '/' ...
-                outputPath = outputPath.replaceAll("/{2,}", "/");
-
-                // Remove the trailing '/@property' ...
-                outputPath = outputPath.replaceAll("/@[^/\\[\\]]+$", "");
-
-                // Remove a trailing '/' ...
-                outputPath = outputPath.replaceAll("/$", "");
-
-                // If the output path is blank, then use the default output expression ...
-                if (outputPath.length() == 0) outputPath = DEFAULT_OUTPUT_EXPRESSION;
-
-            }
-            if (DEFAULT_OUTPUT_EXPRESSION.equals(outputPath)) {
-                // The output path is the default expression, so use the selected path ...
-                outputPath = selectedPath;
-            }
-        }
-
-        return new Matcher(inputMatcher, outputPath);
-    }
-
-    @Immutable
-    public static class Matcher {
-
-        private final PathExpression.Matcher inputMatcher;
-        private final String outputPath;
-        private final int hc;
-
-        protected Matcher( PathExpression.Matcher inputMatcher,
-                           String outputPath ) {
-            this.inputMatcher = inputMatcher;
-            this.outputPath = outputPath;
-            this.hc = HashCode.compute(super.hashCode(), this.outputPath);
-        }
-
-        public boolean matches() {
-            return inputMatcher.matches() && this.outputPath != null;
-        }
-
-        /**
-         * @return inputPath
-         */
-        public String getInputPath() {
-            return inputMatcher.getInputPath();
-        }
-
-        /**
-         * @return selectPattern
-         */
-        public String getSelectedPath() {
-            return inputMatcher.getSelectedNodePath();
-        }
-
-        /**
-         * @return outputPath
-         */
-        public String getOutputPath() {
-            return this.outputPath;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public int hashCode() {
-            return this.hc;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public boolean equals( Object obj ) {
-            if (obj == this) return true;
-            if (obj instanceof SequencerPathExpression.Matcher) {
-                SequencerPathExpression.Matcher that = (SequencerPathExpression.Matcher)obj;
-                if (!super.equals(that)) return false;
-                if (!this.outputPath.equalsIgnoreCase(that.outputPath)) return false;
-                return true;
-            }
-            return false;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public String toString() {
-            return inputMatcher + " => " + this.outputPath;
-        }
-    }
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerPathExpression.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerPathExpression.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerPathExpression.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencerPathExpression.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,294 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.property.PathExpression;
+import org.jboss.dna.repository.RepositoryI18n;
+
+/**
+ * An expression that defines a selection of some change in the repository that signals a sequencing operation should be run, and
+ * the location where the sequencing output should be placed. Sequencer path expressions are used within the
+ * {@link SequencerConfig sequencer configurations} and used to determine whether information in the repository needs to be
+ * sequenced.
+ * <p>
+ * A simple example is the following:
+ * 
+ * <pre>
+ *     /a/b/c at title =&gt; /d/e/f
+ * </pre>
+ * 
+ * which means that a sequencer (that uses this expression in its configuration) should be run any time there is a new or modified
+ * <code>title</code> property on the <code>/a/b/c</code> node, and that the output of the sequencing should be placed at
+ * <code>/d/e/f</code>.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class SequencerPathExpression implements Serializable {
+
+    /**
+     */
+    private static final long serialVersionUID = 229464314137494765L;
+
+    /**
+     * The pattern used to break the initial input string into the two major parts, the selection and output expressions. Group 1
+     * contains the selection expression, and group 2 contains the output expression.
+     */
+    private static final Pattern TWO_PART_PATTERN = Pattern.compile("((?:[^=]|=(?!>))+)(?:=>(.+))?");
+
+    protected static final String DEFAULT_OUTPUT_EXPRESSION = ".";
+
+    private static final String PARENT_PATTERN_STRING = "[^/]+/\\.\\./"; // [^/]+/\.\./
+    private static final Pattern PARENT_PATTERN = Pattern.compile(PARENT_PATTERN_STRING);
+
+    private static final String REPLACEMENT_VARIABLE_PATTERN_STRING = "(?<!\\\\)\\$(\\d+)"; // (?<!\\)\$(\d+)
+    private static final Pattern REPLACEMENT_VARIABLE_PATTERN = Pattern.compile(REPLACEMENT_VARIABLE_PATTERN_STRING);
+
+    /**
+     * Compile the supplied expression and return the resulting SequencerPathExpression instance.
+     * 
+     * @param expression the expression
+     * @return the path expression; never null
+     * @throws IllegalArgumentException if the expression is null
+     * @throws InvalidSequencerPathExpression if the expression is blank or is not a valid expression
+     */
+    public static final SequencerPathExpression compile( String expression ) throws InvalidSequencerPathExpression {
+        CheckArg.isNotNull(expression, "sequencer path expression");
+        expression = expression.trim();
+        if (expression.length() == 0) {
+            throw new InvalidSequencerPathExpression(RepositoryI18n.pathExpressionMayNotBeBlank.text());
+        }
+        java.util.regex.Matcher matcher = TWO_PART_PATTERN.matcher(expression);
+        if (!matcher.matches()) {
+            throw new InvalidSequencerPathExpression(RepositoryI18n.pathExpressionIsInvalid.text(expression));
+        }
+        String selectExpression = matcher.group(1);
+        String outputExpression = matcher.group(2);
+        return new SequencerPathExpression(PathExpression.compile(selectExpression), outputExpression);
+    }
+
+    private final PathExpression selectExpression;
+    private final String outputExpression;
+    private final int hc;
+
+    protected SequencerPathExpression( PathExpression selectExpression,
+                                       String outputExpression ) throws InvalidSequencerPathExpression {
+        CheckArg.isNotNull(selectExpression, "select expression");
+        this.selectExpression = selectExpression;
+        this.outputExpression = outputExpression != null ? outputExpression.trim() : DEFAULT_OUTPUT_EXPRESSION;
+        this.hc = HashCode.compute(this.selectExpression, this.outputExpression);
+    }
+
+    /**
+     * @return selectExpression
+     */
+    public String getSelectExpression() {
+        return this.selectExpression.getSelectExpression();
+    }
+
+    /**
+     * @return outputExpression
+     */
+    public String getOutputExpression() {
+        return this.outputExpression;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return this.hc;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof SequencerPathExpression) {
+            SequencerPathExpression that = (SequencerPathExpression)obj;
+            if (!this.selectExpression.equals(that.selectExpression)) return false;
+            if (!this.outputExpression.equalsIgnoreCase(that.outputExpression)) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return this.selectExpression + "=>" + this.outputExpression;
+    }
+
+    /**
+     * @param absolutePath
+     * @return the matcher
+     */
+    public Matcher matcher( String absolutePath ) {
+        PathExpression.Matcher inputMatcher = selectExpression.matcher(absolutePath);
+        String outputPath = null;
+        if (inputMatcher.matches()) {
+            // Grab the named groups ...
+            Map<Integer, String> replacements = new HashMap<Integer, String>();
+            for (int i = 0, count = inputMatcher.groupCount(); i <= count; ++i) {
+                replacements.put(i, inputMatcher.group(i));
+            }
+
+            // Grab the selected path ...
+            String selectedPath = inputMatcher.getSelectedNodePath();
+
+            // Find the output path using the groups from the match pattern ...
+            outputPath = this.outputExpression;
+            if (!DEFAULT_OUTPUT_EXPRESSION.equals(outputPath)) {
+                java.util.regex.Matcher replacementMatcher = REPLACEMENT_VARIABLE_PATTERN.matcher(outputPath);
+                StringBuffer sb = new StringBuffer();
+                if (replacementMatcher.find()) {
+                    do {
+                        String variable = replacementMatcher.group(1);
+                        String replacement = replacements.get(Integer.valueOf(variable));
+                        if (replacement == null) replacement = replacementMatcher.group(0);
+                        replacementMatcher.appendReplacement(sb, replacement);
+                    } while (replacementMatcher.find());
+                    replacementMatcher.appendTail(sb);
+                    outputPath = sb.toString();
+                }
+                // Make sure there is a trailing '/' ...
+                if (!outputPath.endsWith("/")) outputPath = outputPath + "/";
+
+                // Replace all references to "/./" with "/" ...
+                outputPath = outputPath.replaceAll("/\\./", "/");
+
+                // Remove any path segment followed by a parent reference ...
+                java.util.regex.Matcher parentMatcher = PARENT_PATTERN.matcher(outputPath);
+                while (parentMatcher.find()) {
+                    outputPath = parentMatcher.replaceAll("");
+                    // Make sure there is a trailing '/' ...
+                    if (!outputPath.endsWith("/")) outputPath = outputPath + "/";
+                    parentMatcher = PARENT_PATTERN.matcher(outputPath);
+                }
+
+                // Remove all multiple occurrences of '/' ...
+                outputPath = outputPath.replaceAll("/{2,}", "/");
+
+                // Remove the trailing '/@property' ...
+                outputPath = outputPath.replaceAll("/@[^/\\[\\]]+$", "");
+
+                // Remove a trailing '/' ...
+                outputPath = outputPath.replaceAll("/$", "");
+
+                // If the output path is blank, then use the default output expression ...
+                if (outputPath.length() == 0) outputPath = DEFAULT_OUTPUT_EXPRESSION;
+
+            }
+            if (DEFAULT_OUTPUT_EXPRESSION.equals(outputPath)) {
+                // The output path is the default expression, so use the selected path ...
+                outputPath = selectedPath;
+            }
+        }
+
+        return new Matcher(inputMatcher, outputPath);
+    }
+
+    @Immutable
+    public static class Matcher {
+
+        private final PathExpression.Matcher inputMatcher;
+        private final String outputPath;
+        private final int hc;
+
+        protected Matcher( PathExpression.Matcher inputMatcher,
+                           String outputPath ) {
+            this.inputMatcher = inputMatcher;
+            this.outputPath = outputPath;
+            this.hc = HashCode.compute(super.hashCode(), this.outputPath);
+        }
+
+        public boolean matches() {
+            return inputMatcher.matches() && this.outputPath != null;
+        }
+
+        /**
+         * @return inputPath
+         */
+        public String getInputPath() {
+            return inputMatcher.getInputPath();
+        }
+
+        /**
+         * @return selectPattern
+         */
+        public String getSelectedPath() {
+            return inputMatcher.getSelectedNodePath();
+        }
+
+        /**
+         * @return outputPath
+         */
+        public String getOutputPath() {
+            return this.outputPath;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int hashCode() {
+            return this.hc;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean equals( Object obj ) {
+            if (obj == this) return true;
+            if (obj instanceof SequencerPathExpression.Matcher) {
+                SequencerPathExpression.Matcher that = (SequencerPathExpression.Matcher)obj;
+                if (!super.equals(that)) return false;
+                if (!this.outputPath.equalsIgnoreCase(that.outputPath)) return false;
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public String toString() {
+            return inputMatcher + " => " + this.outputPath;
+        }
+    }
+
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencingService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencingService.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,796 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import java.security.AccessControlContext;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.observation.Event;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import net.jcip.annotations.Immutable;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.collection.SimpleProblems;
-import org.jboss.dna.common.component.ClassLoaderFactory;
-import org.jboss.dna.common.component.ComponentLibrary;
-import org.jboss.dna.common.component.StandardClassLoaderFactory;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.HashCode;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.graph.mimetype.MimeTypeDetector;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.repository.RepositoryI18n;
-import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.observation.NodeChangeListener;
-import org.jboss.dna.repository.observation.NodeChanges;
-import org.jboss.dna.repository.services.AbstractServiceAdministrator;
-import org.jboss.dna.repository.services.AdministeredService;
-import org.jboss.dna.repository.services.ServiceAdministrator;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-import org.jboss.dna.repository.util.JcrTools;
-import org.jboss.dna.repository.util.RepositoryNodePath;
-import org.jboss.dna.repository.util.SessionFactory;
-
-/**
- * A sequencing system is used to monitor changes in the content of {@link Repository JCR repositories} and to sequence the
- * content to extract or to generate structured information.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class SequencingService implements AdministeredService, NodeChangeListener {
-
-    /**
-     * Interface used to select the set of {@link Sequencer} instances that should be run.
-     * 
-     * @author Randall Hauch
-     */
-    public static interface Selector {
-
-        /**
-         * Select the sequencers that should be used to sequence the supplied node.
-         * 
-         * @param sequencers the list of all sequencers available at the moment; never null
-         * @param node the node to be sequenced; never null
-         * @param nodeChange the set of node changes; never null
-         * @return the list of sequencers that should be used; may not be null
-         */
-        List<Sequencer> selectSequencers( List<Sequencer> sequencers,
-                                          Node node,
-                                          NodeChange nodeChange );
-    }
-
-    /**
-     * The default {@link Selector} implementation that selects every sequencer every time it's called, regardless of the node (or
-     * logger) supplied.
-     * 
-     * @author Randall Hauch
-     */
-    protected static class DefaultSelector implements Selector {
-
-        public List<Sequencer> selectSequencers( List<Sequencer> sequencers,
-                                                 Node node,
-                                                 NodeChange nodeChange ) {
-            return sequencers;
-        }
-    }
-
-    /**
-     * Interface used to determine whether a {@link NodeChange} should be processed.
-     * 
-     * @author Randall Hauch
-     */
-    public static interface NodeFilter {
-
-        /**
-         * Determine whether the node represented by the supplied change should be submitted for sequencing.
-         * 
-         * @param nodeChange the node change event
-         * @return true if the node should be submitted for sequencing, or false if the change should be ignored
-         */
-        boolean accept( NodeChange nodeChange );
-    }
-
-    /**
-     * The default filter implementation, which accepts only new nodes or nodes that have new or changed properties.
-     * 
-     * @author Randall Hauch
-     */
-    protected static class DefaultNodeFilter implements NodeFilter {
-
-        public boolean accept( NodeChange nodeChange ) {
-            // Only care about new nodes or nodes that have new/changed properies ...
-            return nodeChange.includesEventTypes(Event.NODE_ADDED, Event.PROPERTY_ADDED, Event.PROPERTY_CHANGED);
-        }
-    }
-
-    /**
-     * The default {@link Selector} that considers every {@link Sequencer} to be used for every node.
-     * 
-     * @see SequencingService#setSequencerSelector(org.jboss.dna.repository.sequencers.SequencingService.Selector)
-     */
-    public static final Selector DEFAULT_SEQUENCER_SELECTOR = new DefaultSelector();
-    /**
-     * The default {@link NodeFilter} that accepts new nodes or nodes that have new/changed properties.
-     * 
-     * @see SequencingService#setSequencerSelector(org.jboss.dna.repository.sequencers.SequencingService.Selector)
-     */
-    public static final NodeFilter DEFAULT_NODE_FILTER = new DefaultNodeFilter();
-
-    /**
-     * Class loader factory instance that always returns the {@link Thread#getContextClassLoader() current thread's context class
-     * loader} (if not null) or component library's class loader.
-     */
-    protected static final ClassLoaderFactory DEFAULT_CLASSLOADER_FACTORY = new StandardClassLoaderFactory(
-                                                                                                           SequencingService.class.getClassLoader());
-
-    /**
-     * The administrative component for this service.
-     * 
-     * @author Randall Hauch
-     */
-    protected class Administrator extends AbstractServiceAdministrator {
-
-        protected Administrator() {
-            super(RepositoryI18n.sequencingServiceName, State.PAUSED);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        protected void doStart( State fromState ) {
-            super.doStart(fromState);
-            startService();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        protected void doShutdown( State fromState ) {
-            super.doShutdown(fromState);
-            shutdownService();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        protected boolean doCheckIsTerminated() {
-            return isServiceTerminated();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean awaitTermination( long timeout,
-                                         TimeUnit unit ) throws InterruptedException {
-            return doAwaitTermination(timeout, unit);
-        }
-
-    }
-
-    private JcrExecutionContext executionContext;
-    private SequencerLibrary sequencerLibrary = new SequencerLibrary();
-    private Selector sequencerSelector = DEFAULT_SEQUENCER_SELECTOR;
-    private NodeFilter nodeFilter = DEFAULT_NODE_FILTER;
-    private ExecutorService executorService;
-    private final Statistics statistics = new Statistics();
-    private final Administrator administrator = new Administrator();
-
-    /**
-     * Create a new sequencing system, configured with no sequencers and not monitoring any workspaces. Upon construction, the
-     * system is {@link ServiceAdministrator#isPaused() paused} and must be configured and then
-     * {@link ServiceAdministrator#start() started}.
-     */
-    public SequencingService() {
-        this.sequencerLibrary.setClassLoaderFactory(DEFAULT_CLASSLOADER_FACTORY);
-    }
-
-    /**
-     * Return the administrative component for this service.
-     * 
-     * @return the administrative component; never null
-     */
-    public ServiceAdministrator getAdministrator() {
-        return this.administrator;
-    }
-
-    /**
-     * Get the statistics for this system.
-     * 
-     * @return statistics
-     */
-    public Statistics getStatistics() {
-        return this.statistics;
-    }
-
-    /**
-     * @return sequencerLibrary
-     */
-    protected ComponentLibrary<Sequencer, SequencerConfig> getSequencerLibrary() {
-        return this.sequencerLibrary;
-    }
-
-    /**
-     * Add the configuration for a sequencer, or update any existing one that represents the
-     * {@link SequencerConfig#equals(Object) same configuration}
-     * 
-     * @param config the new configuration
-     * @return true if the sequencer was added, or false if there already was an existing and
-     *         {@link SequencerConfig#hasChanged(SequencerConfig) unchanged} sequencer configuration
-     * @throws IllegalArgumentException if <code>config</code> is null
-     * @see #updateSequencer(SequencerConfig)
-     * @see #removeSequencer(SequencerConfig)
-     */
-    public boolean addSequencer( SequencerConfig config ) {
-        return this.sequencerLibrary.add(config);
-    }
-
-    /**
-     * Update the configuration for a sequencer, or add it if there is no {@link SequencerConfig#equals(Object) matching
-     * configuration}.
-     * 
-     * @param config the updated (or new) configuration
-     * @return true if the sequencer was updated, or false if there already was an existing and
-     *         {@link SequencerConfig#hasChanged(SequencerConfig) unchanged} sequencer configuration
-     * @throws IllegalArgumentException if <code>config</code> is null
-     * @see #addSequencer(SequencerConfig)
-     * @see #removeSequencer(SequencerConfig)
-     */
-    public boolean updateSequencer( SequencerConfig config ) {
-        return this.sequencerLibrary.update(config);
-    }
-
-    /**
-     * Remove the configuration for a sequencer.
-     * 
-     * @param config the configuration to be removed
-     * @return true if the sequencer was removed, or false if there was no existing sequencer
-     * @throws IllegalArgumentException if <code>config</code> is null
-     * @see #addSequencer(SequencerConfig)
-     * @see #updateSequencer(SequencerConfig)
-     */
-    public boolean removeSequencer( SequencerConfig config ) {
-        return this.sequencerLibrary.remove(config);
-    }
-
-    /**
-     * @return executionContext
-     */
-    public JcrExecutionContext getExecutionContext() {
-        return this.executionContext;
-    }
-
-    /**
-     * @param executionContext Sets executionContext to the specified value.
-     */
-    public void setExecutionContext( JcrExecutionContext executionContext ) {
-        CheckArg.isNotNull(executionContext, "execution context");
-        if (this.getAdministrator().isStarted()) {
-            throw new IllegalStateException(RepositoryI18n.unableToChangeExecutionContextWhileRunning.text());
-        }
-        this.executionContext = executionContext;
-        this.sequencerLibrary.setClassLoaderFactory(executionContext);
-    }
-
-    /**
-     * Get the executor service used to run the sequencers.
-     * 
-     * @return the executor service
-     * @see #setExecutorService(ExecutorService)
-     */
-    public ExecutorService getExecutorService() {
-        return this.executorService;
-    }
-
-    /**
-     * Set the executor service that should be used by this system. By default, the system is set up with a
-     * {@link Executors#newSingleThreadExecutor() executor that uses a single thread}.
-     * 
-     * @param executorService the executor service
-     * @see #getExecutorService()
-     * @see Executors#newCachedThreadPool()
-     * @see Executors#newCachedThreadPool(java.util.concurrent.ThreadFactory)
-     * @see Executors#newFixedThreadPool(int)
-     * @see Executors#newFixedThreadPool(int, java.util.concurrent.ThreadFactory)
-     * @see Executors#newScheduledThreadPool(int)
-     * @see Executors#newScheduledThreadPool(int, java.util.concurrent.ThreadFactory)
-     * @see Executors#newSingleThreadExecutor()
-     * @see Executors#newSingleThreadExecutor(java.util.concurrent.ThreadFactory)
-     * @see Executors#newSingleThreadScheduledExecutor()
-     * @see Executors#newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory)
-     */
-    public void setExecutorService( ExecutorService executorService ) {
-        CheckArg.isNotNull(executorService, "executor service");
-        if (this.getAdministrator().isStarted()) {
-            throw new IllegalStateException(RepositoryI18n.unableToChangeExecutionContextWhileRunning.text());
-        }
-        this.executorService = executorService;
-    }
-
-    /**
-     * Override this method to creates a different kind of default executor service. This method is called when the system is
-     * {@link #startService() started} without an executor service being {@link #setExecutorService(ExecutorService) set}.
-     * <p>
-     * This method creates a {@link Executors#newSingleThreadExecutor() single-threaded executor}.
-     * </p>
-     * 
-     * @return the executor service
-     */
-    protected ExecutorService createDefaultExecutorService() {
-        return Executors.newSingleThreadExecutor();
-    }
-
-    protected void startService() {
-        if (this.getExecutionContext() == null) {
-            throw new IllegalStateException(RepositoryI18n.unableToStartSequencingServiceWithoutExecutionContext.text());
-        }
-        if (this.executorService == null) {
-            this.executorService = createDefaultExecutorService();
-        }
-        assert this.executorService != null;
-        assert this.sequencerSelector != null;
-        assert this.nodeFilter != null;
-        assert this.sequencerLibrary != null;
-    }
-
-    protected void shutdownService() {
-        if (this.executorService != null) {
-            this.executorService.shutdown();
-        }
-    }
-
-    protected boolean isServiceTerminated() {
-        if (this.executorService != null) {
-            return this.executorService.isTerminated();
-        }
-        return true;
-    }
-
-    protected boolean doAwaitTermination( long timeout,
-                                          TimeUnit unit ) throws InterruptedException {
-        if (this.executorService == null || this.executorService.isTerminated()) return true;
-        return this.executorService.awaitTermination(timeout, unit);
-    }
-
-    /**
-     * Get the sequencing selector used by this system.
-     * 
-     * @return the sequencing selector
-     */
-    public Selector getSequencerSelector() {
-        return this.sequencerSelector;
-    }
-
-    /**
-     * Set the sequencer selector, or null if the {@link #DEFAULT_SEQUENCER_SELECTOR default sequencer selector} should be used.
-     * 
-     * @param sequencerSelector the selector
-     */
-    public void setSequencerSelector( Selector sequencerSelector ) {
-        this.sequencerSelector = sequencerSelector != null ? sequencerSelector : DEFAULT_SEQUENCER_SELECTOR;
-    }
-
-    /**
-     * Get the node filter used by this system.
-     * 
-     * @return the node filter
-     */
-    public NodeFilter getNodeFilter() {
-        return this.nodeFilter;
-    }
-
-    /**
-     * Set the filter that checks which nodes are to be sequenced, or null if the {@link #DEFAULT_NODE_FILTER default node filter}
-     * should be used.
-     * 
-     * @param nodeFilter the new node filter
-     */
-    public void setNodeFilter( NodeFilter nodeFilter ) {
-        this.nodeFilter = nodeFilter != null ? nodeFilter : DEFAULT_NODE_FILTER;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void onNodeChanges( NodeChanges changes ) {
-        NodeFilter filter = this.getNodeFilter();
-        for (final NodeChange changedNode : changes) {
-            // Only care about new nodes or nodes that have new/changed properies ...
-            if (filter.accept(changedNode)) {
-                try {
-                    this.executorService.execute(new Runnable() {
-
-                        public void run() {
-                            processChangedNode(changedNode);
-                        }
-                    });
-                } catch (RejectedExecutionException e) {
-                    // The executor service has been shut down, so do nothing with this set of changes
-                }
-            }
-        }
-    }
-
-    /**
-     * Do the work of processing by sequencing the node. This method is called by the {@link #executorService executor service}
-     * when it performs it's work on the enqueued {@link NodeChange NodeChange runnable objects}.
-     * 
-     * @param changedNode the node to be processed.
-     */
-    protected void processChangedNode( NodeChange changedNode ) {
-        final JcrExecutionContext context = this.getExecutionContext();
-        final Logger logger = context.getLogger(getClass());
-        assert logger != null;
-        try {
-            final String repositoryWorkspaceName = changedNode.getRepositoryWorkspaceName();
-            Session session = null;
-            try {
-                // Figure out which sequencers accept this path,
-                // and track which output nodes should be passed to each sequencer...
-                final String nodePath = changedNode.getAbsolutePath();
-                Map<SequencerCall, Set<RepositoryNodePath>> sequencerCalls = new HashMap<SequencerCall, Set<RepositoryNodePath>>();
-                List<Sequencer> allSequencers = this.sequencerLibrary.getInstances();
-                List<Sequencer> sequencers = new ArrayList<Sequencer>(allSequencers.size());
-                for (Sequencer sequencer : allSequencers) {
-                    final SequencerConfig config = sequencer.getConfiguration();
-                    for (SequencerPathExpression pathExpression : config.getPathExpressions()) {
-                        for (String propertyName : changedNode.getModifiedProperties()) {
-                            String path = nodePath + "/@" + propertyName;
-                            SequencerPathExpression.Matcher matcher = pathExpression.matcher(path);
-                            if (matcher.matches()) {
-                                // String selectedPath = matcher.getSelectedPath();
-                                RepositoryNodePath outputPath = RepositoryNodePath.parse(matcher.getOutputPath(),
-                                                                                         repositoryWorkspaceName);
-                                SequencerCall call = new SequencerCall(sequencer, propertyName);
-                                // Record the output path ...
-                                Set<RepositoryNodePath> outputPaths = sequencerCalls.get(call);
-                                if (outputPaths == null) {
-                                    outputPaths = new HashSet<RepositoryNodePath>();
-                                    sequencerCalls.put(call, outputPaths);
-                                }
-                                outputPaths.add(outputPath);
-                                sequencers.add(sequencer);
-                                break;
-                            }
-                        }
-                    }
-                }
-
-                Node node = null;
-                if (!sequencers.isEmpty()) {
-                    // Create a session that we'll use for all sequencing ...
-                    session = context.getSessionFactory().createSession(repositoryWorkspaceName);
-
-                    // Find the changed node ...
-                    String relPath = changedNode.getAbsolutePath().replaceAll("^/+", "");
-                    node = session.getRootNode().getNode(relPath);
-
-                    // Figure out which sequencers should run ...
-                    sequencers = this.sequencerSelector.selectSequencers(sequencers, node, changedNode);
-                }
-                if (sequencers.isEmpty()) {
-                    this.statistics.recordNodeSkipped();
-                    if (logger.isDebugEnabled()) {
-                        logger.trace("Skipping '{0}': no sequencers matched this condition", changedNode);
-                    }
-                } else {
-                    // Run each of those sequencers ...
-                    for (Map.Entry<SequencerCall, Set<RepositoryNodePath>> entry : sequencerCalls.entrySet()) {
-                        final SequencerCall sequencerCall = entry.getKey();
-                        final Set<RepositoryNodePath> outputPaths = entry.getValue();
-                        final Sequencer sequencer = sequencerCall.getSequencer();
-                        final String sequencerName = sequencer.getConfiguration().getName();
-                        final String propertyName = sequencerCall.getSequencedPropertyName();
-
-                        // Get the paths to the nodes where the sequencer should write it's output ...
-                        assert outputPaths != null && outputPaths.size() != 0;
-
-                        // Create a new execution context for each sequencer
-                        final Context executionContext = new Context(context);
-                        final SimpleProblems problems = new SimpleProblems();
-                        try {
-                            sequencer.execute(node, propertyName, changedNode, outputPaths, executionContext, problems);
-                        } catch (RepositoryException e) {
-                            logger.error(e, RepositoryI18n.errorInRepositoryWhileSequencingNode, sequencerName, changedNode);
-                        } catch (SequencerException e) {
-                            logger.error(e, RepositoryI18n.errorWhileSequencingNode, sequencerName, changedNode);
-                        } finally {
-                            try {
-                                // Save the changes made by each sequencer ...
-                                if (session != null) session.save();
-                            } finally {
-                                // And always close the context.
-                                // This closes all sessions that may have been created by the sequencer.
-                                executionContext.close();
-                            }
-                        }
-                    }
-                    this.statistics.recordNodeSequenced();
-                }
-            } finally {
-                if (session != null) session.logout();
-            }
-        } catch (RepositoryException e) {
-            logger.error(e, RepositoryI18n.errorInRepositoryWhileFindingSequencersToRunAgainstNode, changedNode);
-        } catch (Throwable e) {
-            logger.error(e, RepositoryI18n.errorFindingSequencersToRunAgainstNode, changedNode);
-        }
-    }
-
-    protected class Context implements JcrExecutionContext {
-
-        protected final JcrExecutionContext delegate;
-        protected final SessionFactory factory;
-        private final Set<Session> sessions = new HashSet<Session>();
-        protected final AtomicBoolean closed = new AtomicBoolean(false);
-
-        protected Context( JcrExecutionContext context ) {
-            this.delegate = context;
-            final SessionFactory delegateSessionFactory = this.delegate.getSessionFactory();
-            this.factory = new SessionFactory() {
-
-                public Session createSession( String name ) throws RepositoryException {
-                    if (closed.get()) throw new IllegalStateException(RepositoryI18n.executionContextHasBeenClosed.text());
-                    Session session = delegateSessionFactory.createSession(name);
-                    recordSession(session);
-                    return session;
-                }
-            };
-        }
-
-        public synchronized void close() {
-            if (this.closed.get()) return;
-            this.closed.set(true);
-            for (Session session : sessions) {
-                if (session != null) session.logout();
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.common.component.ClassLoaderFactory#getClassLoader(java.lang.String[])
-         */
-        public ClassLoader getClassLoader( String... classpath ) {
-            return delegate.getClassLoader(classpath);
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.ExecutionContext#getMimeTypeDetector()
-         */
-        public MimeTypeDetector getMimeTypeDetector() {
-            return delegate.getMimeTypeDetector();
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.ExecutionContext#getAccessControlContext()
-         */
-        public AccessControlContext getAccessControlContext() {
-            return delegate.getAccessControlContext();
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.ExecutionContext#getLoginContext()
-         */
-        public LoginContext getLoginContext() {
-            return delegate.getLoginContext();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public NamespaceRegistry getNamespaceRegistry() {
-            return this.delegate.getNamespaceRegistry();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public PropertyFactory getPropertyFactory() {
-            return this.delegate.getPropertyFactory();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public SessionFactory getSessionFactory() {
-            return this.factory;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.ExecutionContext#getSubject()
-         */
-        public Subject getSubject() {
-            return this.delegate.getSubject();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public JcrTools getTools() {
-            return SequencingService.this.getExecutionContext().getTools();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public ValueFactories getValueFactories() {
-            return this.delegate.getValueFactories();
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.ExecutionContext#getLogger(java.lang.Class)
-         */
-        public Logger getLogger( Class<?> clazz ) {
-            return this.delegate.getLogger(clazz);
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.graph.ExecutionContext#getLogger(java.lang.String)
-         */
-        public Logger getLogger( String name ) {
-            return this.delegate.getLogger(name);
-        }
-
-        protected synchronized void recordSession( Session session ) {
-            if (session != null) sessions.add(session);
-        }
-    }
-
-    /**
-     * The statistics for the system. Each sequencing system has an instance of this class that is updated.
-     * 
-     * @author Randall Hauch
-     */
-    @ThreadSafe
-    public class Statistics {
-
-        private final AtomicLong numberOfNodesSequenced = new AtomicLong(0);
-        private final AtomicLong numberOfNodesSkipped = new AtomicLong(0);
-        private final AtomicLong startTime;
-
-        protected Statistics() {
-            startTime = new AtomicLong(System.currentTimeMillis());
-        }
-
-        public Statistics reset() {
-            this.startTime.set(System.currentTimeMillis());
-            this.numberOfNodesSequenced.set(0);
-            this.numberOfNodesSkipped.set(0);
-            return this;
-        }
-
-        /**
-         * @return the system time when the statistics were started
-         */
-        public long getStartTime() {
-            return this.startTime.get();
-        }
-
-        /**
-         * @return the number of nodes that were sequenced
-         */
-        public long getNumberOfNodesSequenced() {
-            return this.numberOfNodesSequenced.get();
-        }
-
-        /**
-         * @return the number of nodes that were skipped because no sequencers applied
-         */
-        public long getNumberOfNodesSkipped() {
-            return this.numberOfNodesSkipped.get();
-        }
-
-        protected void recordNodeSequenced() {
-            this.numberOfNodesSequenced.incrementAndGet();
-        }
-
-        protected void recordNodeSkipped() {
-            this.numberOfNodesSkipped.incrementAndGet();
-        }
-    }
-
-    @Immutable
-    protected class SequencerCall {
-
-        private final Sequencer sequencer;
-        private final String sequencerName;
-        private final String sequencedPropertyName;
-        private final int hc;
-
-        protected SequencerCall( Sequencer sequencer,
-                                 String sequencedPropertyName ) {
-            this.sequencer = sequencer;
-            this.sequencerName = sequencer.getConfiguration().getName();
-            this.sequencedPropertyName = sequencedPropertyName;
-            this.hc = HashCode.compute(this.sequencerName, this.sequencedPropertyName);
-        }
-
-        /**
-         * @return sequencer
-         */
-        public Sequencer getSequencer() {
-            return this.sequencer;
-        }
-
-        /**
-         * @return sequencedPropertyName
-         */
-        public String getSequencedPropertyName() {
-            return this.sequencedPropertyName;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public int hashCode() {
-            return this.hc;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public boolean equals( Object obj ) {
-            if (obj == this) return true;
-            if (obj instanceof SequencerCall) {
-                SequencerCall that = (SequencerCall)obj;
-                if (!this.sequencerName.equals(that.sequencerName)) return false;
-                if (!this.sequencedPropertyName.equals(that.sequencedPropertyName)) return false;
-                return true;
-            }
-            return false;
-        }
-    }
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencingService.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencingService.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/SequencingService.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,654 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import net.jcip.annotations.Immutable;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.collection.SimpleProblems;
+import org.jboss.dna.common.component.ClassLoaderFactory;
+import org.jboss.dna.common.component.ComponentLibrary;
+import org.jboss.dna.common.component.StandardClassLoaderFactory;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.repository.RepositoryI18n;
+import org.jboss.dna.repository.observation.NodeChange;
+import org.jboss.dna.repository.observation.NodeChangeListener;
+import org.jboss.dna.repository.observation.NodeChanges;
+import org.jboss.dna.repository.service.AbstractServiceAdministrator;
+import org.jboss.dna.repository.service.AdministeredService;
+import org.jboss.dna.repository.service.ServiceAdministrator;
+import org.jboss.dna.repository.util.JcrExecutionContext;
+import org.jboss.dna.repository.util.RepositoryNodePath;
+
+/**
+ * A sequencing system is used to monitor changes in the content of {@link Repository JCR repositories} and to sequence the
+ * content to extract or to generate structured information.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class SequencingService implements AdministeredService, NodeChangeListener {
+
+    /**
+     * Interface used to select the set of {@link Sequencer} instances that should be run.
+     * 
+     * @author Randall Hauch
+     */
+    public static interface Selector {
+
+        /**
+         * Select the sequencers that should be used to sequence the supplied node.
+         * 
+         * @param sequencers the list of all sequencers available at the moment; never null
+         * @param node the node to be sequenced; never null
+         * @param nodeChange the set of node changes; never null
+         * @return the list of sequencers that should be used; may not be null
+         */
+        List<Sequencer> selectSequencers( List<Sequencer> sequencers,
+                                          Node node,
+                                          NodeChange nodeChange );
+    }
+
+    /**
+     * The default {@link Selector} implementation that selects every sequencer every time it's called, regardless of the node (or
+     * logger) supplied.
+     * 
+     * @author Randall Hauch
+     */
+    protected static class DefaultSelector implements Selector {
+
+        public List<Sequencer> selectSequencers( List<Sequencer> sequencers,
+                                                 Node node,
+                                                 NodeChange nodeChange ) {
+            return sequencers;
+        }
+    }
+
+    /**
+     * Interface used to determine whether a {@link NodeChange} should be processed.
+     * 
+     * @author Randall Hauch
+     */
+    public static interface NodeFilter {
+
+        /**
+         * Determine whether the node represented by the supplied change should be submitted for sequencing.
+         * 
+         * @param nodeChange the node change event
+         * @return true if the node should be submitted for sequencing, or false if the change should be ignored
+         */
+        boolean accept( NodeChange nodeChange );
+    }
+
+    /**
+     * The default filter implementation, which accepts only new nodes or nodes that have new or changed properties.
+     * 
+     * @author Randall Hauch
+     */
+    protected static class DefaultNodeFilter implements NodeFilter {
+
+        public boolean accept( NodeChange nodeChange ) {
+            // Only care about new nodes or nodes that have new/changed properies ...
+            return nodeChange.includesEventTypes(Event.NODE_ADDED, Event.PROPERTY_ADDED, Event.PROPERTY_CHANGED);
+        }
+    }
+
+    /**
+     * The default {@link Selector} that considers every {@link Sequencer} to be used for every node.
+     * 
+     * @see SequencingService#setSequencerSelector(org.jboss.dna.repository.sequencer.SequencingService.Selector)
+     */
+    public static final Selector DEFAULT_SEQUENCER_SELECTOR = new DefaultSelector();
+    /**
+     * The default {@link NodeFilter} that accepts new nodes or nodes that have new/changed properties.
+     * 
+     * @see SequencingService#setSequencerSelector(org.jboss.dna.repository.sequencer.SequencingService.Selector)
+     */
+    public static final NodeFilter DEFAULT_NODE_FILTER = new DefaultNodeFilter();
+
+    /**
+     * Class loader factory instance that always returns the {@link Thread#getContextClassLoader() current thread's context class
+     * loader} (if not null) or component library's class loader.
+     */
+    protected static final ClassLoaderFactory DEFAULT_CLASSLOADER_FACTORY = new StandardClassLoaderFactory(
+                                                                                                           SequencingService.class.getClassLoader());
+
+    /**
+     * The administrative component for this service.
+     * 
+     * @author Randall Hauch
+     */
+    protected class Administrator extends AbstractServiceAdministrator {
+
+        protected Administrator() {
+            super(RepositoryI18n.sequencingServiceName, State.PAUSED);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected void doStart( State fromState ) {
+            super.doStart(fromState);
+            startService();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected void doShutdown( State fromState ) {
+            super.doShutdown(fromState);
+            shutdownService();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected boolean doCheckIsTerminated() {
+            return isServiceTerminated();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean awaitTermination( long timeout,
+                                         TimeUnit unit ) throws InterruptedException {
+            return doAwaitTermination(timeout, unit);
+        }
+
+    }
+
+    private JcrExecutionContext executionContext;
+    private SequencerLibrary sequencerLibrary = new SequencerLibrary();
+    private Selector sequencerSelector = DEFAULT_SEQUENCER_SELECTOR;
+    private NodeFilter nodeFilter = DEFAULT_NODE_FILTER;
+    private ExecutorService executorService;
+    private final Statistics statistics = new Statistics();
+    private final Administrator administrator = new Administrator();
+
+    /**
+     * Create a new sequencing system, configured with no sequencers and not monitoring any workspaces. Upon construction, the
+     * system is {@link ServiceAdministrator#isPaused() paused} and must be configured and then
+     * {@link ServiceAdministrator#start() started}.
+     */
+    public SequencingService() {
+        this.sequencerLibrary.setClassLoaderFactory(DEFAULT_CLASSLOADER_FACTORY);
+    }
+
+    /**
+     * Return the administrative component for this service.
+     * 
+     * @return the administrative component; never null
+     */
+    public ServiceAdministrator getAdministrator() {
+        return this.administrator;
+    }
+
+    /**
+     * Get the statistics for this system.
+     * 
+     * @return statistics
+     */
+    public Statistics getStatistics() {
+        return this.statistics;
+    }
+
+    /**
+     * @return sequencerLibrary
+     */
+    protected ComponentLibrary<Sequencer, SequencerConfig> getSequencerLibrary() {
+        return this.sequencerLibrary;
+    }
+
+    /**
+     * Add the configuration for a sequencer, or update any existing one that represents the
+     * {@link SequencerConfig#equals(Object) same configuration}
+     * 
+     * @param config the new configuration
+     * @return true if the sequencer was added, or false if there already was an existing and
+     *         {@link SequencerConfig#hasChanged(SequencerConfig) unchanged} sequencer configuration
+     * @throws IllegalArgumentException if <code>config</code> is null
+     * @see #updateSequencer(SequencerConfig)
+     * @see #removeSequencer(SequencerConfig)
+     */
+    public boolean addSequencer( SequencerConfig config ) {
+        return this.sequencerLibrary.add(config);
+    }
+
+    /**
+     * Update the configuration for a sequencer, or add it if there is no {@link SequencerConfig#equals(Object) matching
+     * configuration}.
+     * 
+     * @param config the updated (or new) configuration
+     * @return true if the sequencer was updated, or false if there already was an existing and
+     *         {@link SequencerConfig#hasChanged(SequencerConfig) unchanged} sequencer configuration
+     * @throws IllegalArgumentException if <code>config</code> is null
+     * @see #addSequencer(SequencerConfig)
+     * @see #removeSequencer(SequencerConfig)
+     */
+    public boolean updateSequencer( SequencerConfig config ) {
+        return this.sequencerLibrary.update(config);
+    }
+
+    /**
+     * Remove the configuration for a sequencer.
+     * 
+     * @param config the configuration to be removed
+     * @return true if the sequencer was removed, or false if there was no existing sequencer
+     * @throws IllegalArgumentException if <code>config</code> is null
+     * @see #addSequencer(SequencerConfig)
+     * @see #updateSequencer(SequencerConfig)
+     */
+    public boolean removeSequencer( SequencerConfig config ) {
+        return this.sequencerLibrary.remove(config);
+    }
+
+    /**
+     * @return executionContext
+     */
+    public JcrExecutionContext getExecutionContext() {
+        return this.executionContext;
+    }
+
+    /**
+     * @param executionContext Sets executionContext to the specified value.
+     */
+    public void setExecutionContext( JcrExecutionContext executionContext ) {
+        CheckArg.isNotNull(executionContext, "execution context");
+        if (this.getAdministrator().isStarted()) {
+            throw new IllegalStateException(RepositoryI18n.unableToChangeExecutionContextWhileRunning.text());
+        }
+        this.executionContext = executionContext;
+        this.sequencerLibrary.setClassLoaderFactory(executionContext);
+    }
+
+    /**
+     * Get the executor service used to run the sequencers.
+     * 
+     * @return the executor service
+     * @see #setExecutorService(ExecutorService)
+     */
+    public ExecutorService getExecutorService() {
+        return this.executorService;
+    }
+
+    /**
+     * Set the executor service that should be used by this system. By default, the system is set up with a
+     * {@link Executors#newSingleThreadExecutor() executor that uses a single thread}.
+     * 
+     * @param executorService the executor service
+     * @see #getExecutorService()
+     * @see Executors#newCachedThreadPool()
+     * @see Executors#newCachedThreadPool(java.util.concurrent.ThreadFactory)
+     * @see Executors#newFixedThreadPool(int)
+     * @see Executors#newFixedThreadPool(int, java.util.concurrent.ThreadFactory)
+     * @see Executors#newScheduledThreadPool(int)
+     * @see Executors#newScheduledThreadPool(int, java.util.concurrent.ThreadFactory)
+     * @see Executors#newSingleThreadExecutor()
+     * @see Executors#newSingleThreadExecutor(java.util.concurrent.ThreadFactory)
+     * @see Executors#newSingleThreadScheduledExecutor()
+     * @see Executors#newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory)
+     */
+    public void setExecutorService( ExecutorService executorService ) {
+        CheckArg.isNotNull(executorService, "executor service");
+        if (this.getAdministrator().isStarted()) {
+            throw new IllegalStateException(RepositoryI18n.unableToChangeExecutionContextWhileRunning.text());
+        }
+        this.executorService = executorService;
+    }
+
+    /**
+     * Override this method to creates a different kind of default executor service. This method is called when the system is
+     * {@link #startService() started} without an executor service being {@link #setExecutorService(ExecutorService) set}.
+     * <p>
+     * This method creates a {@link Executors#newSingleThreadExecutor() single-threaded executor}.
+     * </p>
+     * 
+     * @return the executor service
+     */
+    protected ExecutorService createDefaultExecutorService() {
+        return Executors.newSingleThreadExecutor();
+    }
+
+    protected void startService() {
+        if (this.getExecutionContext() == null) {
+            throw new IllegalStateException(RepositoryI18n.unableToStartSequencingServiceWithoutExecutionContext.text());
+        }
+        if (this.executorService == null) {
+            this.executorService = createDefaultExecutorService();
+        }
+        assert this.executorService != null;
+        assert this.sequencerSelector != null;
+        assert this.nodeFilter != null;
+        assert this.sequencerLibrary != null;
+    }
+
+    protected void shutdownService() {
+        if (this.executorService != null) {
+            this.executorService.shutdown();
+        }
+    }
+
+    protected boolean isServiceTerminated() {
+        if (this.executorService != null) {
+            return this.executorService.isTerminated();
+        }
+        return true;
+    }
+
+    protected boolean doAwaitTermination( long timeout,
+                                          TimeUnit unit ) throws InterruptedException {
+        if (this.executorService == null || this.executorService.isTerminated()) return true;
+        return this.executorService.awaitTermination(timeout, unit);
+    }
+
+    /**
+     * Get the sequencing selector used by this system.
+     * 
+     * @return the sequencing selector
+     */
+    public Selector getSequencerSelector() {
+        return this.sequencerSelector;
+    }
+
+    /**
+     * Set the sequencer selector, or null if the {@link #DEFAULT_SEQUENCER_SELECTOR default sequencer selector} should be used.
+     * 
+     * @param sequencerSelector the selector
+     */
+    public void setSequencerSelector( Selector sequencerSelector ) {
+        this.sequencerSelector = sequencerSelector != null ? sequencerSelector : DEFAULT_SEQUENCER_SELECTOR;
+    }
+
+    /**
+     * Get the node filter used by this system.
+     * 
+     * @return the node filter
+     */
+    public NodeFilter getNodeFilter() {
+        return this.nodeFilter;
+    }
+
+    /**
+     * Set the filter that checks which nodes are to be sequenced, or null if the {@link #DEFAULT_NODE_FILTER default node filter}
+     * should be used.
+     * 
+     * @param nodeFilter the new node filter
+     */
+    public void setNodeFilter( NodeFilter nodeFilter ) {
+        this.nodeFilter = nodeFilter != null ? nodeFilter : DEFAULT_NODE_FILTER;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void onNodeChanges( NodeChanges changes ) {
+        NodeFilter filter = this.getNodeFilter();
+        for (final NodeChange changedNode : changes) {
+            // Only care about new nodes or nodes that have new/changed properies ...
+            if (filter.accept(changedNode)) {
+                try {
+                    this.executorService.execute(new Runnable() {
+
+                        public void run() {
+                            processChangedNode(changedNode);
+                        }
+                    });
+                } catch (RejectedExecutionException e) {
+                    // The executor service has been shut down, so do nothing with this set of changes
+                }
+            }
+        }
+    }
+
+    /**
+     * Do the work of processing by sequencing the node. This method is called by the {@link #executorService executor service}
+     * when it performs it's work on the enqueued {@link NodeChange NodeChange runnable objects}.
+     * 
+     * @param changedNode the node to be processed.
+     */
+    protected void processChangedNode( NodeChange changedNode ) {
+        final JcrExecutionContext context = this.getExecutionContext();
+        final Logger logger = context.getLogger(getClass());
+        assert logger != null;
+        try {
+            final String repositoryWorkspaceName = changedNode.getRepositoryWorkspaceName();
+            Session session = null;
+            try {
+                // Figure out which sequencers accept this path,
+                // and track which output nodes should be passed to each sequencer...
+                final String nodePath = changedNode.getAbsolutePath();
+                Map<SequencerCall, Set<RepositoryNodePath>> sequencerCalls = new HashMap<SequencerCall, Set<RepositoryNodePath>>();
+                List<Sequencer> allSequencers = this.sequencerLibrary.getInstances();
+                List<Sequencer> sequencers = new ArrayList<Sequencer>(allSequencers.size());
+                for (Sequencer sequencer : allSequencers) {
+                    final SequencerConfig config = sequencer.getConfiguration();
+                    for (SequencerPathExpression pathExpression : config.getPathExpressions()) {
+                        for (String propertyName : changedNode.getModifiedProperties()) {
+                            String path = nodePath + "/@" + propertyName;
+                            SequencerPathExpression.Matcher matcher = pathExpression.matcher(path);
+                            if (matcher.matches()) {
+                                // String selectedPath = matcher.getSelectedPath();
+                                RepositoryNodePath outputPath = RepositoryNodePath.parse(matcher.getOutputPath(),
+                                                                                         repositoryWorkspaceName);
+                                SequencerCall call = new SequencerCall(sequencer, propertyName);
+                                // Record the output path ...
+                                Set<RepositoryNodePath> outputPaths = sequencerCalls.get(call);
+                                if (outputPaths == null) {
+                                    outputPaths = new HashSet<RepositoryNodePath>();
+                                    sequencerCalls.put(call, outputPaths);
+                                }
+                                outputPaths.add(outputPath);
+                                sequencers.add(sequencer);
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                Node node = null;
+                if (!sequencers.isEmpty()) {
+                    // Create a session that we'll use for all sequencing ...
+                    session = context.getSessionFactory().createSession(repositoryWorkspaceName);
+
+                    // Find the changed node ...
+                    String relPath = changedNode.getAbsolutePath().replaceAll("^/+", "");
+                    node = session.getRootNode().getNode(relPath);
+
+                    // Figure out which sequencers should run ...
+                    sequencers = this.sequencerSelector.selectSequencers(sequencers, node, changedNode);
+                }
+                if (sequencers.isEmpty()) {
+                    this.statistics.recordNodeSkipped();
+                    if (logger.isDebugEnabled()) {
+                        logger.trace("Skipping '{0}': no sequencers matched this condition", changedNode);
+                    }
+                } else {
+                    // Run each of those sequencers ...
+                    for (Map.Entry<SequencerCall, Set<RepositoryNodePath>> entry : sequencerCalls.entrySet()) {
+                        final SequencerCall sequencerCall = entry.getKey();
+                        final Set<RepositoryNodePath> outputPaths = entry.getValue();
+                        final Sequencer sequencer = sequencerCall.getSequencer();
+                        final String sequencerName = sequencer.getConfiguration().getName();
+                        final String propertyName = sequencerCall.getSequencedPropertyName();
+
+                        // Get the paths to the nodes where the sequencer should write it's output ...
+                        assert outputPaths != null && outputPaths.size() != 0;
+
+                        // Create a new execution context for each sequencer
+                        final SimpleProblems problems = new SimpleProblems();
+                        JcrExecutionContext sequencerContext = context.clone();
+                        try {
+                            sequencer.execute(node, propertyName, changedNode, outputPaths, sequencerContext, problems);
+                        } catch (RepositoryException e) {
+                            logger.error(e, RepositoryI18n.errorInRepositoryWhileSequencingNode, sequencerName, changedNode);
+                        } catch (SequencerException e) {
+                            logger.error(e, RepositoryI18n.errorWhileSequencingNode, sequencerName, changedNode);
+                        } finally {
+                            try {
+                                // Save the changes made by each sequencer ...
+                                if (session != null) session.save();
+                            } finally {
+                                // And always close the context.
+                                // This closes all sessions that may have been created by the sequencer.
+                                sequencerContext.close();
+                            }
+                        }
+                    }
+                    this.statistics.recordNodeSequenced();
+                }
+            } finally {
+                if (session != null) session.logout();
+            }
+        } catch (RepositoryException e) {
+            logger.error(e, RepositoryI18n.errorInRepositoryWhileFindingSequencersToRunAgainstNode, changedNode);
+        } catch (Throwable e) {
+            logger.error(e, RepositoryI18n.errorFindingSequencersToRunAgainstNode, changedNode);
+        }
+    }
+
+    /**
+     * The statistics for the system. Each sequencing system has an instance of this class that is updated.
+     * 
+     * @author Randall Hauch
+     */
+    @ThreadSafe
+    public class Statistics {
+
+        private final AtomicLong numberOfNodesSequenced = new AtomicLong(0);
+        private final AtomicLong numberOfNodesSkipped = new AtomicLong(0);
+        private final AtomicLong startTime;
+
+        protected Statistics() {
+            startTime = new AtomicLong(System.currentTimeMillis());
+        }
+
+        public Statistics reset() {
+            this.startTime.set(System.currentTimeMillis());
+            this.numberOfNodesSequenced.set(0);
+            this.numberOfNodesSkipped.set(0);
+            return this;
+        }
+
+        /**
+         * @return the system time when the statistics were started
+         */
+        public long getStartTime() {
+            return this.startTime.get();
+        }
+
+        /**
+         * @return the number of nodes that were sequenced
+         */
+        public long getNumberOfNodesSequenced() {
+            return this.numberOfNodesSequenced.get();
+        }
+
+        /**
+         * @return the number of nodes that were skipped because no sequencers applied
+         */
+        public long getNumberOfNodesSkipped() {
+            return this.numberOfNodesSkipped.get();
+        }
+
+        protected void recordNodeSequenced() {
+            this.numberOfNodesSequenced.incrementAndGet();
+        }
+
+        protected void recordNodeSkipped() {
+            this.numberOfNodesSkipped.incrementAndGet();
+        }
+    }
+
+    @Immutable
+    protected class SequencerCall {
+
+        private final Sequencer sequencer;
+        private final String sequencerName;
+        private final String sequencedPropertyName;
+        private final int hc;
+
+        protected SequencerCall( Sequencer sequencer,
+                                 String sequencedPropertyName ) {
+            this.sequencer = sequencer;
+            this.sequencerName = sequencer.getConfiguration().getName();
+            this.sequencedPropertyName = sequencedPropertyName;
+            this.hc = HashCode.compute(this.sequencerName, this.sequencedPropertyName);
+        }
+
+        /**
+         * @return sequencer
+         */
+        public Sequencer getSequencer() {
+            return this.sequencer;
+        }
+
+        /**
+         * @return sequencedPropertyName
+         */
+        public String getSequencedPropertyName() {
+            return this.sequencedPropertyName;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int hashCode() {
+            return this.hc;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean equals( Object obj ) {
+            if (obj == this) return true;
+            if (obj instanceof SequencerCall) {
+                SequencerCall that = (SequencerCall)obj;
+                if (!this.sequencerName.equals(that.sequencerName)) return false;
+                if (!this.sequencedPropertyName.equals(that.sequencedPropertyName)) return false;
+                return true;
+            }
+            return false;
+        }
+    }
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapter.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,291 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import java.io.InputStream;
-import java.math.BigDecimal;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Set;
-import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import org.jboss.dna.common.collection.Problems;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
-import org.jboss.dna.repository.RepositoryI18n;
-import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-import org.jboss.dna.repository.util.RepositoryNodePath;
-
-/**
- * An adapter class that wraps a {@link StreamSequencer} instance to be a {@link Sequencer}.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class StreamSequencerAdapter implements Sequencer {
-
-    private SequencerConfig configuration;
-    private final StreamSequencer streamSequencer;
-
-    public StreamSequencerAdapter( StreamSequencer streamSequencer ) {
-        this.streamSequencer = streamSequencer;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public SequencerConfig getConfiguration() {
-        return this.configuration;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setConfiguration( SequencerConfig configuration ) {
-        this.configuration = configuration;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void execute( Node input,
-                         String sequencedPropertyName,
-                         NodeChange changes,
-                         Set<RepositoryNodePath> outputPaths,
-                         JcrExecutionContext execContext,
-                         Problems problems ) throws RepositoryException, SequencerException {
-        // 'sequencedPropertyName' contains the name of the modified property on 'input' that resulted in the call to this
-        // sequencer.
-        // 'changes' contains all of the changes to this node that occurred in the transaction.
-        // 'outputPaths' contains the paths of the node(s) where this sequencer is to save it's data.
-
-        // Get the property that contains the data, given by 'propertyName' ...
-        Property sequencedProperty = null;
-        try {
-            sequencedProperty = input.getProperty(sequencedPropertyName);
-        } catch (PathNotFoundException e) {
-            String msg = RepositoryI18n.unableToFindPropertyForSequencing.text(sequencedPropertyName, input.getPath());
-            throw new SequencerException(msg, e);
-        }
-
-        // Get the binary property with the image content, and build the image metadata from the image ...
-        SequencerOutputMap output = new SequencerOutputMap(execContext.getValueFactories());
-        InputStream stream = null;
-        Throwable firstError = null;
-        try {
-            stream = sequencedProperty.getStream();
-            SequencerNodeContext sequencerContext = new SequencerNodeContext(input, sequencedProperty, execContext, problems);
-            this.streamSequencer.sequence(stream, output, sequencerContext);
-        } catch (Throwable t) {
-            // Record the error ...
-            firstError = t;
-        } finally {
-            if (stream != null) {
-                // Always close the stream, recording the error if we've not yet seen an error
-                try {
-                    stream.close();
-                } catch (Throwable t) {
-                    if (firstError == null) firstError = t;
-                } finally {
-                    stream = null;
-                }
-            }
-            if (firstError != null) {
-                // Wrap and throw the first error that we saw ...
-                throw new SequencerException(firstError);
-            }
-        }
-
-        // Find each output node and save the image metadata there ...
-        for (RepositoryNodePath outputPath : outputPaths) {
-            Session session = null;
-            try {
-                // Get the name of the repository workspace and the path to the output node
-                final String repositoryWorkspaceName = outputPath.getRepositoryWorkspaceName();
-                final String nodePath = outputPath.getNodePath();
-
-                // Create a session to the repository where the data should be written ...
-                session = execContext.getSessionFactory().createSession(repositoryWorkspaceName);
-
-                // Find or create the output node in this session ...
-                Node outputNode = execContext.getTools().findOrCreateNode(session, nodePath);
-
-                // Now save the image metadata to the output node ...
-                if (saveOutput(outputNode, output, execContext)) {
-                    session.save();
-                }
-            } finally {
-                // Always close the session ...
-                if (session != null) session.logout();
-            }
-        }
-    }
-
-    /**
-     * Save the sequencing output to the supplied node. This method does not need to save the output, as that is done by the
-     * caller of this method.
-     * 
-     * @param outputNode the existing node onto (or below) which the output is to be written; never null
-     * @param output the (immutable) sequencing output; never null
-     * @param context the execution context for this sequencing operation; never null
-     * @return true if the output was written to the node, or false if no information was written
-     * @throws RepositoryException
-     */
-    protected boolean saveOutput( Node outputNode,
-                                  SequencerOutputMap output,
-                                  JcrExecutionContext context ) throws RepositoryException {
-        if (output.isEmpty()) return false;
-        final PathFactory pathFactory = context.getValueFactories().getPathFactory();
-        final NamespaceRegistry namespaceRegistry = context.getNamespaceRegistry();
-        final Path outputNodePath = pathFactory.create(outputNode.getPath());
-        final Name jcrPrimaryTypePropertyName = context.getValueFactories().getNameFactory().create("jcr:primaryType");
-
-        // Iterate over the entries in the output, in Path's natural order (shorter paths first and in lexicographical order by
-        // prefix and name)
-        for (SequencerOutputMap.Entry entry : output) {
-            Path targetNodePath = entry.getPath();
-            Name primaryType = entry.getPrimaryTypeValue();
-
-            // Resolve this path relative to the output node path, handling any parent or self references ...
-            Path absolutePath = targetNodePath.isAbsolute() ? targetNodePath : outputNodePath.resolve(targetNodePath);
-            Path relativePath = absolutePath.relativeTo(outputNodePath);
-
-            // Find or add the node (which may involve adding intermediate nodes) ...
-            Node targetNode = outputNode;
-            for (int i = 0, max = relativePath.size(); i != max; ++i) {
-                Path.Segment segment = relativePath.getSegment(i);
-                String qualifiedName = segment.getString(namespaceRegistry);
-                if (targetNode.hasNode(qualifiedName)) {
-                    targetNode = targetNode.getNode(qualifiedName);
-                } else {
-                    // It doesn't exist, so create it ...
-                    if (segment.hasIndex()) {
-                        // Use a name without an index ...
-                        qualifiedName = segment.getName().getString(namespaceRegistry);
-                    }
-                    // We only have the primary type for the final one ...
-                    if (i == (max - 1) && primaryType != null) {
-                        targetNode = targetNode.addNode(qualifiedName, primaryType.getString(namespaceRegistry,
-                                                                                             Path.NO_OP_ENCODER));
-                    } else {
-                        targetNode = targetNode.addNode(qualifiedName);
-                    }
-                }
-                assert targetNode != null;
-            }
-            assert targetNode != null;
-
-            // Set all of the properties on this
-            for (SequencerOutputMap.PropertyValue property : entry.getPropertyValues()) {
-                String propertyName = property.getName().getString(namespaceRegistry, Path.NO_OP_ENCODER);
-                Object value = property.getValue();
-                if (jcrPrimaryTypePropertyName.equals(property.getName())) {
-                    // Skip the primary type property (which is protected in Jackrabbit 1.5)
-                    Logger.getLogger(this.getClass()).trace("Skipping property {0}/{1}={2}",
-                                                            targetNode.getPath(),
-                                                            propertyName,
-                                                            value);
-                    continue;
-                }
-                Logger.getLogger(this.getClass()).trace("Writing property {0}/{1}={2}", targetNode.getPath(), propertyName, value);
-                if (value instanceof Boolean) {
-                    targetNode.setProperty(propertyName, ((Boolean)value).booleanValue());
-                } else if (value instanceof String) {
-                    targetNode.setProperty(propertyName, (String)value);
-                } else if (value instanceof String[]) {
-                    targetNode.setProperty(propertyName, (String[])value);
-                } else if (value instanceof Integer) {
-                    targetNode.setProperty(propertyName, ((Integer)value).intValue());
-                } else if (value instanceof Short) {
-                    targetNode.setProperty(propertyName, ((Short)value).shortValue());
-                } else if (value instanceof Long) {
-                    targetNode.setProperty(propertyName, ((Long)value).longValue());
-                } else if (value instanceof Float) {
-                    targetNode.setProperty(propertyName, ((Float)value).floatValue());
-                } else if (value instanceof Double) {
-                    targetNode.setProperty(propertyName, ((Double)value).doubleValue());
-                } else if (value instanceof Binary) {
-                    Binary binaryValue = (Binary)value;
-                    try {
-                        binaryValue.acquire();
-                        targetNode.setProperty(propertyName, binaryValue.getStream());
-                    } finally {
-                        binaryValue.release();
-                    }
-                } else if (value instanceof BigDecimal) {
-                    targetNode.setProperty(propertyName, ((BigDecimal)value).doubleValue());
-                } else if (value instanceof DateTime) {
-                    targetNode.setProperty(propertyName, ((DateTime)value).toCalendar());
-                } else if (value instanceof Date) {
-                    DateTime instant = context.getValueFactories().getDateFactory().create((Date)value);
-                    targetNode.setProperty(propertyName, instant.toCalendar());
-                } else if (value instanceof Calendar) {
-                    targetNode.setProperty(propertyName, (Calendar)value);
-                } else if (value instanceof Name) {
-                    Name nameValue = (Name)value;
-                    String stringValue = nameValue.getString(namespaceRegistry);
-                    targetNode.setProperty(propertyName, stringValue);
-                } else if (value instanceof Path) {
-                    // Find the path to reference node ...
-                    Path pathToReferencedNode = (Path)value;
-                    if (!pathToReferencedNode.isAbsolute()) {
-                        // Resolve the path relative to the output node ...
-                        pathToReferencedNode = outputNodePath.resolve(pathToReferencedNode);
-                    }
-                    // Find the referenced node ...
-                    try {
-                        Node referencedNode = outputNode.getNode(pathToReferencedNode.getString());
-                        targetNode.setProperty(propertyName, referencedNode);
-                    } catch (PathNotFoundException e) {
-                        String msg = RepositoryI18n.errorGettingNodeRelativeToNode.text(value, outputNode.getPath());
-                        throw new SequencerException(msg, e);
-                    }
-                } else if (value == null) {
-                    // Remove the property ...
-                    targetNode.setProperty(propertyName, (String)null);
-                } else {
-                    String msg = RepositoryI18n.unknownPropertyValueType.text(value, value.getClass().getName());
-                    throw new SequencerException(msg);
-                }
-            }
-        }
-
-        return true;
-    }
-
-    protected String[] extractMixinTypes( Object value ) {
-        if (value instanceof String[]) return (String[])value;
-        if (value instanceof String) return new String[] {(String)value};
-        return null;
-    }
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapter.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,402 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.StreamSequencer;
+import org.jboss.dna.repository.RepositoryI18n;
+import org.jboss.dna.repository.mimetype.MimeType;
+import org.jboss.dna.repository.observation.NodeChange;
+import org.jboss.dna.repository.util.JcrExecutionContext;
+import org.jboss.dna.repository.util.RepositoryNodePath;
+
+/**
+ * An adapter class that wraps a {@link StreamSequencer} instance to be a {@link Sequencer}.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class StreamSequencerAdapter implements Sequencer {
+
+    private SequencerConfig configuration;
+    private final StreamSequencer streamSequencer;
+
+    public StreamSequencerAdapter( StreamSequencer streamSequencer ) {
+        this.streamSequencer = streamSequencer;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public SequencerConfig getConfiguration() {
+        return this.configuration;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setConfiguration( SequencerConfig configuration ) {
+        this.configuration = configuration;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void execute( Node input,
+                         String sequencedPropertyName,
+                         NodeChange changes,
+                         Set<RepositoryNodePath> outputPaths,
+                         JcrExecutionContext execContext,
+                         Problems problems ) throws RepositoryException, SequencerException {
+        // 'sequencedPropertyName' contains the name of the modified property on 'input' that resulted in the call to this
+        // sequencer.
+        // 'changes' contains all of the changes to this node that occurred in the transaction.
+        // 'outputPaths' contains the paths of the node(s) where this sequencer is to save it's data.
+
+        // Get the property that contains the data, given by 'propertyName' ...
+        Property sequencedProperty = null;
+        try {
+            sequencedProperty = input.getProperty(sequencedPropertyName);
+        } catch (PathNotFoundException e) {
+            String msg = RepositoryI18n.unableToFindPropertyForSequencing.text(sequencedPropertyName, input.getPath());
+            throw new SequencerException(msg, e);
+        }
+
+        // Get the binary property with the image content, and build the image metadata from the image ...
+        SequencerOutputMap output = new SequencerOutputMap(execContext.getValueFactories());
+        InputStream stream = null;
+        Throwable firstError = null;
+        try {
+            stream = sequencedProperty.getStream();
+            SequencerContext sequencerContext = createSequencerContext(input, sequencedProperty, execContext, problems);
+            this.streamSequencer.sequence(stream, output, sequencerContext);
+        } catch (Throwable t) {
+            // Record the error ...
+            firstError = t;
+        } finally {
+            if (stream != null) {
+                // Always close the stream, recording the error if we've not yet seen an error
+                try {
+                    stream.close();
+                } catch (Throwable t) {
+                    if (firstError == null) firstError = t;
+                } finally {
+                    stream = null;
+                }
+            }
+            if (firstError != null) {
+                // Wrap and throw the first error that we saw ...
+                throw new SequencerException(firstError);
+            }
+        }
+
+        // Find each output node and save the image metadata there ...
+        for (RepositoryNodePath outputPath : outputPaths) {
+            Session session = null;
+            try {
+                // Get the name of the repository workspace and the path to the output node
+                final String repositoryWorkspaceName = outputPath.getRepositoryWorkspaceName();
+                final String nodePath = outputPath.getNodePath();
+
+                // Create a session to the repository where the data should be written ...
+                session = execContext.getSessionFactory().createSession(repositoryWorkspaceName);
+
+                // Find or create the output node in this session ...
+                Node outputNode = execContext.getTools().findOrCreateNode(session, nodePath);
+
+                // Now save the image metadata to the output node ...
+                if (saveOutput(outputNode, output, execContext)) {
+                    session.save();
+                }
+            } finally {
+                // Always close the session ...
+                if (session != null) session.logout();
+            }
+        }
+    }
+
+    /**
+     * Save the sequencing output to the supplied node. This method does not need to save the output, as that is done by the
+     * caller of this method.
+     * 
+     * @param outputNode the existing node onto (or below) which the output is to be written; never null
+     * @param output the (immutable) sequencing output; never null
+     * @param context the execution context for this sequencing operation; never null
+     * @return true if the output was written to the node, or false if no information was written
+     * @throws RepositoryException
+     */
+    protected boolean saveOutput( Node outputNode,
+                                  SequencerOutputMap output,
+                                  JcrExecutionContext context ) throws RepositoryException {
+        if (output.isEmpty()) return false;
+        final PathFactory pathFactory = context.getValueFactories().getPathFactory();
+        final NamespaceRegistry namespaceRegistry = context.getNamespaceRegistry();
+        final Path outputNodePath = pathFactory.create(outputNode.getPath());
+        final Name jcrPrimaryTypePropertyName = context.getValueFactories().getNameFactory().create("jcr:primaryType");
+
+        // Iterate over the entries in the output, in Path's natural order (shorter paths first and in lexicographical order by
+        // prefix and name)
+        for (SequencerOutputMap.Entry entry : output) {
+            Path targetNodePath = entry.getPath();
+            Name primaryType = entry.getPrimaryTypeValue();
+
+            // Resolve this path relative to the output node path, handling any parent or self references ...
+            Path absolutePath = targetNodePath.isAbsolute() ? targetNodePath : outputNodePath.resolve(targetNodePath);
+            Path relativePath = absolutePath.relativeTo(outputNodePath);
+
+            // Find or add the node (which may involve adding intermediate nodes) ...
+            Node targetNode = outputNode;
+            for (int i = 0, max = relativePath.size(); i != max; ++i) {
+                Path.Segment segment = relativePath.getSegment(i);
+                String qualifiedName = segment.getString(namespaceRegistry);
+                if (targetNode.hasNode(qualifiedName)) {
+                    targetNode = targetNode.getNode(qualifiedName);
+                } else {
+                    // It doesn't exist, so create it ...
+                    if (segment.hasIndex()) {
+                        // Use a name without an index ...
+                        qualifiedName = segment.getName().getString(namespaceRegistry);
+                    }
+                    // We only have the primary type for the final one ...
+                    if (i == (max - 1) && primaryType != null) {
+                        targetNode = targetNode.addNode(qualifiedName, primaryType.getString(namespaceRegistry,
+                                                                                             Path.NO_OP_ENCODER));
+                    } else {
+                        targetNode = targetNode.addNode(qualifiedName);
+                    }
+                }
+                assert targetNode != null;
+            }
+            assert targetNode != null;
+
+            // Set all of the properties on this
+            for (SequencerOutputMap.PropertyValue property : entry.getPropertyValues()) {
+                String propertyName = property.getName().getString(namespaceRegistry, Path.NO_OP_ENCODER);
+                Object value = property.getValue();
+                if (jcrPrimaryTypePropertyName.equals(property.getName())) {
+                    // Skip the primary type property (which is protected in Jackrabbit 1.5)
+                    Logger.getLogger(this.getClass()).trace("Skipping property {0}/{1}={2}",
+                                                            targetNode.getPath(),
+                                                            propertyName,
+                                                            value);
+                    continue;
+                }
+                Logger.getLogger(this.getClass()).trace("Writing property {0}/{1}={2}", targetNode.getPath(), propertyName, value);
+                if (value instanceof Boolean) {
+                    targetNode.setProperty(propertyName, ((Boolean)value).booleanValue());
+                } else if (value instanceof String) {
+                    targetNode.setProperty(propertyName, (String)value);
+                } else if (value instanceof String[]) {
+                    targetNode.setProperty(propertyName, (String[])value);
+                } else if (value instanceof Integer) {
+                    targetNode.setProperty(propertyName, ((Integer)value).intValue());
+                } else if (value instanceof Short) {
+                    targetNode.setProperty(propertyName, ((Short)value).shortValue());
+                } else if (value instanceof Long) {
+                    targetNode.setProperty(propertyName, ((Long)value).longValue());
+                } else if (value instanceof Float) {
+                    targetNode.setProperty(propertyName, ((Float)value).floatValue());
+                } else if (value instanceof Double) {
+                    targetNode.setProperty(propertyName, ((Double)value).doubleValue());
+                } else if (value instanceof Binary) {
+                    Binary binaryValue = (Binary)value;
+                    try {
+                        binaryValue.acquire();
+                        targetNode.setProperty(propertyName, binaryValue.getStream());
+                    } finally {
+                        binaryValue.release();
+                    }
+                } else if (value instanceof BigDecimal) {
+                    targetNode.setProperty(propertyName, ((BigDecimal)value).doubleValue());
+                } else if (value instanceof DateTime) {
+                    targetNode.setProperty(propertyName, ((DateTime)value).toCalendar());
+                } else if (value instanceof Date) {
+                    DateTime instant = context.getValueFactories().getDateFactory().create((Date)value);
+                    targetNode.setProperty(propertyName, instant.toCalendar());
+                } else if (value instanceof Calendar) {
+                    targetNode.setProperty(propertyName, (Calendar)value);
+                } else if (value instanceof Name) {
+                    Name nameValue = (Name)value;
+                    String stringValue = nameValue.getString(namespaceRegistry);
+                    targetNode.setProperty(propertyName, stringValue);
+                } else if (value instanceof Path) {
+                    // Find the path to reference node ...
+                    Path pathToReferencedNode = (Path)value;
+                    if (!pathToReferencedNode.isAbsolute()) {
+                        // Resolve the path relative to the output node ...
+                        pathToReferencedNode = outputNodePath.resolve(pathToReferencedNode);
+                    }
+                    // Find the referenced node ...
+                    try {
+                        Node referencedNode = outputNode.getNode(pathToReferencedNode.getString());
+                        targetNode.setProperty(propertyName, referencedNode);
+                    } catch (PathNotFoundException e) {
+                        String msg = RepositoryI18n.errorGettingNodeRelativeToNode.text(value, outputNode.getPath());
+                        throw new SequencerException(msg, e);
+                    }
+                } else if (value == null) {
+                    // Remove the property ...
+                    targetNode.setProperty(propertyName, (String)null);
+                } else {
+                    String msg = RepositoryI18n.unknownPropertyValueType.text(value, value.getClass().getName());
+                    throw new SequencerException(msg);
+                }
+            }
+        }
+
+        return true;
+    }
+
+    protected String[] extractMixinTypes( Object value ) {
+        if (value instanceof String[]) return (String[])value;
+        if (value instanceof String) return new String[] {(String)value};
+        return null;
+    }
+
+    protected SequencerContext createSequencerContext( Node input,
+                                                       Property sequencedProperty,
+                                                       ExecutionContext context,
+                                                       Problems problems ) throws RepositoryException {
+        assert input != null;
+        assert sequencedProperty != null;
+        assert context != null;
+        assert problems != null;
+        // Translate JCR path and property values to DNA constructs and cache them to improve performance and prevent
+        // RepositoryException from being thrown by getters
+        // Note: getMimeType() will still operate lazily, and thus throw a SequencerException, since it is very intrusive and
+        // potentially slow-running.
+        ValueFactories factories = context.getValueFactories();
+        Path path = factories.getPathFactory().create(input.getPath());
+        Set<org.jboss.dna.graph.property.Property> props = new HashSet<org.jboss.dna.graph.property.Property>();
+        for (PropertyIterator iter = input.getProperties(); iter.hasNext();) {
+            javax.jcr.Property jcrProp = iter.nextProperty();
+            org.jboss.dna.graph.property.Property prop;
+            if (jcrProp.getDefinition().isMultiple()) {
+                Value[] jcrVals = jcrProp.getValues();
+                Object[] vals = new Object[jcrVals.length];
+                int ndx = 0;
+                for (Value jcrVal : jcrVals) {
+                    vals[ndx++] = convert(factories, jcrProp.getName(), jcrVal);
+                }
+                prop = context.getPropertyFactory().create(factories.getNameFactory().create(jcrProp.getName()), vals);
+            } else {
+                Value jcrVal = jcrProp.getValue();
+                Object val = convert(factories, jcrProp.getName(), jcrVal);
+                prop = context.getPropertyFactory().create(factories.getNameFactory().create(jcrProp.getName()), val);
+            }
+            props.add(prop);
+        }
+        props = Collections.unmodifiableSet(props);
+        String mimeType = getMimeType(sequencedProperty, path.getLastSegment().getName().getLocalName());
+        return new SequencerContext(context, path, props, mimeType, problems);
+    }
+
+    protected Object convert( ValueFactories factories,
+                              String name,
+                              Value jcrValue ) throws RepositoryException {
+        switch (jcrValue.getType()) {
+            case PropertyType.BINARY: {
+                return factories.getBinaryFactory().create(jcrValue.getStream());
+            }
+            case PropertyType.BOOLEAN: {
+                return factories.getBooleanFactory().create(jcrValue.getBoolean());
+            }
+            case PropertyType.DATE: {
+                return factories.getDateFactory().create(jcrValue.getDate());
+            }
+            case PropertyType.DOUBLE: {
+                return factories.getDoubleFactory().create(jcrValue.getDouble());
+            }
+            case PropertyType.LONG: {
+                return factories.getLongFactory().create(jcrValue.getLong());
+            }
+            case PropertyType.NAME: {
+                return factories.getNameFactory().create(jcrValue.getString());
+            }
+            case PropertyType.PATH: {
+                return factories.getPathFactory().create(jcrValue.getString());
+            }
+            case PropertyType.REFERENCE: {
+                return factories.getReferenceFactory().create(jcrValue.getString());
+            }
+            case PropertyType.STRING: {
+                return factories.getStringFactory().create(jcrValue.getString());
+            }
+            default: {
+                throw new RepositoryException(RepositoryI18n.unknownPropertyValueType.text(name, jcrValue.getType()));
+            }
+        }
+    }
+
+    @SuppressWarnings( "null" )
+    // The need for the SuppressWarnings looks like an Eclipse bug
+    protected String getMimeType( Property sequencedProperty,
+                                  String name ) {
+        SequencerException err = null;
+        String mimeType = null;
+        InputStream stream = null;
+        try {
+            stream = sequencedProperty.getStream();
+            mimeType = MimeType.of(name, stream);
+            return mimeType;
+        } catch (Exception error) {
+            err = new SequencerException(error);
+        } finally {
+            if (stream != null) {
+                try {
+                    stream.close();
+                } catch (IOException error) {
+                    // Only throw exception if an exception was not already thrown
+                    if (err == null) err = new SequencerException(error);
+                }
+            }
+        }
+        if (err != null) throw err;
+        return mimeType;
+    }
+}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/service (from rev 705, trunk/dna-repository/src/main/java/org/jboss/dna/repository/services)

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AbstractServiceAdministrator.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/AbstractServiceAdministrator.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AbstractServiceAdministrator.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,310 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.services;
-
-import java.util.Locale;
-import net.jcip.annotations.GuardedBy;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.i18n.I18n;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.repository.RepositoryI18n;
-
-/**
- * Simple abstract implementation of the service administrator interface that can be easily subclassed by services that require an
- * administrative interface.
- * 
- * @author Randall Hauch
- */
- at ThreadSafe
-public abstract class AbstractServiceAdministrator implements ServiceAdministrator {
-
-    private volatile State state;
-    private final I18n serviceName;
-    private final Logger logger;
-
-    protected AbstractServiceAdministrator( I18n serviceName,
-                                            State initialState ) {
-        assert initialState != null;
-        assert serviceName != null;
-        this.state = initialState;
-        this.serviceName = serviceName;
-        this.logger = Logger.getLogger(getClass());
-    }
-
-    /**
-     * Return the current state of this service.
-     * 
-     * @return the current state
-     */
-    public State getState() {
-        return this.state;
-    }
-
-    /**
-     * Set the state of the service. This method does nothing if the desired state matches the current state.
-     * 
-     * @param state the desired state
-     * @return this object for method chaining purposes
-     * @see #setState(String)
-     * @see #start()
-     * @see #pause()
-     * @see #shutdown()
-     */
-    @GuardedBy( "this" )
-    public synchronized ServiceAdministrator setState( State state ) {
-        switch (state) {
-            case STARTED:
-                start();
-                break;
-            case PAUSED:
-                pause();
-                break;
-            case SHUTDOWN:
-            case TERMINATED:
-                shutdown();
-                break;
-        }
-        return this;
-    }
-
-    /**
-     * Set the state of the service. This method does nothing if the desired state matches the current state.
-     * 
-     * @param state the desired state in string form
-     * @return this object for method chaining purposes
-     * @throws IllegalArgumentException if the specified state string is null or does not match one of the predefined
-     *         {@link ServiceAdministrator.State predefined enumerated values}
-     * @see #setState(State)
-     * @see #start()
-     * @see #pause()
-     * @see #shutdown()
-     */
-    public ServiceAdministrator setState( String state ) {
-        State newState = state == null ? null : State.valueOf(state.toUpperCase());
-        if (newState == null) {
-            throw new IllegalArgumentException(RepositoryI18n.invalidStateString.text(state));
-        }
-        return setState(newState);
-    }
-
-    /**
-     * Start monitoring and sequence the events. This method can be called multiple times, including after the service is
-     * {@link #pause() paused}. However, once the service is {@link #shutdown() shutdown}, it cannot be started or paused.
-     * 
-     * @return this object for method chaining purposes
-     * @throws IllegalStateException if called when the service has been {@link #shutdown() shutdown}.
-     * @see #pause()
-     * @see #shutdown()
-     * @see #isStarted()
-     */
-    public synchronized ServiceAdministrator start() {
-        switch (this.state) {
-            case STARTED:
-                break;
-            case PAUSED:
-                logger.trace("Starting \"{0}\"", getServiceName());
-                doStart(this.state);
-                this.state = State.STARTED;
-                logger.trace("Started \"{0}\"", getServiceName());
-                break;
-            case SHUTDOWN:
-            case TERMINATED:
-                throw new IllegalStateException(RepositoryI18n.serviceShutdowAndMayNotBeStarted.text(getServiceName()));
-        }
-        return this;
-    }
-
-    /**
-     * Implementation of the functionality to switch to the started state. This method is only called if the state from which the
-     * service is transitioning is appropriate ({@link ServiceAdministrator.State#PAUSED}). This method does nothing by default,
-     * and should be overridden if needed.
-     * 
-     * @param fromState the state from which this service is transitioning; never null
-     * @throws IllegalStateException if the service is such that it cannot be transitioned from the supplied state
-     */
-    @GuardedBy( "this" )
-    protected void doStart( State fromState ) {
-    }
-
-    /**
-     * Temporarily stop monitoring and sequencing events. This method can be called multiple times, including after the service is
-     * {@link #start() started}. However, once the service is {@link #shutdown() shutdown}, it cannot be started or paused.
-     * 
-     * @return this object for method chaining purposes
-     * @throws IllegalStateException if called when the service has been {@link #shutdown() shutdown}.
-     * @see #start()
-     * @see #shutdown()
-     * @see #isPaused()
-     */
-    public synchronized ServiceAdministrator pause() {
-        switch (this.state) {
-            case STARTED:
-                logger.trace("Pausing \"{0}\"", getServiceName());
-                doPause(this.state);
-                this.state = State.PAUSED;
-                logger.trace("Paused \"{0}\"", getServiceName());
-                break;
-            case PAUSED:
-                break;
-            case SHUTDOWN:
-            case TERMINATED:
-                throw new IllegalStateException(RepositoryI18n.serviceShutdowAndMayNotBePaused.text(getServiceName()));
-        }
-        return this;
-    }
-
-    /**
-     * Implementation of the functionality to switch to the paused state. This method is only called if the state from which the
-     * service is transitioning is appropriate ({@link ServiceAdministrator.State#STARTED}). This method does nothing by default,
-     * and should be overridden if needed.
-     * 
-     * @param fromState the state from which this service is transitioning; never null
-     * @throws IllegalStateException if the service is such that it cannot be transitioned from the supplied state
-     */
-    @GuardedBy( "this" )
-    protected void doPause( State fromState ) {
-    }
-
-    /**
-     * Permanently stop monitoring and sequencing events. This method can be called multiple times, but only the first call has an
-     * effect. Once the service has been shutdown, it may not be {@link #start() restarted} or {@link #pause() paused}.
-     * 
-     * @return this object for method chaining purposes
-     * @see #start()
-     * @see #pause()
-     * @see #isShutdown()
-     */
-    public synchronized ServiceAdministrator shutdown() {
-        switch (this.state) {
-            case STARTED:
-            case PAUSED:
-                logger.trace("Initiating shutdown of \"{0}\"", getServiceName());
-                this.state = State.SHUTDOWN;
-                doShutdown(this.state);
-                logger.trace("Initiated shutdown of \"{0}\"", getServiceName());
-                isTerminated();
-                break;
-            case SHUTDOWN:
-            case TERMINATED:
-                isTerminated();
-                break;
-        }
-        return this;
-    }
-
-    /**
-     * Implementation of the functionality to switch to the shutdown state. This method is only called if the state from which the
-     * service is transitioning is appropriate ({@link ServiceAdministrator.State#STARTED} or
-     * {@link ServiceAdministrator.State#PAUSED}). This method does nothing by default, and should be overridden if needed.
-     * 
-     * @param fromState the state from which this service is transitioning; never null
-     * @throws IllegalStateException if the service is such that it cannot be transitioned from the supplied state
-     */
-    @GuardedBy( "this" )
-    protected void doShutdown( State fromState ) {
-    }
-
-    /**
-     * Return whether this service has been started and is currently running.
-     * 
-     * @return true if started and currently running, or false otherwise
-     * @see #start()
-     * @see #pause()
-     * @see #isPaused()
-     * @see #isShutdown()
-     */
-    public boolean isStarted() {
-        return this.state == State.STARTED;
-    }
-
-    /**
-     * Return whether this service is currently paused.
-     * 
-     * @return true if currently paused, or false otherwise
-     * @see #pause()
-     * @see #start()
-     * @see #isStarted()
-     * @see #isShutdown()
-     */
-    public boolean isPaused() {
-        return this.state == State.PAUSED;
-    }
-
-    /**
-     * Return whether this service is stopped and unable to be restarted.
-     * 
-     * @return true if currently shutdown, or false otherwise
-     * @see #shutdown()
-     * @see #isPaused()
-     * @see #isStarted()
-     */
-    public boolean isShutdown() {
-        return this.state == State.SHUTDOWN || this.state == State.TERMINATED;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isTerminated() {
-        switch (this.state) {
-            case PAUSED:
-            case STARTED:
-            case SHUTDOWN:
-                if (doCheckIsTerminated()) {
-                    this.state = State.TERMINATED;
-                    logger.trace("Service \"{0}\" has terminated", getServiceName());
-                    return true;
-                }
-                return false;
-            case TERMINATED:
-                return true;
-        }
-        return false;
-    }
-
-    /**
-     * Subclasses should implement this method to determine whether the service has completed shutdown.
-     * 
-     * @return true if terminated, or false otherwise
-     */
-    protected abstract boolean doCheckIsTerminated();
-
-    /**
-     * Get the name of this service in the current locale.
-     * 
-     * @return the service name
-     */
-    public String getServiceName() {
-        return this.serviceName.text();
-    }
-
-    /**
-     * Get the name of this service in the specified locale.
-     * 
-     * @param locale the locale in which the service name is to be returned; may be null if the default locale is to be used
-     * @return the service name
-     */
-    public String getServiceName( Locale locale ) {
-        return this.serviceName.text(locale);
-    }
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AbstractServiceAdministrator.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/AbstractServiceAdministrator.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AbstractServiceAdministrator.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AbstractServiceAdministrator.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,310 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.service;
+
+import java.util.Locale;
+import net.jcip.annotations.GuardedBy;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.i18n.I18n;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.repository.RepositoryI18n;
+
+/**
+ * Simple abstract implementation of the service administrator interface that can be easily subclassed by services that require an
+ * administrative interface.
+ * 
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public abstract class AbstractServiceAdministrator implements ServiceAdministrator {
+
+    private volatile State state;
+    private final I18n serviceName;
+    private final Logger logger;
+
+    protected AbstractServiceAdministrator( I18n serviceName,
+                                            State initialState ) {
+        assert initialState != null;
+        assert serviceName != null;
+        this.state = initialState;
+        this.serviceName = serviceName;
+        this.logger = Logger.getLogger(getClass());
+    }
+
+    /**
+     * Return the current state of this service.
+     * 
+     * @return the current state
+     */
+    public State getState() {
+        return this.state;
+    }
+
+    /**
+     * Set the state of the service. This method does nothing if the desired state matches the current state.
+     * 
+     * @param state the desired state
+     * @return this object for method chaining purposes
+     * @see #setState(String)
+     * @see #start()
+     * @see #pause()
+     * @see #shutdown()
+     */
+    @GuardedBy( "this" )
+    public synchronized ServiceAdministrator setState( State state ) {
+        switch (state) {
+            case STARTED:
+                start();
+                break;
+            case PAUSED:
+                pause();
+                break;
+            case SHUTDOWN:
+            case TERMINATED:
+                shutdown();
+                break;
+        }
+        return this;
+    }
+
+    /**
+     * Set the state of the service. This method does nothing if the desired state matches the current state.
+     * 
+     * @param state the desired state in string form
+     * @return this object for method chaining purposes
+     * @throws IllegalArgumentException if the specified state string is null or does not match one of the predefined
+     *         {@link ServiceAdministrator.State predefined enumerated values}
+     * @see #setState(State)
+     * @see #start()
+     * @see #pause()
+     * @see #shutdown()
+     */
+    public ServiceAdministrator setState( String state ) {
+        State newState = state == null ? null : State.valueOf(state.toUpperCase());
+        if (newState == null) {
+            throw new IllegalArgumentException(RepositoryI18n.invalidStateString.text(state));
+        }
+        return setState(newState);
+    }
+
+    /**
+     * Start monitoring and sequence the events. This method can be called multiple times, including after the service is
+     * {@link #pause() paused}. However, once the service is {@link #shutdown() shutdown}, it cannot be started or paused.
+     * 
+     * @return this object for method chaining purposes
+     * @throws IllegalStateException if called when the service has been {@link #shutdown() shutdown}.
+     * @see #pause()
+     * @see #shutdown()
+     * @see #isStarted()
+     */
+    public synchronized ServiceAdministrator start() {
+        switch (this.state) {
+            case STARTED:
+                break;
+            case PAUSED:
+                logger.trace("Starting \"{0}\"", getServiceName());
+                doStart(this.state);
+                this.state = State.STARTED;
+                logger.trace("Started \"{0}\"", getServiceName());
+                break;
+            case SHUTDOWN:
+            case TERMINATED:
+                throw new IllegalStateException(RepositoryI18n.serviceShutdowAndMayNotBeStarted.text(getServiceName()));
+        }
+        return this;
+    }
+
+    /**
+     * Implementation of the functionality to switch to the started state. This method is only called if the state from which the
+     * service is transitioning is appropriate ({@link ServiceAdministrator.State#PAUSED}). This method does nothing by default,
+     * and should be overridden if needed.
+     * 
+     * @param fromState the state from which this service is transitioning; never null
+     * @throws IllegalStateException if the service is such that it cannot be transitioned from the supplied state
+     */
+    @GuardedBy( "this" )
+    protected void doStart( State fromState ) {
+    }
+
+    /**
+     * Temporarily stop monitoring and sequencing events. This method can be called multiple times, including after the service is
+     * {@link #start() started}. However, once the service is {@link #shutdown() shutdown}, it cannot be started or paused.
+     * 
+     * @return this object for method chaining purposes
+     * @throws IllegalStateException if called when the service has been {@link #shutdown() shutdown}.
+     * @see #start()
+     * @see #shutdown()
+     * @see #isPaused()
+     */
+    public synchronized ServiceAdministrator pause() {
+        switch (this.state) {
+            case STARTED:
+                logger.trace("Pausing \"{0}\"", getServiceName());
+                doPause(this.state);
+                this.state = State.PAUSED;
+                logger.trace("Paused \"{0}\"", getServiceName());
+                break;
+            case PAUSED:
+                break;
+            case SHUTDOWN:
+            case TERMINATED:
+                throw new IllegalStateException(RepositoryI18n.serviceShutdowAndMayNotBePaused.text(getServiceName()));
+        }
+        return this;
+    }
+
+    /**
+     * Implementation of the functionality to switch to the paused state. This method is only called if the state from which the
+     * service is transitioning is appropriate ({@link ServiceAdministrator.State#STARTED}). This method does nothing by default,
+     * and should be overridden if needed.
+     * 
+     * @param fromState the state from which this service is transitioning; never null
+     * @throws IllegalStateException if the service is such that it cannot be transitioned from the supplied state
+     */
+    @GuardedBy( "this" )
+    protected void doPause( State fromState ) {
+    }
+
+    /**
+     * Permanently stop monitoring and sequencing events. This method can be called multiple times, but only the first call has an
+     * effect. Once the service has been shutdown, it may not be {@link #start() restarted} or {@link #pause() paused}.
+     * 
+     * @return this object for method chaining purposes
+     * @see #start()
+     * @see #pause()
+     * @see #isShutdown()
+     */
+    public synchronized ServiceAdministrator shutdown() {
+        switch (this.state) {
+            case STARTED:
+            case PAUSED:
+                logger.trace("Initiating shutdown of \"{0}\"", getServiceName());
+                this.state = State.SHUTDOWN;
+                doShutdown(this.state);
+                logger.trace("Initiated shutdown of \"{0}\"", getServiceName());
+                isTerminated();
+                break;
+            case SHUTDOWN:
+            case TERMINATED:
+                isTerminated();
+                break;
+        }
+        return this;
+    }
+
+    /**
+     * Implementation of the functionality to switch to the shutdown state. This method is only called if the state from which the
+     * service is transitioning is appropriate ({@link ServiceAdministrator.State#STARTED} or
+     * {@link ServiceAdministrator.State#PAUSED}). This method does nothing by default, and should be overridden if needed.
+     * 
+     * @param fromState the state from which this service is transitioning; never null
+     * @throws IllegalStateException if the service is such that it cannot be transitioned from the supplied state
+     */
+    @GuardedBy( "this" )
+    protected void doShutdown( State fromState ) {
+    }
+
+    /**
+     * Return whether this service has been started and is currently running.
+     * 
+     * @return true if started and currently running, or false otherwise
+     * @see #start()
+     * @see #pause()
+     * @see #isPaused()
+     * @see #isShutdown()
+     */
+    public boolean isStarted() {
+        return this.state == State.STARTED;
+    }
+
+    /**
+     * Return whether this service is currently paused.
+     * 
+     * @return true if currently paused, or false otherwise
+     * @see #pause()
+     * @see #start()
+     * @see #isStarted()
+     * @see #isShutdown()
+     */
+    public boolean isPaused() {
+        return this.state == State.PAUSED;
+    }
+
+    /**
+     * Return whether this service is stopped and unable to be restarted.
+     * 
+     * @return true if currently shutdown, or false otherwise
+     * @see #shutdown()
+     * @see #isPaused()
+     * @see #isStarted()
+     */
+    public boolean isShutdown() {
+        return this.state == State.SHUTDOWN || this.state == State.TERMINATED;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isTerminated() {
+        switch (this.state) {
+            case PAUSED:
+            case STARTED:
+            case SHUTDOWN:
+                if (doCheckIsTerminated()) {
+                    this.state = State.TERMINATED;
+                    logger.trace("Service \"{0}\" has terminated", getServiceName());
+                    return true;
+                }
+                return false;
+            case TERMINATED:
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Subclasses should implement this method to determine whether the service has completed shutdown.
+     * 
+     * @return true if terminated, or false otherwise
+     */
+    protected abstract boolean doCheckIsTerminated();
+
+    /**
+     * Get the name of this service in the current locale.
+     * 
+     * @return the service name
+     */
+    public String getServiceName() {
+        return this.serviceName.text();
+    }
+
+    /**
+     * Get the name of this service in the specified locale.
+     * 
+     * @param locale the locale in which the service name is to be returned; may be null if the default locale is to be used
+     * @return the service name
+     */
+    public String getServiceName( Locale locale ) {
+        return this.serviceName.text(locale);
+    }
+
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AdministeredService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/AdministeredService.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AdministeredService.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,30 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.services;
-
-/**
- * @author Randall Hauch
- */
-public interface AdministeredService {
-
-    ServiceAdministrator getAdministrator();
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AdministeredService.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/AdministeredService.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AdministeredService.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/AdministeredService.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,30 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.service;
+
+/**
+ * @author Randall Hauch
+ */
+public interface AdministeredService {
+
+    ServiceAdministrator getAdministrator();
+}

Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/ServiceAdministrator.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/ServiceAdministrator.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/ServiceAdministrator.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,174 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.services;
-
-import java.util.concurrent.TimeUnit;
-import net.jcip.annotations.ThreadSafe;
-
-/**
- * Contract defining an administrative interface for controlling the running state of a service.
- * 
- * @author Randall Hauch
- */
- at ThreadSafe
-public interface ServiceAdministrator {
-
-    /**
-     * The available states.
-     * 
-     * @author Randall Hauch
-     */
-    public static enum State {
-        STARTED,
-        PAUSED,
-        SHUTDOWN,
-        TERMINATED;
-    }
-
-    /**
-     * Return the current state of this system.
-     * 
-     * @return the current state
-     */
-    public State getState();
-
-    /**
-     * Set the state of the system. This method does nothing if the desired state matches the current state.
-     * 
-     * @param state the desired state
-     * @return this object for method chaining purposes
-     * @see #setState(String)
-     * @see #start()
-     * @see #pause()
-     * @see #shutdown()
-     */
-    public ServiceAdministrator setState( State state );
-
-    /**
-     * Set the state of the system. This method does nothing if the desired state matches the current state.
-     * 
-     * @param state the desired state in string form
-     * @return this object for method chaining purposes
-     * @throws IllegalArgumentException if the specified state string is null or does not match one of the predefined
-     * {@link State predefined enumerated values}
-     * @see #setState(State)
-     * @see #start()
-     * @see #pause()
-     * @see #shutdown()
-     */
-    public ServiceAdministrator setState( String state );
-
-    /**
-     * Start monitoring and sequence the events. This method can be called multiple times, including after the system is
-     * {@link #pause() paused}. However, once the system is {@link #shutdown() shutdown}, it cannot be started or paused.
-     * 
-     * @return this object for method chaining purposes
-     * @throws IllegalStateException if called when the system has been {@link #shutdown() shutdown}.
-     * @see #pause()
-     * @see #shutdown()
-     * @see #isStarted()
-     */
-    public ServiceAdministrator start();
-
-    /**
-     * Temporarily stop monitoring and sequencing events. This method can be called multiple times, including after the system is
-     * {@link #start() started}. However, once the system is {@link #shutdown() shutdown}, it cannot be started or paused.
-     * 
-     * @return this object for method chaining purposes
-     * @throws IllegalStateException if called when the system has been {@link #shutdown() shutdown}.
-     * @see #start()
-     * @see #shutdown()
-     * @see #isPaused()
-     */
-    public ServiceAdministrator pause();
-
-    /**
-     * Permanently stop monitoring and sequencing events. This method can be called multiple times, but only the first call has an
-     * effect. Once the system has been shutdown, it may not be {@link #start() restarted} or {@link #pause() paused}.
-     * 
-     * @return this object for method chaining purposes
-     * @see #start()
-     * @see #pause()
-     * @see #isShutdown()
-     */
-    public ServiceAdministrator shutdown();
-
-    /**
-     * Blocks until the shutdown has completed, or the timeout occurs, or the current thread is interrupted, whichever happens
-     * first.
-     * 
-     * @param timeout the maximum time to wait
-     * @param unit the time unit of the timeout argument
-     * @return <tt>true</tt> if this service complete shut down and <tt>false</tt> if the timeout elapsed before it was shut
-     * down completely
-     * @throws InterruptedException if interrupted while waiting
-     */
-    boolean awaitTermination( long timeout, TimeUnit unit ) throws InterruptedException;
-
-    /**
-     * Return whether this system has been started and is currently running.
-     * 
-     * @return true if started and currently running, or false otherwise
-     * @see #start()
-     * @see #pause()
-     * @see #isPaused()
-     * @see #isShutdown()
-     * @see #isTerminated()
-     */
-    public boolean isStarted();
-
-    /**
-     * Return whether this system is currently paused.
-     * 
-     * @return true if currently paused, or false otherwise
-     * @see #pause()
-     * @see #start()
-     * @see #isStarted()
-     * @see #isShutdown()
-     * @see #isTerminated()
-     */
-    public boolean isPaused();
-
-    /**
-     * Return whether this system has been shut down.
-     * 
-     * @return true if this service has been shut down, or false otherwise
-     * @see #shutdown()
-     * @see #isPaused()
-     * @see #isStarted()
-     * @see #isTerminated()
-     */
-    public boolean isShutdown();
-
-    /**
-     * Return whether this system has finished {@link #shutdown() shutting down}. Note that <code>isTerminated</code> is never
-     * <code>true</code> unless either {@link #shutdown()} was called first.
-     * 
-     * @return true if the system has finished shutting down, or false otherwise
-     * @see #shutdown()
-     * @see #isPaused()
-     * @see #isStarted()
-     * @see #isShutdown()
-     */
-    public boolean isTerminated();
-
-}

Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/ServiceAdministrator.java (from rev 706, trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/ServiceAdministrator.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/ServiceAdministrator.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/service/ServiceAdministrator.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.service;
+
+import java.util.concurrent.TimeUnit;
+import net.jcip.annotations.ThreadSafe;
+
+/**
+ * Contract defining an administrative interface for controlling the running state of a service.
+ * 
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public interface ServiceAdministrator {
+
+    /**
+     * The available states.
+     * 
+     * @author Randall Hauch
+     */
+    public static enum State {
+        STARTED,
+        PAUSED,
+        SHUTDOWN,
+        TERMINATED;
+    }
+
+    /**
+     * Return the current state of this system.
+     * 
+     * @return the current state
+     */
+    public State getState();
+
+    /**
+     * Set the state of the system. This method does nothing if the desired state matches the current state.
+     * 
+     * @param state the desired state
+     * @return this object for method chaining purposes
+     * @see #setState(String)
+     * @see #start()
+     * @see #pause()
+     * @see #shutdown()
+     */
+    public ServiceAdministrator setState( State state );
+
+    /**
+     * Set the state of the system. This method does nothing if the desired state matches the current state.
+     * 
+     * @param state the desired state in string form
+     * @return this object for method chaining purposes
+     * @throws IllegalArgumentException if the specified state string is null or does not match one of the predefined
+     * {@link State predefined enumerated values}
+     * @see #setState(State)
+     * @see #start()
+     * @see #pause()
+     * @see #shutdown()
+     */
+    public ServiceAdministrator setState( String state );
+
+    /**
+     * Start monitoring and sequence the events. This method can be called multiple times, including after the system is
+     * {@link #pause() paused}. However, once the system is {@link #shutdown() shutdown}, it cannot be started or paused.
+     * 
+     * @return this object for method chaining purposes
+     * @throws IllegalStateException if called when the system has been {@link #shutdown() shutdown}.
+     * @see #pause()
+     * @see #shutdown()
+     * @see #isStarted()
+     */
+    public ServiceAdministrator start();
+
+    /**
+     * Temporarily stop monitoring and sequencing events. This method can be called multiple times, including after the system is
+     * {@link #start() started}. However, once the system is {@link #shutdown() shutdown}, it cannot be started or paused.
+     * 
+     * @return this object for method chaining purposes
+     * @throws IllegalStateException if called when the system has been {@link #shutdown() shutdown}.
+     * @see #start()
+     * @see #shutdown()
+     * @see #isPaused()
+     */
+    public ServiceAdministrator pause();
+
+    /**
+     * Permanently stop monitoring and sequencing events. This method can be called multiple times, but only the first call has an
+     * effect. Once the system has been shutdown, it may not be {@link #start() restarted} or {@link #pause() paused}.
+     * 
+     * @return this object for method chaining purposes
+     * @see #start()
+     * @see #pause()
+     * @see #isShutdown()
+     */
+    public ServiceAdministrator shutdown();
+
+    /**
+     * Blocks until the shutdown has completed, or the timeout occurs, or the current thread is interrupted, whichever happens
+     * first.
+     * 
+     * @param timeout the maximum time to wait
+     * @param unit the time unit of the timeout argument
+     * @return <tt>true</tt> if this service complete shut down and <tt>false</tt> if the timeout elapsed before it was shut
+     * down completely
+     * @throws InterruptedException if interrupted while waiting
+     */
+    boolean awaitTermination( long timeout, TimeUnit unit ) throws InterruptedException;
+
+    /**
+     * Return whether this system has been started and is currently running.
+     * 
+     * @return true if started and currently running, or false otherwise
+     * @see #start()
+     * @see #pause()
+     * @see #isPaused()
+     * @see #isShutdown()
+     * @see #isTerminated()
+     */
+    public boolean isStarted();
+
+    /**
+     * Return whether this system is currently paused.
+     * 
+     * @return true if currently paused, or false otherwise
+     * @see #pause()
+     * @see #start()
+     * @see #isStarted()
+     * @see #isShutdown()
+     * @see #isTerminated()
+     */
+    public boolean isPaused();
+
+    /**
+     * Return whether this system has been shut down.
+     * 
+     * @return true if this service has been shut down, or false otherwise
+     * @see #shutdown()
+     * @see #isPaused()
+     * @see #isStarted()
+     * @see #isTerminated()
+     */
+    public boolean isShutdown();
+
+    /**
+     * Return whether this system has finished {@link #shutdown() shutting down}. Note that <code>isTerminated</code> is never
+     * <code>true</code> unless either {@link #shutdown()} was called first.
+     * 
+     * @return true if the system has finished shutting down, or false otherwise
+     * @see #shutdown()
+     * @see #isPaused()
+     * @see #isStarted()
+     * @see #isShutdown()
+     */
+    public boolean isTerminated();
+
+}

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrNamespaceRegistry.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrNamespaceRegistry.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrNamespaceRegistry.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -27,9 +27,9 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.properties.NamespaceException;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.basic.BasicNamespace;
+import org.jboss.dna.graph.property.NamespaceException;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.basic.BasicNamespace;
 
 /**
  * @author Randall Hauch
@@ -144,7 +144,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.properties.NamespaceRegistry#unregister(java.lang.String)
+     * @see org.jboss.dna.graph.property.NamespaceRegistry#unregister(java.lang.String)
      */
     public boolean unregister( String namespaceUri ) {
         Session session = null;
@@ -190,7 +190,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.properties.NamespaceRegistry#getNamespaces()
+     * @see org.jboss.dna.graph.property.NamespaceRegistry#getNamespaces()
      */
     public Set<Namespace> getNamespaces() {
         Session session = null;

Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -37,12 +37,12 @@
 import org.jboss.dna.connector.federation.FederationException;
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.SimpleRepository;
-import org.jboss.dna.graph.connectors.SimpleRepositorySource;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.repository.services.ServiceAdministrator;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.SimpleRepository;
+import org.jboss.dna.graph.connector.SimpleRepositorySource;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.repository.service.ServiceAdministrator;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer (from rev 705, trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers)

Deleted: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerA.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerA.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerA.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,101 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.dna.repository.sequencers;
-
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.jcr.Node;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.collection.Problems;
-import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-import org.jboss.dna.repository.util.RepositoryNodePath;
-
-/**
- * A sequencer that can be used for basic unit testing.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at ThreadSafe
-public class MockSequencerA implements Sequencer {
-
-    private SequencerConfig config;
-    private AtomicInteger counter = new AtomicInteger();
-    private volatile CountDownLatch latch = new CountDownLatch(0);
-
-    public void setExpectedCount( int numExpected ) {
-        this.latch = new CountDownLatch(numExpected);
-    }
-
-    public boolean awaitExecution( long timeout,
-                                   TimeUnit unit ) throws InterruptedException {
-        return this.latch.await(timeout, unit);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setConfiguration( SequencerConfig sequencerConfiguration ) {
-        this.config = sequencerConfiguration;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void execute( Node input,
-                         String sequencedPropertyName,
-                         NodeChange changes,
-                         Set<RepositoryNodePath> outputPaths,
-                         JcrExecutionContext context,
-                         Problems problems ) {
-        // increment the counter and record the progress ...
-        this.counter.incrementAndGet();
-        this.latch.countDown();
-    }
-
-    public int getCounter() {
-        return this.counter.get();
-    }
-
-    public boolean isConfigured() {
-        return this.config != null;
-    }
-
-    /**
-     * @return config
-     */
-    public SequencerConfig getConfiguration() {
-        return this.config;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return (this.config != null ? this.config.getName() : "SampleSequencer") + " [" + this.getCounter() + "]";
-    }
-}

Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerA.java (from rev 706, trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerA.java)
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerA.java	                        (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerA.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,103 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.dna.repository.sequencer;
+
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.jcr.Node;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.repository.observation.NodeChange;
+import org.jboss.dna.repository.sequencer.Sequencer;
+import org.jboss.dna.repository.sequencer.SequencerConfig;
+import org.jboss.dna.repository.util.JcrExecutionContext;
+import org.jboss.dna.repository.util.RepositoryNodePath;
+
+/**
+ * A sequencer that can be used for basic unit testing.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at ThreadSafe
+public class MockSequencerA implements Sequencer {
+
+    private SequencerConfig config;
+    private AtomicInteger counter = new AtomicInteger();
+    private volatile CountDownLatch latch = new CountDownLatch(0);
+
+    public void setExpectedCount( int numExpected ) {
+        this.latch = new CountDownLatch(numExpected);
+    }
+
+    public boolean awaitExecution( long timeout,
+                                   TimeUnit unit ) throws InterruptedException {
+        return this.latch.await(timeout, unit);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setConfiguration( SequencerConfig sequencerConfiguration ) {
+        this.config = sequencerConfiguration;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void execute( Node input,
+                         String sequencedPropertyName,
+                         NodeChange changes,
+                         Set<RepositoryNodePath> outputPaths,
+                         JcrExecutionContext context,
+                         Problems problems ) {
+        // increment the counter and record the progress ...
+        this.counter.incrementAndGet();
+        this.latch.countDown();
+    }
+
+    public int getCounter() {
+        return this.counter.get();
+    }
+
+    public boolean isConfigured() {
+        return this.config != null;
+    }
+
+    /**
+     * @return config
+     */
+    public SequencerConfig getConfiguration() {
+        return this.config;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return (this.config != null ? this.config.getName() : "SampleSequencer") + " [" + this.getCounter() + "]";
+    }
+}

Deleted: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerB.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerB.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerB.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,101 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.dna.repository.sequencers;
-
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.jcr.Node;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.collection.Problems;
-import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-import org.jboss.dna.repository.util.RepositoryNodePath;
-
-/**
- * A sequencer that can be used for basic unit testing.
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
- at ThreadSafe
-public class MockSequencerB implements Sequencer {
-
-    private SequencerConfig config;
-    private AtomicInteger counter = new AtomicInteger();
-    private CountDownLatch latch = new CountDownLatch(0);
-
-    public void setExpectedCount( int numExpected ) {
-        this.latch = new CountDownLatch(numExpected);
-    }
-
-    public boolean awaitExecution( long timeout,
-                                   TimeUnit unit ) throws InterruptedException {
-        return this.latch.await(timeout, unit);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setConfiguration( SequencerConfig sequencerConfiguration ) {
-        this.config = sequencerConfiguration;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void execute( Node input,
-                         String sequencedPropertyName,
-                         NodeChange changes,
-                         Set<RepositoryNodePath> outputPaths,
-                         JcrExecutionContext context,
-                         Problems problems ) {
-        // increment the counter and record the progress ...
-        this.counter.incrementAndGet();
-        this.latch.countDown();
-    }
-
-    public int getCounter() {
-        return this.counter.get();
-    }
-
-    public boolean isConfigured() {
-        return this.config != null;
-    }
-
-    /**
-     * @return config
-     */
-    public SequencerConfig getConfiguration() {
-        return this.config;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        return (this.config != null ? this.config.getName() : "SampleSequencer") + " [" + this.getCounter() + "]";
-    }
-}

Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerB.java (from rev 706, trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerB.java)
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerB.java	                        (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/MockSequencerB.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,103 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.dna.repository.sequencer;
+
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.jcr.Node;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.repository.observation.NodeChange;
+import org.jboss.dna.repository.sequencer.Sequencer;
+import org.jboss.dna.repository.sequencer.SequencerConfig;
+import org.jboss.dna.repository.util.JcrExecutionContext;
+import org.jboss.dna.repository.util.RepositoryNodePath;
+
+/**
+ * A sequencer that can be used for basic unit testing.
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+ at ThreadSafe
+public class MockSequencerB implements Sequencer {
+
+    private SequencerConfig config;
+    private AtomicInteger counter = new AtomicInteger();
+    private CountDownLatch latch = new CountDownLatch(0);
+
+    public void setExpectedCount( int numExpected ) {
+        this.latch = new CountDownLatch(numExpected);
+    }
+
+    public boolean awaitExecution( long timeout,
+                                   TimeUnit unit ) throws InterruptedException {
+        return this.latch.await(timeout, unit);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setConfiguration( SequencerConfig sequencerConfiguration ) {
+        this.config = sequencerConfiguration;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void execute( Node input,
+                         String sequencedPropertyName,
+                         NodeChange changes,
+                         Set<RepositoryNodePath> outputPaths,
+                         JcrExecutionContext context,
+                         Problems problems ) {
+        // increment the counter and record the progress ...
+        this.counter.incrementAndGet();
+        this.latch.countDown();
+    }
+
+    public int getCounter() {
+        return this.counter.get();
+    }
+
+    public boolean isConfigured() {
+        return this.config != null;
+    }
+
+    /**
+     * @return config
+     */
+    public SequencerConfig getConfiguration() {
+        return this.config;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return (this.config != null ? this.config.getName() : "SampleSequencer") + " [" + this.getCounter() + "]";
+    }
+}

Deleted: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerConfigTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerConfigTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerConfigTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,135 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.dna.repository.sequencers;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class SequencerConfigTest {
-
-    private SequencerConfig configA;
-    private SequencerConfig configB;
-    private SequencerConfig configA2;
-    private String validName;
-    private String validDescription;
-    private String validClassname;
-    private String[] validPathExpressions;
-    private String[] validMavenIds;
-
-    @Before
-    public void beforeEach() {
-        this.validName = "valid configuration name";
-        this.validDescription = "a sequencer";
-        this.validClassname = MockSequencerA.class.getName();
-        this.validPathExpressions = new String[] {"/a/b/c/d[e/@attribute] => ."};
-        this.validMavenIds = new String[] {"com.acme:configA:1.0,com.acme:configB:1.0"};
-        this.configA = new SequencerConfig("configA", validDescription, MockSequencerA.class.getName(), validMavenIds,
-                                           validPathExpressions);
-        this.configB = new SequencerConfig("configB", validDescription, MockSequencerB.class.getName(), validMavenIds,
-                                           validPathExpressions);
-        this.configA2 = new SequencerConfig("conFigA", validDescription, MockSequencerA.class.getName(), validMavenIds,
-                                            validPathExpressions);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNullNameInConstructor() {
-        new SequencerConfig(null, validDescription, validClassname, validMavenIds, validPathExpressions);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowEmptyNameInConstructor() {
-        new SequencerConfig("", validDescription, validClassname, validMavenIds, validPathExpressions);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowBlankNameInConstructor() {
-        new SequencerConfig("   \t", validDescription, validClassname, validMavenIds, validPathExpressions);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowNullClassNameInConstructor() {
-        new SequencerConfig(validName, validDescription, null, validMavenIds, validPathExpressions);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowEmptyClassNameInConstructor() {
-        new SequencerConfig(validName, validDescription, "", validMavenIds, validPathExpressions);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowBlankClassNameInConstructor() {
-        new SequencerConfig(validName, validDescription, "   \t", validMavenIds, validPathExpressions);
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotAllowInvalidClassNameInConstructor() {
-        new SequencerConfig(validName, validDescription, "12.this is not a valid classname", validMavenIds, validPathExpressions);
-    }
-
-    @Test
-    public void shouldConsiderSameIfNamesAreEqualIgnoringCase() {
-        assertThat(configA.equals(configA2), is(true));
-    }
-
-    @Test
-    public void shouldConsiderNotSameIfNamesAreNotEqualIgnoringCase() {
-        assertThat(configA.equals(configB), is(false));
-    }
-
-    @Test
-    public void shouldNotAddNullOrBlankPathExpressions() {
-        assertThat(SequencerConfig.buildPathExpressionSet(null, "", "   ", validPathExpressions[0]).size(), is(1));
-    }
-
-    @Test
-    public void shouldNotAddSamePathExpressionMoreThanOnce() {
-        assertThat(SequencerConfig.buildPathExpressionSet(validPathExpressions[0],
-                                                          validPathExpressions[0],
-                                                          validPathExpressions[0]).size(), is(1));
-    }
-
-    @Test
-    public void shouldHaveNonNullPathExpressionCollectionWhenThereAreNoPathExpressions() {
-        configA = new SequencerConfig("configA", validDescription, validClassname, validMavenIds);
-        assertThat(configA.getPathExpressions().size(), is(0));
-    }
-
-    @Test
-    public void shouldSetClasspathWithValidMavenIds() {
-        assertThat(configA.getComponentClasspath().size(), is(validMavenIds.length));
-        assertThat(configA.getComponentClasspathArray(), is(validMavenIds));
-    }
-
-    @Test
-    public void shouldGetNonNullSequencerClasspathWhenEmpty() {
-        configA = new SequencerConfig("configA", validDescription, validClassname, null, validPathExpressions);
-        assertThat(configA.getComponentClasspath().size(), is(0));
-        assertThat(configA.getComponentClasspathArray().length, is(0));
-    }
-
-}

Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerConfigTest.java (from rev 706, trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerConfigTest.java)
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerConfigTest.java	                        (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerConfigTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,136 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.dna.repository.sequencer;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.repository.sequencer.SequencerConfig;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class SequencerConfigTest {
+
+    private SequencerConfig configA;
+    private SequencerConfig configB;
+    private SequencerConfig configA2;
+    private String validName;
+    private String validDescription;
+    private String validClassname;
+    private String[] validPathExpressions;
+    private String[] validMavenIds;
+
+    @Before
+    public void beforeEach() {
+        this.validName = "valid configuration name";
+        this.validDescription = "a sequencer";
+        this.validClassname = MockSequencerA.class.getName();
+        this.validPathExpressions = new String[] {"/a/b/c/d[e/@attribute] => ."};
+        this.validMavenIds = new String[] {"com.acme:configA:1.0,com.acme:configB:1.0"};
+        this.configA = new SequencerConfig("configA", validDescription, MockSequencerA.class.getName(), validMavenIds,
+                                           validPathExpressions);
+        this.configB = new SequencerConfig("configB", validDescription, MockSequencerB.class.getName(), validMavenIds,
+                                           validPathExpressions);
+        this.configA2 = new SequencerConfig("conFigA", validDescription, MockSequencerA.class.getName(), validMavenIds,
+                                            validPathExpressions);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNullNameInConstructor() {
+        new SequencerConfig(null, validDescription, validClassname, validMavenIds, validPathExpressions);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowEmptyNameInConstructor() {
+        new SequencerConfig("", validDescription, validClassname, validMavenIds, validPathExpressions);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowBlankNameInConstructor() {
+        new SequencerConfig("   \t", validDescription, validClassname, validMavenIds, validPathExpressions);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowNullClassNameInConstructor() {
+        new SequencerConfig(validName, validDescription, null, validMavenIds, validPathExpressions);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowEmptyClassNameInConstructor() {
+        new SequencerConfig(validName, validDescription, "", validMavenIds, validPathExpressions);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowBlankClassNameInConstructor() {
+        new SequencerConfig(validName, validDescription, "   \t", validMavenIds, validPathExpressions);
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotAllowInvalidClassNameInConstructor() {
+        new SequencerConfig(validName, validDescription, "12.this is not a valid classname", validMavenIds, validPathExpressions);
+    }
+
+    @Test
+    public void shouldConsiderSameIfNamesAreEqualIgnoringCase() {
+        assertThat(configA.equals(configA2), is(true));
+    }
+
+    @Test
+    public void shouldConsiderNotSameIfNamesAreNotEqualIgnoringCase() {
+        assertThat(configA.equals(configB), is(false));
+    }
+
+    @Test
+    public void shouldNotAddNullOrBlankPathExpressions() {
+        assertThat(SequencerConfig.buildPathExpressionSet(null, "", "   ", validPathExpressions[0]).size(), is(1));
+    }
+
+    @Test
+    public void shouldNotAddSamePathExpressionMoreThanOnce() {
+        assertThat(SequencerConfig.buildPathExpressionSet(validPathExpressions[0],
+                                                          validPathExpressions[0],
+                                                          validPathExpressions[0]).size(), is(1));
+    }
+
+    @Test
+    public void shouldHaveNonNullPathExpressionCollectionWhenThereAreNoPathExpressions() {
+        configA = new SequencerConfig("configA", validDescription, validClassname, validMavenIds);
+        assertThat(configA.getPathExpressions().size(), is(0));
+    }
+
+    @Test
+    public void shouldSetClasspathWithValidMavenIds() {
+        assertThat(configA.getComponentClasspath().size(), is(validMavenIds.length));
+        assertThat(configA.getComponentClasspathArray(), is(validMavenIds));
+    }
+
+    @Test
+    public void shouldGetNonNullSequencerClasspathWhenEmpty() {
+        configA = new SequencerConfig("configA", validDescription, validClassname, null, validPathExpressions);
+        assertThat(configA.getComponentClasspath().size(), is(0));
+        assertThat(configA.getComponentClasspathArray().length, is(0));
+    }
+
+}

Deleted: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerNodeContextTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerNodeContextTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerNodeContextTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,178 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import java.io.IOException;
-import java.util.Iterator;
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import org.jboss.dna.common.collection.Problems;
-import org.jboss.dna.common.collection.SimpleProblems;
-import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.repository.util.BasicJcrExecutionContext;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-import org.jboss.dna.repository.util.JcrNamespaceRegistry;
-import org.jboss.dna.repository.util.JcrTools;
-import org.jboss.dna.repository.util.SessionFactory;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
-
-/**
- * @author John Verhaeg
- */
-public class SequencerNodeContextTest extends AbstractJcrRepositoryTest {
-
-    private JcrExecutionContext execContext;
-    private Session session;
-    private JcrTools tools;
-    private Problems problems;
-    @Mock
-    private javax.jcr.Property sequencedProperty;
-
-    @Before
-    public void before() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        final SessionFactory sessionFactory = new SessionFactory() {
-
-            public Session createSession( String name ) throws RepositoryException {
-                try {
-                    return getRepository().login(getTestCredentials());
-                } catch (IOException error) {
-                    throw new RepositoryException(error);
-                }
-            }
-        };
-        NamespaceRegistry registry = new JcrNamespaceRegistry(sessionFactory, "doesn't matter");
-        execContext = new BasicJcrExecutionContext(sessionFactory, registry, null, null);
-        startRepository();
-        session = getRepository().login(getTestCredentials());
-        tools = new JcrTools();
-        problems = new SimpleProblems();
-    }
-
-    @After
-    public void after() {
-        if (session != null) {
-            try {
-                session.logout();
-            } finally {
-                session = null;
-            }
-        }
-    }
-
-    private void verifyProperty( SequencerContext context,
-                                 String name,
-                                 Object... values ) {
-        Property prop = context.getInputProperty(execContext.getValueFactories().getNameFactory().create(name));
-        assertThat(prop, notNullValue());
-        assertThat(prop.getName(), is(execContext.getValueFactories().getNameFactory().create(name)));
-        assertThat(prop.isEmpty(), is(false));
-        assertThat(prop.size(), is(values.length));
-        assertThat(prop.isMultiple(), is(values.length > 1));
-        assertThat(prop.isSingle(), is(values.length == 1));
-        Iterator<?> iter = prop.getValues();
-        for (Object val : values) {
-            assertThat(iter.hasNext(), is(true));
-            assertThat(iter.next(), is(val));
-        }
-    }
-
-    @Test( expected = java.lang.AssertionError.class )
-    public void shouldNotAllowNullInputNode() throws Exception {
-        new SequencerNodeContext(null, sequencedProperty, execContext, problems);
-    }
-
-    @Test( expected = java.lang.AssertionError.class )
-    public void shouldNotAllowNullSequencedProperty() throws Exception {
-        Node input = tools.findOrCreateNode(session, "/a");
-        new SequencerNodeContext(input, null, execContext, problems);
-    }
-
-    @Test( expected = java.lang.AssertionError.class )
-    public void shouldNotAllowNullExecutionContext() throws Exception {
-        Node input = tools.findOrCreateNode(session, "/a");
-        new SequencerNodeContext(input, sequencedProperty, null, problems);
-    }
-
-    @Test
-    public void shouldProvideNamespaceRegistry() throws Exception {
-        Node input = tools.findOrCreateNode(session, "/a/b/c");
-        SequencerNodeContext sequencerContext = new SequencerNodeContext(input, sequencedProperty, execContext, problems);
-        assertThat(sequencerContext.getNamespaceRegistry(), notNullValue());
-    }
-
-    @Test
-    public void shouldProvideValueFactories() throws Exception {
-        Node input = tools.findOrCreateNode(session, "/a/b/c");
-        SequencerNodeContext sequencerContext = new SequencerNodeContext(input, sequencedProperty, execContext, problems);
-        assertThat(sequencerContext.getValueFactories(), notNullValue());
-    }
-
-    @Test
-    public void shouldProvidePathToInput() throws Exception {
-        Node input = tools.findOrCreateNode(session, "/a/b/c");
-        SequencerNodeContext sequencerContext = new SequencerNodeContext(input, sequencedProperty, execContext, problems);
-        assertThat(sequencerContext.getInputPath(), is(execContext.getValueFactories().getPathFactory().create("/a/b/c")));
-    }
-
-    @Test
-    public void shouldNeverReturnNullInputProperties() throws Exception {
-        Node input = tools.findOrCreateNode(session, "/a/b/c");
-        SequencerNodeContext sequencerContext = new SequencerNodeContext(input, sequencedProperty, execContext, problems);
-        assertThat(sequencerContext.getInputProperties(), notNullValue());
-        assertThat(sequencerContext.getInputProperties().isEmpty(), is(false));
-    }
-
-    @Test
-    public void shouldProvideInputProperties() throws Exception {
-        Node input = tools.findOrCreateNode(session, "/a/b/c");
-        input.setProperty("x", true);
-        input.setProperty("y", new String[] {"asdf", "xyzzy"});
-        SequencerNodeContext sequencerContext = new SequencerNodeContext(input, sequencedProperty, execContext, problems);
-        assertThat(sequencerContext.getInputProperties(), notNullValue());
-        assertThat(sequencerContext.getInputProperties().isEmpty(), is(false));
-        assertThat(sequencerContext.getInputProperties().size(), is(3));
-        verifyProperty(sequencerContext,
-                       "jcr:primaryType",
-                       execContext.getValueFactories().getNameFactory().create("{http://www.jcp.org/jcr/nt/1.0}unstructured"));
-        verifyProperty(sequencerContext, "x", true);
-        verifyProperty(sequencerContext, "y", "asdf", "xyzzy");
-    }
-
-    @Test
-    public void shouldProvideMimeType() throws Exception {
-        Node input = tools.findOrCreateNode(session, "/a/b/c");
-        SequencerNodeContext sequencerContext = new SequencerNodeContext(input, sequencedProperty, execContext, problems);
-        assertThat(sequencerContext.getMimeType(), is("text/plain"));
-    }
-}

Deleted: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerPathExpressionTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerPathExpressionTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerPathExpressionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,300 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.junit.Assert.assertThat;
-import org.jboss.dna.graph.properties.PathExpression;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class SequencerPathExpressionTest {
-
-    private SequencerPathExpression expr;
-
-    @Before
-    public void beforeEach() throws Exception {
-        expr = new SequencerPathExpression(new PathExpression(".*"), "/output");
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotCompileNullExpression() {
-        SequencerPathExpression.compile(null);
-    }
-
-    @Test( expected = InvalidSequencerPathExpression.class )
-    public void shouldNotCompileZeroLengthExpression() {
-        SequencerPathExpression.compile("");
-    }
-
-    @Test( expected = InvalidSequencerPathExpression.class )
-    public void shouldNotCompileBlankExpression() {
-        SequencerPathExpression.compile("    ");
-    }
-
-    @Test
-    public void shouldCompileExpressionWithOnlySelectionExpression() {
-        expr = SequencerPathExpression.compile("/a/b/c");
-        assertThat(expr, is(notNullValue()));
-        assertThat(expr.getSelectExpression(), is("/a/b/c"));
-        assertThat(expr.getOutputExpression(), is(SequencerPathExpression.DEFAULT_OUTPUT_EXPRESSION));
-    }
-
-    @Test( expected = InvalidSequencerPathExpression.class )
-    public void shouldNotCompileExpressionWithSelectionExpressionAndDelimiterAndNoOutputExpression() {
-        SequencerPathExpression.compile("/a/b/c=>");
-    }
-
-    @Test
-    public void shouldCompileExpressionWithSelectionExpressionAndDelimiterAndOutputExpression() {
-        expr = SequencerPathExpression.compile("/a/b/c=>.");
-        assertThat(expr, is(notNullValue()));
-        assertThat(expr.getSelectExpression(), is("/a/b/c"));
-        assertThat(expr.getOutputExpression(), is("."));
-
-        expr = SequencerPathExpression.compile("/a/b/c=>/x/y");
-        assertThat(expr, is(notNullValue()));
-        assertThat(expr.getSelectExpression(), is("/a/b/c"));
-        assertThat(expr.getOutputExpression(), is("/x/y"));
-    }
-
-    @Test
-    public void shouldCompileExpressionWithExtraWhitespace() {
-        expr = SequencerPathExpression.compile(" /a/b/c => . ");
-        assertThat(expr, is(notNullValue()));
-        assertThat(expr.getSelectExpression(), is("/a/b/c"));
-        assertThat(expr.getOutputExpression(), is("."));
-
-        expr = SequencerPathExpression.compile("  /a/b/c => /x/y ");
-        assertThat(expr, is(notNullValue()));
-        assertThat(expr.getSelectExpression(), is("/a/b/c"));
-        assertThat(expr.getOutputExpression(), is("/x/y"));
-    }
-
-    @Test
-    public void shouldCompileExpressionWithIndexes() {
-        assertThat(SequencerPathExpression.compile("/a/b[0]/c[1]/d/e"), is(notNullValue()));
-        assertThat(SequencerPathExpression.compile("/a/b[0]/c[1]/d/e[2]"), is(notNullValue()));
-    }
-
-    protected void assertNotMatches( SequencerPathExpression.Matcher matcher ) {
-        assertThat(matcher, is(notNullValue()));
-        assertThat(matcher.getSelectedPath(), is(nullValue()));
-        assertThat(matcher.getOutputPath(), is(nullValue()));
-        assertThat(matcher.matches(), is(false));
-    }
-
-    protected void assertMatches( SequencerPathExpression.Matcher matcher,
-                                  String selectedPath,
-                                  String outputPath ) {
-        assertThat(matcher, is(notNullValue()));
-        assertThat(matcher.getSelectedPath(), is(selectedPath));
-        assertThat(matcher.getOutputPath(), is(outputPath));
-        if (selectedPath == null) {
-            assertThat(matcher.matches(), is(false));
-        } else {
-            assertThat(matcher.matches(), is(true));
-        }
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithoutRegardToCase() {
-        expr = SequencerPathExpression.compile("/a/b/c/d/e[@something] => .");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/a/b/c/d/e");
-        assertMatches(expr.matcher("/a/b/c/d/E/@something"), "/a/b/c/d/E", "/a/b/c/d/E");
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithExactFullPath() {
-        expr = SequencerPathExpression.compile("/a/b/c/d/e[@something] => .");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/a/b/c/d/e");
-        assertNotMatches(expr.matcher("/a/b/c/d/E/@something2"));
-        assertNotMatches(expr.matcher("/a/b/c/d/ex/@something"));
-        assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something"));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithExactFullPathAndExtraPathInsideMatch() {
-        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => .");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/a/b/c");
-        assertNotMatches(expr.matcher("/a/b/c/d/E/@something2"));
-        assertNotMatches(expr.matcher("/a/b/c/d/ex/@something"));
-        assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something"));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithWildcardSelection() {
-        expr = SequencerPathExpression.compile("/a/*/c[d/e/@something] => .");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/a/b/c");
-        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c", "/a/b[2]/c");
-        assertMatches(expr.matcher("/a/rt/c/d/e/@something"), "/a/rt/c", "/a/rt/c");
-        assertNotMatches(expr.matcher("/ac/d/e/@something"));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithFilenameLikeWildcardSelection() {
-        expr = SequencerPathExpression.compile("/a/*.txt[@something] => .");
-        assertMatches(expr.matcher("/a/b.txt/@something"), "/a/b.txt", "/a/b.txt");
-        assertNotMatches(expr.matcher("/a/b.tx/@something"));
-
-        expr = SequencerPathExpression.compile("/a/*.txt/c[@something] => .");
-        assertMatches(expr.matcher("/a/b.txt/c/@something"), "/a/b.txt/c", "/a/b.txt/c");
-        assertNotMatches(expr.matcher("/a/b.tx/c/@something"));
-
-        expr = SequencerPathExpression.compile("//*.txt[*]/c[@something] => .");
-        assertMatches(expr.matcher("/a/b.txt/c/@something"), "/a/b.txt/c", "/a/b.txt/c");
-        assertNotMatches(expr.matcher("/a/b.tx/c/@something"));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithSegmentWildcardSelection() {
-        expr = SequencerPathExpression.compile("/a//c[d/e/@something] => .");
-        assertMatches(expr.matcher("/a/c/d/e/@something"), "/a/c", "/a/c");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/a/b/c");
-        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c", "/a/b[2]/c");
-        assertMatches(expr.matcher("/a/rt/c/d/e/@something"), "/a/rt/c", "/a/rt/c");
-        assertMatches(expr.matcher("/a/r/s/t/c/d/e/@something"), "/a/r/s/t/c", "/a/r/s/t/c");
-        assertMatches(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something"), "/a/r[1]/s[2]/t[33]/c", "/a/r[1]/s[2]/t[33]/c");
-        assertNotMatches(expr.matcher("/a[3]/c/d/e/@something"));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithIndexesInSelectionPaths() {
-        expr = SequencerPathExpression.compile("/a/b[2,3,4,5]/c/d/e[@something] => /x/y");
-        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[3]/c/d/e/@something"), "/a/b[3]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[4]/c/d/e/@something"), "/a/b[4]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[5]/c/d/e/@something"), "/a/b[5]/c/d/e", "/x/y");
-        assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something"));
-        assertNotMatches(expr.matcher("/a/b/c/d/e/@something"));
-        assertNotMatches(expr.matcher("/a[1]/b/c/d/e/@something"));
-
-        expr = SequencerPathExpression.compile("/a/b[0,2,3,4,5]/c/d/e[@something] => /x/y");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[3]/c/d/e/@something"), "/a/b[3]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[4]/c/d/e/@something"), "/a/b[4]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[5]/c/d/e/@something"), "/a/b[5]/c/d/e", "/x/y");
-        assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something"));
-        assertNotMatches(expr.matcher("/a[1]/b/c/d/e/@something"));
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithAnyIndexesInSelectionPaths() {
-        expr = SequencerPathExpression.compile("/a/b[*]/c[]/d/e[@something] => /x/y");
-        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[3]/c/d/e/@something"), "/a/b[3]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[4]/c/d/e/@something"), "/a/b[4]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[5]/c/d/e/@something"), "/a/b[5]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[1]/c/d/e/@something"), "/a/b[1]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[6]/c/d/e/@something"), "/a/b[6]/c/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b[6]/c[1]/d/e/@something"), "/a/b[6]/c[1]/d/e", "/x/y");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/x/y");
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithFullOutputPath() {
-        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => /x/y");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/y");
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithRepositoryInSelectionPath() {
-        expr = SequencerPathExpression.compile("reposA:/a/b/c[d/e/@something] => /x/y");
-        assertMatches(expr.matcher("reposA:/a/b/c/d/e/@something"), "reposA:/a/b/c", "/x/y");
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithRepositoryInFullOutputPath() {
-        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => reposA:/x/y");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "reposA:/x/y");
-    }
-
-    @Test
-    public void shouldMatchExpressionsWithNamedGroupsInOutputPath() {
-        expr = SequencerPathExpression.compile("/a(//c)[d/e/@something] => $1/y/z");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/b/c/y/z");
-
-        expr = SequencerPathExpression.compile("/a(/(b|c|d|)/e)[f/g/@something] => $1/y/z");
-        assertMatches(expr.matcher("/a/b/e/f/g/@something"), "/a/b/e", "/b/e/y/z");
-        assertMatches(expr.matcher("/a/c/e/f/g/@something"), "/a/c/e", "/c/e/y/z");
-        assertMatches(expr.matcher("/a/d/e/f/g/@something"), "/a/d/e", "/d/e/y/z");
-        assertMatches(expr.matcher("/a/e/f/g/@something"), "/a/e", "/e/y/z");
-        assertNotMatches(expr.matcher("/a/t/e/f/g/@something"));
-
-        expr = SequencerPathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something] => /u/$1/y/z/$2/$3");
-        assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c", "/u/b/c/y/z/d/f");
-        assertMatches(expr.matcher("/a/b/c/e/f/@something"), "/a/b/c", "/u/b/c/y/z/e/f");
-        assertMatches(expr.matcher("/a/b/c/d/g/@something"), "/a/b/c", "/u/b/c/y/z/d/g");
-        assertMatches(expr.matcher("/a/b/c/e/g/@something"), "/a/b/c", "/u/b/c/y/z/e/g");
-
-        expr = SequencerPathExpression.compile("/a/(b/c)/(d|e)/(f|g)/@something => /u/$1/y/z/$2/$3");
-        assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c/d/f", "/u/b/c/y/z/d/f");
-        assertMatches(expr.matcher("/a/b/c/e/f/@something"), "/a/b/c/e/f", "/u/b/c/y/z/e/f");
-        assertMatches(expr.matcher("/a/b/c/d/g/@something"), "/a/b/c/d/g", "/u/b/c/y/z/d/g");
-        assertMatches(expr.matcher("/a/b/c/e/g/@something"), "/a/b/c/e/g", "/u/b/c/y/z/e/g");
-    }
-
-    @Test
-    public void shouldMatchExpressionWithReoccurringNamedGroupsDollarsInOutputPath() {
-        expr = SequencerPathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something] => /u/$1/y/z/$2/$3/$1/$1");
-        assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c", "/u/b/c/y/z/d/f/b/c/b/c");
-    }
-
-    @Test
-    public void shouldMatchExpressionWithNamedGroupsAndEscapedDollarsInOutputPath() {
-        expr = SequencerPathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something] => /\\$2u/$1/y/z/$2/$3");
-        assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c", "/\\$2u/b/c/y/z/d/f");
-    }
-
-    @Test
-    public void shouldMatchExpressionWithParentReferencesInOutputPath() {
-        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => /x/y/z/../..");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x");
-
-        expr = SequencerPathExpression.compile("/a/(b/c)[d/e/@something] => /x/$1/z/../../v");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/b/v");
-    }
-
-    @Test
-    public void shouldMatchExpressionWithSelfReferencesInOutputPath() {
-        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => /x/y/./z/.");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/y/z");
-
-        expr = SequencerPathExpression.compile("/a/(b/c)[d/e/@something] => /x/$1/./z");
-        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/b/c/z");
-    }
-
-    @Test
-    public void shouldMatchExpressionWithFilenamePatternAndChildProperty() {
-        expr = SequencerPathExpression.compile("//(*.(jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data]=>/images/$1");
-        assertMatches(expr.matcher("/a/b/caution.png/jcr:content/@jcr:data"),
-                      "/a/b/caution.png/jcr:content",
-                      "/images/caution.png");
-    }
-
-}

Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerPathExpressionTest.java (from rev 706, trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerPathExpressionTest.java)
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerPathExpressionTest.java	                        (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencerPathExpressionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,302 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.property.PathExpression;
+import org.jboss.dna.repository.sequencer.InvalidSequencerPathExpression;
+import org.jboss.dna.repository.sequencer.SequencerPathExpression;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class SequencerPathExpressionTest {
+
+    private SequencerPathExpression expr;
+
+    @Before
+    public void beforeEach() throws Exception {
+        expr = new SequencerPathExpression(new PathExpression(".*"), "/output");
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldNotCompileNullExpression() {
+        SequencerPathExpression.compile(null);
+    }
+
+    @Test( expected = InvalidSequencerPathExpression.class )
+    public void shouldNotCompileZeroLengthExpression() {
+        SequencerPathExpression.compile("");
+    }
+
+    @Test( expected = InvalidSequencerPathExpression.class )
+    public void shouldNotCompileBlankExpression() {
+        SequencerPathExpression.compile("    ");
+    }
+
+    @Test
+    public void shouldCompileExpressionWithOnlySelectionExpression() {
+        expr = SequencerPathExpression.compile("/a/b/c");
+        assertThat(expr, is(notNullValue()));
+        assertThat(expr.getSelectExpression(), is("/a/b/c"));
+        assertThat(expr.getOutputExpression(), is(SequencerPathExpression.DEFAULT_OUTPUT_EXPRESSION));
+    }
+
+    @Test( expected = InvalidSequencerPathExpression.class )
+    public void shouldNotCompileExpressionWithSelectionExpressionAndDelimiterAndNoOutputExpression() {
+        SequencerPathExpression.compile("/a/b/c=>");
+    }
+
+    @Test
+    public void shouldCompileExpressionWithSelectionExpressionAndDelimiterAndOutputExpression() {
+        expr = SequencerPathExpression.compile("/a/b/c=>.");
+        assertThat(expr, is(notNullValue()));
+        assertThat(expr.getSelectExpression(), is("/a/b/c"));
+        assertThat(expr.getOutputExpression(), is("."));
+
+        expr = SequencerPathExpression.compile("/a/b/c=>/x/y");
+        assertThat(expr, is(notNullValue()));
+        assertThat(expr.getSelectExpression(), is("/a/b/c"));
+        assertThat(expr.getOutputExpression(), is("/x/y"));
+    }
+
+    @Test
+    public void shouldCompileExpressionWithExtraWhitespace() {
+        expr = SequencerPathExpression.compile(" /a/b/c => . ");
+        assertThat(expr, is(notNullValue()));
+        assertThat(expr.getSelectExpression(), is("/a/b/c"));
+        assertThat(expr.getOutputExpression(), is("."));
+
+        expr = SequencerPathExpression.compile("  /a/b/c => /x/y ");
+        assertThat(expr, is(notNullValue()));
+        assertThat(expr.getSelectExpression(), is("/a/b/c"));
+        assertThat(expr.getOutputExpression(), is("/x/y"));
+    }
+
+    @Test
+    public void shouldCompileExpressionWithIndexes() {
+        assertThat(SequencerPathExpression.compile("/a/b[0]/c[1]/d/e"), is(notNullValue()));
+        assertThat(SequencerPathExpression.compile("/a/b[0]/c[1]/d/e[2]"), is(notNullValue()));
+    }
+
+    protected void assertNotMatches( SequencerPathExpression.Matcher matcher ) {
+        assertThat(matcher, is(notNullValue()));
+        assertThat(matcher.getSelectedPath(), is(nullValue()));
+        assertThat(matcher.getOutputPath(), is(nullValue()));
+        assertThat(matcher.matches(), is(false));
+    }
+
+    protected void assertMatches( SequencerPathExpression.Matcher matcher,
+                                  String selectedPath,
+                                  String outputPath ) {
+        assertThat(matcher, is(notNullValue()));
+        assertThat(matcher.getSelectedPath(), is(selectedPath));
+        assertThat(matcher.getOutputPath(), is(outputPath));
+        if (selectedPath == null) {
+            assertThat(matcher.matches(), is(false));
+        } else {
+            assertThat(matcher.matches(), is(true));
+        }
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithoutRegardToCase() {
+        expr = SequencerPathExpression.compile("/a/b/c/d/e[@something] => .");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/a/b/c/d/e");
+        assertMatches(expr.matcher("/a/b/c/d/E/@something"), "/a/b/c/d/E", "/a/b/c/d/E");
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithExactFullPath() {
+        expr = SequencerPathExpression.compile("/a/b/c/d/e[@something] => .");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/a/b/c/d/e");
+        assertNotMatches(expr.matcher("/a/b/c/d/E/@something2"));
+        assertNotMatches(expr.matcher("/a/b/c/d/ex/@something"));
+        assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something"));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithExactFullPathAndExtraPathInsideMatch() {
+        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => .");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/a/b/c");
+        assertNotMatches(expr.matcher("/a/b/c/d/E/@something2"));
+        assertNotMatches(expr.matcher("/a/b/c/d/ex/@something"));
+        assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something"));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithWildcardSelection() {
+        expr = SequencerPathExpression.compile("/a/*/c[d/e/@something] => .");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/a/b/c");
+        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c", "/a/b[2]/c");
+        assertMatches(expr.matcher("/a/rt/c/d/e/@something"), "/a/rt/c", "/a/rt/c");
+        assertNotMatches(expr.matcher("/ac/d/e/@something"));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithFilenameLikeWildcardSelection() {
+        expr = SequencerPathExpression.compile("/a/*.txt[@something] => .");
+        assertMatches(expr.matcher("/a/b.txt/@something"), "/a/b.txt", "/a/b.txt");
+        assertNotMatches(expr.matcher("/a/b.tx/@something"));
+
+        expr = SequencerPathExpression.compile("/a/*.txt/c[@something] => .");
+        assertMatches(expr.matcher("/a/b.txt/c/@something"), "/a/b.txt/c", "/a/b.txt/c");
+        assertNotMatches(expr.matcher("/a/b.tx/c/@something"));
+
+        expr = SequencerPathExpression.compile("//*.txt[*]/c[@something] => .");
+        assertMatches(expr.matcher("/a/b.txt/c/@something"), "/a/b.txt/c", "/a/b.txt/c");
+        assertNotMatches(expr.matcher("/a/b.tx/c/@something"));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithSegmentWildcardSelection() {
+        expr = SequencerPathExpression.compile("/a//c[d/e/@something] => .");
+        assertMatches(expr.matcher("/a/c/d/e/@something"), "/a/c", "/a/c");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/a/b/c");
+        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c", "/a/b[2]/c");
+        assertMatches(expr.matcher("/a/rt/c/d/e/@something"), "/a/rt/c", "/a/rt/c");
+        assertMatches(expr.matcher("/a/r/s/t/c/d/e/@something"), "/a/r/s/t/c", "/a/r/s/t/c");
+        assertMatches(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something"), "/a/r[1]/s[2]/t[33]/c", "/a/r[1]/s[2]/t[33]/c");
+        assertNotMatches(expr.matcher("/a[3]/c/d/e/@something"));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithIndexesInSelectionPaths() {
+        expr = SequencerPathExpression.compile("/a/b[2,3,4,5]/c/d/e[@something] => /x/y");
+        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[3]/c/d/e/@something"), "/a/b[3]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[4]/c/d/e/@something"), "/a/b[4]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[5]/c/d/e/@something"), "/a/b[5]/c/d/e", "/x/y");
+        assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something"));
+        assertNotMatches(expr.matcher("/a/b/c/d/e/@something"));
+        assertNotMatches(expr.matcher("/a[1]/b/c/d/e/@something"));
+
+        expr = SequencerPathExpression.compile("/a/b[0,2,3,4,5]/c/d/e[@something] => /x/y");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[3]/c/d/e/@something"), "/a/b[3]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[4]/c/d/e/@something"), "/a/b[4]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[5]/c/d/e/@something"), "/a/b[5]/c/d/e", "/x/y");
+        assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something"));
+        assertNotMatches(expr.matcher("/a[1]/b/c/d/e/@something"));
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithAnyIndexesInSelectionPaths() {
+        expr = SequencerPathExpression.compile("/a/b[*]/c[]/d/e[@something] => /x/y");
+        assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[3]/c/d/e/@something"), "/a/b[3]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[4]/c/d/e/@something"), "/a/b[4]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[5]/c/d/e/@something"), "/a/b[5]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[1]/c/d/e/@something"), "/a/b[1]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[6]/c/d/e/@something"), "/a/b[6]/c/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b[6]/c[1]/d/e/@something"), "/a/b[6]/c[1]/d/e", "/x/y");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/x/y");
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithFullOutputPath() {
+        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => /x/y");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/y");
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithRepositoryInSelectionPath() {
+        expr = SequencerPathExpression.compile("reposA:/a/b/c[d/e/@something] => /x/y");
+        assertMatches(expr.matcher("reposA:/a/b/c/d/e/@something"), "reposA:/a/b/c", "/x/y");
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithRepositoryInFullOutputPath() {
+        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => reposA:/x/y");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "reposA:/x/y");
+    }
+
+    @Test
+    public void shouldMatchExpressionsWithNamedGroupsInOutputPath() {
+        expr = SequencerPathExpression.compile("/a(//c)[d/e/@something] => $1/y/z");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/b/c/y/z");
+
+        expr = SequencerPathExpression.compile("/a(/(b|c|d|)/e)[f/g/@something] => $1/y/z");
+        assertMatches(expr.matcher("/a/b/e/f/g/@something"), "/a/b/e", "/b/e/y/z");
+        assertMatches(expr.matcher("/a/c/e/f/g/@something"), "/a/c/e", "/c/e/y/z");
+        assertMatches(expr.matcher("/a/d/e/f/g/@something"), "/a/d/e", "/d/e/y/z");
+        assertMatches(expr.matcher("/a/e/f/g/@something"), "/a/e", "/e/y/z");
+        assertNotMatches(expr.matcher("/a/t/e/f/g/@something"));
+
+        expr = SequencerPathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something] => /u/$1/y/z/$2/$3");
+        assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c", "/u/b/c/y/z/d/f");
+        assertMatches(expr.matcher("/a/b/c/e/f/@something"), "/a/b/c", "/u/b/c/y/z/e/f");
+        assertMatches(expr.matcher("/a/b/c/d/g/@something"), "/a/b/c", "/u/b/c/y/z/d/g");
+        assertMatches(expr.matcher("/a/b/c/e/g/@something"), "/a/b/c", "/u/b/c/y/z/e/g");
+
+        expr = SequencerPathExpression.compile("/a/(b/c)/(d|e)/(f|g)/@something => /u/$1/y/z/$2/$3");
+        assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c/d/f", "/u/b/c/y/z/d/f");
+        assertMatches(expr.matcher("/a/b/c/e/f/@something"), "/a/b/c/e/f", "/u/b/c/y/z/e/f");
+        assertMatches(expr.matcher("/a/b/c/d/g/@something"), "/a/b/c/d/g", "/u/b/c/y/z/d/g");
+        assertMatches(expr.matcher("/a/b/c/e/g/@something"), "/a/b/c/e/g", "/u/b/c/y/z/e/g");
+    }
+
+    @Test
+    public void shouldMatchExpressionWithReoccurringNamedGroupsDollarsInOutputPath() {
+        expr = SequencerPathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something] => /u/$1/y/z/$2/$3/$1/$1");
+        assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c", "/u/b/c/y/z/d/f/b/c/b/c");
+    }
+
+    @Test
+    public void shouldMatchExpressionWithNamedGroupsAndEscapedDollarsInOutputPath() {
+        expr = SequencerPathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something] => /\\$2u/$1/y/z/$2/$3");
+        assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c", "/\\$2u/b/c/y/z/d/f");
+    }
+
+    @Test
+    public void shouldMatchExpressionWithParentReferencesInOutputPath() {
+        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => /x/y/z/../..");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x");
+
+        expr = SequencerPathExpression.compile("/a/(b/c)[d/e/@something] => /x/$1/z/../../v");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/b/v");
+    }
+
+    @Test
+    public void shouldMatchExpressionWithSelfReferencesInOutputPath() {
+        expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => /x/y/./z/.");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/y/z");
+
+        expr = SequencerPathExpression.compile("/a/(b/c)[d/e/@something] => /x/$1/./z");
+        assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/b/c/z");
+    }
+
+    @Test
+    public void shouldMatchExpressionWithFilenamePatternAndChildProperty() {
+        expr = SequencerPathExpression.compile("//(*.(jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data]=>/images/$1");
+        assertMatches(expr.matcher("/a/b/caution.png/jcr:content/@jcr:data"),
+                      "/a/b/caution.png/jcr:content",
+                      "/images/caution.png");
+    }
+
+}

Deleted: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencingServiceTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencingServiceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,336 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.dna.repository.sequencers;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItem;
-import java.util.concurrent.TimeUnit;
-import javax.jcr.Node;
-import javax.jcr.Session;
-import javax.jcr.observation.Event;
-import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
-import org.jboss.dna.repository.observation.ObservationService;
-import org.jboss.dna.repository.services.ServiceAdministrator;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-import org.jboss.dna.repository.util.MockJcrExecutionContext;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class SequencingServiceTest extends AbstractJcrRepositoryTest {
-
-    public static final int ALL_EVENT_TYPES = Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED
-                                              | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
-    public static final String REPOSITORY_WORKSPACE_NAME = "testRepository-Workspace";
-
-    private ObservationService observationService;
-    private SequencingService sequencingService;
-    private JcrExecutionContext executionContext;
-
-    @Before
-    public void beforeEach() {
-        this.executionContext = new MockJcrExecutionContext(this, REPOSITORY_WORKSPACE_NAME);
-        this.sequencingService = new SequencingService();
-        this.sequencingService.setExecutionContext(this.executionContext);
-        this.observationService = new ObservationService(this.executionContext.getSessionFactory());
-        this.observationService.addListener(this.sequencingService);
-    }
-
-    @After
-    public void afterEach() throws Exception {
-        this.observationService.getAdministrator().shutdown();
-        this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-        this.sequencingService.getAdministrator().shutdown();
-        this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-        super.shutdownRepository();
-    }
-
-    @Test
-    public void shouldHaveTheDefaultSelectorUponConstruction() {
-        assertThat(sequencingService.getSequencerSelector(), is(sameInstance(SequencingService.DEFAULT_SEQUENCER_SELECTOR)));
-    }
-
-    @Test
-    public void shouldHaveNoExecutorServiceUponConstruction() {
-        assertThat(sequencingService.getExecutorService(), is(nullValue()));
-    }
-
-    @Test
-    public void shouldCreateDefaultExecutorServiceWhenStartedIfNoExecutorServiceHasBeenSet() {
-        assertThat(sequencingService.getExecutorService(), is(nullValue()));
-        sequencingService.getAdministrator().start();
-        assertThat(sequencingService.getExecutorService(), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldCreateExecutorServiceWhenStarted() {
-        assertThat(sequencingService.getExecutorService(), is(nullValue()));
-        sequencingService.getAdministrator().start();
-        assertThat(sequencingService.getExecutorService(), is(notNullValue()));
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailToSetStateToUnknownString() {
-        sequencingService.getAdministrator().setState("asdf");
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldFailToSetStateToNullString() {
-        sequencingService.getAdministrator().setState((String)null);
-    }
-
-    @Test
-    public void shouldSetStateUsingLowercaseString() {
-        assertThat(sequencingService.getAdministrator().setState("started").isStarted(), is(true));
-        assertThat(sequencingService.getAdministrator().setState("paused").isPaused(), is(true));
-        assertThat(sequencingService.getAdministrator().setState("shutdown").isShutdown(), is(true));
-    }
-
-    @Test
-    public void shouldSetStateUsingMixedCaseString() {
-        assertThat(sequencingService.getAdministrator().setState("StarTeD").isStarted(), is(true));
-        assertThat(sequencingService.getAdministrator().setState("PauSed").isPaused(), is(true));
-        assertThat(sequencingService.getAdministrator().setState("ShuTDowN").isShutdown(), is(true));
-    }
-
-    @Test
-    public void shouldSetStateUsingUppercasString() {
-        assertThat(sequencingService.getAdministrator().setState("STARTED").isStarted(), is(true));
-        assertThat(sequencingService.getAdministrator().setState("PAUSED").isPaused(), is(true));
-        assertThat(sequencingService.getAdministrator().setState("SHUTDOWN").isShutdown(), is(true));
-    }
-
-    @Test
-    public void shouldBePausedUponConstruction() {
-        assertThat(sequencingService.getAdministrator().isPaused(), is(true));
-        assertThat(sequencingService.getAdministrator().getState(), is(ServiceAdministrator.State.PAUSED));
-        assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
-        assertThat(sequencingService.getAdministrator().isStarted(), is(false));
-    }
-
-    @Test
-    public void shouldBeAbleToShutdownWhenNotStarted() {
-        assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
-        for (int i = 0; i != 3; ++i) {
-            assertThat(sequencingService.getAdministrator().shutdown().isShutdown(), is(true));
-            assertThat(sequencingService.getAdministrator().isPaused(), is(false));
-            assertThat(sequencingService.getAdministrator().isStarted(), is(false));
-            ServiceAdministrator.State actualState = sequencingService.getAdministrator().getState();
-            assertThat(actualState == ServiceAdministrator.State.SHUTDOWN || actualState == ServiceAdministrator.State.TERMINATED,
-                       is(true));
-        }
-    }
-
-    @Test
-    public void shouldBeAbleToBePauseAndRestarted() {
-        assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
-        for (int i = 0; i != 3; ++i) {
-            // Now pause it ...
-            assertThat(sequencingService.getAdministrator().pause().isPaused(), is(true));
-            assertThat(sequencingService.getAdministrator().isStarted(), is(false));
-            assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
-            assertThat(sequencingService.getAdministrator().getState(), is(ServiceAdministrator.State.PAUSED));
-
-            // Now start it back up ...
-            assertThat(sequencingService.getAdministrator().start().isStarted(), is(true));
-            assertThat(sequencingService.getAdministrator().isPaused(), is(false));
-            assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
-            assertThat(sequencingService.getAdministrator().getState(), is(ServiceAdministrator.State.STARTED));
-        }
-    }
-
-    @Test( expected = IllegalStateException.class )
-    public void shouldNotBeAbleToBeRestartedAfterBeingShutdown() {
-        assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
-        // Shut it down ...
-        assertThat(sequencingService.getAdministrator().shutdown().isShutdown(), is(true));
-        assertThat(sequencingService.getAdministrator().isPaused(), is(false));
-        assertThat(sequencingService.getAdministrator().isStarted(), is(false));
-        ServiceAdministrator.State actualState = sequencingService.getAdministrator().getState();
-        assertThat(actualState == ServiceAdministrator.State.SHUTDOWN || actualState == ServiceAdministrator.State.TERMINATED,
-                   is(true));
-
-        // Now start it back up ... this will fail
-        sequencingService.getAdministrator().start();
-    }
-
-    @Test
-    public void shouldBeAbleToMonitorWorkspaceWhenPausedOrStarted() throws Exception {
-        startRepository();
-        Session session = getRepository().login(getTestCredentials());
-
-        // Try when paused ...
-        assertThat(sequencingService.getAdministrator().isPaused(), is(true));
-        assertThat(observationService.getAdministrator().pause().isPaused(), is(true));
-        ObservationService.WorkspaceListener listener = observationService.monitor(REPOSITORY_WORKSPACE_NAME, Event.NODE_ADDED);
-        assertThat(listener, is(notNullValue()));
-        assertThat(listener.getAbsolutePath(), is("/"));
-        assertThat(listener.getEventTypes(), is(Event.NODE_ADDED));
-
-        // Cause an event ...
-        session.getRootNode().addNode("testnodeA", "nt:unstructured");
-        session.save();
-        Thread.sleep(100); // let the events be handled ...
-        assertThat(observationService.getStatistics().getNumberOfEventsIgnored(), is((long)1));
-
-        // Reset the statistics and remove the listener ...
-        sequencingService.getStatistics().reset();
-        observationService.getStatistics().reset();
-        assertThat(listener.isRegistered(), is(true));
-        listener.unregister();
-        assertThat(listener.isRegistered(), is(false));
-
-        // Start the sequencing sequencingService and try monitoring the workspace ...
-        assertThat(sequencingService.getAdministrator().start().isStarted(), is(true));
-        assertThat(observationService.getAdministrator().start().isStarted(), is(true));
-        ObservationService.WorkspaceListener listener2 = observationService.monitor(REPOSITORY_WORKSPACE_NAME, Event.NODE_ADDED);
-        assertThat(listener2.isRegistered(), is(true));
-        assertThat(listener2, is(notNullValue()));
-        assertThat(listener2.getAbsolutePath(), is("/"));
-        assertThat(listener2.getEventTypes(), is(Event.NODE_ADDED));
-
-        // Cause an event ...
-        session.getRootNode().addNode("testnodeB", "nt:unstructured");
-        session.save();
-        Thread.sleep(100); // let the events be handled ...
-
-        // Check the results: nothing ignored, and 1 node skipped (since no sequencers apply)
-        assertThat(observationService.getStatistics().getNumberOfEventsIgnored(), is((long)0));
-        assertThat(sequencingService.getStatistics().getNumberOfNodesSkipped(), is((long)1));
-
-        sequencingService.getAdministrator().shutdown();
-        sequencingService.getStatistics().reset();
-        observationService.getAdministrator().shutdown();
-        observationService.getStatistics().reset();
-
-        // Cause another event ...
-        session.getRootNode().addNode("testnodeC", "nt:unstructured");
-        session.save();
-        Thread.sleep(100); // let the events be handled ...
-        // The listener should no longer be registered ...
-        assertThat(listener2.isRegistered(), is(false));
-
-        // Check the results: nothing ignored, and nothing skipped
-        assertThat(observationService.getStatistics().getNumberOfEventsIgnored(), is((long)0));
-        assertThat(sequencingService.getStatistics().getNumberOfNodesSkipped(), is((long)0));
-    }
-
-    @Test
-    public void shouldUnregisterAllWorkspaceListenersWhenSystemIsShutdownAndNotWhenPaused() throws Exception {
-        startRepository();
-        Session session = getRepository().login(getTestCredentials());
-
-        // Start the sequencing sequencingService and try monitoring the workspace ...
-        assertThat(sequencingService.getAdministrator().start().isStarted(), is(true));
-        ObservationService.WorkspaceListener listener = observationService.monitor(REPOSITORY_WORKSPACE_NAME, Event.NODE_ADDED);
-        assertThat(listener.isRegistered(), is(true));
-        assertThat(listener, is(notNullValue()));
-        assertThat(listener.getAbsolutePath(), is("/"));
-        assertThat(listener.getEventTypes(), is(Event.NODE_ADDED));
-
-        // Cause an event ...
-        session.getRootNode().addNode("testnodeB", "nt:unstructured");
-        session.save();
-        assertThat(listener.isRegistered(), is(true));
-
-        // Pause the sequencingService, can cause an event ...
-        sequencingService.getAdministrator().pause();
-        session.getRootNode().addNode("testnodeB", "nt:unstructured");
-        session.save();
-        assertThat(listener.isRegistered(), is(true));
-
-        // Shut down the services and await termination ...
-        sequencingService.getAdministrator().shutdown();
-        observationService.getAdministrator().shutdown();
-        sequencingService.getAdministrator().awaitTermination(2, TimeUnit.SECONDS);
-        observationService.getAdministrator().awaitTermination(2, TimeUnit.SECONDS);
-
-        // Cause another event ...
-        session.getRootNode().addNode("testnodeC", "nt:unstructured");
-        session.save();
-
-        // The listener should no longer be registered ...
-        assertThat(listener.isRegistered(), is(false));
-    }
-
-    @Test
-    public void shouldExecuteSequencersUponChangesToRepositoryThatMatchSequencerPathExpressions() throws Exception {
-        // Add configurations for a sequencer ...
-        String name = "MockSequencerA";
-        String desc = "A mock sequencer that accumulates the number of times it's called";
-        String classname = MockSequencerA.class.getName();
-        String[] classpath = null;
-        String[] pathExpressions = {"/testnodeC/testnodeD/@description => ."};
-        SequencerConfig configA = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
-        sequencingService.addSequencer(configA);
-
-        // Start the repository and get a session ...
-        startRepository();
-        Session session = getRepository().login(getTestCredentials());
-
-        // Start the sequencing sequencingService and try monitoring the workspace ...
-        assertThat(sequencingService.getAdministrator().start().isStarted(), is(true));
-        ObservationService.WorkspaceListener listener = observationService.monitor(REPOSITORY_WORKSPACE_NAME, ALL_EVENT_TYPES);
-        assertThat(listener.isRegistered(), is(true));
-        assertThat(listener, is(notNullValue()));
-        assertThat(listener.getAbsolutePath(), is("/"));
-        assertThat(listener.getEventTypes(), is(ALL_EVENT_TYPES));
-
-        // The sequencer should not yet have run ...
-        MockSequencerA sequencerA = (MockSequencerA)sequencingService.getSequencerLibrary().getInstances().get(0);
-        assertThat(sequencerA, is(notNullValue()));
-        assertThat(sequencerA.getCounter(), is(0));
-        sequencerA.setExpectedCount(1);
-        assertThat(sequencingService.getSequencerLibrary().getInstances(), hasItem((Sequencer)sequencerA));
-
-        // Cause an event, but not one that the sequencer cares about ...
-        Node nodeC = session.getRootNode().addNode("testnodeC", "nt:unstructured");
-        assertThat(nodeC, is(notNullValue()));
-        session.save();
-        assertThat(sequencerA.getCounter(), is(0));
-        assertThat(sequencingService.getSequencerLibrary().getInstances(), hasItem((Sequencer)sequencerA));
-
-        // Cause another event, but again one that the sequencer does not care about ...
-        Node nodeD = nodeC.addNode("testnodeD", "nt:unstructured");
-        assertThat(nodeD, is(notNullValue()));
-        session.save();
-        assertThat(sequencerA.getCounter(), is(0));
-        assertThat(sequencingService.getSequencerLibrary().getInstances(), hasItem((Sequencer)sequencerA));
-
-        // Now set the property that the sequencer DOES care about ...
-        nodeD.setProperty("description", "This is the value");
-        session.save();
-
-        // Wait for the event to be processed and the sequencer to be called ...
-        sequencerA.awaitExecution(4, TimeUnit.SECONDS); // wait for the sequencer to be called
-        assertThat(sequencerA.getCounter(), is(1));
-        assertThat(sequencingService.getSequencerLibrary().getInstances(), hasItem((Sequencer)sequencerA));
-    }
-}

Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencingServiceTest.java (from rev 706, trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java)
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencingServiceTest.java	                        (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/SequencingServiceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,352 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.dna.repository.sequencer;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItem;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import org.jboss.dna.common.SystemFailureException;
+import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
+import org.jboss.dna.repository.observation.ObservationService;
+import org.jboss.dna.repository.sequencer.Sequencer;
+import org.jboss.dna.repository.sequencer.SequencerConfig;
+import org.jboss.dna.repository.sequencer.SequencingService;
+import org.jboss.dna.repository.service.ServiceAdministrator;
+import org.jboss.dna.repository.util.JcrExecutionContext;
+import org.jboss.dna.repository.util.SessionFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class SequencingServiceTest extends AbstractJcrRepositoryTest {
+
+    public static final int ALL_EVENT_TYPES = Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED
+                                              | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
+    public static final String REPOSITORY_WORKSPACE_NAME = "testRepository-Workspace";
+
+    private ObservationService observationService;
+    private SequencingService sequencingService;
+    private JcrExecutionContext executionContext;
+
+    @Before
+    public void beforeEach() {
+        SessionFactory sessionFactory = new SessionFactory() {
+            public Session createSession( String name ) throws RepositoryException {
+                assertThat(name, is(REPOSITORY_WORKSPACE_NAME));
+                try {
+                    return getRepository().login(getTestCredentials());
+                } catch (IOException e) {
+                    throw new SystemFailureException(e);
+                }
+            }
+        };
+        this.executionContext = new JcrExecutionContext(sessionFactory, REPOSITORY_WORKSPACE_NAME);
+        this.sequencingService = new SequencingService();
+        this.sequencingService.setExecutionContext(this.executionContext);
+        this.observationService = new ObservationService(this.executionContext.getSessionFactory());
+        this.observationService.addListener(this.sequencingService);
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        this.observationService.getAdministrator().shutdown();
+        this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+        this.sequencingService.getAdministrator().shutdown();
+        this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+        super.shutdownRepository();
+    }
+
+    @Test
+    public void shouldHaveTheDefaultSelectorUponConstruction() {
+        assertThat(sequencingService.getSequencerSelector(), is(sameInstance(SequencingService.DEFAULT_SEQUENCER_SELECTOR)));
+    }
+
+    @Test
+    public void shouldHaveNoExecutorServiceUponConstruction() {
+        assertThat(sequencingService.getExecutorService(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldCreateDefaultExecutorServiceWhenStartedIfNoExecutorServiceHasBeenSet() {
+        assertThat(sequencingService.getExecutorService(), is(nullValue()));
+        sequencingService.getAdministrator().start();
+        assertThat(sequencingService.getExecutorService(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldCreateExecutorServiceWhenStarted() {
+        assertThat(sequencingService.getExecutorService(), is(nullValue()));
+        sequencingService.getAdministrator().start();
+        assertThat(sequencingService.getExecutorService(), is(notNullValue()));
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailToSetStateToUnknownString() {
+        sequencingService.getAdministrator().setState("asdf");
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void shouldFailToSetStateToNullString() {
+        sequencingService.getAdministrator().setState((String)null);
+    }
+
+    @Test
+    public void shouldSetStateUsingLowercaseString() {
+        assertThat(sequencingService.getAdministrator().setState("started").isStarted(), is(true));
+        assertThat(sequencingService.getAdministrator().setState("paused").isPaused(), is(true));
+        assertThat(sequencingService.getAdministrator().setState("shutdown").isShutdown(), is(true));
+    }
+
+    @Test
+    public void shouldSetStateUsingMixedCaseString() {
+        assertThat(sequencingService.getAdministrator().setState("StarTeD").isStarted(), is(true));
+        assertThat(sequencingService.getAdministrator().setState("PauSed").isPaused(), is(true));
+        assertThat(sequencingService.getAdministrator().setState("ShuTDowN").isShutdown(), is(true));
+    }
+
+    @Test
+    public void shouldSetStateUsingUppercasString() {
+        assertThat(sequencingService.getAdministrator().setState("STARTED").isStarted(), is(true));
+        assertThat(sequencingService.getAdministrator().setState("PAUSED").isPaused(), is(true));
+        assertThat(sequencingService.getAdministrator().setState("SHUTDOWN").isShutdown(), is(true));
+    }
+
+    @Test
+    public void shouldBePausedUponConstruction() {
+        assertThat(sequencingService.getAdministrator().isPaused(), is(true));
+        assertThat(sequencingService.getAdministrator().getState(), is(ServiceAdministrator.State.PAUSED));
+        assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
+        assertThat(sequencingService.getAdministrator().isStarted(), is(false));
+    }
+
+    @Test
+    public void shouldBeAbleToShutdownWhenNotStarted() {
+        assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
+        for (int i = 0; i != 3; ++i) {
+            assertThat(sequencingService.getAdministrator().shutdown().isShutdown(), is(true));
+            assertThat(sequencingService.getAdministrator().isPaused(), is(false));
+            assertThat(sequencingService.getAdministrator().isStarted(), is(false));
+            ServiceAdministrator.State actualState = sequencingService.getAdministrator().getState();
+            assertThat(actualState == ServiceAdministrator.State.SHUTDOWN || actualState == ServiceAdministrator.State.TERMINATED,
+                       is(true));
+        }
+    }
+
+    @Test
+    public void shouldBeAbleToBePauseAndRestarted() {
+        assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
+        for (int i = 0; i != 3; ++i) {
+            // Now pause it ...
+            assertThat(sequencingService.getAdministrator().pause().isPaused(), is(true));
+            assertThat(sequencingService.getAdministrator().isStarted(), is(false));
+            assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
+            assertThat(sequencingService.getAdministrator().getState(), is(ServiceAdministrator.State.PAUSED));
+
+            // Now start it back up ...
+            assertThat(sequencingService.getAdministrator().start().isStarted(), is(true));
+            assertThat(sequencingService.getAdministrator().isPaused(), is(false));
+            assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
+            assertThat(sequencingService.getAdministrator().getState(), is(ServiceAdministrator.State.STARTED));
+        }
+    }
+
+    @Test( expected = IllegalStateException.class )
+    public void shouldNotBeAbleToBeRestartedAfterBeingShutdown() {
+        assertThat(sequencingService.getAdministrator().isShutdown(), is(false));
+        // Shut it down ...
+        assertThat(sequencingService.getAdministrator().shutdown().isShutdown(), is(true));
+        assertThat(sequencingService.getAdministrator().isPaused(), is(false));
+        assertThat(sequencingService.getAdministrator().isStarted(), is(false));
+        ServiceAdministrator.State actualState = sequencingService.getAdministrator().getState();
+        assertThat(actualState == ServiceAdministrator.State.SHUTDOWN || actualState == ServiceAdministrator.State.TERMINATED,
+                   is(true));
+
+        // Now start it back up ... this will fail
+        sequencingService.getAdministrator().start();
+    }
+
+    @Test
+    public void shouldBeAbleToMonitorWorkspaceWhenPausedOrStarted() throws Exception {
+        startRepository();
+        Session session = getRepository().login(getTestCredentials());
+
+        // Try when paused ...
+        assertThat(sequencingService.getAdministrator().isPaused(), is(true));
+        assertThat(observationService.getAdministrator().pause().isPaused(), is(true));
+        ObservationService.WorkspaceListener listener = observationService.monitor(REPOSITORY_WORKSPACE_NAME, Event.NODE_ADDED);
+        assertThat(listener, is(notNullValue()));
+        assertThat(listener.getAbsolutePath(), is("/"));
+        assertThat(listener.getEventTypes(), is(Event.NODE_ADDED));
+
+        // Cause an event ...
+        session.getRootNode().addNode("testnodeA", "nt:unstructured");
+        session.save();
+        Thread.sleep(100); // let the events be handled ...
+        assertThat(observationService.getStatistics().getNumberOfEventsIgnored(), is((long)1));
+
+        // Reset the statistics and remove the listener ...
+        sequencingService.getStatistics().reset();
+        observationService.getStatistics().reset();
+        assertThat(listener.isRegistered(), is(true));
+        listener.unregister();
+        assertThat(listener.isRegistered(), is(false));
+
+        // Start the sequencing sequencingService and try monitoring the workspace ...
+        assertThat(sequencingService.getAdministrator().start().isStarted(), is(true));
+        assertThat(observationService.getAdministrator().start().isStarted(), is(true));
+        ObservationService.WorkspaceListener listener2 = observationService.monitor(REPOSITORY_WORKSPACE_NAME, Event.NODE_ADDED);
+        assertThat(listener2.isRegistered(), is(true));
+        assertThat(listener2, is(notNullValue()));
+        assertThat(listener2.getAbsolutePath(), is("/"));
+        assertThat(listener2.getEventTypes(), is(Event.NODE_ADDED));
+
+        // Cause an event ...
+        session.getRootNode().addNode("testnodeB", "nt:unstructured");
+        session.save();
+        Thread.sleep(100); // let the events be handled ...
+
+        // Check the results: nothing ignored, and 1 node skipped (since no sequencers apply)
+        assertThat(observationService.getStatistics().getNumberOfEventsIgnored(), is((long)0));
+        assertThat(sequencingService.getStatistics().getNumberOfNodesSkipped(), is((long)1));
+
+        sequencingService.getAdministrator().shutdown();
+        sequencingService.getStatistics().reset();
+        observationService.getAdministrator().shutdown();
+        observationService.getStatistics().reset();
+
+        // Cause another event ...
+        session.getRootNode().addNode("testnodeC", "nt:unstructured");
+        session.save();
+        Thread.sleep(100); // let the events be handled ...
+        // The listener should no longer be registered ...
+        assertThat(listener2.isRegistered(), is(false));
+
+        // Check the results: nothing ignored, and nothing skipped
+        assertThat(observationService.getStatistics().getNumberOfEventsIgnored(), is((long)0));
+        assertThat(sequencingService.getStatistics().getNumberOfNodesSkipped(), is((long)0));
+    }
+
+    @Test
+    public void shouldUnregisterAllWorkspaceListenersWhenSystemIsShutdownAndNotWhenPaused() throws Exception {
+        startRepository();
+        Session session = getRepository().login(getTestCredentials());
+
+        // Start the sequencing sequencingService and try monitoring the workspace ...
+        assertThat(sequencingService.getAdministrator().start().isStarted(), is(true));
+        ObservationService.WorkspaceListener listener = observationService.monitor(REPOSITORY_WORKSPACE_NAME, Event.NODE_ADDED);
+        assertThat(listener.isRegistered(), is(true));
+        assertThat(listener, is(notNullValue()));
+        assertThat(listener.getAbsolutePath(), is("/"));
+        assertThat(listener.getEventTypes(), is(Event.NODE_ADDED));
+
+        // Cause an event ...
+        session.getRootNode().addNode("testnodeB", "nt:unstructured");
+        session.save();
+        assertThat(listener.isRegistered(), is(true));
+
+        // Pause the sequencingService, can cause an event ...
+        sequencingService.getAdministrator().pause();
+        session.getRootNode().addNode("testnodeB", "nt:unstructured");
+        session.save();
+        assertThat(listener.isRegistered(), is(true));
+
+        // Shut down the services and await termination ...
+        sequencingService.getAdministrator().shutdown();
+        observationService.getAdministrator().shutdown();
+        sequencingService.getAdministrator().awaitTermination(2, TimeUnit.SECONDS);
+        observationService.getAdministrator().awaitTermination(2, TimeUnit.SECONDS);
+
+        // Cause another event ...
+        session.getRootNode().addNode("testnodeC", "nt:unstructured");
+        session.save();
+
+        // The listener should no longer be registered ...
+        assertThat(listener.isRegistered(), is(false));
+    }
+
+    @Test
+    public void shouldExecuteSequencersUponChangesToRepositoryThatMatchSequencerPathExpressions() throws Exception {
+        // Add configurations for a sequencer ...
+        String name = "MockSequencerA";
+        String desc = "A mock sequencer that accumulates the number of times it's called";
+        String classname = MockSequencerA.class.getName();
+        String[] classpath = null;
+        String[] pathExpressions = {"/testnodeC/testnodeD/@description => ."};
+        SequencerConfig configA = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
+        sequencingService.addSequencer(configA);
+
+        // Start the repository and get a session ...
+        startRepository();
+        Session session = getRepository().login(getTestCredentials());
+
+        // Start the sequencing sequencingService and try monitoring the workspace ...
+        assertThat(sequencingService.getAdministrator().start().isStarted(), is(true));
+        ObservationService.WorkspaceListener listener = observationService.monitor(REPOSITORY_WORKSPACE_NAME, ALL_EVENT_TYPES);
+        assertThat(listener.isRegistered(), is(true));
+        assertThat(listener, is(notNullValue()));
+        assertThat(listener.getAbsolutePath(), is("/"));
+        assertThat(listener.getEventTypes(), is(ALL_EVENT_TYPES));
+
+        // The sequencer should not yet have run ...
+        MockSequencerA sequencerA = (MockSequencerA)sequencingService.getSequencerLibrary().getInstances().get(0);
+        assertThat(sequencerA, is(notNullValue()));
+        assertThat(sequencerA.getCounter(), is(0));
+        sequencerA.setExpectedCount(1);
+        assertThat(sequencingService.getSequencerLibrary().getInstances(), hasItem((Sequencer)sequencerA));
+
+        // Cause an event, but not one that the sequencer cares about ...
+        Node nodeC = session.getRootNode().addNode("testnodeC", "nt:unstructured");
+        assertThat(nodeC, is(notNullValue()));
+        session.save();
+        assertThat(sequencerA.getCounter(), is(0));
+        assertThat(sequencingService.getSequencerLibrary().getInstances(), hasItem((Sequencer)sequencerA));
+
+        // Cause another event, but again one that the sequencer does not care about ...
+        Node nodeD = nodeC.addNode("testnodeD", "nt:unstructured");
+        assertThat(nodeD, is(notNullValue()));
+        session.save();
+        assertThat(sequencerA.getCounter(), is(0));
+        assertThat(sequencingService.getSequencerLibrary().getInstances(), hasItem((Sequencer)sequencerA));
+
+        // Now set the property that the sequencer DOES care about ...
+        nodeD.setProperty("description", "This is the value");
+        session.save();
+
+        // Wait for the event to be processed and the sequencer to be called ...
+        sequencerA.awaitExecution(4, TimeUnit.SECONDS); // wait for the sequencer to be called
+        assertThat(sequencerA.getCounter(), is(1));
+        assertThat(sequencingService.getSequencerLibrary().getInstances(), hasItem((Sequencer)sequencerA));
+    }
+}

Deleted: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapterTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,403 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.sequencers;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import javax.jcr.Node;
-import javax.jcr.Session;
-import javax.jcr.observation.Event;
-import org.jboss.dna.common.collection.Problems;
-import org.jboss.dna.common.collection.SimpleProblems;
-import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
-import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.util.BasicJcrExecutionContext;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-import org.jboss.dna.repository.util.JcrNamespaceRegistry;
-import org.jboss.dna.repository.util.JcrTools;
-import org.jboss.dna.repository.util.RepositoryNodePath;
-import org.jboss.dna.repository.util.SessionFactory;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class StreamSequencerAdapterTest extends AbstractJcrRepositoryTest {
-
-    private StreamSequencer streamSequencer;
-    private StreamSequencerAdapter sequencer;
-    private String[] validExpressions = {"/a/* => /output"};
-    private SequencerConfig validConfig = new SequencerConfig("name", "desc", "something.class", null, validExpressions);
-    private JcrTools tools;
-    private Session session;
-    private SequencerOutputMap sequencerOutput;
-    private String sampleData = "The little brown fox didn't something bad.";
-    private JcrExecutionContext context;
-    private String repositoryWorkspaceName = "something";
-    private Problems problems;
-
-    @Before
-    public void beforeEach() {
-        final JcrTools tools = new JcrTools();
-        this.tools = tools;
-        final SessionFactory sessionFactory = new SessionFactory() {
-
-            public Session createSession( String name ) {
-                return createTestSession();
-            }
-        };
-        problems = new SimpleProblems();
-        NamespaceRegistry registry = new JcrNamespaceRegistry(sessionFactory, "doesn't matter");
-        this.context = new BasicJcrExecutionContext(sessionFactory, registry, null, null);
-        this.sequencerOutput = new SequencerOutputMap(this.context.getValueFactories());
-        final SequencerOutputMap finalOutput = sequencerOutput;
-        this.streamSequencer = new StreamSequencer() {
-
-            /**
-             * This method always copies the {@link StreamSequencerAdapterTest#sequencerOutput} data into the output {@inheritDoc}
-             * , and does nothing else with any of the other parameters.
-             */
-            public void sequence( InputStream stream,
-                                  SequencerOutput output,
-                                  SequencerContext context ) {
-                for (SequencerOutputMap.Entry entry : finalOutput) {
-                    Path nodePath = entry.getPath();
-                    for (SequencerOutputMap.PropertyValue property : entry.getPropertyValues()) {
-                        output.setProperty(nodePath, property.getName(), property.getValue());
-                    }
-                }
-            }
-        };
-        sequencer = new StreamSequencerAdapter(streamSequencer);
-    }
-
-    @After
-    public void afterEach() {
-        if (session != null) {
-            try {
-                session.logout();
-            } finally {
-                session = null;
-            }
-        }
-    }
-
-    protected Session createTestSession() {
-        try {
-            return getRepository().login(getTestCredentials());
-        } catch (Exception e) {
-            fail("Unable to create repository session: " + e.getMessage());
-            return null; // won't get here
-        }
-    }
-
-    protected void testSequencer( final StreamSequencer sequencer ) throws Throwable {
-        StreamSequencer streamSequencer = new StreamSequencer() {
-
-            public void sequence( InputStream stream,
-                                  SequencerOutput output,
-                                  SequencerContext context ) {
-                sequencer.sequence(stream, output, context);
-            }
-        };
-        StreamSequencerAdapter adapter = new StreamSequencerAdapter(streamSequencer);
-        startRepository();
-        session = getRepository().login(getTestCredentials());
-        Node inputNode = tools.findOrCreateNode(session, "/a/b/c");
-        Node outputNode = tools.findOrCreateNode(session, "/d/e");
-        inputNode.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
-        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, inputNode.getPath(), Event.PROPERTY_CHANGED,
-                                               Collections.singleton("sequencedProperty"), null);
-        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
-        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, outputNode.getPath()));
-        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
-        adapter.execute(inputNode, "sequencedProperty", nodeChange, outputPaths, context, problems);
-    }
-
-    @Test
-    public void shouldNotHaveSequencerUponInstantiation() {
-        assertThat(sequencer.getConfiguration(), is(nullValue()));
-        sequencer.setConfiguration(validConfig);
-        assertThat(sequencer.getConfiguration(), is(sameInstance(validConfig)));
-    }
-
-    @Test
-    public void shouldExtractNullMixinTypesFromNullValue() {
-        assertThat(sequencer.extractMixinTypes(null), is(nullValue()));
-    }
-
-    @Test
-    public void shouldExtractMixinTypesFromStringValue() {
-        assertThat(sequencer.extractMixinTypes("value"), is(new String[] {"value"}));
-        assertThat(sequencer.extractMixinTypes(""), is(new String[] {""}));
-    }
-
-    @Test
-    public void shouldExtractMixinTypesFromStringArrayValue() {
-        assertThat(sequencer.extractMixinTypes(new String[] {"value1"}), is(new String[] {"value1"}));
-        assertThat(sequencer.extractMixinTypes(new String[] {"value1", "value2"}), is(new String[] {"value1", "value2"}));
-    }
-
-    @Test
-    public void shouldExtractMixinTypesFromStringArrayWithNullValue() {
-        assertThat(sequencer.extractMixinTypes(new String[] {"value1", null, "value2"}), is(new String[] {"value1", null,
-            "value2"}));
-    }
-
-    @Test
-    public void shouldExecuteSequencerOnExistingNodeAndOutputToExistingNode() throws Exception {
-        startRepository();
-        session = getRepository().login(getTestCredentials());
-
-        // Set up the repository for the test ...
-        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
-        Node nodeE = tools.findOrCreateNode(session, "/d/e");
-        assertThat(nodeC, is(notNullValue()));
-        assertThat(nodeE, is(notNullValue()));
-        assertThat(nodeE.getNodes().getSize(), is(0l));
-        assertThat(nodeE.getProperties().getSize(), is(1l)); // jcr:primaryType
-        assertThat(nodeE.getProperty("jcr:primaryType").getString(), is("nt:unstructured"));
-
-        // Set the property that will be sequenced ...
-        nodeC.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
-
-        // Set up the node changes ...
-        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
-                                               Collections.singleton("sequencedProperty"), null);
-
-        // Set up the output directory ...
-        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
-        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, nodeE.getPath()));
-
-        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
-        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
-
-        // Call the sequencer ...
-        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
-    }
-
-    @Test( expected = SequencerException.class )
-    public void shouldExecuteSequencerOnExistingNodeWithMissingSequencedPropertyAndOutputToExistingNode() throws Exception {
-        startRepository();
-        session = getRepository().login(getTestCredentials());
-
-        // Set up the repository for the test ...
-        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
-        Node nodeE = tools.findOrCreateNode(session, "/d/e");
-        assertThat(nodeC, is(notNullValue()));
-        assertThat(nodeE, is(notNullValue()));
-        assertThat(nodeE.getNodes().getSize(), is(0l));
-        assertThat(nodeE.getProperties().getSize(), is(1l)); // jcr:primaryType
-        assertThat(nodeE.getProperty("jcr:primaryType").getString(), is("nt:unstructured"));
-
-        // Set the property that will be sequenced ...
-        // THIS TEST REQUIRES THIS PROPERTY TO BE NULL OR NON-EXISTANT
-        nodeC.setProperty("sequencedProperty", (InputStream)null);
-
-        // Set up the node changes ...
-        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
-                                               Collections.singleton("sequencedProperty"), null);
-
-        // Set up the output directory ...
-        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
-        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, nodeE.getPath()));
-
-        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
-        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
-
-        // Call the sequencer, which should cause the exception ...
-        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
-    }
-
-    @Test
-    public void shouldExecuteSequencerOnExistingNodeAndOutputToMultipleExistingNodes() throws Exception {
-        startRepository();
-        session = getRepository().login(getTestCredentials());
-
-        // Set up the repository for the test ...
-        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
-        Node nodeE = tools.findOrCreateNode(session, "/d/e");
-        assertThat(nodeC, is(notNullValue()));
-        assertThat(nodeE, is(notNullValue()));
-        assertThat(nodeE.getNodes().getSize(), is(0l));
-        assertThat(nodeE.getProperties().getSize(), is(1l)); // jcr:primaryType
-        assertThat(nodeE.getProperty("jcr:primaryType").getString(), is("nt:unstructured"));
-
-        // Set the property that will be sequenced ...
-        nodeC.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
-
-        // Set up the node changes ...
-        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
-                                               Collections.singleton("sequencedProperty"), null);
-
-        // Set up the output directory ...
-        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
-        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/d/e"));
-        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/x/y/z"));
-
-        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
-        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
-
-        // Call the sequencer ...
-        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
-
-        // Check to see that the output nodes have been created ...
-        assertThat(session.getRootNode().hasNode("d/e"), is(true));
-        assertThat(session.getRootNode().hasNode("x/y/z"), is(true));
-    }
-
-    @Test
-    public void shouldExecuteSequencerOnExistingNodeAndOutputToNonExistingNode() throws Exception {
-        startRepository();
-        session = getRepository().login(getTestCredentials());
-
-        // Set up the repository for the test ...
-        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
-        assertThat(session.getRootNode().hasNode("d"), is(false));
-        assertThat(nodeC, is(notNullValue()));
-
-        // Set the property that will be sequenced ...
-        nodeC.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
-
-        // Set up the node changes ...
-        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
-                                               Collections.singleton("sequencedProperty"), null);
-
-        // Set up the output directory ...
-        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
-        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/d/e"));
-
-        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
-        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
-
-        // Call the sequencer ...
-        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
-
-        // Check to see that the "/d/e" node has been created ...
-        assertThat(session.getRootNode().hasNode("d/e"), is(true));
-    }
-
-    @Test
-    public void shouldExecuteSequencerOnExistingNodeAndOutputToMultipleNonExistingNodes() throws Exception {
-        startRepository();
-        session = getRepository().login(getTestCredentials());
-
-        // Set up the repository for the test ...
-        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
-        assertThat(session.getRootNode().hasNode("d"), is(false));
-        assertThat(session.getRootNode().hasNode("x"), is(false));
-        assertThat(nodeC, is(notNullValue()));
-
-        // Set the property that will be sequenced ...
-        nodeC.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
-
-        // Set up the node changes ...
-        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
-                                               Collections.singleton("sequencedProperty"), null);
-
-        // Set up the output directory ...
-        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
-        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/d/e"));
-        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/x/y/z"));
-        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/x/z"));
-
-        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
-        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
-
-        // Call the sequencer ...
-        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
-
-        // Check to see that the output nodes have been created ...
-        assertThat(session.getRootNode().hasNode("d/e"), is(true));
-        assertThat(session.getRootNode().hasNode("x/y/z"), is(true));
-        assertThat(session.getRootNode().hasNode("x/z"), is(true));
-
-        // Check to see that the sequencer-generated nodes have been created ...
-        // Node beta = session.getRootNode().getNode("d/e/alpha/beta");
-        // for (PropertyIterator iter = beta.getProperties(); iter.hasNext();) {
-        // Property property = iter.nextProperty();
-        // System.out.println("Property on " + beta.getPath() + " ===> " + property.getName() + " = " + property.getValue());
-        // }
-        assertThat(session.getRootNode().getNode("d/e/alpha/beta").getProperty("isSomething").getBoolean(), is(true));
-        assertThat(session.getRootNode().getNode("x/y/z/alpha/beta").getProperty("isSomething").getBoolean(), is(true));
-        assertThat(session.getRootNode().getNode("x/z/alpha/beta").getProperty("isSomething").getBoolean(), is(true));
-    }
-
-    @Test
-    public void shouldSequencerOutputProvideAccessToNamespaceRegistry() {
-        assertThat(context.getNamespaceRegistry(), notNullValue());
-    }
-
-    @Test
-    public void shouldPassNonNullInputStreamToSequencer() throws Throwable {
-        testSequencer(new StreamSequencer() {
-
-            public void sequence( InputStream stream,
-                                  SequencerOutput output,
-                                  SequencerContext context ) {
-                assertThat(stream, notNullValue());
-            }
-        });
-    }
-
-    @Test
-    public void shouldPassNonNullSequencerOutputToSequencer() throws Throwable {
-        testSequencer(new StreamSequencer() {
-
-            public void sequence( InputStream stream,
-                                  SequencerOutput output,
-                                  SequencerContext context ) {
-                assertThat(output, notNullValue());
-            }
-        });
-    }
-
-    @Test
-    public void shouldPassNonNullSequencerContextToSequencer() throws Throwable {
-        testSequencer(new StreamSequencer() {
-
-            public void sequence( InputStream stream,
-                                  SequencerOutput output,
-                                  SequencerContext context ) {
-                assertThat(context, notNullValue());
-            }
-        });
-    }
-
-}

Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java (from rev 706, trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapterTest.java)
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java	                        (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,523 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencer;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import javax.jcr.Node;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.common.collection.SimpleProblems;
+import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
+import org.jboss.dna.graph.sequencer.StreamSequencer;
+import org.jboss.dna.repository.observation.NodeChange;
+import org.jboss.dna.repository.sequencer.SequencerConfig;
+import org.jboss.dna.repository.sequencer.SequencerException;
+import org.jboss.dna.repository.sequencer.SequencerOutputMap;
+import org.jboss.dna.repository.sequencer.StreamSequencerAdapter;
+import org.jboss.dna.repository.util.JcrExecutionContext;
+import org.jboss.dna.repository.util.JcrTools;
+import org.jboss.dna.repository.util.RepositoryNodePath;
+import org.jboss.dna.repository.util.SessionFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class StreamSequencerAdapterTest extends AbstractJcrRepositoryTest {
+
+    private StreamSequencer streamSequencer;
+    private StreamSequencerAdapter sequencer;
+    private String[] validExpressions = {"/a/* => /output"};
+    private SequencerConfig validConfig = new SequencerConfig("name", "desc", "something.class", null, validExpressions);
+    private JcrTools tools;
+    private Session session;
+    private SequencerOutputMap sequencerOutput;
+    private String sampleData = "The little brown fox didn't something bad.";
+    private JcrExecutionContext context;
+    private String repositoryWorkspaceName = "something";
+    private Problems problems;
+    private javax.jcr.Property sequencedProperty;
+
+    @Before
+    public void beforeEach() {
+        final JcrTools tools = new JcrTools();
+        this.tools = tools;
+        final SessionFactory sessionFactory = new SessionFactory() {
+
+            public Session createSession( String name ) {
+                return createTestSession();
+            }
+        };
+        problems = new SimpleProblems();
+        this.context = new JcrExecutionContext(sessionFactory, "doesn't matter");
+        this.sequencerOutput = new SequencerOutputMap(this.context.getValueFactories());
+        final SequencerOutputMap finalOutput = sequencerOutput;
+        this.streamSequencer = new StreamSequencer() {
+
+            /**
+             * This method always copies the {@link StreamSequencerAdapterTest#sequencerOutput} data into the output {@inheritDoc}
+             * , and does nothing else with any of the other parameters.
+             */
+            public void sequence( InputStream stream,
+                                  SequencerOutput output,
+                                  SequencerContext context ) {
+                for (SequencerOutputMap.Entry entry : finalOutput) {
+                    Path nodePath = entry.getPath();
+                    for (SequencerOutputMap.PropertyValue property : entry.getPropertyValues()) {
+                        output.setProperty(nodePath, property.getName(), property.getValue());
+                    }
+                }
+            }
+        };
+        sequencer = new StreamSequencerAdapter(streamSequencer);
+    }
+
+    @After
+    public void afterEach() {
+        if (session != null) {
+            try {
+                session.logout();
+            } finally {
+                session = null;
+            }
+        }
+    }
+
+    protected Session createTestSession() {
+        try {
+            return getRepository().login(getTestCredentials());
+        } catch (Exception e) {
+            fail("Unable to create repository session: " + e.getMessage());
+            return null; // won't get here
+        }
+    }
+
+    protected void testSequencer( final StreamSequencer sequencer ) throws Throwable {
+        StreamSequencer streamSequencer = new StreamSequencer() {
+
+            public void sequence( InputStream stream,
+                                  SequencerOutput output,
+                                  SequencerContext context ) {
+                sequencer.sequence(stream, output, context);
+            }
+        };
+        StreamSequencerAdapter adapter = new StreamSequencerAdapter(streamSequencer);
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+        Node inputNode = tools.findOrCreateNode(session, "/a/b/c");
+        Node outputNode = tools.findOrCreateNode(session, "/d/e");
+        inputNode.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
+        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, inputNode.getPath(), Event.PROPERTY_CHANGED,
+                                               Collections.singleton("sequencedProperty"), null);
+        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
+        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, outputNode.getPath()));
+        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
+        adapter.execute(inputNode, "sequencedProperty", nodeChange, outputPaths, context, problems);
+    }
+
+    @Test
+    public void shouldNotHaveSequencerUponInstantiation() {
+        assertThat(sequencer.getConfiguration(), is(nullValue()));
+        sequencer.setConfiguration(validConfig);
+        assertThat(sequencer.getConfiguration(), is(sameInstance(validConfig)));
+    }
+
+    @Test
+    public void shouldExtractNullMixinTypesFromNullValue() {
+        assertThat(sequencer.extractMixinTypes(null), is(nullValue()));
+    }
+
+    @Test
+    public void shouldExtractMixinTypesFromStringValue() {
+        assertThat(sequencer.extractMixinTypes("value"), is(new String[] {"value"}));
+        assertThat(sequencer.extractMixinTypes(""), is(new String[] {""}));
+    }
+
+    @Test
+    public void shouldExtractMixinTypesFromStringArrayValue() {
+        assertThat(sequencer.extractMixinTypes(new String[] {"value1"}), is(new String[] {"value1"}));
+        assertThat(sequencer.extractMixinTypes(new String[] {"value1", "value2"}), is(new String[] {"value1", "value2"}));
+    }
+
+    @Test
+    public void shouldExtractMixinTypesFromStringArrayWithNullValue() {
+        assertThat(sequencer.extractMixinTypes(new String[] {"value1", null, "value2"}), is(new String[] {"value1", null,
+            "value2"}));
+    }
+
+    @Test
+    public void shouldExecuteSequencerOnExistingNodeAndOutputToExistingNode() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        // Set up the repository for the test ...
+        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
+        Node nodeE = tools.findOrCreateNode(session, "/d/e");
+        assertThat(nodeC, is(notNullValue()));
+        assertThat(nodeE, is(notNullValue()));
+        assertThat(nodeE.getNodes().getSize(), is(0l));
+        assertThat(nodeE.getProperties().getSize(), is(1l)); // jcr:primaryType
+        assertThat(nodeE.getProperty("jcr:primaryType").getString(), is("nt:unstructured"));
+
+        // Set the property that will be sequenced ...
+        nodeC.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
+
+        // Set up the node changes ...
+        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
+                                               Collections.singleton("sequencedProperty"), null);
+
+        // Set up the output directory ...
+        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
+        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, nodeE.getPath()));
+
+        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
+        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
+
+        // Call the sequencer ...
+        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
+    }
+
+    @Test( expected = SequencerException.class )
+    public void shouldExecuteSequencerOnExistingNodeWithMissingSequencedPropertyAndOutputToExistingNode() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        // Set up the repository for the test ...
+        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
+        Node nodeE = tools.findOrCreateNode(session, "/d/e");
+        assertThat(nodeC, is(notNullValue()));
+        assertThat(nodeE, is(notNullValue()));
+        assertThat(nodeE.getNodes().getSize(), is(0l));
+        assertThat(nodeE.getProperties().getSize(), is(1l)); // jcr:primaryType
+        assertThat(nodeE.getProperty("jcr:primaryType").getString(), is("nt:unstructured"));
+
+        // Set the property that will be sequenced ...
+        // THIS TEST REQUIRES THIS PROPERTY TO BE NULL OR NON-EXISTANT
+        nodeC.setProperty("sequencedProperty", (InputStream)null);
+
+        // Set up the node changes ...
+        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
+                                               Collections.singleton("sequencedProperty"), null);
+
+        // Set up the output directory ...
+        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
+        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, nodeE.getPath()));
+
+        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
+        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
+
+        // Call the sequencer, which should cause the exception ...
+        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
+    }
+
+    @Test
+    public void shouldExecuteSequencerOnExistingNodeAndOutputToMultipleExistingNodes() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        // Set up the repository for the test ...
+        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
+        Node nodeE = tools.findOrCreateNode(session, "/d/e");
+        assertThat(nodeC, is(notNullValue()));
+        assertThat(nodeE, is(notNullValue()));
+        assertThat(nodeE.getNodes().getSize(), is(0l));
+        assertThat(nodeE.getProperties().getSize(), is(1l)); // jcr:primaryType
+        assertThat(nodeE.getProperty("jcr:primaryType").getString(), is("nt:unstructured"));
+
+        // Set the property that will be sequenced ...
+        nodeC.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
+
+        // Set up the node changes ...
+        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
+                                               Collections.singleton("sequencedProperty"), null);
+
+        // Set up the output directory ...
+        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
+        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/d/e"));
+        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/x/y/z"));
+
+        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
+        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
+
+        // Call the sequencer ...
+        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
+
+        // Check to see that the output nodes have been created ...
+        assertThat(session.getRootNode().hasNode("d/e"), is(true));
+        assertThat(session.getRootNode().hasNode("x/y/z"), is(true));
+    }
+
+    @Test
+    public void shouldExecuteSequencerOnExistingNodeAndOutputToNonExistingNode() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        // Set up the repository for the test ...
+        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
+        assertThat(session.getRootNode().hasNode("d"), is(false));
+        assertThat(nodeC, is(notNullValue()));
+
+        // Set the property that will be sequenced ...
+        nodeC.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
+
+        // Set up the node changes ...
+        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
+                                               Collections.singleton("sequencedProperty"), null);
+
+        // Set up the output directory ...
+        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
+        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/d/e"));
+
+        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
+        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
+
+        // Call the sequencer ...
+        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
+
+        // Check to see that the "/d/e" node has been created ...
+        assertThat(session.getRootNode().hasNode("d/e"), is(true));
+    }
+
+    @Test
+    public void shouldExecuteSequencerOnExistingNodeAndOutputToMultipleNonExistingNodes() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        // Set up the repository for the test ...
+        Node nodeC = tools.findOrCreateNode(session, "/a/b/c");
+        assertThat(session.getRootNode().hasNode("d"), is(false));
+        assertThat(session.getRootNode().hasNode("x"), is(false));
+        assertThat(nodeC, is(notNullValue()));
+
+        // Set the property that will be sequenced ...
+        nodeC.setProperty("sequencedProperty", new ByteArrayInputStream(sampleData.getBytes()));
+
+        // Set up the node changes ...
+        NodeChange nodeChange = new NodeChange(repositoryWorkspaceName, nodeC.getPath(), Event.PROPERTY_CHANGED,
+                                               Collections.singleton("sequencedProperty"), null);
+
+        // Set up the output directory ...
+        Set<RepositoryNodePath> outputPaths = new HashSet<RepositoryNodePath>();
+        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/d/e"));
+        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/x/y/z"));
+        outputPaths.add(new RepositoryNodePath(repositoryWorkspaceName, "/x/z"));
+
+        // Generate the output data that the sequencer subclass will produce and that should be saved to the repository ...
+        sequencerOutput.setProperty("alpha/beta", "isSomething", true);
+
+        // Call the sequencer ...
+        sequencer.execute(nodeC, "sequencedProperty", nodeChange, outputPaths, context, problems);
+
+        // Check to see that the output nodes have been created ...
+        assertThat(session.getRootNode().hasNode("d/e"), is(true));
+        assertThat(session.getRootNode().hasNode("x/y/z"), is(true));
+        assertThat(session.getRootNode().hasNode("x/z"), is(true));
+
+        // Check to see that the sequencer-generated nodes have been created ...
+        // Node beta = session.getRootNode().getNode("d/e/alpha/beta");
+        // for (PropertyIterator iter = beta.getProperties(); iter.hasNext();) {
+        // Property property = iter.nextProperty();
+        // System.out.println("Property on " + beta.getPath() + " ===> " + property.getName() + " = " + property.getValue());
+        // }
+        assertThat(session.getRootNode().getNode("d/e/alpha/beta").getProperty("isSomething").getBoolean(), is(true));
+        assertThat(session.getRootNode().getNode("x/y/z/alpha/beta").getProperty("isSomething").getBoolean(), is(true));
+        assertThat(session.getRootNode().getNode("x/z/alpha/beta").getProperty("isSomething").getBoolean(), is(true));
+    }
+
+    @Test
+    public void shouldSequencerOutputProvideAccessToNamespaceRegistry() {
+        assertThat(context.getNamespaceRegistry(), notNullValue());
+    }
+
+    @Test
+    public void shouldPassNonNullInputStreamToSequencer() throws Throwable {
+        testSequencer(new StreamSequencer() {
+
+            public void sequence( InputStream stream,
+                                  SequencerOutput output,
+                                  SequencerContext context ) {
+                assertThat(stream, notNullValue());
+            }
+        });
+    }
+
+    @Test
+    public void shouldPassNonNullSequencerOutputToSequencer() throws Throwable {
+        testSequencer(new StreamSequencer() {
+
+            public void sequence( InputStream stream,
+                                  SequencerOutput output,
+                                  SequencerContext context ) {
+                assertThat(output, notNullValue());
+            }
+        });
+    }
+
+    @Test
+    public void shouldPassNonNullSequencerContextToSequencer() throws Throwable {
+        testSequencer(new StreamSequencer() {
+
+            public void sequence( InputStream stream,
+                                  SequencerOutput output,
+                                  SequencerContext context ) {
+                assertThat(context, notNullValue());
+            }
+        });
+    }
+
+    @Test( expected = java.lang.AssertionError.class )
+    public void shouldNotAllowNullInputNode() throws Exception {
+        sequencer.createSequencerContext(null, sequencedProperty, context, problems);
+    }
+
+    @Test( expected = java.lang.AssertionError.class )
+    public void shouldNotAllowNullSequencedProperty() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        Node input = tools.findOrCreateNode(session, "/a");
+        sequencer.createSequencerContext(input, null, context, problems);
+    }
+
+    @Test( expected = java.lang.AssertionError.class )
+    public void shouldNotAllowNullExecutionContext() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        Node input = tools.findOrCreateNode(session, "/a");
+        sequencer.createSequencerContext(input, sequencedProperty, null, problems);
+    }
+
+    @Test
+    public void shouldProvideNamespaceRegistry() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        this.sequencedProperty = mock(javax.jcr.Property.class);
+        Node input = tools.findOrCreateNode(session, "/a/b/c");
+        SequencerContext sequencerContext = sequencer.createSequencerContext(input, sequencedProperty, context, problems);
+        assertThat(sequencerContext.getNamespaceRegistry(), notNullValue());
+    }
+
+    @Test
+    public void shouldProvideValueFactories() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        this.sequencedProperty = mock(javax.jcr.Property.class);
+        Node input = tools.findOrCreateNode(session, "/a/b/c");
+        SequencerContext sequencerContext = sequencer.createSequencerContext(input, sequencedProperty, context, problems);
+        assertThat(sequencerContext.getValueFactories(), notNullValue());
+    }
+
+    @Test
+    public void shouldProvidePathToInput() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        this.sequencedProperty = mock(javax.jcr.Property.class);
+        Node input = tools.findOrCreateNode(session, "/a/b/c");
+        SequencerContext sequencerContext = sequencer.createSequencerContext(input, sequencedProperty, context, problems);
+        assertThat(sequencerContext.getInputPath(), is(context.getValueFactories().getPathFactory().create("/a/b/c")));
+    }
+
+    @Test
+    public void shouldNeverReturnNullInputProperties() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        this.sequencedProperty = mock(javax.jcr.Property.class);
+        Node input = tools.findOrCreateNode(session, "/a/b/c");
+        SequencerContext sequencerContext = sequencer.createSequencerContext(input, sequencedProperty, context, problems);
+        assertThat(sequencerContext.getInputProperties(), notNullValue());
+        assertThat(sequencerContext.getInputProperties().isEmpty(), is(false));
+    }
+
+    @Test
+    public void shouldProvideInputProperties() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        this.sequencedProperty = mock(javax.jcr.Property.class);
+        Node input = tools.findOrCreateNode(session, "/a/b/c");
+        input.setProperty("x", true);
+        input.setProperty("y", new String[] {"asdf", "xyzzy"});
+        SequencerContext sequencerContext = sequencer.createSequencerContext(input, sequencedProperty, context, problems);
+        assertThat(sequencerContext.getInputProperties(), notNullValue());
+        assertThat(sequencerContext.getInputProperties().isEmpty(), is(false));
+        assertThat(sequencerContext.getInputProperties().size(), is(3));
+        verifyProperty(sequencerContext,
+                       "jcr:primaryType",
+                       context.getValueFactories().getNameFactory().create("{http://www.jcp.org/jcr/nt/1.0}unstructured"));
+        verifyProperty(sequencerContext, "x", true);
+        verifyProperty(sequencerContext, "y", "asdf", "xyzzy");
+    }
+
+    @Test
+    public void shouldCreateSequencerContextThatProvidesMimeType() throws Exception {
+        startRepository();
+        session = getRepository().login(getTestCredentials());
+
+        this.sequencedProperty = mock(javax.jcr.Property.class);
+        Node input = tools.findOrCreateNode(session, "/a/b/c");
+        SequencerContext sequencerContext = sequencer.createSequencerContext(input, sequencedProperty, context, problems);
+        assertThat(sequencerContext.getMimeType(), is("text/plain"));
+    }
+
+    private void verifyProperty( SequencerContext context,
+                                 String name,
+                                 Object... values ) {
+        Property prop = context.getInputProperty(context.getValueFactories().getNameFactory().create(name));
+        assertThat(prop, notNullValue());
+        assertThat(prop.getName(), is(context.getValueFactories().getNameFactory().create(name)));
+        assertThat(prop.isEmpty(), is(false));
+        assertThat(prop.size(), is(values.length));
+        assertThat(prop.isMultiple(), is(values.length > 1));
+        assertThat(prop.isSingle(), is(values.length == 1));
+        Iterator<?> iter = prop.getValues();
+        for (Object val : values) {
+            assertThat(iter.hasNext(), is(true));
+            assertThat(iter.next(), is(val));
+        }
+    }
+
+}

Modified: trunk/dna-repository/src/test/resources/master.xml
===================================================================
--- trunk/dna-repository/src/test/resources/master.xml	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/dna-repository/src/test/resources/master.xml	2009-01-15 18:32:57 UTC (rev 707)
@@ -1492,7 +1492,7 @@
       <para>Create a Maven 2 project for your sequencer;</para>
     </listitem>
     <listitem>
-      <para>Implement the <code>org.jboss.dna.graph.sequencers.StreamSequencer</code> interface with your own implementation, and create unit tests to verify
+      <para>Implement the <code>org.jboss.dna.graph.sequencer.StreamSequencer</code> interface with your own implementation, and create unit tests to verify
       the functionality and expected behavior;</para>
     </listitem>
     <listitem>
@@ -1631,7 +1631,7 @@
   <sect1 id="custom_sequencer_implementation">
     <title>Implementing the StreamSequencer interface</title>
     <para>After creating the project and setting up the dependencies, the next step is to create a Java class that implements
-    the <code>org.jboss.dna.graph.sequencers.StreamSequencer</code> interface.  This interface is very straightforward
+    the <code>org.jboss.dna.graph.sequencer.StreamSequencer</code> interface.  This interface is very straightforward
     and involves a single method:
     <programlisting>
 public interface StreamSequencer {

Modified: trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
===================================================================
--- trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -46,10 +46,10 @@
 import org.jboss.dna.graph.ExecutionContextFactory;
 import org.jboss.dna.graph.Graph;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
 import org.jboss.dna.jcr.JcrRepository;
 import org.jboss.dna.repository.RepositoryLibrary;
 import org.jboss.dna.repository.RepositoryService;

Modified: trunk/docs/examples/gettingstarted/repositories/src/test/resources/log4j.properties
===================================================================
--- trunk/docs/examples/gettingstarted/repositories/src/test/resources/log4j.properties	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/docs/examples/gettingstarted/repositories/src/test/resources/log4j.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -5,10 +5,10 @@
 log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %m%n
 
 # Root logger option
-log4j.rootLogger=INFO, stdout
+log4j.rootLogger=WARNING, stdout
 
 # Set up the default logging to be INFO level, then override specific units
-log4j.logger.org.jboss.dna=INFO
+log4j.logger.org.jboss.dna=ERROR
 #log4j.logger.org.jboss.dna.repository.sequencers=TRACE
 #log4j.logger.org.jboss.dna.sequencer=DEBUG
 #log4j.logger.org.jboss.dna.connector=TRACE
@@ -16,3 +16,6 @@
 #log4j.logger.org.jboss.dna.spi=DEBUG
 #log4j.logger.org.jboss.example.dna=TRACE
 
+# Jackrabbit logging
+log4j.logger.org.apache.jackrabbit=WARN, stdout
+

Modified: trunk/docs/examples/gettingstarted/sequencers/src/main/config/run.sh
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/config/run.sh	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/config/run.sh	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,3 +1,3 @@
 #!/bin/sh
 
-java -Djava.ext.dirs=`pwd`/lib -cp .:dna-example-sequencers-0.1-SNAPSHOT.jar org.jboss.example.dna.sequencers.SequencingClient $1
\ No newline at end of file
+java -Djava.ext.dirs=`pwd`/lib -cp .:dna-example-sequencers-0.1-SNAPSHOT.jar org.jboss.example.dna.sequencer.SequencingClient $1
\ No newline at end of file

Copied: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer (from rev 705, trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers)

Deleted: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ConsoleInput.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ConsoleInput.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,203 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.example.dna.sequencers;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.List;
-import org.jboss.dna.repository.sequencers.SequencingService;
-
-/**
- * @author Randall Hauch
- */
-public class ConsoleInput implements UserInterface {
-
-    protected static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
-
-    public ConsoleInput( final SequencingClient client ) {
-        try {
-            System.out.println();
-            System.out.print("Starting repository and sequencing service ... ");
-            client.startRepository();
-            System.out.print("done.\nStarting sequencing service ... ");
-            client.startDnaServices();
-            System.out.println("done.");
-            System.out.println();
-
-            System.out.println(getMenu());
-            Thread eventThread = new Thread(new Runnable() {
-
-                private boolean quit = false;
-
-                public void run() {
-                    try {
-                        while (!quit) {
-                            System.out.print(">");
-                            try {
-                                String input = in.readLine();
-                                if (input.length() != 1) {
-                                    System.out.println("Please enter a valid option.");
-                                    continue;
-                                }
-
-                                char option = input.charAt(0);
-                                switch (option) {
-                                    case 'u':
-                                        client.uploadFile();
-                                        break;
-                                    case 's':
-                                        client.search();
-                                        break;
-                                    case 'm':
-                                    case '?':
-                                    case 'h':
-                                        System.out.println(getMenu());
-                                        break;
-                                    case 'd':
-                                        System.out.println(getStatistics(client.getStatistics()));
-                                        break;
-                                    case 'q':
-                                        quit = true;
-                                        break;
-                                    default:
-                                        System.out.println("Invalid option.");
-                                        break;
-                                }
-                            } catch (NumberFormatException e) {
-                                System.out.println("Invalid integer " + e.getMessage());
-                            } catch (IllegalArgumentException e) {
-                                System.out.println(e.getMessage());
-                            } catch (IOException e) {
-                                e.printStackTrace();
-                            } catch (Throwable e) {
-                                e.printStackTrace();
-                            }
-                        }
-                    } finally {
-                        try {
-                            // Terminate ...
-                            System.out.println();
-                            System.out.print("Shutting down sequencing service ... ");
-                            client.shutdownDnaServices();
-                            System.out.print("done.\nShutting down repository ... ");
-                            client.shutdownRepository();
-                            System.out.print("done.");
-                            System.out.println();
-                            System.out.println();
-                        } catch (Exception err) {
-                            System.out.println("Error shutting down sequencing service and repository: "
-                                               + err.getLocalizedMessage());
-                            err.printStackTrace(System.err);
-                        }
-                    }
-                }
-            });
-
-            eventThread.start();
-        } catch (Exception err) {
-            System.out.println("Error: " + err.getLocalizedMessage());
-            err.printStackTrace(System.err);
-        }
-    }
-
-    protected String getMenu() {
-        StringBuilder buffer = new StringBuilder();
-        buffer.append("-----------------------------------\n");
-        buffer.append("Menu:\n");
-        buffer.append("\n");
-        buffer.append("u) Upload a file to the repository\n");
-        buffer.append("s) Search the repository using extracted metadata\n");
-        buffer.append("\n");
-        buffer.append("d) Display statistics\n");
-        buffer.append("\n");
-        buffer.append("?) Show this menu\n");
-        buffer.append("q) Quit");
-        return buffer.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URL getFileToUpload() throws IllegalArgumentException, IOException {
-        System.out.println("Please enter the file to upload:");
-        String path = in.readLine();
-        File file = new File(path);
-        if (!file.exists()) {
-            throw new IllegalArgumentException("The file \"" + file.getAbsolutePath() + "\" does not exist.");
-        }
-        if (!file.canRead()) {
-            throw new IllegalArgumentException("Unable to read \"" + file.getAbsolutePath() + "\".");
-        }
-        if (!file.isFile()) {
-            throw new IllegalArgumentException("Please specify a file.  The file \"" + file.getAbsolutePath()
-                                               + "\" is a directory.");
-        }
-        return file.toURI().toURL();
-    }
-
-    public String getRepositoryPath( String defaultPath ) throws IllegalArgumentException, IOException {
-        if (defaultPath != null) defaultPath = defaultPath.trim();
-        if (defaultPath.length() == 0) defaultPath = null;
-        String displayDefaultPath = defaultPath == null ? "" : " [" + defaultPath.trim() + "]";
-        System.out.println("Please enter the repository path where the file should be placed" + displayDefaultPath + ":");
-        String path = in.readLine().trim();
-        if (path.length() == 0) {
-            if (defaultPath == null) {
-                throw new IllegalArgumentException("The path \"" + path + "\" is not valid.");
-            }
-            path = defaultPath;
-        }
-        return path;
-    }
-
-    public void displaySearchResults( List<ContentInfo> contentInfos ) {
-        System.out.println();
-        if (contentInfos.isEmpty()) {
-            System.out.println("No results were found.");
-            System.out.println();
-            return;
-        }
-        if (contentInfos.size() == 1) {
-            System.out.println("1 result was found:");
-        } else {
-            System.out.println("" + contentInfos.size() + " results were found:");
-        }
-        int counter = 1;
-        for (ContentInfo info : contentInfos) {
-            System.out.println(" " + info.getInfoType() + " " + counter++);
-            System.out.println(info.toString());
-        }
-        System.out.println();
-    }
-
-    public String getStatistics( SequencingService.Statistics stats ) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("\n");
-        sb.append("# nodes sequenced: ").append(stats.getNumberOfNodesSequenced()).append("\n");
-        sb.append("# nodes skipped: ").append(stats.getNumberOfNodesSkipped()).append("\n");
-        sb.append("\n");
-        return sb.toString();
-    }
-}

Copied: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ConsoleInput.java (from rev 706, trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java)
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ConsoleInput.java	                        (rev 0)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ConsoleInput.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,203 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.List;
+import org.jboss.dna.repository.sequencer.SequencingService;
+
+/**
+ * @author Randall Hauch
+ */
+public class ConsoleInput implements UserInterface {
+
+    protected static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+
+    public ConsoleInput( final SequencingClient client ) {
+        try {
+            System.out.println();
+            System.out.print("Starting repository and sequencing service ... ");
+            client.startRepository();
+            System.out.print("done.\nStarting sequencing service ... ");
+            client.startDnaServices();
+            System.out.println("done.");
+            System.out.println();
+
+            System.out.println(getMenu());
+            Thread eventThread = new Thread(new Runnable() {
+
+                private boolean quit = false;
+
+                public void run() {
+                    try {
+                        while (!quit) {
+                            System.out.print(">");
+                            try {
+                                String input = in.readLine();
+                                if (input.length() != 1) {
+                                    System.out.println("Please enter a valid option.");
+                                    continue;
+                                }
+
+                                char option = input.charAt(0);
+                                switch (option) {
+                                    case 'u':
+                                        client.uploadFile();
+                                        break;
+                                    case 's':
+                                        client.search();
+                                        break;
+                                    case 'm':
+                                    case '?':
+                                    case 'h':
+                                        System.out.println(getMenu());
+                                        break;
+                                    case 'd':
+                                        System.out.println(getStatistics(client.getStatistics()));
+                                        break;
+                                    case 'q':
+                                        quit = true;
+                                        break;
+                                    default:
+                                        System.out.println("Invalid option.");
+                                        break;
+                                }
+                            } catch (NumberFormatException e) {
+                                System.out.println("Invalid integer " + e.getMessage());
+                            } catch (IllegalArgumentException e) {
+                                System.out.println(e.getMessage());
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            } catch (Throwable e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    } finally {
+                        try {
+                            // Terminate ...
+                            System.out.println();
+                            System.out.print("Shutting down sequencing service ... ");
+                            client.shutdownDnaServices();
+                            System.out.print("done.\nShutting down repository ... ");
+                            client.shutdownRepository();
+                            System.out.print("done.");
+                            System.out.println();
+                            System.out.println();
+                        } catch (Exception err) {
+                            System.out.println("Error shutting down sequencing service and repository: "
+                                               + err.getLocalizedMessage());
+                            err.printStackTrace(System.err);
+                        }
+                    }
+                }
+            });
+
+            eventThread.start();
+        } catch (Exception err) {
+            System.out.println("Error: " + err.getLocalizedMessage());
+            err.printStackTrace(System.err);
+        }
+    }
+
+    protected String getMenu() {
+        StringBuilder buffer = new StringBuilder();
+        buffer.append("-----------------------------------\n");
+        buffer.append("Menu:\n");
+        buffer.append("\n");
+        buffer.append("u) Upload a file to the repository\n");
+        buffer.append("s) Search the repository using extracted metadata\n");
+        buffer.append("\n");
+        buffer.append("d) Display statistics\n");
+        buffer.append("\n");
+        buffer.append("?) Show this menu\n");
+        buffer.append("q) Quit");
+        return buffer.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URL getFileToUpload() throws IllegalArgumentException, IOException {
+        System.out.println("Please enter the file to upload:");
+        String path = in.readLine();
+        File file = new File(path);
+        if (!file.exists()) {
+            throw new IllegalArgumentException("The file \"" + file.getAbsolutePath() + "\" does not exist.");
+        }
+        if (!file.canRead()) {
+            throw new IllegalArgumentException("Unable to read \"" + file.getAbsolutePath() + "\".");
+        }
+        if (!file.isFile()) {
+            throw new IllegalArgumentException("Please specify a file.  The file \"" + file.getAbsolutePath()
+                                               + "\" is a directory.");
+        }
+        return file.toURI().toURL();
+    }
+
+    public String getRepositoryPath( String defaultPath ) throws IllegalArgumentException, IOException {
+        if (defaultPath != null) defaultPath = defaultPath.trim();
+        if (defaultPath.length() == 0) defaultPath = null;
+        String displayDefaultPath = defaultPath == null ? "" : " [" + defaultPath.trim() + "]";
+        System.out.println("Please enter the repository path where the file should be placed" + displayDefaultPath + ":");
+        String path = in.readLine().trim();
+        if (path.length() == 0) {
+            if (defaultPath == null) {
+                throw new IllegalArgumentException("The path \"" + path + "\" is not valid.");
+            }
+            path = defaultPath;
+        }
+        return path;
+    }
+
+    public void displaySearchResults( List<ContentInfo> contentInfos ) {
+        System.out.println();
+        if (contentInfos.isEmpty()) {
+            System.out.println("No results were found.");
+            System.out.println();
+            return;
+        }
+        if (contentInfos.size() == 1) {
+            System.out.println("1 result was found:");
+        } else {
+            System.out.println("" + contentInfos.size() + " results were found:");
+        }
+        int counter = 1;
+        for (ContentInfo info : contentInfos) {
+            System.out.println(" " + info.getInfoType() + " " + counter++);
+            System.out.println(info.toString());
+        }
+        System.out.println();
+    }
+
+    public String getStatistics( SequencingService.Statistics stats ) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("\n");
+        sb.append("# nodes sequenced: ").append(stats.getNumberOfNodesSequenced()).append("\n");
+        sb.append("# nodes skipped: ").append(stats.getNumberOfNodesSkipped()).append("\n");
+        sb.append("\n");
+        return sb.toString();
+    }
+}

Deleted: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ContentInfo.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/ContentInfo.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ContentInfo.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,73 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.example.dna.sequencers;
-
-import java.util.Map;
-import java.util.Properties;
-import net.jcip.annotations.Immutable;
-
-/**
- * @author Randall Hauch
- */
- at Immutable
-public class ContentInfo {
-
-    private final Properties properties = new Properties();
-    private final String name;
-    private final String path;
-
-    protected ContentInfo( String path,
-                           String name,
-                           Properties props ) {
-        this.name = name;
-        this.path = path;
-        if (props != null) this.properties.putAll(props);
-    }
-
-    public String getName() {
-        return this.name;
-    }
-
-    public String getPath() {
-        return this.path;
-    }
-
-    public Properties getProperties() {
-        return this.properties;
-    }
-
-    public String getInfoType() {
-        return this.getClass().getSimpleName().replaceAll("Info$", "");
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("   Name: " + getName() + "\n");
-        sb.append("   Path: " + getPath() + "\n");
-        for (Map.Entry<Object, Object> entry : getProperties().entrySet()) {
-            sb.append("   " + entry.getKey() + ": " + entry.getValue() + "\n");
-        }
-        return sb.toString();
-    }
-
-}

Copied: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ContentInfo.java (from rev 706, trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/ContentInfo.java)
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ContentInfo.java	                        (rev 0)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/ContentInfo.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,73 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencer;
+
+import java.util.Map;
+import java.util.Properties;
+import net.jcip.annotations.Immutable;
+
+/**
+ * @author Randall Hauch
+ */
+ at Immutable
+public class ContentInfo {
+
+    private final Properties properties = new Properties();
+    private final String name;
+    private final String path;
+
+    protected ContentInfo( String path,
+                           String name,
+                           Properties props ) {
+        this.name = name;
+        this.path = path;
+        if (props != null) this.properties.putAll(props);
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public String getPath() {
+        return this.path;
+    }
+
+    public Properties getProperties() {
+        return this.properties;
+    }
+
+    public String getInfoType() {
+        return this.getClass().getSimpleName().replaceAll("Info$", "");
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("   Name: " + getName() + "\n");
+        sb.append("   Path: " + getPath() + "\n");
+        for (Map.Entry<Object, Object> entry : getProperties().entrySet()) {
+            sb.append("   " + entry.getKey() + ": " + entry.getValue() + "\n");
+        }
+        return sb.toString();
+    }
+
+}

Deleted: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/JavaInfo.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/JavaInfo.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/JavaInfo.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,82 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.example.dna.sequencers;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.TreeMap;
-import net.jcip.annotations.Immutable;
-
-/**
- * @author Serge Pagop
- * @author Randall Hauch
- */
- at Immutable
-public class JavaInfo extends ContentInfo {
-
-    private final Map<String, List<Properties>> javaElements;
-    private final String type;
-
-    protected JavaInfo( String path,
-                        String name,
-                        String type,
-                        Map<String, List<Properties>> javaElements ) {
-        super(path, name, null);
-        this.type = type;
-        this.javaElements = javaElements != null ? new TreeMap<String, List<Properties>>(javaElements) : new TreeMap<String, List<Properties>>();
-    }
-
-    public String getType() {
-        return this.type;
-    }
-
-    /**
-     * @return javaElements
-     */
-    public Map<String, List<Properties>> getJavaElements() {
-        return javaElements;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("   Name: " + getName() + "\n");
-        sb.append("   Path: " + getPath() + "\n");
-        sb.append("   Type: " + getType() + "\n");
-        for (Map.Entry<Object, Object> entry : getProperties().entrySet()) {
-            sb.append("   " + entry.getKey() + ": " + entry.getValue() + "\n");
-        }
-        for (Map.Entry<String, List<Properties>> javaElement : getJavaElements().entrySet()) {
-            sb.append("\n   ------ " + javaElement.getKey() + " ------\n");
-            for (Properties props : javaElement.getValue()) {
-                for (Map.Entry<Object, Object> entry : props.entrySet()) {
-                    if (!entry.getKey().equals("jcr:primaryType")) {
-                        sb.append("   " + entry.getKey() + " => " + entry.getValue() + "\n");
-                    }
-                }
-            }
-        }
-        return sb.toString();
-    }
-
-}

Copied: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/JavaInfo.java (from rev 706, trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/JavaInfo.java)
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/JavaInfo.java	                        (rev 0)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/JavaInfo.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencer;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+import net.jcip.annotations.Immutable;
+
+/**
+ * @author Serge Pagop
+ * @author Randall Hauch
+ */
+ at Immutable
+public class JavaInfo extends ContentInfo {
+
+    private final Map<String, List<Properties>> javaElements;
+    private final String type;
+
+    protected JavaInfo( String path,
+                        String name,
+                        String type,
+                        Map<String, List<Properties>> javaElements ) {
+        super(path, name, null);
+        this.type = type;
+        this.javaElements = javaElements != null ? new TreeMap<String, List<Properties>>(javaElements) : new TreeMap<String, List<Properties>>();
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    /**
+     * @return javaElements
+     */
+    public Map<String, List<Properties>> getJavaElements() {
+        return javaElements;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("   Name: " + getName() + "\n");
+        sb.append("   Path: " + getPath() + "\n");
+        sb.append("   Type: " + getType() + "\n");
+        for (Map.Entry<Object, Object> entry : getProperties().entrySet()) {
+            sb.append("   " + entry.getKey() + ": " + entry.getValue() + "\n");
+        }
+        for (Map.Entry<String, List<Properties>> javaElement : getJavaElements().entrySet()) {
+            sb.append("\n   ------ " + javaElement.getKey() + " ------\n");
+            for (Properties props : javaElement.getValue()) {
+                for (Map.Entry<Object, Object> entry : props.entrySet()) {
+                    if (!entry.getKey().equals("jcr:primaryType")) {
+                        sb.append("   " + entry.getKey() + " => " + entry.getValue() + "\n");
+                    }
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+}

Deleted: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/MediaInfo.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/MediaInfo.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/MediaInfo.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,60 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.example.dna.sequencers;
-
-import java.util.Map;
-import java.util.Properties;
-import net.jcip.annotations.Immutable;
-
-/**
- * @author Randall Hauch
- */
- at Immutable
-public class MediaInfo extends ContentInfo {
-
-    private final String mediaType;
-
-    protected MediaInfo( String path,
-                         String name,
-                         String mediaType,
-                         Properties props ) {
-        super(path, name, props);
-        this.mediaType = mediaType;
-    }
-
-    public String getMediaType() {
-        return this.mediaType;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("   Name: " + getName() + "\n");
-        sb.append("   Path: " + getPath() + "\n");
-        sb.append("   Type: " + getMediaType() + "\n");
-        for (Map.Entry<Object, Object> entry : getProperties().entrySet()) {
-            sb.append("   " + entry.getKey() + ": " + entry.getValue() + "\n");
-        }
-        return sb.toString();
-    }
-
-}

Copied: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/MediaInfo.java (from rev 706, trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/MediaInfo.java)
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/MediaInfo.java	                        (rev 0)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/MediaInfo.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencer;
+
+import java.util.Map;
+import java.util.Properties;
+import net.jcip.annotations.Immutable;
+
+/**
+ * @author Randall Hauch
+ */
+ at Immutable
+public class MediaInfo extends ContentInfo {
+
+    private final String mediaType;
+
+    protected MediaInfo( String path,
+                         String name,
+                         String mediaType,
+                         Properties props ) {
+        super(path, name, props);
+        this.mediaType = mediaType;
+    }
+
+    public String getMediaType() {
+        return this.mediaType;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("   Name: " + getName() + "\n");
+        sb.append("   Path: " + getPath() + "\n");
+        sb.append("   Type: " + getMediaType() + "\n");
+        for (Map.Entry<Object, Object> entry : getProperties().entrySet()) {
+            sb.append("   " + entry.getKey() + ": " + entry.getValue() + "\n");
+        }
+        return sb.toString();
+    }
+
+}

Deleted: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,563 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.example.dna.sequencers;
-
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.TreeMap;
-import java.util.concurrent.TimeUnit;
-import javax.jcr.Credentials;
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import javax.jcr.Value;
-import javax.jcr.ValueFormatException;
-import javax.jcr.observation.Event;
-import org.apache.jackrabbit.api.JackrabbitNodeTypeManager;
-import org.apache.jackrabbit.core.TransientRepository;
-import org.jboss.dna.common.SystemFailureException;
-import org.jboss.dna.repository.observation.ObservationService;
-import org.jboss.dna.repository.sequencers.SequencerConfig;
-import org.jboss.dna.repository.sequencers.SequencingService;
-import org.jboss.dna.repository.util.BasicJcrExecutionContext;
-import org.jboss.dna.repository.util.JcrExecutionContext;
-import org.jboss.dna.repository.util.JcrTools;
-import org.jboss.dna.repository.util.SessionFactory;
-import org.jboss.dna.repository.util.SimpleSessionFactory;
-
-/**
- * @author Randall Hauch
- */
-public class SequencingClient {
-
-    public static final String DEFAULT_JACKRABBIT_CONFIG_PATH = "jackrabbitConfig.xml";
-    public static final String DEFAULT_WORKING_DIRECTORY = "repositoryData";
-    public static final String DEFAULT_REPOSITORY_NAME = "repo";
-    public static final String DEFAULT_WORKSPACE_NAME = "default";
-    public static final String DEFAULT_USERNAME = "jsmith";
-    public static final char[] DEFAULT_PASSWORD = "secret".toCharArray();
-
-    public static void main( String[] args ) {
-        SequencingClient client = new SequencingClient();
-        client.setRepositoryInformation(DEFAULT_REPOSITORY_NAME, DEFAULT_WORKSPACE_NAME, DEFAULT_USERNAME, DEFAULT_PASSWORD);
-        client.setUserInterface(new ConsoleInput(client));
-    }
-
-    private String repositoryName;
-    private String workspaceName;
-    private String username;
-    private char[] password;
-    private String jackrabbitConfigPath;
-    private String workingDirectory;
-    private Session keepAliveSession;
-    private Repository repository;
-    private SequencingService sequencingService;
-    private ObservationService observationService;
-    private UserInterface userInterface;
-    private JcrExecutionContext executionContext;
-
-    public SequencingClient() {
-        setJackrabbitConfigPath(DEFAULT_JACKRABBIT_CONFIG_PATH);
-        setWorkingDirectory(DEFAULT_WORKING_DIRECTORY);
-        setRepositoryInformation(DEFAULT_REPOSITORY_NAME, DEFAULT_WORKSPACE_NAME, DEFAULT_USERNAME, DEFAULT_PASSWORD);
-    }
-
-    protected void setWorkingDirectory( String workingDirectoryPath ) {
-        this.workingDirectory = workingDirectoryPath != null ? workingDirectoryPath : DEFAULT_WORKING_DIRECTORY;
-    }
-
-    protected void setJackrabbitConfigPath( String jackrabbitConfigPath ) {
-        this.jackrabbitConfigPath = jackrabbitConfigPath != null ? jackrabbitConfigPath : DEFAULT_JACKRABBIT_CONFIG_PATH;
-    }
-
-    protected void setRepositoryInformation( String repositoryName,
-                                             String workspaceName,
-                                             String username,
-                                             char[] password ) {
-        if (this.repository != null) {
-            throw new IllegalArgumentException("Unable to set repository information when repository is already running");
-        }
-        this.repositoryName = repositoryName != null ? repositoryName : DEFAULT_REPOSITORY_NAME;
-        this.workspaceName = workspaceName != null ? workspaceName : DEFAULT_WORKSPACE_NAME;
-        this.username = username;
-        this.password = password;
-    }
-
-    /**
-     * Set the user interface that this client should use.
-     * 
-     * @param userInterface
-     */
-    public void setUserInterface( UserInterface userInterface ) {
-        this.userInterface = userInterface;
-    }
-
-    /**
-     * Start up the JCR repository. This method only operates using the JCR API and Jackrabbit-specific API.
-     * 
-     * @throws Exception
-     */
-    public void startRepository() throws Exception {
-        if (this.repository == null) {
-            try {
-
-                // Load the Jackrabbit configuration ...
-                File configFile = new File(this.jackrabbitConfigPath);
-                if (!configFile.exists()) {
-                    throw new SystemFailureException("The Jackrabbit configuration file cannot be found at "
-                                                     + configFile.getAbsoluteFile());
-                }
-                if (!configFile.canRead()) {
-                    throw new SystemFailureException("Unable to read the Jackrabbit configuration file at "
-                                                     + configFile.getAbsoluteFile());
-                }
-                String pathToConfig = configFile.getAbsolutePath();
-
-                // Find the directory where the Jackrabbit repository data will be stored ...
-                File workingDirectory = new File(this.workingDirectory);
-                if (workingDirectory.exists()) {
-                    if (!workingDirectory.isDirectory()) {
-                        throw new SystemFailureException("Unable to create working directory at "
-                                                         + workingDirectory.getAbsolutePath());
-                    }
-                }
-                String workingDirectoryPath = workingDirectory.getAbsolutePath();
-
-                // Get the Jackrabbit custom node definition (CND) file ...
-                URL cndFile = Thread.currentThread().getContextClassLoader().getResource("jackrabbitNodeTypes.cnd");
-
-                // Create the Jackrabbit repository instance and establish a session to keep the repository alive ...
-                this.repository = new TransientRepository(pathToConfig, workingDirectoryPath);
-                if (this.username != null) {
-                    Credentials credentials = new SimpleCredentials(this.username, this.password);
-                    this.keepAliveSession = this.repository.login(credentials, this.workspaceName);
-                } else {
-                    this.keepAliveSession = this.repository.login();
-                }
-
-                try {
-                    // Register the node types (only valid the first time) ...
-                    JackrabbitNodeTypeManager mgr = (JackrabbitNodeTypeManager)this.keepAliveSession.getWorkspace().getNodeTypeManager();
-                    mgr.registerNodeTypes(cndFile.openStream(), JackrabbitNodeTypeManager.TEXT_X_JCR_CND);
-                } catch (RepositoryException e) {
-                    if (!e.getMessage().contains("already exists")) throw e;
-                }
-
-            } catch (Exception e) {
-                this.repository = null;
-                this.keepAliveSession = null;
-                throw e;
-            }
-        }
-    }
-
-    /**
-     * Shutdown the repository. This method only uses the JCR API.
-     * 
-     * @throws Exception
-     */
-    public void shutdownRepository() throws Exception {
-        if (this.repository != null) {
-            try {
-                this.keepAliveSession.logout();
-            } finally {
-                this.repository = null;
-                this.keepAliveSession = null;
-            }
-        }
-    }
-
-    /**
-     * Start the DNA services.
-     * 
-     * @throws Exception
-     */
-    public void startDnaServices() throws Exception {
-        if (this.repository == null) {
-            this.startRepository();
-        }
-        if (this.sequencingService == null) {
-
-            // Create an execution context for the sequencing service. This execution context provides an environment
-            // for the DNA services which knows about the JCR repositories, workspaces, and credentials used to
-            // establish sessions to these workspaces. This example uses the BasicJcrExecutionContext, but there is
-            // implementation for use with JCR repositories registered in JNDI.
-            final String repositoryWorkspaceName = this.repositoryName + "/" + this.workspaceName;
-            SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
-            sessionFactory.registerRepository(this.repositoryName, this.repository);
-            if (this.username != null) {
-                Credentials credentials = new SimpleCredentials(this.username, this.password);
-                sessionFactory.registerCredentials(repositoryWorkspaceName, credentials);
-            }
-            this.executionContext = new BasicJcrExecutionContext(sessionFactory, repositoryWorkspaceName);
-
-            // Create the sequencing service, passing in the execution context ...
-            this.sequencingService = new SequencingService();
-            this.sequencingService.setExecutionContext(executionContext);
-
-            // Configure the sequencers. In this example, we only two sequencers that processes image and mp3 files.
-            // So create a configurations. Note that the sequencing service expects the class to be on the thread's current
-            // context
-            // classloader, or if that's null the classloader that loaded the SequencingService class.
-            //
-            // Part of the configuration includes telling DNA which JCR paths should be processed by the sequencer.
-            // These path expressions tell the service that this sequencer should be invoked on the "jcr:data" property
-            // on the "jcr:content" child node of any node uploaded to the repository whose name ends with one of the
-            // supported extensions, and the sequencer should place the generated output metadata in a node with the same name as
-            // the file but immediately below the "/images" node. Path expressions can be fairly complex, and can even
-            // specify that the generated information be placed in a different repository.
-            // 
-            // Sequencer configurations can be added before or after the service is started, but here we do it before the service
-            // is running.
-            String name = "Image Sequencer";
-            String desc = "Sequences image files to extract the characteristics of the image";
-            String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
-            String[] classpath = null; // Use the current classpath
-            String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd)[*])/jcr:content[@jcr:data] => /images/$1"};
-            SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
-            this.sequencingService.addSequencer(imageSequencerConfig);
-
-            // Set up the MP3 sequencer ...
-            name = "Mp3 Sequencer";
-            desc = "Sequences mp3 files to extract the id3 tags of the audio file";
-            classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
-            String[] mp3PathExpressions = {"//(*.mp3[*])/jcr:content[@jcr:data] => /mp3s/$1"};
-            SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname, classpath, mp3PathExpressions);
-            this.sequencingService.addSequencer(mp3SequencerConfig);
-
-            // Set up the MP3 sequencer ...
-            name = "Java Sequencer";
-            desc = "Sequences java files to extract the characteristics of the java sources";
-            classname = "org.jboss.dna.sequencer.java.JavaMetadataSequencer";
-            String[] javaPathExpressions = {"//(*.java[*])/jcr:content[@jcr:data] => /java/$1"};
-            SequencerConfig javaSequencerConfig = new SequencerConfig(name, desc, classname, classpath, javaPathExpressions);
-            this.sequencingService.addSequencer(javaSequencerConfig);
-
-            // Use the DNA observation service to listen to the JCR repository (or multiple ones), and
-            // then register the sequencing service as a listener to this observation service...
-            this.observationService = new ObservationService(this.executionContext.getSessionFactory());
-            this.observationService.getAdministrator().start();
-            this.observationService.addListener(this.sequencingService);
-            this.observationService.monitor(repositoryWorkspaceName, Event.NODE_ADDED | Event.PROPERTY_ADDED
-                                                                     | Event.PROPERTY_CHANGED);
-        }
-        // Start up the sequencing service ...
-        this.sequencingService.getAdministrator().start();
-    }
-
-    /**
-     * Shut down the DNA services.
-     * 
-     * @throws Exception
-     */
-    public void shutdownDnaServices() throws Exception {
-        if (this.sequencingService == null) return;
-
-        // Shut down the service and wait until it's all shut down ...
-        this.sequencingService.getAdministrator().shutdown();
-        this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-
-        // Shut down the observation service ...
-        this.observationService.getAdministrator().shutdown();
-        this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-    }
-
-    /**
-     * Get the sequencing statistics.
-     * 
-     * @return the statistics; never null
-     */
-    public SequencingService.Statistics getStatistics() {
-        return this.sequencingService.getStatistics();
-    }
-
-    /**
-     * Prompt the user interface for the file to upload into the JCR repository, then upload it using the JCR API.
-     * 
-     * @throws Exception
-     */
-    public void uploadFile() throws Exception {
-        URL url = this.userInterface.getFileToUpload();
-        // Grab the last segment of the URL path, using it as the filename
-        String filename = url.getPath().replaceAll("([^/]*/)*", "");
-        String nodePath = this.userInterface.getRepositoryPath("/a/b/" + filename);
-        String mimeType = getMimeType(url);
-
-        // Now use the JCR API to upload the file ...
-        Session session = createSession();
-        JcrTools tools = this.executionContext.getTools();
-        try {
-            // Create the node at the supplied path ...
-            Node node = tools.findOrCreateNode(session, nodePath, "nt:folder", "nt:file");
-
-            // Upload the file to that node ...
-            Node contentNode = tools.findOrCreateChild(session, node, "jcr:content", "nt:resource");
-            contentNode.setProperty("jcr:mimeType", mimeType);
-            contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
-            contentNode.setProperty("jcr:data", url.openStream());
-
-            // Save the session ...
-            session.save();
-        } finally {
-            session.logout();
-        }
-    }
-
-    /**
-     * Perform a search of the repository for all image metadata automatically created by the image sequencer.
-     * 
-     * @throws Exception
-     */
-    public void search() throws Exception {
-        // Use JCR to search the repository for image metadata ...
-        List<ContentInfo> infos = new ArrayList<ContentInfo>();
-        Session session = createSession();
-        try {
-            // Find the node ...
-            Node root = session.getRootNode();
-
-            if (root.hasNode("images") || root.hasNode("mp3s")) {
-                Node mediasNode;
-                if (root.hasNode("images")) {
-                    mediasNode = root.getNode("images");
-
-                    for (NodeIterator iter = mediasNode.getNodes(); iter.hasNext();) {
-                        Node mediaNode = iter.nextNode();
-                        if (mediaNode.hasNode("image:metadata")) {
-                            infos.add(extractMediaInfo("image:metadata", "image", mediaNode));
-                        }
-                    }
-                }
-                if (root.hasNode("mp3s")) {
-                    mediasNode = root.getNode("mp3s");
-
-                    for (NodeIterator iter = mediasNode.getNodes(); iter.hasNext();) {
-                        Node mediaNode = iter.nextNode();
-                        if (mediaNode.hasNode("mp3:metadata")) {
-                            infos.add(extractMediaInfo("mp3:metadata", "mp3", mediaNode));
-                        }
-                    }
-                }
-
-            }
-            if (root.hasNode("java")) {
-                Map<String, List<Properties>> tree = new TreeMap<String, List<Properties>>();
-                // Find the compilation unit node ...
-                List<Properties> javaElements;
-                if (root.hasNode("java")) {
-                    Node javaSourcesNode = root.getNode("java");
-                    for (NodeIterator i = javaSourcesNode.getNodes(); i.hasNext();) {
-
-                        Node javaSourceNode = i.nextNode();
-
-                        if (javaSourceNode.hasNodes()) {
-                            Node javaCompilationUnit = javaSourceNode.getNodes().nextNode();
-                            // package informations
-
-                            javaElements = new ArrayList<Properties>();
-                            try {
-                                Node javaPackageDeclarationNode = javaCompilationUnit.getNode("java:package/java:packageDeclaration");
-                                javaElements.add(extractJavaInfo(javaPackageDeclarationNode));
-                                tree.put("Class package", javaElements);
-                            } catch (PathNotFoundException e) {
-                                // do nothing
-                            }
-
-                            // import informations
-                            javaElements = new ArrayList<Properties>();
-                            try {
-                                for (NodeIterator singleImportIterator = javaCompilationUnit.getNode("java:import/java:importDeclaration/java:singleImport").getNodes(); singleImportIterator.hasNext();) {
-                                    Node javasingleTypeImportDeclarationNode = singleImportIterator.nextNode();
-                                    javaElements.add(extractJavaInfo(javasingleTypeImportDeclarationNode));
-                                }
-                                tree.put("Class single Imports", javaElements);
-                            } catch (PathNotFoundException e) {
-                                // do nothing
-                            }
-
-                            javaElements = new ArrayList<Properties>();
-                            try {
-                                for (NodeIterator javaImportOnDemandIterator = javaCompilationUnit.getNode("java:import/java:importDeclaration/java:importOnDemand").getNodes(); javaImportOnDemandIterator.hasNext();) {
-                                    Node javaImportOnDemandtDeclarationNode = javaImportOnDemandIterator.nextNode();
-                                    javaElements.add(extractJavaInfo(javaImportOnDemandtDeclarationNode));
-                                }
-                                tree.put("Class on demand imports", javaElements);
-
-                            } catch (PathNotFoundException e) {
-                                // do nothing
-                            }
-                            // class head informations
-                            javaElements = new ArrayList<Properties>();
-                            Node javaNormalDeclarationClassNode = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration");
-                            javaElements.add(extractJavaInfo(javaNormalDeclarationClassNode));
-                            tree.put("Class head information", javaElements);
-
-                            // field member informations
-                            javaElements = new ArrayList<Properties>();
-                            for (NodeIterator javaFieldTypeIterator = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:field/java:fieldType").getNodes(); javaFieldTypeIterator.hasNext();) {
-                                Node rootFieldTypeNode = javaFieldTypeIterator.nextNode();
-                                if (rootFieldTypeNode.hasNode("java:primitiveType")) {
-                                    Node javaPrimitiveTypeNode = rootFieldTypeNode.getNode("java:primitiveType");
-                                    javaElements.add(extractJavaInfo(javaPrimitiveTypeNode));
-                                    // more informations
-                                }
-
-                                if (rootFieldTypeNode.hasNode("java:simpleType")) {
-                                    Node javaSimpleTypeNode = rootFieldTypeNode.getNode("java:simpleType");
-                                    javaElements.add(extractJavaInfo(javaSimpleTypeNode));
-                                }
-                                if (rootFieldTypeNode.hasNode("java:parameterizedType")) {
-                                    Node javaParameterizedType = rootFieldTypeNode.getNode("java:parameterizedType");
-                                    javaElements.add(extractJavaInfo(javaParameterizedType));
-                                }
-                                if (rootFieldTypeNode.hasNode("java:arrayType")) {
-                                    Node javaArrayType = rootFieldTypeNode.getNode("java:arrayType[2]");
-                                    javaElements.add(extractJavaInfo(javaArrayType));
-                                }
-                            }
-                            tree.put("Class field members", javaElements);
-
-                            // constructor informations
-                            javaElements = new ArrayList<Properties>();
-                            for (NodeIterator javaConstructorIterator = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:constructor").getNodes(); javaConstructorIterator.hasNext();) {
-                                Node javaConstructor = javaConstructorIterator.nextNode();
-                                javaElements.add(extractJavaInfo(javaConstructor));
-                            }
-                            tree.put("Class constructors", javaElements);
-
-                            // method informations
-                            javaElements = new ArrayList<Properties>();
-                            for (NodeIterator javaMethodIterator = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:method").getNodes(); javaMethodIterator.hasNext();) {
-                                Node javaMethod = javaMethodIterator.nextNode();
-                                javaElements.add(extractJavaInfo(javaMethod));
-                            }
-                            tree.put("Class member functions", javaElements);
-
-                            JavaInfo javaInfo = new JavaInfo(javaCompilationUnit.getPath(), javaCompilationUnit.getName(),
-                                                             "java source", tree);
-                            infos.add(javaInfo);
-                        }
-                    }
-                }
-
-            }
-        } finally {
-            session.logout();
-        }
-
-        // Display the search results ...
-        this.userInterface.displaySearchResults(infos);
-    }
-
-    private MediaInfo extractMediaInfo( String metadataNodeName,
-                                        String mediaType,
-                                        Node mediaNode ) throws RepositoryException, PathNotFoundException, ValueFormatException {
-        String nodePath = mediaNode.getPath();
-        String nodeName = mediaNode.getName();
-        mediaNode = mediaNode.getNode(metadataNodeName);
-
-        // Create a Properties object containing the properties for this node; ignore any children ...
-        Properties props = new Properties();
-        for (PropertyIterator propertyIter = mediaNode.getProperties(); propertyIter.hasNext();) {
-            Property property = propertyIter.nextProperty();
-            String name = property.getName();
-            String stringValue = null;
-            if (property.getDefinition().isMultiple()) {
-                StringBuilder sb = new StringBuilder();
-                boolean first = true;
-                for (Value value : property.getValues()) {
-                    if (!first) {
-                        sb.append(", ");
-                        first = false;
-                    }
-                    sb.append(value.getString());
-                }
-                stringValue = sb.toString();
-            } else {
-                stringValue = property.getValue().getString();
-            }
-            props.put(name, stringValue);
-        }
-        // Create the image information object, and add it to the collection ...
-        return new MediaInfo(nodePath, nodeName, mediaType, props);
-    }
-
-    /**
-     * Extract informations from a specific node.
-     * 
-     * @param node - node, that contains informations.
-     * @return a properties of keys/values.
-     * @throws RepositoryException
-     * @throws IllegalStateException
-     * @throws ValueFormatException
-     */
-    private Properties extractJavaInfo( Node node ) throws ValueFormatException, IllegalStateException, RepositoryException {
-        if (node.hasProperties()) {
-            Properties properties = new Properties();
-            for (PropertyIterator propertyIter = node.getProperties(); propertyIter.hasNext();) {
-                Property property = propertyIter.nextProperty();
-                String name = property.getName();
-                String stringValue = property.getValue().getString();
-                properties.put(name, stringValue);
-            }
-            return properties;
-        }
-        return null;
-    }
-
-    /**
-     * Utility method to create a new JCR session from the execution context's {@link SessionFactory}.
-     * 
-     * @return the session
-     * @throws RepositoryException
-     */
-    protected Session createSession() throws RepositoryException {
-        return this.executionContext.getSessionFactory().createSession(this.repositoryName + "/" + this.workspaceName);
-    }
-
-    protected String getMimeType( URL file ) {
-        String filename = file.getPath().toLowerCase();
-        if (filename.endsWith(".gif")) return "image/gif";
-        if (filename.endsWith(".png")) return "image/png";
-        if (filename.endsWith(".pict")) return "image/x-pict";
-        if (filename.endsWith(".bmp")) return "image/bmp";
-        if (filename.endsWith(".jpg")) return "image/jpeg";
-        if (filename.endsWith(".jpe")) return "image/jpeg";
-        if (filename.endsWith(".jpeg")) return "image/jpeg";
-        if (filename.endsWith(".ras")) return "image/x-cmu-raster";
-        if (filename.endsWith(".mp3")) return "audio/mpeg";
-        if (filename.endsWith(".java")) return "text/x-java-source";
-        throw new SystemFailureException("Unknown mime type for " + file);
-    }
-
-}

Copied: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java (from rev 706, trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java)
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java	                        (rev 0)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,561 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencer;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import javax.jcr.observation.Event;
+import org.apache.jackrabbit.api.JackrabbitNodeTypeManager;
+import org.apache.jackrabbit.core.TransientRepository;
+import org.jboss.dna.common.SystemFailureException;
+import org.jboss.dna.repository.observation.ObservationService;
+import org.jboss.dna.repository.sequencer.SequencerConfig;
+import org.jboss.dna.repository.sequencer.SequencingService;
+import org.jboss.dna.repository.util.JcrExecutionContext;
+import org.jboss.dna.repository.util.JcrTools;
+import org.jboss.dna.repository.util.SessionFactory;
+import org.jboss.dna.repository.util.SimpleSessionFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public class SequencingClient {
+
+    public static final String DEFAULT_JACKRABBIT_CONFIG_PATH = "jackrabbitConfig.xml";
+    public static final String DEFAULT_WORKING_DIRECTORY = "repositoryData";
+    public static final String DEFAULT_REPOSITORY_NAME = "repo";
+    public static final String DEFAULT_WORKSPACE_NAME = "default";
+    public static final String DEFAULT_USERNAME = "jsmith";
+    public static final char[] DEFAULT_PASSWORD = "secret".toCharArray();
+
+    public static void main( String[] args ) {
+        SequencingClient client = new SequencingClient();
+        client.setRepositoryInformation(DEFAULT_REPOSITORY_NAME, DEFAULT_WORKSPACE_NAME, DEFAULT_USERNAME, DEFAULT_PASSWORD);
+        client.setUserInterface(new ConsoleInput(client));
+    }
+
+    private String repositoryName;
+    private String workspaceName;
+    private String username;
+    private char[] password;
+    private String jackrabbitConfigPath;
+    private String workingDirectory;
+    private Session keepAliveSession;
+    private Repository repository;
+    private SequencingService sequencingService;
+    private ObservationService observationService;
+    private UserInterface userInterface;
+    private JcrExecutionContext executionContext;
+
+    public SequencingClient() {
+        setJackrabbitConfigPath(DEFAULT_JACKRABBIT_CONFIG_PATH);
+        setWorkingDirectory(DEFAULT_WORKING_DIRECTORY);
+        setRepositoryInformation(DEFAULT_REPOSITORY_NAME, DEFAULT_WORKSPACE_NAME, DEFAULT_USERNAME, DEFAULT_PASSWORD);
+    }
+
+    protected void setWorkingDirectory( String workingDirectoryPath ) {
+        this.workingDirectory = workingDirectoryPath != null ? workingDirectoryPath : DEFAULT_WORKING_DIRECTORY;
+    }
+
+    protected void setJackrabbitConfigPath( String jackrabbitConfigPath ) {
+        this.jackrabbitConfigPath = jackrabbitConfigPath != null ? jackrabbitConfigPath : DEFAULT_JACKRABBIT_CONFIG_PATH;
+    }
+
+    protected void setRepositoryInformation( String repositoryName,
+                                             String workspaceName,
+                                             String username,
+                                             char[] password ) {
+        if (this.repository != null) {
+            throw new IllegalArgumentException("Unable to set repository information when repository is already running");
+        }
+        this.repositoryName = repositoryName != null ? repositoryName : DEFAULT_REPOSITORY_NAME;
+        this.workspaceName = workspaceName != null ? workspaceName : DEFAULT_WORKSPACE_NAME;
+        this.username = username;
+        this.password = password;
+    }
+
+    /**
+     * Set the user interface that this client should use.
+     * 
+     * @param userInterface
+     */
+    public void setUserInterface( UserInterface userInterface ) {
+        this.userInterface = userInterface;
+    }
+
+    /**
+     * Start up the JCR repository. This method only operates using the JCR API and Jackrabbit-specific API.
+     * 
+     * @throws Exception
+     */
+    public void startRepository() throws Exception {
+        if (this.repository == null) {
+            try {
+
+                // Load the Jackrabbit configuration ...
+                File configFile = new File(this.jackrabbitConfigPath);
+                if (!configFile.exists()) {
+                    throw new SystemFailureException("The Jackrabbit configuration file cannot be found at "
+                                                     + configFile.getAbsoluteFile());
+                }
+                if (!configFile.canRead()) {
+                    throw new SystemFailureException("Unable to read the Jackrabbit configuration file at "
+                                                     + configFile.getAbsoluteFile());
+                }
+                String pathToConfig = configFile.getAbsolutePath();
+
+                // Find the directory where the Jackrabbit repository data will be stored ...
+                File workingDirectory = new File(this.workingDirectory);
+                if (workingDirectory.exists()) {
+                    if (!workingDirectory.isDirectory()) {
+                        throw new SystemFailureException("Unable to create working directory at "
+                                                         + workingDirectory.getAbsolutePath());
+                    }
+                }
+                String workingDirectoryPath = workingDirectory.getAbsolutePath();
+
+                // Get the Jackrabbit custom node definition (CND) file ...
+                URL cndFile = Thread.currentThread().getContextClassLoader().getResource("jackrabbitNodeTypes.cnd");
+
+                // Create the Jackrabbit repository instance and establish a session to keep the repository alive ...
+                this.repository = new TransientRepository(pathToConfig, workingDirectoryPath);
+                if (this.username != null) {
+                    Credentials credentials = new SimpleCredentials(this.username, this.password);
+                    this.keepAliveSession = this.repository.login(credentials, this.workspaceName);
+                } else {
+                    this.keepAliveSession = this.repository.login();
+                }
+
+                try {
+                    // Register the node types (only valid the first time) ...
+                    JackrabbitNodeTypeManager mgr = (JackrabbitNodeTypeManager)this.keepAliveSession.getWorkspace().getNodeTypeManager();
+                    mgr.registerNodeTypes(cndFile.openStream(), JackrabbitNodeTypeManager.TEXT_X_JCR_CND);
+                } catch (RepositoryException e) {
+                    if (!e.getMessage().contains("already exists")) throw e;
+                }
+
+            } catch (Exception e) {
+                this.repository = null;
+                this.keepAliveSession = null;
+                throw e;
+            }
+        }
+    }
+
+    /**
+     * Shutdown the repository. This method only uses the JCR API.
+     * 
+     * @throws Exception
+     */
+    public void shutdownRepository() throws Exception {
+        if (this.repository != null) {
+            try {
+                this.keepAliveSession.logout();
+            } finally {
+                this.repository = null;
+                this.keepAliveSession = null;
+            }
+        }
+    }
+
+    /**
+     * Start the DNA services.
+     * 
+     * @throws Exception
+     */
+    public void startDnaServices() throws Exception {
+        if (this.repository == null) {
+            this.startRepository();
+        }
+        if (this.sequencingService == null) {
+
+            // Create an execution context for the sequencing service. This execution context provides an environment
+            // for the DNA services which knows about the JCR repositories, workspaces, and credentials used to
+            // establish sessions to these workspaces.
+            final String repositoryWorkspaceName = this.repositoryName + "/" + this.workspaceName;
+            SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
+            sessionFactory.registerRepository(this.repositoryName, this.repository);
+            if (this.username != null) {
+                Credentials credentials = new SimpleCredentials(this.username, this.password);
+                sessionFactory.registerCredentials(repositoryWorkspaceName, credentials);
+            }
+            this.executionContext = new JcrExecutionContext(sessionFactory, repositoryWorkspaceName);
+
+            // Create the sequencing service, passing in the execution context ...
+            this.sequencingService = new SequencingService();
+            this.sequencingService.setExecutionContext(executionContext);
+
+            // Configure the sequencers. In this example, we only two sequencers that processes image and mp3 files.
+            // So create a configurations. Note that the sequencing service expects the class to be on the thread's current
+            // context
+            // classloader, or if that's null the classloader that loaded the SequencingService class.
+            //
+            // Part of the configuration includes telling DNA which JCR paths should be processed by the sequencer.
+            // These path expressions tell the service that this sequencer should be invoked on the "jcr:data" property
+            // on the "jcr:content" child node of any node uploaded to the repository whose name ends with one of the
+            // supported extensions, and the sequencer should place the generated output metadata in a node with the same name as
+            // the file but immediately below the "/images" node. Path expressions can be fairly complex, and can even
+            // specify that the generated information be placed in a different repository.
+            // 
+            // Sequencer configurations can be added before or after the service is started, but here we do it before the service
+            // is running.
+            String name = "Image Sequencer";
+            String desc = "Sequences image files to extract the characteristics of the image";
+            String classname = "org.jboss.dna.sequencer.image.ImageMetadataSequencer";
+            String[] classpath = null; // Use the current classpath
+            String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd)[*])/jcr:content[@jcr:data] => /images/$1"};
+            SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
+            this.sequencingService.addSequencer(imageSequencerConfig);
+
+            // Set up the MP3 sequencer ...
+            name = "Mp3 Sequencer";
+            desc = "Sequences mp3 files to extract the id3 tags of the audio file";
+            classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
+            String[] mp3PathExpressions = {"//(*.mp3[*])/jcr:content[@jcr:data] => /mp3s/$1"};
+            SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname, classpath, mp3PathExpressions);
+            this.sequencingService.addSequencer(mp3SequencerConfig);
+
+            // Set up the MP3 sequencer ...
+            name = "Java Sequencer";
+            desc = "Sequences java files to extract the characteristics of the java sources";
+            classname = "org.jboss.dna.sequencer.java.JavaMetadataSequencer";
+            String[] javaPathExpressions = {"//(*.java[*])/jcr:content[@jcr:data] => /java/$1"};
+            SequencerConfig javaSequencerConfig = new SequencerConfig(name, desc, classname, classpath, javaPathExpressions);
+            this.sequencingService.addSequencer(javaSequencerConfig);
+
+            // Use the DNA observation service to listen to the JCR repository (or multiple ones), and
+            // then register the sequencing service as a listener to this observation service...
+            this.observationService = new ObservationService(this.executionContext.getSessionFactory());
+            this.observationService.getAdministrator().start();
+            this.observationService.addListener(this.sequencingService);
+            this.observationService.monitor(repositoryWorkspaceName, Event.NODE_ADDED | Event.PROPERTY_ADDED
+                                                                     | Event.PROPERTY_CHANGED);
+        }
+        // Start up the sequencing service ...
+        this.sequencingService.getAdministrator().start();
+    }
+
+    /**
+     * Shut down the DNA services.
+     * 
+     * @throws Exception
+     */
+    public void shutdownDnaServices() throws Exception {
+        if (this.sequencingService == null) return;
+
+        // Shut down the service and wait until it's all shut down ...
+        this.sequencingService.getAdministrator().shutdown();
+        this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+
+        // Shut down the observation service ...
+        this.observationService.getAdministrator().shutdown();
+        this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+    }
+
+    /**
+     * Get the sequencing statistics.
+     * 
+     * @return the statistics; never null
+     */
+    public SequencingService.Statistics getStatistics() {
+        return this.sequencingService.getStatistics();
+    }
+
+    /**
+     * Prompt the user interface for the file to upload into the JCR repository, then upload it using the JCR API.
+     * 
+     * @throws Exception
+     */
+    public void uploadFile() throws Exception {
+        URL url = this.userInterface.getFileToUpload();
+        // Grab the last segment of the URL path, using it as the filename
+        String filename = url.getPath().replaceAll("([^/]*/)*", "");
+        String nodePath = this.userInterface.getRepositoryPath("/a/b/" + filename);
+        String mimeType = getMimeType(url);
+
+        // Now use the JCR API to upload the file ...
+        Session session = createSession();
+        JcrTools tools = this.executionContext.getTools();
+        try {
+            // Create the node at the supplied path ...
+            Node node = tools.findOrCreateNode(session, nodePath, "nt:folder", "nt:file");
+
+            // Upload the file to that node ...
+            Node contentNode = tools.findOrCreateChild(session, node, "jcr:content", "nt:resource");
+            contentNode.setProperty("jcr:mimeType", mimeType);
+            contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
+            contentNode.setProperty("jcr:data", url.openStream());
+
+            // Save the session ...
+            session.save();
+        } finally {
+            session.logout();
+        }
+    }
+
+    /**
+     * Perform a search of the repository for all image metadata automatically created by the image sequencer.
+     * 
+     * @throws Exception
+     */
+    public void search() throws Exception {
+        // Use JCR to search the repository for image metadata ...
+        List<ContentInfo> infos = new ArrayList<ContentInfo>();
+        Session session = createSession();
+        try {
+            // Find the node ...
+            Node root = session.getRootNode();
+
+            if (root.hasNode("images") || root.hasNode("mp3s")) {
+                Node mediasNode;
+                if (root.hasNode("images")) {
+                    mediasNode = root.getNode("images");
+
+                    for (NodeIterator iter = mediasNode.getNodes(); iter.hasNext();) {
+                        Node mediaNode = iter.nextNode();
+                        if (mediaNode.hasNode("image:metadata")) {
+                            infos.add(extractMediaInfo("image:metadata", "image", mediaNode));
+                        }
+                    }
+                }
+                if (root.hasNode("mp3s")) {
+                    mediasNode = root.getNode("mp3s");
+
+                    for (NodeIterator iter = mediasNode.getNodes(); iter.hasNext();) {
+                        Node mediaNode = iter.nextNode();
+                        if (mediaNode.hasNode("mp3:metadata")) {
+                            infos.add(extractMediaInfo("mp3:metadata", "mp3", mediaNode));
+                        }
+                    }
+                }
+
+            }
+            if (root.hasNode("java")) {
+                Map<String, List<Properties>> tree = new TreeMap<String, List<Properties>>();
+                // Find the compilation unit node ...
+                List<Properties> javaElements;
+                if (root.hasNode("java")) {
+                    Node javaSourcesNode = root.getNode("java");
+                    for (NodeIterator i = javaSourcesNode.getNodes(); i.hasNext();) {
+
+                        Node javaSourceNode = i.nextNode();
+
+                        if (javaSourceNode.hasNodes()) {
+                            Node javaCompilationUnit = javaSourceNode.getNodes().nextNode();
+                            // package informations
+
+                            javaElements = new ArrayList<Properties>();
+                            try {
+                                Node javaPackageDeclarationNode = javaCompilationUnit.getNode("java:package/java:packageDeclaration");
+                                javaElements.add(extractJavaInfo(javaPackageDeclarationNode));
+                                tree.put("Class package", javaElements);
+                            } catch (PathNotFoundException e) {
+                                // do nothing
+                            }
+
+                            // import informations
+                            javaElements = new ArrayList<Properties>();
+                            try {
+                                for (NodeIterator singleImportIterator = javaCompilationUnit.getNode("java:import/java:importDeclaration/java:singleImport").getNodes(); singleImportIterator.hasNext();) {
+                                    Node javasingleTypeImportDeclarationNode = singleImportIterator.nextNode();
+                                    javaElements.add(extractJavaInfo(javasingleTypeImportDeclarationNode));
+                                }
+                                tree.put("Class single Imports", javaElements);
+                            } catch (PathNotFoundException e) {
+                                // do nothing
+                            }
+
+                            javaElements = new ArrayList<Properties>();
+                            try {
+                                for (NodeIterator javaImportOnDemandIterator = javaCompilationUnit.getNode("java:import/java:importDeclaration/java:importOnDemand").getNodes(); javaImportOnDemandIterator.hasNext();) {
+                                    Node javaImportOnDemandtDeclarationNode = javaImportOnDemandIterator.nextNode();
+                                    javaElements.add(extractJavaInfo(javaImportOnDemandtDeclarationNode));
+                                }
+                                tree.put("Class on demand imports", javaElements);
+
+                            } catch (PathNotFoundException e) {
+                                // do nothing
+                            }
+                            // class head informations
+                            javaElements = new ArrayList<Properties>();
+                            Node javaNormalDeclarationClassNode = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration");
+                            javaElements.add(extractJavaInfo(javaNormalDeclarationClassNode));
+                            tree.put("Class head information", javaElements);
+
+                            // field member informations
+                            javaElements = new ArrayList<Properties>();
+                            for (NodeIterator javaFieldTypeIterator = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:field/java:fieldType").getNodes(); javaFieldTypeIterator.hasNext();) {
+                                Node rootFieldTypeNode = javaFieldTypeIterator.nextNode();
+                                if (rootFieldTypeNode.hasNode("java:primitiveType")) {
+                                    Node javaPrimitiveTypeNode = rootFieldTypeNode.getNode("java:primitiveType");
+                                    javaElements.add(extractJavaInfo(javaPrimitiveTypeNode));
+                                    // more informations
+                                }
+
+                                if (rootFieldTypeNode.hasNode("java:simpleType")) {
+                                    Node javaSimpleTypeNode = rootFieldTypeNode.getNode("java:simpleType");
+                                    javaElements.add(extractJavaInfo(javaSimpleTypeNode));
+                                }
+                                if (rootFieldTypeNode.hasNode("java:parameterizedType")) {
+                                    Node javaParameterizedType = rootFieldTypeNode.getNode("java:parameterizedType");
+                                    javaElements.add(extractJavaInfo(javaParameterizedType));
+                                }
+                                if (rootFieldTypeNode.hasNode("java:arrayType")) {
+                                    Node javaArrayType = rootFieldTypeNode.getNode("java:arrayType[2]");
+                                    javaElements.add(extractJavaInfo(javaArrayType));
+                                }
+                            }
+                            tree.put("Class field members", javaElements);
+
+                            // constructor informations
+                            javaElements = new ArrayList<Properties>();
+                            for (NodeIterator javaConstructorIterator = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:constructor").getNodes(); javaConstructorIterator.hasNext();) {
+                                Node javaConstructor = javaConstructorIterator.nextNode();
+                                javaElements.add(extractJavaInfo(javaConstructor));
+                            }
+                            tree.put("Class constructors", javaElements);
+
+                            // method informations
+                            javaElements = new ArrayList<Properties>();
+                            for (NodeIterator javaMethodIterator = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:method").getNodes(); javaMethodIterator.hasNext();) {
+                                Node javaMethod = javaMethodIterator.nextNode();
+                                javaElements.add(extractJavaInfo(javaMethod));
+                            }
+                            tree.put("Class member functions", javaElements);
+
+                            JavaInfo javaInfo = new JavaInfo(javaCompilationUnit.getPath(), javaCompilationUnit.getName(),
+                                                             "java source", tree);
+                            infos.add(javaInfo);
+                        }
+                    }
+                }
+
+            }
+        } finally {
+            session.logout();
+        }
+
+        // Display the search results ...
+        this.userInterface.displaySearchResults(infos);
+    }
+
+    private MediaInfo extractMediaInfo( String metadataNodeName,
+                                        String mediaType,
+                                        Node mediaNode ) throws RepositoryException, PathNotFoundException, ValueFormatException {
+        String nodePath = mediaNode.getPath();
+        String nodeName = mediaNode.getName();
+        mediaNode = mediaNode.getNode(metadataNodeName);
+
+        // Create a Properties object containing the properties for this node; ignore any children ...
+        Properties props = new Properties();
+        for (PropertyIterator propertyIter = mediaNode.getProperties(); propertyIter.hasNext();) {
+            Property property = propertyIter.nextProperty();
+            String name = property.getName();
+            String stringValue = null;
+            if (property.getDefinition().isMultiple()) {
+                StringBuilder sb = new StringBuilder();
+                boolean first = true;
+                for (Value value : property.getValues()) {
+                    if (!first) {
+                        sb.append(", ");
+                        first = false;
+                    }
+                    sb.append(value.getString());
+                }
+                stringValue = sb.toString();
+            } else {
+                stringValue = property.getValue().getString();
+            }
+            props.put(name, stringValue);
+        }
+        // Create the image information object, and add it to the collection ...
+        return new MediaInfo(nodePath, nodeName, mediaType, props);
+    }
+
+    /**
+     * Extract informations from a specific node.
+     * 
+     * @param node - node, that contains informations.
+     * @return a properties of keys/values.
+     * @throws RepositoryException
+     * @throws IllegalStateException
+     * @throws ValueFormatException
+     */
+    private Properties extractJavaInfo( Node node ) throws ValueFormatException, IllegalStateException, RepositoryException {
+        if (node.hasProperties()) {
+            Properties properties = new Properties();
+            for (PropertyIterator propertyIter = node.getProperties(); propertyIter.hasNext();) {
+                Property property = propertyIter.nextProperty();
+                String name = property.getName();
+                String stringValue = property.getValue().getString();
+                properties.put(name, stringValue);
+            }
+            return properties;
+        }
+        return null;
+    }
+
+    /**
+     * Utility method to create a new JCR session from the execution context's {@link SessionFactory}.
+     * 
+     * @return the session
+     * @throws RepositoryException
+     */
+    protected Session createSession() throws RepositoryException {
+        return this.executionContext.getSessionFactory().createSession(this.repositoryName + "/" + this.workspaceName);
+    }
+
+    protected String getMimeType( URL file ) {
+        String filename = file.getPath().toLowerCase();
+        if (filename.endsWith(".gif")) return "image/gif";
+        if (filename.endsWith(".png")) return "image/png";
+        if (filename.endsWith(".pict")) return "image/x-pict";
+        if (filename.endsWith(".bmp")) return "image/bmp";
+        if (filename.endsWith(".jpg")) return "image/jpeg";
+        if (filename.endsWith(".jpe")) return "image/jpeg";
+        if (filename.endsWith(".jpeg")) return "image/jpeg";
+        if (filename.endsWith(".ras")) return "image/x-cmu-raster";
+        if (filename.endsWith(".mp3")) return "audio/mpeg";
+        if (filename.endsWith(".java")) return "text/x-java-source";
+        throw new SystemFailureException("Unknown mime type for " + file);
+    }
+
+}

Deleted: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/UserInterface.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/UserInterface.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,38 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.example.dna.sequencers;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.List;
-
-/**
- * @author Randall Hauch
- */
-public interface UserInterface {
-
-    public URL getFileToUpload() throws IllegalArgumentException, IOException;
-
-    public String getRepositoryPath( String defaultPath ) throws IllegalArgumentException, IOException;
-
-    public void displaySearchResults( List<ContentInfo> contentInfo ) throws IOException;
-}

Copied: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/UserInterface.java (from rev 706, trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java)
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/UserInterface.java	                        (rev 0)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/UserInterface.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencer;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+/**
+ * @author Randall Hauch
+ */
+public interface UserInterface {
+
+    public URL getFileToUpload() throws IllegalArgumentException, IOException;
+
+    public String getRepositoryPath( String defaultPath ) throws IllegalArgumentException, IOException;
+
+    public void displaySearchResults( List<ContentInfo> contentInfo ) throws IOException;
+}

Copied: trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer (from rev 705, trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers)

Deleted: trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/MockUserInterface.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/MockUserInterface.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/MockUserInterface.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,71 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.example.dna.sequencers;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.net.URL;
-import java.util.List;
-
-/**
- * @author Randall Hauch
- */
-public class MockUserInterface implements UserInterface {
-
-    private final String repositoryPath;
-    private final URL fileToUpload;
-    private final int numberOfSearchResults;
-
-    public MockUserInterface( URL fileToUpload,
-                              String repositoryPath,
-                              int numSearchResults ) {
-        this.repositoryPath = repositoryPath;
-        this.fileToUpload = fileToUpload;
-        this.numberOfSearchResults = numSearchResults;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void displaySearchResults( List<ContentInfo> infos ) {
-        assertThat(infos.size(), is(this.numberOfSearchResults));
-        for (ContentInfo info : infos) {
-            System.out.println("Info: ");
-            System.out.println(info);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public URL getFileToUpload() {
-        return this.fileToUpload;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getRepositoryPath( String defaultPath ) {
-        return this.repositoryPath != null ? this.repositoryPath : defaultPath;
-    }
-
-}

Copied: trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/MockUserInterface.java (from rev 706, trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/MockUserInterface.java)
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/MockUserInterface.java	                        (rev 0)
+++ trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/MockUserInterface.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,73 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencer;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.net.URL;
+import java.util.List;
+import org.jboss.example.dna.sequencer.ContentInfo;
+import org.jboss.example.dna.sequencer.UserInterface;
+
+/**
+ * @author Randall Hauch
+ */
+public class MockUserInterface implements UserInterface {
+
+    private final String repositoryPath;
+    private final URL fileToUpload;
+    private final int numberOfSearchResults;
+
+    public MockUserInterface( URL fileToUpload,
+                              String repositoryPath,
+                              int numSearchResults ) {
+        this.repositoryPath = repositoryPath;
+        this.fileToUpload = fileToUpload;
+        this.numberOfSearchResults = numSearchResults;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void displaySearchResults( List<ContentInfo> infos ) {
+        assertThat(infos.size(), is(this.numberOfSearchResults));
+        for (ContentInfo info : infos) {
+            System.out.println("Info: ");
+            System.out.println(info);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URL getFileToUpload() {
+        return this.fileToUpload;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getRepositoryPath( String defaultPath ) {
+        return this.repositoryPath != null ? this.repositoryPath : defaultPath;
+    }
+
+}

Deleted: trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,200 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt pngImageUrl in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.example.dna.sequencers;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import org.jboss.dna.common.util.FileUtil;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class SequencingClientTest {
-
-    private URL pngImageUrl;
-    private URL pictImageUrl;
-    private URL jpegImageUrl;
-    private URL mp3Url;
-    private URL javaSourceUrl;
-    private SequencingClient client;
-
-    @Before
-    public void beforeEach() throws MalformedURLException {
-        this.pngImageUrl = Thread.currentThread().getContextClassLoader().getResource("caution.png");
-        this.pictImageUrl = Thread.currentThread().getContextClassLoader().getResource("caution.pict");
-        this.jpegImageUrl = Thread.currentThread().getContextClassLoader().getResource("caution.jpg");
-        this.mp3Url = Thread.currentThread().getContextClassLoader().getResource("sample1.mp3");
-        // Get the URL of source (MySource.java), that have to be sequencing
-        this.javaSourceUrl = FileUtil.convertFileToURL("workspace/project1/src/org/acme/MySource.java");
-
-        client = new SequencingClient();
-        client.setWorkingDirectory("target/repositoryData");
-        client.setJackrabbitConfigPath("src/main/resources/jackrabbitConfig.xml");
-        FileUtil.delete("target/repositoryData");
-    }
-
-    @After
-    public void afterEach() throws Exception {
-        client.shutdownDnaServices();
-        client.shutdownRepository();
-        FileUtil.delete("target/repositoryData");
-    }
-
-    @Test
-    public void shouldFindMedias() {
-        assertThat(this.pictImageUrl, is(notNullValue()));
-        assertThat(this.pngImageUrl, is(notNullValue()));
-        assertThat(this.jpegImageUrl, is(notNullValue()));
-        assertThat(this.mp3Url, is(notNullValue()));
-    }
-
-    @Test
-    public void shouldStartupAndShutdownRepository() throws Exception {
-        client.startRepository();
-        client.shutdownRepository();
-
-    }
-
-    @Test
-    public void shouldStartupAndShutdownRepositoryAndSequencingService() throws Exception {
-        client.startRepository();
-        client.startDnaServices();
-        client.shutdownDnaServices();
-        client.shutdownRepository();
-    }
-
-    @Test
-    public void shouldUploadAndSequencePngFile() throws Exception {
-        client.setUserInterface(new MockUserInterface(this.pngImageUrl, "/a/b/caution.png", 1));
-        client.startRepository();
-        client.startDnaServices();
-        client.uploadFile();
-
-        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
-        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
-        Thread.sleep(1000);
-        client.shutdownDnaServices();
-
-        // The sequencers should have run, so perform the search.
-        // The mock user interface checks the results.
-        client.search();
-
-        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
-    }
-
-    @Test
-    public void shouldUploadAndSequenceJpegFile() throws Exception {
-        client.setUserInterface(new MockUserInterface(this.jpegImageUrl, "/a/b/caution.jpeg", 1));
-        client.startRepository();
-        client.startDnaServices();
-        client.uploadFile();
-
-        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
-        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
-        Thread.sleep(1000);
-        client.shutdownDnaServices();
-
-        // The sequencers should have run, so perform the search.
-        // The mock user interface checks the results.
-        client.search();
-
-        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
-    }
-
-    @Test
-    public void shouldUploadAndNotSequencePictFile() throws Exception {
-        client.setUserInterface(new MockUserInterface(this.pictImageUrl, "/a/b/caution.pict", 0));
-        client.startRepository();
-        client.startDnaServices();
-        client.uploadFile();
-
-        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
-        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
-        Thread.sleep(1000);
-        client.shutdownDnaServices();
-
-        // The sequencers should have run, so perform the search.
-        // The mock user interface checks the results.
-        client.search();
-
-        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(0l));
-    }
-
-    @Test
-    public void shouldUploadAndSequenceMp3File() throws Exception {
-        client.setUserInterface(new MockUserInterface(this.mp3Url, "/a/b/test.mp3", 1));
-        client.startRepository();
-        client.startDnaServices();
-        client.uploadFile();
-
-        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
-        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
-        Thread.sleep(1000);
-        client.shutdownDnaServices();
-
-        // The sequencers should have run, so perform the search.
-        // The mock user interface checks the results.
-        client.search();
-
-        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
-    }
-
-    @Test
-    public void shouldFindCompilationUnitSource() throws IOException {
-        assertThat(this.javaSourceUrl, is(notNullValue()));
-        InputStream stream = this.javaSourceUrl.openStream();
-        try {
-            byte[] buffer = new byte[1024];
-            while (stream.read(buffer) != -1) {
-            }
-        } finally {
-            stream.close();
-        }
-    }
-
-    @Test
-    public void shouldUploadAndSequenceJavaSourceFile() throws Exception {
-        client.setUserInterface(new MockUserInterface(this.javaSourceUrl, "/a/b/MySource.java", 1));
-        client.startRepository();
-        client.startDnaServices();
-        client.uploadFile();
-
-        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
-        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
-        Thread.sleep(1000);
-        client.shutdownDnaServices();
-
-        // The sequencers should have run, so perform the search.
-        // The mock user interface checks the results.
-        client.search();
-        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1L));
-    }
-
-}

Copied: trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java (from rev 706, trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java)
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java	                        (rev 0)
+++ trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,201 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt pngImageUrl in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencer;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.jboss.dna.common.util.FileUtil;
+import org.jboss.example.dna.sequencer.SequencingClient;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class SequencingClientTest {
+
+    private URL pngImageUrl;
+    private URL pictImageUrl;
+    private URL jpegImageUrl;
+    private URL mp3Url;
+    private URL javaSourceUrl;
+    private SequencingClient client;
+
+    @Before
+    public void beforeEach() throws MalformedURLException {
+        this.pngImageUrl = Thread.currentThread().getContextClassLoader().getResource("caution.png");
+        this.pictImageUrl = Thread.currentThread().getContextClassLoader().getResource("caution.pict");
+        this.jpegImageUrl = Thread.currentThread().getContextClassLoader().getResource("caution.jpg");
+        this.mp3Url = Thread.currentThread().getContextClassLoader().getResource("sample1.mp3");
+        // Get the URL of source (MySource.java), that have to be sequencing
+        this.javaSourceUrl = FileUtil.convertFileToURL("workspace/project1/src/org/acme/MySource.java");
+
+        client = new SequencingClient();
+        client.setWorkingDirectory("target/repositoryData");
+        client.setJackrabbitConfigPath("src/main/resources/jackrabbitConfig.xml");
+        FileUtil.delete("target/repositoryData");
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        client.shutdownDnaServices();
+        client.shutdownRepository();
+        FileUtil.delete("target/repositoryData");
+    }
+
+    @Test
+    public void shouldFindMedias() {
+        assertThat(this.pictImageUrl, is(notNullValue()));
+        assertThat(this.pngImageUrl, is(notNullValue()));
+        assertThat(this.jpegImageUrl, is(notNullValue()));
+        assertThat(this.mp3Url, is(notNullValue()));
+    }
+
+    @Test
+    public void shouldStartupAndShutdownRepository() throws Exception {
+        client.startRepository();
+        client.shutdownRepository();
+
+    }
+
+    @Test
+    public void shouldStartupAndShutdownRepositoryAndSequencingService() throws Exception {
+        client.startRepository();
+        client.startDnaServices();
+        client.shutdownDnaServices();
+        client.shutdownRepository();
+    }
+
+    @Test
+    public void shouldUploadAndSequencePngFile() throws Exception {
+        client.setUserInterface(new MockUserInterface(this.pngImageUrl, "/a/b/caution.png", 1));
+        client.startRepository();
+        client.startDnaServices();
+        client.uploadFile();
+
+        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
+        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
+        Thread.sleep(1000);
+        client.shutdownDnaServices();
+
+        // The sequencers should have run, so perform the search.
+        // The mock user interface checks the results.
+        client.search();
+
+        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
+    }
+
+    @Test
+    public void shouldUploadAndSequenceJpegFile() throws Exception {
+        client.setUserInterface(new MockUserInterface(this.jpegImageUrl, "/a/b/caution.jpeg", 1));
+        client.startRepository();
+        client.startDnaServices();
+        client.uploadFile();
+
+        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
+        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
+        Thread.sleep(1000);
+        client.shutdownDnaServices();
+
+        // The sequencers should have run, so perform the search.
+        // The mock user interface checks the results.
+        client.search();
+
+        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
+    }
+
+    @Test
+    public void shouldUploadAndNotSequencePictFile() throws Exception {
+        client.setUserInterface(new MockUserInterface(this.pictImageUrl, "/a/b/caution.pict", 0));
+        client.startRepository();
+        client.startDnaServices();
+        client.uploadFile();
+
+        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
+        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
+        Thread.sleep(1000);
+        client.shutdownDnaServices();
+
+        // The sequencers should have run, so perform the search.
+        // The mock user interface checks the results.
+        client.search();
+
+        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(0l));
+    }
+
+    @Test
+    public void shouldUploadAndSequenceMp3File() throws Exception {
+        client.setUserInterface(new MockUserInterface(this.mp3Url, "/a/b/test.mp3", 1));
+        client.startRepository();
+        client.startDnaServices();
+        client.uploadFile();
+
+        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
+        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
+        Thread.sleep(1000);
+        client.shutdownDnaServices();
+
+        // The sequencers should have run, so perform the search.
+        // The mock user interface checks the results.
+        client.search();
+
+        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
+    }
+
+    @Test
+    public void shouldFindCompilationUnitSource() throws IOException {
+        assertThat(this.javaSourceUrl, is(notNullValue()));
+        InputStream stream = this.javaSourceUrl.openStream();
+        try {
+            byte[] buffer = new byte[1024];
+            while (stream.read(buffer) != -1) {
+            }
+        } finally {
+            stream.close();
+        }
+    }
+
+    @Test
+    public void shouldUploadAndSequenceJavaSourceFile() throws Exception {
+        client.setUserInterface(new MockUserInterface(this.javaSourceUrl, "/a/b/MySource.java", 1));
+        client.startRepository();
+        client.startDnaServices();
+        client.uploadFile();
+
+        // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
+        // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
+        Thread.sleep(1000);
+        client.shutdownDnaServices();
+
+        // The sequencers should have run, so perform the search.
+        // The mock user interface checks the results.
+        client.search();
+        assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1L));
+    }
+
+}

Modified: trunk/docs/examples/gettingstarted/sequencers/src/test/resources/log4j.properties
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/test/resources/log4j.properties	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/docs/examples/gettingstarted/sequencers/src/test/resources/log4j.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -5,8 +5,10 @@
 log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %m%n
 
 # Root logger option
-log4j.rootLogger=INFO, stdout
+log4j.rootLogger=WARNING, stdout
 
 # Set up the default logging to be INFO level, then override specific units
-log4j.logger.org.jboss.dna=INFO
+log4j.logger.org.jboss.dna=WARNING
 
+# Jackrabbit logging
+log4j.logger.org.apache.jackrabbit=WARN, stdout

Modified: trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_for_sequencing.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_for_sequencing.xml	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_for_sequencing.xml	2009-01-15 18:32:57 UTC (rev 707)
@@ -105,7 +105,7 @@
     <programlisting role="JAVA"><![CDATA[
 String name = "Image Sequencer";
 String desc = "Sequences image files to extract the characteristics of the image";
-String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
+String classname = "org.jboss.dna.sequencer.image.ImageMetadataSequencer";
 String[] classpath = null; // Use the current classpath
 String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png)[*])/jcr:content[@jcr:data] => /images/$1"};
 SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, 

Modified: trunk/docs/reference/src/main/docbook/en-US/custom.dtd
===================================================================
--- trunk/docs/reference/src/main/docbook/en-US/custom.dtd	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/docs/reference/src/main/docbook/en-US/custom.dtd	2009-01-15 18:32:57 UTC (rev 707)
@@ -62,39 +62,39 @@
 <!ENTITY Location							       	"<ulink url='&API;graph/Location.html'><classname>Location</classname></ulink>">
 <!ENTITY ExecutionContext		       		"<ulink url='&API;graph/ExecutionContext.html'><classname>ExecutionContext</classname></ulink>">
 <!ENTITY ExecutionContextFactory   		"<ulink url='&API;graph/ExecutionContextFactory.html'><interface>ExecutionContextFactory</interface></ulink>">
-<!ENTITY Name								       		"<ulink url='&API;graph/properties/Name.html'><interface>Name</interface></ulink>">
-<!ENTITY Path								       		"<ulink url='&API;graph/properties/Path.html'><interface>Path</interface></ulink>">
-<!ENTITY PathSegment				       		"<ulink url='&API;graph/properties/Path.Segment.html'><interface>Path.Segment</interface></ulink>">
-<!ENTITY Property						       		"<ulink url='&API;graph/properties/Property.html'><interface>Property</interface></ulink>">
-<!ENTITY ValueFactories       				"<ulink url='&API;graph/properties/ValueFactories.html'><interface>ValueFactories</interface></ulink>">
-<!ENTITY NamespaceRegistry       			"<ulink url='&API;graph/properties/NamespaceRegistry.html'><interface>NamespaceRegistry</interface></ulink>">
-<!ENTITY PropertyFactory       				"<ulink url='&API;graph/properties/PropertyFactory.html'><interface>PropertyFactory</interface></ulink>">
-<!ENTITY PathNotFoundException				"<ulink url='&API;graph/properties/PathNotFoundException.html'><classname>PathNotFoundException</classname></ulink>">
-<!ENTITY RepositorySource       			"<ulink url='&API;graph/connectors/RepositorySource.html'><interface>RepositorySource</interface></ulink>">
-<!ENTITY RepositoryConnection    			"<ulink url='&API;graph/connectors/RepositoryConnection.html'><interface>RepositoryConnection</interface></ulink>">
-<!ENTITY RepositoryConnectionFactory	"<ulink url='&API;graph/connectors/RepositoryConnectionFactory.html'><interface>RepositoryConnectionFactory</interface></ulink>">
-<!ENTITY RepositorySourceListener			"<ulink url='&API;graph/connectors/RepositorySourceListener.html'><interface>RepositorySourceListener</interface></ulink>">
-<!ENTITY RepositorySourceCapabilities	"<ulink url='&API;graph/connectors/RepositorySourceCapabilities.html'><classname>RepositorySourceCapabilities</classname></ulink>">
+<!ENTITY Name								       		"<ulink url='&API;graph/property/Name.html'><interface>Name</interface></ulink>">
+<!ENTITY Path								       		"<ulink url='&API;graph/property/Path.html'><interface>Path</interface></ulink>">
+<!ENTITY PathSegment				       		"<ulink url='&API;graph/property/Path.Segment.html'><interface>Path.Segment</interface></ulink>">
+<!ENTITY Property						       		"<ulink url='&API;graph/property/Property.html'><interface>Property</interface></ulink>">
+<!ENTITY ValueFactories       				"<ulink url='&API;graph/property/ValueFactories.html'><interface>ValueFactories</interface></ulink>">
+<!ENTITY NamespaceRegistry       			"<ulink url='&API;graph/property/NamespaceRegistry.html'><interface>NamespaceRegistry</interface></ulink>">
+<!ENTITY PropertyFactory       				"<ulink url='&API;graph/property/PropertyFactory.html'><interface>PropertyFactory</interface></ulink>">
+<!ENTITY PathNotFoundException				"<ulink url='&API;graph/property/PathNotFoundException.html'><classname>PathNotFoundException</classname></ulink>">
+<!ENTITY RepositorySource       			"<ulink url='&API;graph/connector/RepositorySource.html'><interface>RepositorySource</interface></ulink>">
+<!ENTITY RepositoryConnection    			"<ulink url='&API;graph/connector/RepositoryConnection.html'><interface>RepositoryConnection</interface></ulink>">
+<!ENTITY RepositoryConnectionFactory	"<ulink url='&API;graph/connector/RepositoryConnectionFactory.html'><interface>RepositoryConnectionFactory</interface></ulink>">
+<!ENTITY RepositorySourceListener			"<ulink url='&API;graph/connector/RepositorySourceListener.html'><interface>RepositorySourceListener</interface></ulink>">
+<!ENTITY RepositorySourceCapabilities	"<ulink url='&API;graph/connector/RepositorySourceCapabilities.html'><classname>RepositorySourceCapabilities</classname></ulink>">
 <!ENTITY CachePolicy							    "<ulink url='&API;graph/cache/CachePolicy.html'><interface>CachePolicy</interface></ulink>">
-<!ENTITY Request					       			"<ulink url='&API;graph/requests/Requests.html'><classname>Request</classname></ulink>">
-<!ENTITY CompositeRequest					    "<ulink url='&API;graph/requests/CompositeRequest.html'><classname>CompositeRequest</classname></ulink>">
-<!ENTITY ReadNodeRequest					    "<ulink url='&API;graph/requests/ReadNodeRequest.html'><classname>ReadNodeRequest</classname></ulink>">
-<!ENTITY CopyBranchRequest					  "<ulink url='&API;graph/requests/CopyBranchRequest.html'><classname>CopyBranchRequest</classname></ulink>">
-<!ENTITY RequestProcessor	       			"<ulink url='&API;graph/requests/processor/RequestProcessor.html'><classname>RequestProcessor</classname></ulink>">
-<!ENTITY StreamSequencer		    			"<ulink url='&API;graph/sequencers/StreamSequencer.html'><interface>StreamSequencer</interface></ulink>">
-<!ENTITY SequencerOutput		    			"<ulink url='&API;graph/sequencers/SequencerOutput.html'><interface>SequencerOutput</interface></ulink>">
-<!ENTITY SequencerContext		    			"<ulink url='&API;graph/sequencers/SequencerContext.html'><interface>SequencerContext</interface></ulink>">
+<!ENTITY Request					       			"<ulink url='&API;graph/request/Requests.html'><classname>Request</classname></ulink>">
+<!ENTITY CompositeRequest					    "<ulink url='&API;graph/request/CompositeRequest.html'><classname>CompositeRequest</classname></ulink>">
+<!ENTITY ReadNodeRequest					    "<ulink url='&API;graph/request/ReadNodeRequest.html'><classname>ReadNodeRequest</classname></ulink>">
+<!ENTITY CopyBranchRequest					  "<ulink url='&API;graph/request/CopyBranchRequest.html'><classname>CopyBranchRequest</classname></ulink>">
+<!ENTITY RequestProcessor	       			"<ulink url='&API;graph/request/processor/RequestProcessor.html'><classname>RequestProcessor</classname></ulink>">
+<!ENTITY StreamSequencer		    			"<ulink url='&API;graph/sequencer/StreamSequencer.html'><interface>StreamSequencer</interface></ulink>">
+<!ENTITY SequencerOutput		    			"<ulink url='&API;graph/sequencer/SequencerOutput.html'><interface>SequencerOutput</interface></ulink>">
+<!ENTITY SequencerContext		    			"<ulink url='&API;graph/sequencer/SequencerContext.html'><interface>SequencerContext</interface></ulink>">
 <!ENTITY MimeTypeDetector					  	"<ulink url='&API;graph/mimetype/MimeTypeDetector.html'><interface>MimeTypeDetector</interface></ulink>">
-<!ENTITY MockSequencerOutput		    	"<ulink url='&API;graph/sequencers/MockSequencerOutput.html'><interface>MockSequencerOutput</interface></ulink>">
-<!ENTITY MockSequencerContext		    	"<ulink url='&API;graph/sequencers/MockSequencerContext.html'><interface>MockSequencerContext</interface></ulink>">
+<!ENTITY MockSequencerOutput		    	"<ulink url='&API;graph/sequencer/MockSequencerOutput.html'><interface>MockSequencerOutput</interface></ulink>">
+<!ENTITY MockSequencerContext		    	"<ulink url='&API;graph/sequencer/MockSequencerContext.html'><interface>MockSequencerContext</interface></ulink>">
 
 <!-- Types in dna-repository -->
 
 <!ENTITY RepositoryLibrary	       		"<ulink url='&API;repository/RepositoryLibrary.html'><classname>RepositoryLibrary</classname></ulink>">
 <!ENTITY RepositoryService	       		"<ulink url='&API;repository/RepositoryService.html'><classname>RepositoryService</classname></ulink>">
-<!ENTITY SequencingService	       		"<ulink url='&API;repository/sequencers/SequencingService.html'><classname>SequencingService</classname></ulink>">
-<!ENTITY ServiceAdministrator   			"<ulink url='&API;repository/services/ServiceAdministrator.html'><interface>ServiceAdministrator</interface></ulink>">
-<!ENTITY SequencerConfig 		       		"<ulink url='&API;repository/sequencers/SequencerConfig.html'><classname>SequencerConfig</classname></ulink>">
+<!ENTITY ServiceAdministrator   			"<ulink url='&API;repository/service/ServiceAdministrator.html'><interface>ServiceAdministrator</interface></ulink>">
+<!ENTITY SequencingService	       		"<ulink url='&API;repository/sequencer/SequencingService.html'><classname>SequencingService</classname></ulink>">
+<!ENTITY SequencerConfig 		       		"<ulink url='&API;repository/sequencer/SequencerConfig.html'><classname>SequencerConfig</classname></ulink>">
 <!ENTITY SessionFactory				   			"<ulink url='&API;repository/util/SessionFactory.html'><interface>SessionFactory</interface></ulink>">
 <!ENTITY JndiSessionFactory				 		"<ulink url='&API;repository/util/JndiSessionFactory.html'><classname>JndiSessionFactory</classname></ulink>">
 <!ENTITY SimpleSessionFactory				 	"<ulink url='&API;repository/util/SimpleSessionFactory.html'><classname>SimpleSessionFactory</classname></ulink>">
@@ -120,5 +120,5 @@
 <!ENTITY ImageMetadataSequencer		  	"<ulink url='&API;sequencer/image/ImageMetadataSequencer.html'><classname>ImageMetadataSequencer</classname></ulink>">
 <!ENTITY ImageMetadata						  	"<ulink url='&API;sequencer/image/ImageMetadata.html'><classname>ImageMetadata</classname></ulink>">
 <!ENTITY ImageSequencerI18n				  	"<ulink url='&API;sequencer/image/ImageSequencerI18n.html'><classname>ImageSequencerI18n</classname></ulink>">
-<!ENTITY ApertureMimeTypeDetector	  	"<ulink url='&API;mimetype/ApertureMimeTypeDetector.html'><classname>ApertureMimeTypeDetector</classname></ulink>">
+<!ENTITY ApertureMimeTypeDetector	  	"<ulink url='&API;mimetype/aperture/ApertureMimeTypeDetector.html'><classname>ApertureMimeTypeDetector</classname></ulink>">
 

Modified: trunk/extensions/dna-common-jdbc/src/main/java/org/jboss/dna/graph/sequencers/JdbcSequencer.java
===================================================================
--- trunk/extensions/dna-common-jdbc/src/main/java/org/jboss/dna/graph/sequencers/JdbcSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-common-jdbc/src/main/java/org/jboss/dna/graph/sequencers/JdbcSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -22,6 +22,8 @@
 package org.jboss.dna.graph.sequencers;
 
 import java.sql.Connection;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
 
 /**
  * The interface for a DNA sequencer that processes a JDBC connection (for instance, JDBC Metadata) and stores in the repository.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -31,11 +31,11 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.connector.federation.executor.FederatingCommandExecutor;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * The component that represents a single federated repository. The federated repository uses a set of {@link RepositorySource
@@ -221,7 +221,7 @@
     }
 
     /**
-     * Called by {@link FederatedRepositoryConnection#execute(ExecutionContext, org.jboss.dna.graph.requests.Request)}.
+     * Called by {@link FederatedRepositoryConnection#execute(ExecutionContext, org.jboss.dna.graph.request.Request)}.
      * 
      * @param context the execution context in which the executor will be run; may not be null
      * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConfig.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConfig.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConfig.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -30,7 +30,7 @@
 import org.jboss.dna.common.collection.ThreadSafeProblems;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySource;
 
 /**
  * The configuration of a federated repository. The configuration defines, among other things, the set of

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -27,11 +27,11 @@
 import net.jcip.annotations.ThreadSafe;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * @author Randall Hauch
@@ -111,8 +111,8 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-     *      org.jboss.dna.graph.requests.Request)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+     *      org.jboss.dna.graph.request.Request)
      */
     public void execute( ExecutionContext context,
                          Request request ) throws RepositorySourceException {

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -52,17 +52,17 @@
 import org.jboss.dna.graph.Subgraph;
 import org.jboss.dna.graph.cache.BasicCachePolicy;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceCapabilities;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.ValueFactory;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.ValueFactory;
 
 /**
  * @author Randall Hauch
@@ -132,7 +132,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#initialize(org.jboss.dna.graph.connectors.RepositoryContext)
+     * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
      */
     public void initialize( RepositoryContext context ) throws RepositorySourceException {
         this.repositoryContext = context;
@@ -177,7 +177,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getRetryLimit()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
      */
     public int getRetryLimit() {
         return retryLimit.get();
@@ -186,7 +186,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#setRetryLimit(int)
+     * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
      */
     public void setRetryLimit( int limit ) {
         retryLimit.set(limit < 0 ? 0 : limit);
@@ -418,7 +418,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getConnection()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
      */
     public RepositoryConnection getConnection() throws RepositorySourceException {
         if (getName() == null) {
@@ -710,7 +710,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getCapabilities()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
      */
     public RepositorySourceCapabilities getCapabilities() {
         return CAPABILITIES;

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -39,10 +39,10 @@
 import org.jboss.dna.common.util.HashCode;
 import org.jboss.dna.common.util.Logger;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
 
 /**
  * A projection of content from a source into the integrated/federated repository. Each project consists of a set of {@link Rule
@@ -624,7 +624,7 @@
         /**
          * {@inheritDoc}
          * 
-         * @see org.jboss.dna.connector.federation.Projection.Rule#getTopLevelPathsInRepository(org.jboss.dna.graph.properties.PathFactory)
+         * @see org.jboss.dna.connector.federation.Projection.Rule#getTopLevelPathsInRepository(org.jboss.dna.graph.property.PathFactory)
          */
         @Override
         public List<Path> getTopLevelPathsInRepository( PathFactory factory ) {
@@ -654,8 +654,8 @@
         /**
          * {@inheritDoc}
          * 
-         * @see org.jboss.dna.connector.federation.Projection.Rule#getPathInRepository(org.jboss.dna.graph.properties.Path,
-         *      org.jboss.dna.graph.properties.PathFactory)
+         * @see org.jboss.dna.connector.federation.Projection.Rule#getPathInRepository(org.jboss.dna.graph.property.Path,
+         *      org.jboss.dna.graph.property.PathFactory)
          */
         @Override
         public Path getPathInRepository( Path pathInSource,

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -32,7 +32,7 @@
 import org.jboss.dna.common.util.StringUtil;
 import org.jboss.dna.connector.federation.Projection.Rule;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.property.NamespaceRegistry;
 
 /**
  * A parser library for {@link Projection projections} and {@link Projection.Rule projection rules}.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -29,10 +29,10 @@
 import java.util.NoSuchElementException;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
 
 /**
  * The contribution of a source to the information for a single federated node. Users of this interface should treat contributions

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -23,7 +23,7 @@
 
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
+import org.jboss.dna.graph.property.DateTime;
 
 /**
  * A source contribution that is empty. In other words, the source has no contribution to make.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiChildContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiChildContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiChildContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -26,7 +26,7 @@
 import java.util.List;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
+import org.jboss.dna.graph.property.DateTime;
 
 /**
  * The contribution of a source to the information for a single federated node.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -26,9 +26,9 @@
 import java.util.Map;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
 
 /**
  * The record of a source contributing only properties to a node.
@@ -91,7 +91,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.graph.properties.Name)
+     * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.graph.property.Name)
      */
     @Override
     public Property getProperty( Name name ) {

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -26,8 +26,8 @@
 import java.util.List;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Property;
 
 /**
  * The contribution of a source to the information for a single federated node.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NonEmptyContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NonEmptyContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NonEmptyContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,7 +24,7 @@
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.common.util.HashCode;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
+import org.jboss.dna.graph.property.DateTime;
 
 /**
  * The record of a non-empty source contribution from a single location within the source.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OneChildContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OneChildContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OneChildContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,7 +24,7 @@
 import java.util.Iterator;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
+import org.jboss.dna.graph.property.DateTime;
 
 /**
  * The record of a source contributing only a single child to a node.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OnePropertyContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OnePropertyContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OnePropertyContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,9 +24,9 @@
 import java.util.Iterator;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
 
 /**
  * The record of a source contributing only properties to a node.
@@ -86,7 +86,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.graph.properties.Name)
+     * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.graph.property.Name)
      */
     @Override
     public Property getProperty( Name name ) {

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PlaceholderContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PlaceholderContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PlaceholderContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -23,7 +23,7 @@
 
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
+import org.jboss.dna.graph.property.DateTime;
 
 /**
  * A placeholder contribution needed because of a source's contribution below the specified children.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,9 +24,9 @@
 import java.util.Iterator;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
 
 /**
  * The record of a source contributing only properties to a node.
@@ -98,7 +98,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.graph.properties.Name)
+     * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.graph.property.Name)
      */
     @Override
     public Property getProperty( Name name ) {

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoChildContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoChildContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoChildContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,7 +24,7 @@
 import java.util.Iterator;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
+import org.jboss.dna.graph.property.DateTime;
 
 /**
  * The record of a source contributing only two children to a node.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContribution.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContribution.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContribution.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,9 +24,9 @@
 import java.util.Iterator;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
 
 /**
  * The record of a source contributing only properties to a node.
@@ -92,7 +92,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.graph.properties.Name)
+     * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.graph.property.Name)
      */
     @Override
     public Property getProperty( Name name ) {

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -49,27 +49,27 @@
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.NodeConflictBehavior;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.requests.CompositeRequest;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CompositeRequest;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * @author Randall Hauch
@@ -237,7 +237,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllChildrenRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
      */
     @Override
     public void process( ReadAllChildrenRequest request ) {
@@ -252,7 +252,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllPropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllPropertiesRequest)
      */
     @Override
     public void process( ReadAllPropertiesRequest request ) {
@@ -267,7 +267,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadNodeRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadNodeRequest)
      */
     @Override
     public void process( ReadNodeRequest request ) {
@@ -285,7 +285,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CopyBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CopyBranchRequest)
      */
     @Override
     public void process( CopyBranchRequest request ) {
@@ -295,7 +295,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CreateNodeRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CreateNodeRequest)
      */
     @Override
     public void process( CreateNodeRequest request ) {
@@ -305,7 +305,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.DeleteBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.DeleteBranchRequest)
      */
     @Override
     public void process( DeleteBranchRequest request ) {
@@ -315,7 +315,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.MoveBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.MoveBranchRequest)
      */
     @Override
     public void process( MoveBranchRequest request ) {
@@ -325,7 +325,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.UpdatePropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.UpdatePropertiesRequest)
      */
     @Override
     public void process( UpdatePropertiesRequest request ) {

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -27,26 +27,26 @@
 import org.jboss.dna.connector.federation.Projection;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * @author Randall Hauch
@@ -124,7 +124,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllChildrenRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
      */
     @Override
     public void process( ReadAllChildrenRequest request ) {
@@ -142,7 +142,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllPropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllPropertiesRequest)
      */
     @Override
     public void process( ReadAllPropertiesRequest request ) {
@@ -161,7 +161,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadNodeRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadNodeRequest)
      */
     @Override
     public void process( ReadNodeRequest request ) {
@@ -183,7 +183,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CreateNodeRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CreateNodeRequest)
      */
     @Override
     public void process( CreateNodeRequest request ) {
@@ -200,7 +200,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.UpdatePropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.UpdatePropertiesRequest)
      */
     @Override
     public void process( UpdatePropertiesRequest request ) {
@@ -216,7 +216,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.DeleteBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.DeleteBranchRequest)
      */
     @Override
     public void process( DeleteBranchRequest request ) {
@@ -232,7 +232,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.MoveBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.MoveBranchRequest)
      */
     @Override
     public void process( MoveBranchRequest request ) {
@@ -249,7 +249,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CopyBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CopyBranchRequest)
      */
     @Override
     public void process( CopyBranchRequest request ) {

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FederatedNode.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FederatedNode.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FederatedNode.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -23,7 +23,7 @@
 
 import java.util.UUID;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
 
 /**
  * An in-memory (and temporary) representation of a federated node and it's merged properties and children.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -38,9 +38,9 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.connector.federation.contribution.Contribution;
 import org.jboss.dna.connector.federation.contribution.EmptyContribution;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
 
 /**
  * This class represents the details about how information from different sources are merged into a single federated node.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -31,10 +31,10 @@
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.ValueFormatException;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.ValueFormatException;
 
 /**
  * A merge strategy that is optimized for merging when there is a single contribution.

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -34,12 +34,12 @@
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueComparators;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.ValueComparators;
 
 /**
  * This merge strategy simply merges all of the contributions' properties and combines the children according to the order of the

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -30,9 +30,9 @@
 import static org.mockito.Mockito.verify;
 import java.util.concurrent.TimeUnit;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.requests.Request;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.request.Request;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceIntegrationTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceIntegrationTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceIntegrationTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -40,17 +40,17 @@
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.ExecutionContextFactory;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.SimpleRepository;
-import org.jboss.dna.graph.connectors.SimpleRepositorySource;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.SimpleRepository;
+import org.jboss.dna.graph.connector.SimpleRepositorySource;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.ReadNodeRequest;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentMatcher;

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -43,12 +43,12 @@
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.ExecutionContextFactory;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.SimpleRepository;
-import org.jboss.dna.graph.connectors.SimpleRepositorySource;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.SimpleRepository;
+import org.jboss.dna.graph.connector.SimpleRepositorySource;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,8 +28,8 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.matchers.JUnitMatchers.hasItems;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -29,9 +29,9 @@
 import org.jboss.dna.common.text.TextEncoder;
 import org.jboss.dna.common.text.UrlEncoder;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -29,8 +29,8 @@
 import static org.mockito.Mockito.stub;
 import java.util.Set;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/EmptyContributionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/EmptyContributionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/EmptyContributionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -26,9 +26,9 @@
 import static org.hamcrest.core.IsSame.sameInstance;
 import static org.junit.Assert.assertThat;
 import static org.mockito.Mockito.mock;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiChildContributionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiChildContributionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiChildContributionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -31,11 +31,11 @@
 import java.util.Iterator;
 import java.util.List;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.RootPath;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.RootPath;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContributionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContributionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContributionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -32,13 +32,13 @@
 import java.util.Iterator;
 import java.util.List;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.RootPath;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.RootPath;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/NodeContributionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/NodeContributionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/NodeContributionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -33,13 +33,13 @@
 import java.util.Iterator;
 import java.util.List;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.RootPath;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.RootPath;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OneChildContributionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OneChildContributionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OneChildContributionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,11 +28,11 @@
 import static org.mockito.Mockito.mock;
 import java.util.Iterator;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.RootPath;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.RootPath;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OnePropertyContributionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OnePropertyContributionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OnePropertyContributionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -30,13 +30,13 @@
 import java.util.Iterator;
 import java.util.List;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.RootPath;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.RootPath;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContributionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContributionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContributionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -30,13 +30,13 @@
 import java.util.Iterator;
 import java.util.List;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.RootPath;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.RootPath;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoChildContributionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoChildContributionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoChildContributionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,11 +28,11 @@
 import static org.mockito.Mockito.mock;
 import java.util.Iterator;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.RootPath;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.RootPath;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContributionTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContributionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContributionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -30,13 +30,13 @@
 import java.util.Iterator;
 import java.util.List;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-import org.jboss.dna.graph.properties.basic.RootPath;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+import org.jboss.dna.graph.property.basic.RootPath;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutorTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutorTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutorTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -45,13 +45,13 @@
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.cache.BasicCachePolicy;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.SimpleRepository;
-import org.jboss.dna.graph.connectors.SimpleRepositorySource;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.SimpleRepository;
+import org.jboss.dna.graph.connector.SimpleRepositorySource;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/FederatedNodeTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/FederatedNodeTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/FederatedNodeTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,7 +28,7 @@
 import static org.mockito.Mockito.mock;
 import java.util.UUID;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.property.Path;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/MergePlanTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/MergePlanTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/MergePlanTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -38,12 +38,12 @@
 import java.util.List;
 import java.util.Map;
 import org.jboss.dna.connector.federation.contribution.Contribution;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.basic.BasicEmptyProperty;
-import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicEmptyProperty;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -37,9 +37,9 @@
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -41,9 +41,9 @@
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;

Modified: trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemConnection.java
===================================================================
--- trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemConnection.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemConnection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -29,11 +29,11 @@
 import javax.transaction.xa.XAResource;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * The {@link RepositoryConnection} implementation for the file system connector. The bulk of the work is performed by the
@@ -69,7 +69,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#getSourceName()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#getSourceName()
      */
     public String getSourceName() {
         return sourceName;
@@ -78,7 +78,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#getDefaultCachePolicy()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#getDefaultCachePolicy()
      */
     public CachePolicy getDefaultCachePolicy() {
         return cachePolicy;
@@ -87,7 +87,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#getXAResource()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#getXAResource()
      */
     public XAResource getXAResource() {
         return null;
@@ -96,7 +96,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#setListener(org.jboss.dna.graph.connectors.RepositorySourceListener)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#setListener(org.jboss.dna.graph.connector.RepositorySourceListener)
      */
     public void setListener( RepositorySourceListener listener ) {
         if (listener != null) {
@@ -107,7 +107,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#ping(long, java.util.concurrent.TimeUnit)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#ping(long, java.util.concurrent.TimeUnit)
      */
     public boolean ping( long time,
                          TimeUnit unit ) {
@@ -117,8 +117,8 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-     *      org.jboss.dna.graph.requests.Request)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+     *      org.jboss.dna.graph.request.Request)
      */
     public void execute( ExecutionContext context,
                          Request request ) throws RepositorySourceException {
@@ -133,7 +133,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#close()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#close()
      */
     public void close() {
     }

Modified: trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -33,27 +33,27 @@
 import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.JcrNtLexicon;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceException;
 import org.jboss.dna.graph.mimetype.MimeTypeDetector;
-import org.jboss.dna.graph.properties.BinaryFactory;
-import org.jboss.dna.graph.properties.DateTimeFactory;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.RemovePropertiesRequest;
-import org.jboss.dna.graph.requests.RenameNodeRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.property.BinaryFactory;
+import org.jboss.dna.graph.property.DateTimeFactory;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.RemovePropertiesRequest;
+import org.jboss.dna.graph.request.RenameNodeRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * The {@link RequestProcessor} implementation for the file systme connector. This is the class that does the bulk of the work in
@@ -97,7 +97,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllChildrenRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
      */
     @Override
     public void process( ReadAllChildrenRequest request ) {
@@ -140,7 +140,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllPropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllPropertiesRequest)
      */
     @Override
     public void process( ReadAllPropertiesRequest request ) {
@@ -212,7 +212,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CreateNodeRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CreateNodeRequest)
      */
     @Override
     public void process( CreateNodeRequest request ) {
@@ -222,7 +222,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.UpdatePropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.UpdatePropertiesRequest)
      */
     @Override
     public void process( UpdatePropertiesRequest request ) {
@@ -232,7 +232,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CopyBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CopyBranchRequest)
      */
     @Override
     public void process( CopyBranchRequest request ) {
@@ -242,7 +242,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.DeleteBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.DeleteBranchRequest)
      */
     @Override
     public void process( DeleteBranchRequest request ) {
@@ -252,7 +252,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.MoveBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.MoveBranchRequest)
      */
     @Override
     public void process( MoveBranchRequest request ) {
@@ -262,7 +262,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.RemovePropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RemovePropertiesRequest)
      */
     @Override
     public void process( RemovePropertiesRequest request ) {
@@ -273,7 +273,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.RenameNodeRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RenameNodeRequest)
      */
     @Override
     public void process( RenameNodeRequest request ) {

Modified: trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java
===================================================================
--- trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -41,11 +41,11 @@
 import org.jboss.dna.common.i18n.I18n;
 import org.jboss.dna.common.util.StringUtil;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceCapabilities;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
+import org.jboss.dna.graph.connector.RepositorySourceException;
 
 /**
  * The {@link RepositorySource} for the connector that exposes an area of the local file system as content in a repository.
@@ -97,7 +97,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getCapabilities()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
      */
     public RepositorySourceCapabilities getCapabilities() {
         return capabilities;
@@ -106,7 +106,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getName()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getName()
      */
     public String getName() {
         return name;
@@ -169,7 +169,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getRetryLimit()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
      */
     public int getRetryLimit() {
         return retryLimit;
@@ -178,7 +178,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#setRetryLimit(int)
+     * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
      */
     public synchronized void setRetryLimit( int limit ) {
         if (limit < 0) limit = 0;
@@ -209,7 +209,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#initialize(org.jboss.dna.graph.connectors.RepositoryContext)
+     * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
      */
     public void initialize( RepositoryContext context ) throws RepositorySourceException {
         // No need to do anything
@@ -280,7 +280,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getConnection()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
      */
     public synchronized RepositoryConnection getConnection() throws RepositorySourceException {
         String sourceName = getName();

Modified: trunk/extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorReadingTest.java
===================================================================
--- trunk/extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorReadingTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorReadingTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -33,9 +33,9 @@
 import org.jboss.dna.graph.JcrNtLexicon;
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.Node;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.test.ReadableConnectorTest;
-import org.jboss.dna.graph.properties.PathNotFoundException;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.test.ReadableConnectorTest;
+import org.jboss.dna.graph.property.PathNotFoundException;
 import org.junit.Test;
 
 /**
@@ -48,7 +48,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.test.AbstractConnectorTest#setUpSource()
+     * @see org.jboss.dna.graph.connector.test.AbstractConnectorTest#setUpSource()
      */
     @Override
     protected RepositorySource setUpSource() throws IOException {
@@ -71,7 +71,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.test.AbstractConnectorTest#initializeContent(org.jboss.dna.graph.Graph)
+     * @see org.jboss.dna.graph.connector.test.AbstractConnectorTest#initializeContent(org.jboss.dna.graph.Graph)
      */
     @Override
     protected void initializeContent( Graph graph ) {

Modified: trunk/extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemSourceTest.java
===================================================================
--- trunk/extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemSourceTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemSourceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -27,8 +27,8 @@
 import static org.junit.Assert.assertThat;
 import java.util.ArrayList;
 import java.util.List;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
===================================================================
--- trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -34,23 +34,23 @@
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.Path.Segment;
-import org.jboss.dna.graph.properties.basic.RootPath;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.Path.Segment;
+import org.jboss.dna.graph.property.basic.RootPath;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * @author Randall Hauch

Modified: trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java
===================================================================
--- trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,15 +24,15 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Lock;
 import javax.transaction.xa.XAResource;
-import org.jboss.dna.common.stats.Stopwatch;
+import org.jboss.dna.common.statistic.Stopwatch;
 import org.jboss.dna.common.util.Logger;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * @author Randall Hauch
@@ -109,8 +109,8 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-     *      org.jboss.dna.graph.requests.Request)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+     *      org.jboss.dna.graph.request.Request)
      */
     public void execute( ExecutionContext context,
                          Request request ) throws RepositorySourceException {

Modified: trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositorySource.java
===================================================================
--- trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositorySource.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -44,11 +44,11 @@
 import org.jboss.dna.common.i18n.I18n;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceCapabilities;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
+import org.jboss.dna.graph.connector.RepositorySourceException;
 
 /**
  * @author Randall Hauch
@@ -93,7 +93,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#initialize(org.jboss.dna.graph.connectors.RepositoryContext)
+     * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
      */
     public void initialize( RepositoryContext context ) throws RepositorySourceException {
         this.repositoryContext = context;
@@ -109,7 +109,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getRetryLimit()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
      */
     public int getRetryLimit() {
         return retryLimit.get();
@@ -118,7 +118,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#setRetryLimit(int)
+     * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
      */
     public void setRetryLimit( int limit ) {
         retryLimit.set(limit < 0 ? 0 : limit);
@@ -220,7 +220,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getConnection()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
      */
     public RepositoryConnection getConnection() throws RepositorySourceException {
         if (repository == null) {
@@ -314,7 +314,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getCapabilities()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
      */
     public RepositorySourceCapabilities getCapabilities() {
         return CAPABILITIES;

Modified: trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/Node.java
===================================================================
--- trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/Node.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/Node.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,10 +28,10 @@
 import java.util.UUID;
 import net.jcip.annotations.NotThreadSafe;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
 
 /**
  * @author Randall Hauch

Modified: trunk/extensions/dna-connector-inmemory/src/test/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryTest.java
===================================================================
--- trunk/extensions/dna-connector-inmemory/src/test/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-inmemory/src/test/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -33,16 +33,16 @@
 import java.util.Set;
 import java.util.UUID;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
-import org.jboss.dna.graph.properties.basic.BasicPropertyFactory;
-import org.jboss.dna.graph.properties.basic.StandardValueFactories;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.BasicPropertyFactory;
+import org.jboss.dna.graph.property.basic.StandardValueFactories;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;

Modified: trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java
===================================================================
--- trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -39,26 +39,26 @@
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.Path.Segment;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.Path.Segment;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * The repository connection to a JBoss Cache instance.
@@ -144,8 +144,8 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-     *      org.jboss.dna.graph.requests.Request)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+     *      org.jboss.dna.graph.request.Request)
      */
     public void execute( final ExecutionContext context,
                          final Request request ) throws RepositorySourceException {

Modified: trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheLexicon.java
===================================================================
--- trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheLexicon.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheLexicon.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.connector.jbosscache;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
 
 /**
  * The namespace and property names used within a {@link JBossCacheSource} to store internal information.

Modified: trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java
===================================================================
--- trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -47,13 +47,13 @@
 import org.jboss.dna.common.i18n.I18n;
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceCapabilities;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
 
 /**
  * A repository source that uses a JBoss Cache instance to manage the content. This source is capable of using an existing
@@ -114,7 +114,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#initialize(org.jboss.dna.graph.connectors.RepositoryContext)
+     * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
      */
     public void initialize( RepositoryContext context ) throws RepositorySourceException {
         this.repositoryContext = context;
@@ -137,7 +137,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getRetryLimit()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
      */
     public int getRetryLimit() {
         return retryLimit.get();
@@ -146,7 +146,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#setRetryLimit(int)
+     * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
      */
     public void setRetryLimit( int limit ) {
         retryLimit.set(limit < 0 ? 0 : limit);
@@ -362,7 +362,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getConnection()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
      */
     @SuppressWarnings( "unchecked" )
     public RepositoryConnection getConnection() throws RepositorySourceException {
@@ -550,7 +550,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getCapabilities()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
      */
     public RepositorySourceCapabilities getCapabilities() {
         return CAPABILITIES;

Modified: trunk/extensions/dna-connector-jbosscache/src/main/resources/org/jboss/dna/connector/jbosscache/JBossCacheConnectorI18n.properties
===================================================================
--- trunk/extensions/dna-connector-jbosscache/src/main/resources/org/jboss/dna/connector/jbosscache/JBossCacheConnectorI18n.properties	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jbosscache/src/main/resources/org/jboss/dna/connector/jbosscache/JBossCacheConnectorI18n.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,5 +24,5 @@
 nodeDoesNotExist = Could not find an existing node at {0}
 propertyIsRequired = The {0} property is required but has no value
 errorSerializingCachePolicyInSource = Error serializing a {0} instance owned by the {1} JBossCacheSource
-objectFoundInJndiWasNotCache = Object in JNDI at {0} found by JBossCacheSource {1} was expected to be a org.jboss.cache.Cache<org.jboss.dna.graph.properties.Name,Object> but instead was {2}
-objectFoundInJndiWasNotCacheFactory = Object in JNDI at {0} found by JBossCacheSource {1} was expected to be a org.jboss.cache.CacheFactory<org.jboss.dna.graph.properties.Name,Object> but instead was {2}
\ No newline at end of file
+objectFoundInJndiWasNotCache = Object in JNDI at {0} found by JBossCacheSource {1} was expected to be a org.jboss.cache.Cache<org.jboss.dna.graph.property.Name,Object> but instead was {2}
+objectFoundInJndiWasNotCacheFactory = Object in JNDI at {0} found by JBossCacheSource {1} was expected to be a org.jboss.cache.CacheFactory<org.jboss.dna.graph.property.Name,Object> but instead was {2}
\ No newline at end of file

Modified: trunk/extensions/dna-connector-jbosscache/src/test/java/org/jboss/dna/connector/jbosscache/JBossCacheConnectionTest.java
===================================================================
--- trunk/extensions/dna-connector-jbosscache/src/test/java/org/jboss/dna/connector/jbosscache/JBossCacheConnectionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jbosscache/src/test/java/org/jboss/dna/connector/jbosscache/JBossCacheConnectionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -44,15 +44,15 @@
 import org.jboss.dna.graph.Graph;
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;

Modified: trunk/extensions/dna-connector-jbosscache/src/test/java/org/jboss/dna/connector/jbosscache/JBossCacheSourceTest.java
===================================================================
--- trunk/extensions/dna-connector-jbosscache/src/test/java/org/jboss/dna/connector/jbosscache/JBossCacheSourceTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jbosscache/src/test/java/org/jboss/dna/connector/jbosscache/JBossCacheSourceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -41,7 +41,7 @@
 import org.jboss.cache.Cache;
 import org.jboss.cache.CacheFactory;
 import org.jboss.dna.graph.cache.BasicCachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnection;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcConnection.java
===================================================================
--- trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcConnection.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcConnection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -32,11 +32,11 @@
 import org.jboss.dna.common.util.Logger;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * JDBC connection wrapper
@@ -71,7 +71,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#getSourceName()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#getSourceName()
      */
     public String getSourceName() {
         return name;
@@ -80,7 +80,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#setListener(org.jboss.dna.graph.connectors.RepositorySourceListener)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#setListener(org.jboss.dna.graph.connector.RepositorySourceListener)
      */
     public void setListener( RepositorySourceListener listener ) {
         if (listener != null) {
@@ -91,7 +91,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#getDefaultCachePolicy()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#getDefaultCachePolicy()
      */
     public CachePolicy getDefaultCachePolicy() {
         return cachePolicy;
@@ -100,7 +100,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#getXAResource()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#getXAResource()
      */
     public XAResource getXAResource() {
         // if implemented by JDBC driver
@@ -120,7 +120,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#ping(long, java.util.concurrent.TimeUnit)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#ping(long, java.util.concurrent.TimeUnit)
      */
     public boolean ping( long time,
                          TimeUnit unit ) {
@@ -140,8 +140,8 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-     *      org.jboss.dna.graph.requests.Request)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+     *      org.jboss.dna.graph.request.Request)
      */
     public void execute( ExecutionContext context,
                          Request request ) throws RepositorySourceException {
@@ -157,7 +157,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#close()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#close()
      */
     public void close() {
         try {

Modified: trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositoryLexicon.java
===================================================================
--- trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositoryLexicon.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositoryLexicon.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.connector.jdbc;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
 
 
 /**

Modified: trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositorySource.java
===================================================================
--- trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositorySource.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -48,11 +48,11 @@
 import org.jboss.dna.common.jdbc.provider.DefaultDriverDatabaseMetadataProvider;
 import org.jboss.dna.common.jdbc.provider.DriverDatabaseMetadataProvider;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceCapabilities;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
+import org.jboss.dna.graph.connector.RepositorySourceException;
 
 /**
  * A description of a JDBC resource that can be used to access database information.
@@ -140,7 +140,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getCapabilities()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
      */
     public RepositorySourceCapabilities getCapabilities() {
         return capabilities;
@@ -149,7 +149,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getConnection()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
      */
     public RepositoryConnection getConnection() throws RepositorySourceException {
         String errMsg = null;
@@ -195,7 +195,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getName()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getName()
      */
     public String getName() {
         return name;
@@ -213,7 +213,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getRetryLimit()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
      */
     public int getRetryLimit() {
         return retryLimit.get();
@@ -222,7 +222,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#initialize(org.jboss.dna.graph.connectors.RepositoryContext)
+     * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
      */
     public void initialize( RepositoryContext context ) throws RepositorySourceException {
         this.repositoryContext = context;
@@ -231,7 +231,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#setRetryLimit(int)
+     * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
      */
     public void setRetryLimit( int limit ) {
         retryLimit.set(limit < 0 ? 0 : limit);

Modified: trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRequestProcesor.java
===================================================================
--- trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRequestProcesor.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRequestProcesor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,15 +24,15 @@
 import java.sql.Connection;
 import org.jboss.dna.common.util.Logger;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * JDBC request processor
@@ -77,7 +77,7 @@
     /**
      * {@inheritDoc}
      *
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CopyBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CopyBranchRequest)
      */
     @Override
     public void process( CopyBranchRequest request ) {
@@ -86,7 +86,7 @@
     /**
      * {@inheritDoc}
      *
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CreateNodeRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CreateNodeRequest)
      */
     @Override
     public void process( CreateNodeRequest request ) {
@@ -95,7 +95,7 @@
     /**
      * {@inheritDoc}
      *
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.DeleteBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.DeleteBranchRequest)
      */
     @Override
     public void process( DeleteBranchRequest request ) {
@@ -104,7 +104,7 @@
     /**
      * {@inheritDoc}
      *
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.MoveBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.MoveBranchRequest)
      */
     @Override
     public void process( MoveBranchRequest request ) {
@@ -113,7 +113,7 @@
     /**
      * {@inheritDoc}
      *
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllChildrenRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
      */
     @Override
     public void process( ReadAllChildrenRequest request ) {
@@ -122,7 +122,7 @@
     /**
      * {@inheritDoc}
      *
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllPropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllPropertiesRequest)
      */
     @Override
     public void process( ReadAllPropertiesRequest request ) {
@@ -131,7 +131,7 @@
     /**
      * {@inheritDoc}
      *
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.UpdatePropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.UpdatePropertiesRequest)
      */
     @Override
     public void process( UpdatePropertiesRequest request ) {

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnection.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnection.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,11 +28,11 @@
 import javax.transaction.xa.XAResource;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * @author Randall Hauch
@@ -74,7 +74,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#getSourceName()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#getSourceName()
      */
     public String getSourceName() {
         return name;
@@ -83,7 +83,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#setListener(org.jboss.dna.graph.connectors.RepositorySourceListener)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#setListener(org.jboss.dna.graph.connector.RepositorySourceListener)
      */
     public void setListener( RepositorySourceListener listener ) {
         if (listener != null) {
@@ -94,7 +94,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#getDefaultCachePolicy()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#getDefaultCachePolicy()
      */
     public CachePolicy getDefaultCachePolicy() {
         return cachePolicy;
@@ -103,7 +103,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#getXAResource()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#getXAResource()
      */
     public XAResource getXAResource() {
         return null;
@@ -112,7 +112,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#ping(long, java.util.concurrent.TimeUnit)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#ping(long, java.util.concurrent.TimeUnit)
      */
     public boolean ping( long time,
                          TimeUnit unit ) {
@@ -122,8 +122,8 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-     *      org.jboss.dna.graph.requests.Request)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+     *      org.jboss.dna.graph.request.Request)
      */
     public void execute( ExecutionContext context,
                          Request request ) throws RepositorySourceException {
@@ -145,7 +145,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#close()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#close()
      */
     public void close() {
     }

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -47,16 +47,16 @@
 import org.jboss.dna.common.i18n.I18n;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.connector.store.jpa.models.basic.BasicModel;
+import org.jboss.dna.connector.store.jpa.model.basic.BasicModel;
 import org.jboss.dna.connector.store.jpa.util.StoreOptionEntity;
 import org.jboss.dna.connector.store.jpa.util.StoreOptions;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceCapabilities;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
+import org.jboss.dna.graph.connector.RepositorySourceException;
 
 /**
  * The {@link RepositorySource} for the connector that stores content in a (custom) relational database. This connector uses Java
@@ -188,7 +188,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getName()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getName()
      */
     public String getName() {
         return name;
@@ -210,7 +210,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getCapabilities()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
      */
     public RepositorySourceCapabilities getCapabilities() {
         return capabilities;
@@ -238,7 +238,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getRetryLimit()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
      */
     public int getRetryLimit() {
         return retryLimit;
@@ -247,7 +247,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#setRetryLimit(int)
+     * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
      */
     public synchronized void setRetryLimit( int limit ) {
         if (limit < 0) limit = 0;
@@ -596,7 +596,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#initialize(org.jboss.dna.graph.connectors.RepositoryContext)
+     * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
      */
     public void initialize( RepositoryContext context ) throws RepositorySourceException {
         this.repositoryContext = context;
@@ -731,7 +731,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getConnection()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
      */
     public synchronized RepositoryConnection getConnection() throws RepositorySourceException {
         if (this.name == null || this.name.trim().length() == 0) {

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/Model.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/Model.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/Model.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,7 +28,7 @@
 import org.jboss.dna.common.i18n.I18n;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 
 /**
  * A descriptor of a schema used by this connector.

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic (from rev 705, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic)

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModel.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModel.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModel.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,143 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.util.UUID;
-import javax.persistence.EntityManager;
-import org.hibernate.ejb.Ejb3Configuration;
-import org.jboss.dna.connector.store.jpa.JpaConnectorI18n;
-import org.jboss.dna.connector.store.jpa.Model;
-import org.jboss.dna.connector.store.jpa.models.common.ChangeLogEntity;
-import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadBranchRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
-
-/**
- * Database model that stores node properties as opaque records and children as transparent records. Large property values are
- * stored separately.
- * <p>
- * The set of tables used in this model includes:
- * <ul>
- * <li>Namespaces - the set of namespace URIs used in paths, property names, and property values.</li>
- * <li>Properties - the properties for each node, stored in a serialized (and optionally compressed) form.</li>
- * <li>Large values - property values larger than a certain size will be broken out into this table, where they are tracked by
- * their SHA-1 has and shared by all properties that have that same value. The values are stored in a binary (and optionally
- * compressed) form.</li>
- * <li>Children - the children for each node, where each child is represented by a separate record. This approach makes it
- * possible to efficiently work with nodes containing large numbers of children, where adding and removing child nodes is largely
- * independent of the number of children. Also, working with properties is also completely independent of the number of child
- * nodes.</li>
- * <li>ReferenceChanges - the references from one node to another</li>
- * <li>Subgraph - a working area for efficiently computing the space of a subgraph; see below</li>
- * <li>Change log - a record of the changes that have been made to the repository. This is used to distribute change events across
- * multiple distributed processes, and to allow a recently-connected client to identify the set of changes that have been made
- * since a particular time or date. Changes are serialized into a binary, compressed format.</i></li>
- * <li>Options - the parameters for this store's configuration (common to all models)</li>
- * </ul>
- * </p>
- * <h3>Subgraph queries</h3>
- * <p>
- * This database model contains two tables that are used in an efficient mechanism to find all of the nodes in the subgraph below
- * a certain node. This process starts by creating a record for the subgraph query, and then proceeds by executing a join to find
- * all the children of the top-level node, and inserting them into the database (in a working area associated with the subgraph
- * query). Then, another join finds all the children of those children and inserts them into the same working area. This continues
- * until the maximum depth has been reached, or until there are no more children (whichever comes first). All of the nodes in the
- * subgraph are then represented by records in the working area, and can be used to quickly and efficient work with the subgraph
- * nodes. When finished, the mechanism deletes the records in the working area associated with the subgraph query.
- * </p>
- * <p>
- * This subgraph query mechanism is extremely efficient, performing one join/insert statement <i>per level of the subgraph</i>,
- * and is completely independent of the number of nodes in the subgraph. For example, consider a subgraph of node A, where A has
- * 10 children, and each child contains 10 children, and each grandchild contains 10 children. This subgraph has a total of 1111
- * nodes (1 root + 10 children + 10*10 grandchildren + 10*10*10 great-grandchildren). Finding the nodes in this subgraph would
- * normally require 1 query per node (in other words, 1111 queries). But with this subgraph query mechanism, all of the nodes in
- * the subgraph can be found with 1 insert plus 4 additional join/inserts.
- * </p>
- * <p>
- * This mechanism has the added benefit that the set of nodes in the subgraph are kept in a working area in the database, meaning
- * they don't have to be pulled into memory.
- * </p>
- * <p>
- * Subgraph queries are used to efficiently process a number of different requests, including {@link ReadBranchRequest},
- * {@link DeleteBranchRequest}, {@link MoveBranchRequest}, and {@link CopyBranchRequest}. Processing each of these kinds of
- * requests requires knowledge of the subgraph, and in fact all but the <code>ReadBranchRequest</code> need to know the complete
- * subgraph.
- * </p>
- * 
- * @author Randall Hauch
- */
-public class BasicModel extends Model {
-
-    public BasicModel() {
-        super("Basic", JpaConnectorI18n.basicModelDescription);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.connector.store.jpa.Model#createRequestProcessor(java.lang.String, org.jboss.dna.graph.ExecutionContext,
-     *      javax.persistence.EntityManager, java.util.UUID, long, boolean, boolean)
-     */
-    @Override
-    public RequestProcessor createRequestProcessor( String sourceName,
-                                                    ExecutionContext context,
-                                                    EntityManager entityManager,
-                                                    UUID rootNodeUuid,
-                                                    long largeValueMinimumSizeInBytes,
-                                                    boolean compressData,
-                                                    boolean enforceReferentialIntegrity ) {
-        return new BasicRequestProcessor(sourceName, context, entityManager, rootNodeUuid, largeValueMinimumSizeInBytes,
-                                         compressData, enforceReferentialIntegrity);
-    }
-
-    /**
-     * Configure the entity class that will be used by JPA to store information in the database.
-     * 
-     * @param configurator the Hibernate {@link Ejb3Configuration} component; never null
-     */
-    @Override
-    public void configure( Ejb3Configuration configurator ) {
-        // Add the annotated classes ...
-        configurator.addAnnotatedClass(NamespaceEntity.class);
-        configurator.addAnnotatedClass(NodeId.class);
-        configurator.addAnnotatedClass(PropertiesEntity.class);
-        configurator.addAnnotatedClass(LargeValueEntity.class);
-        configurator.addAnnotatedClass(LargeValueId.class);
-        configurator.addAnnotatedClass(ChildEntity.class);
-        configurator.addAnnotatedClass(ChildId.class);
-        configurator.addAnnotatedClass(ReferenceEntity.class);
-        configurator.addAnnotatedClass(ReferenceId.class);
-        configurator.addAnnotatedClass(SubgraphQueryEntity.class);
-        configurator.addAnnotatedClass(SubgraphNodeEntity.class);
-        configurator.addAnnotatedClass(ChangeLogEntity.class);
-
-        // Set the cache information for each persistent class ...
-        // configurator.setProperty("hibernate.ejb.classcache." + KidpackNode.class.getName(), "read-write");
-        // configurator.setProperty("hibernate.ejb.collectioncache" + KidpackNode.class.getName() + ".distributors",
-        // "read-write, RegionName");
-    }
-
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModel.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModel.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModel.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModel.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,143 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.util.UUID;
+import javax.persistence.EntityManager;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.jboss.dna.connector.store.jpa.JpaConnectorI18n;
+import org.jboss.dna.connector.store.jpa.Model;
+import org.jboss.dna.connector.store.jpa.model.common.ChangeLogEntity;
+import org.jboss.dna.connector.store.jpa.model.common.NamespaceEntity;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadBranchRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
+
+/**
+ * Database model that stores node properties as opaque records and children as transparent records. Large property values are
+ * stored separately.
+ * <p>
+ * The set of tables used in this model includes:
+ * <ul>
+ * <li>Namespaces - the set of namespace URIs used in paths, property names, and property values.</li>
+ * <li>Properties - the properties for each node, stored in a serialized (and optionally compressed) form.</li>
+ * <li>Large values - property values larger than a certain size will be broken out into this table, where they are tracked by
+ * their SHA-1 has and shared by all properties that have that same value. The values are stored in a binary (and optionally
+ * compressed) form.</li>
+ * <li>Children - the children for each node, where each child is represented by a separate record. This approach makes it
+ * possible to efficiently work with nodes containing large numbers of children, where adding and removing child nodes is largely
+ * independent of the number of children. Also, working with properties is also completely independent of the number of child
+ * nodes.</li>
+ * <li>ReferenceChanges - the references from one node to another</li>
+ * <li>Subgraph - a working area for efficiently computing the space of a subgraph; see below</li>
+ * <li>Change log - a record of the changes that have been made to the repository. This is used to distribute change events across
+ * multiple distributed processes, and to allow a recently-connected client to identify the set of changes that have been made
+ * since a particular time or date. Changes are serialized into a binary, compressed format.</i></li>
+ * <li>Options - the parameters for this store's configuration (common to all models)</li>
+ * </ul>
+ * </p>
+ * <h3>Subgraph queries</h3>
+ * <p>
+ * This database model contains two tables that are used in an efficient mechanism to find all of the nodes in the subgraph below
+ * a certain node. This process starts by creating a record for the subgraph query, and then proceeds by executing a join to find
+ * all the children of the top-level node, and inserting them into the database (in a working area associated with the subgraph
+ * query). Then, another join finds all the children of those children and inserts them into the same working area. This continues
+ * until the maximum depth has been reached, or until there are no more children (whichever comes first). All of the nodes in the
+ * subgraph are then represented by records in the working area, and can be used to quickly and efficient work with the subgraph
+ * nodes. When finished, the mechanism deletes the records in the working area associated with the subgraph query.
+ * </p>
+ * <p>
+ * This subgraph query mechanism is extremely efficient, performing one join/insert statement <i>per level of the subgraph</i>,
+ * and is completely independent of the number of nodes in the subgraph. For example, consider a subgraph of node A, where A has
+ * 10 children, and each child contains 10 children, and each grandchild contains 10 children. This subgraph has a total of 1111
+ * nodes (1 root + 10 children + 10*10 grandchildren + 10*10*10 great-grandchildren). Finding the nodes in this subgraph would
+ * normally require 1 query per node (in other words, 1111 queries). But with this subgraph query mechanism, all of the nodes in
+ * the subgraph can be found with 1 insert plus 4 additional join/inserts.
+ * </p>
+ * <p>
+ * This mechanism has the added benefit that the set of nodes in the subgraph are kept in a working area in the database, meaning
+ * they don't have to be pulled into memory.
+ * </p>
+ * <p>
+ * Subgraph queries are used to efficiently process a number of different requests, including {@link ReadBranchRequest},
+ * {@link DeleteBranchRequest}, {@link MoveBranchRequest}, and {@link CopyBranchRequest}. Processing each of these kinds of
+ * requests requires knowledge of the subgraph, and in fact all but the <code>ReadBranchRequest</code> need to know the complete
+ * subgraph.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+public class BasicModel extends Model {
+
+    public BasicModel() {
+        super("Basic", JpaConnectorI18n.basicModelDescription);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.connector.store.jpa.Model#createRequestProcessor(java.lang.String, org.jboss.dna.graph.ExecutionContext,
+     *      javax.persistence.EntityManager, java.util.UUID, long, boolean, boolean)
+     */
+    @Override
+    public RequestProcessor createRequestProcessor( String sourceName,
+                                                    ExecutionContext context,
+                                                    EntityManager entityManager,
+                                                    UUID rootNodeUuid,
+                                                    long largeValueMinimumSizeInBytes,
+                                                    boolean compressData,
+                                                    boolean enforceReferentialIntegrity ) {
+        return new BasicRequestProcessor(sourceName, context, entityManager, rootNodeUuid, largeValueMinimumSizeInBytes,
+                                         compressData, enforceReferentialIntegrity);
+    }
+
+    /**
+     * Configure the entity class that will be used by JPA to store information in the database.
+     * 
+     * @param configurator the Hibernate {@link Ejb3Configuration} component; never null
+     */
+    @Override
+    public void configure( Ejb3Configuration configurator ) {
+        // Add the annotated classes ...
+        configurator.addAnnotatedClass(NamespaceEntity.class);
+        configurator.addAnnotatedClass(NodeId.class);
+        configurator.addAnnotatedClass(PropertiesEntity.class);
+        configurator.addAnnotatedClass(LargeValueEntity.class);
+        configurator.addAnnotatedClass(LargeValueId.class);
+        configurator.addAnnotatedClass(ChildEntity.class);
+        configurator.addAnnotatedClass(ChildId.class);
+        configurator.addAnnotatedClass(ReferenceEntity.class);
+        configurator.addAnnotatedClass(ReferenceId.class);
+        configurator.addAnnotatedClass(SubgraphQueryEntity.class);
+        configurator.addAnnotatedClass(SubgraphNodeEntity.class);
+        configurator.addAnnotatedClass(ChangeLogEntity.class);
+
+        // Set the cache information for each persistent class ...
+        // configurator.setProperty("hibernate.ejb.classcache." + KidpackNode.class.getName(), "read-write");
+        // configurator.setProperty("hibernate.ejb.collectioncache" + KidpackNode.class.getName() + ".distributors",
+        // "read-write, RegionName");
+    }
+
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicRequestProcessor.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,1845 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityTransaction;
-import javax.persistence.NoResultException;
-import javax.persistence.Query;
-import net.jcip.annotations.Immutable;
-import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.common.util.IoUtil;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.common.util.StringUtil;
-import org.jboss.dna.connector.store.jpa.JpaConnectorI18n;
-import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
-import org.jboss.dna.connector.store.jpa.util.Namespaces;
-import org.jboss.dna.connector.store.jpa.util.RequestProcessorCache;
-import org.jboss.dna.connector.store.jpa.util.Serializer;
-import org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.JcrLexicon;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ReferentialIntegrityException;
-import org.jboss.dna.graph.properties.UuidFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.InvalidRequestException;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadBranchRequest;
-import org.jboss.dna.graph.requests.ReadNextBlockOfChildrenRequest;
-import org.jboss.dna.graph.requests.ReadNodeRequest;
-import org.jboss.dna.graph.requests.ReadPropertyRequest;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
-
-/**
- * @author Randall Hauch
- */
- at NotThreadSafe
-public class BasicRequestProcessor extends RequestProcessor {
-
-    protected final EntityManager entities;
-    protected final ValueFactory<String> stringFactory;
-    protected final PathFactory pathFactory;
-    protected final NameFactory nameFactory;
-    protected final UuidFactory uuidFactory;
-    protected final Namespaces namespaces;
-    protected final UUID rootNodeUuid;
-    protected final String rootNodeUuidString;
-    protected final Serializer serializer;
-    protected final long largeValueMinimumSizeInBytes;
-    protected final boolean compressData;
-    protected final Logger logger;
-    protected final RequestProcessorCache cache;
-    protected final boolean enforceReferentialIntegrity;
-    private boolean referencesChanged;
-
-    /**
-     * @param sourceName
-     * @param context
-     * @param entityManager
-     * @param rootNodeUuid
-     * @param largeValueMinimumSizeInBytes
-     * @param compressData
-     * @param enforceReferentialIntegrity
-     */
-    public BasicRequestProcessor( String sourceName,
-                                  ExecutionContext context,
-                                  EntityManager entityManager,
-                                  UUID rootNodeUuid,
-                                  long largeValueMinimumSizeInBytes,
-                                  boolean compressData,
-                                  boolean enforceReferentialIntegrity ) {
-        super(sourceName, context);
-        assert entityManager != null;
-        assert rootNodeUuid != null;
-        this.entities = entityManager;
-        ValueFactories valuesFactory = context.getValueFactories();
-        this.stringFactory = valuesFactory.getStringFactory();
-        this.pathFactory = valuesFactory.getPathFactory();
-        this.nameFactory = valuesFactory.getNameFactory();
-        this.uuidFactory = valuesFactory.getUuidFactory();
-        this.namespaces = new Namespaces(entityManager);
-        this.rootNodeUuid = rootNodeUuid;
-        this.rootNodeUuidString = this.rootNodeUuid.toString();
-        this.largeValueMinimumSizeInBytes = largeValueMinimumSizeInBytes;
-        this.compressData = compressData;
-        this.enforceReferentialIntegrity = enforceReferentialIntegrity;
-        this.serializer = new Serializer(context, true);
-        this.logger = getExecutionContext().getLogger(getClass());
-        this.cache = new RequestProcessorCache(this.pathFactory);
-
-        // Start the transaction ...
-        this.entities.getTransaction().begin();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CreateNodeRequest)
-     */
-    @Override
-    public void process( CreateNodeRequest request ) {
-        logger.trace(request.toString());
-        Location actualLocation = null;
-        try {
-            // Create nodes have to be defined via a path ...
-            Location parentLocation = request.under();
-            ActualLocation actual = getActualLocation(parentLocation);
-            String parentUuidString = actual.uuid;
-            assert parentUuidString != null;
-
-            // We need to look for an existing UUID property in the request,
-            // so since we have to iterate through the properties, go ahead an serialize them right away ...
-            String uuidString = null;
-            for (Property property : request.properties()) {
-                if (property.getName().equals(DnaLexicon.UUID)) {
-                    uuidString = stringFactory.create(property.getFirstValue());
-                    break;
-                }
-            }
-            if (uuidString == null) uuidString = UUID.randomUUID().toString();
-            assert uuidString != null;
-            createProperties(uuidString, request.properties());
-
-            // Find or create the namespace for the child ...
-            Name childName = request.named();
-            String childNsUri = childName.getNamespaceUri();
-            NamespaceEntity ns = namespaces.get(childNsUri, true);
-            assert ns != null;
-            final Path parentPath = actual.location.getPath();
-            assert parentPath != null;
-
-            // Figure out the next SNS index and index-in-parent for this new child ...
-            actualLocation = addNewChild(actual, uuidString, childName);
-
-            // Since we've just created this node, we know about all the children (actually, there are none).
-            cache.setAllChildren(actualLocation.getPath(), new LinkedList<Location>());
-
-            // Flush the entities ...
-            // entities.flush();
-
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            logger.trace(e, "Problem " + request);
-            return;
-        }
-        request.setActualLocationOfNode(actualLocation);
-    }
-
-    protected Location addNewChild( ActualLocation parent,
-                                    String childUuid,
-                                    Name childName ) {
-        int nextSnsIndex = 1; // SNS index is 1-based
-        int nextIndexInParent = 0; // index-in-parent is 0-based
-        String childNsUri = childName.getNamespaceUri();
-        NamespaceEntity ns = namespaces.get(childNsUri, true);
-        assert ns != null;
-
-        final Path parentPath = parent.location.getPath();
-        assert parentPath != null;
-
-        // Look in the cache for the children of the parent node.
-        LinkedList<Location> childrenOfParent = cache.getAllChildren(parentPath);
-        if (childrenOfParent != null) {
-            // The cache had the complete list of children for the parent node, which means
-            // we know about all of the children and can walk the children to figure out the next indexes.
-            nextIndexInParent = childrenOfParent.size();
-            if (nextIndexInParent > 1) {
-                // Since we want the last indexes, process the list backwards ...
-                ListIterator<Location> iter = childrenOfParent.listIterator(childrenOfParent.size());
-                while (iter.hasPrevious()) {
-                    Location existing = iter.previous();
-                    Path.Segment segment = existing.getPath().getLastSegment();
-                    if (!segment.getName().equals(childName)) continue;
-                    // Otherwise the name matched, so get the indexes ...
-                    nextSnsIndex = segment.getIndex() + 1;
-                }
-            }
-        } else {
-            // The cache did not have the complete list of children for the parent node,
-            // so we need to look the values up by querying the database ...
-
-            // Find the largest SNS index in the existing ChildEntity objects with the same name ...
-            String childLocalName = childName.getLocalName();
-            Query query = entities.createNamedQuery("ChildEntity.findMaximumSnsIndex");
-            query.setParameter("parentUuid", parent.uuid);
-            query.setParameter("ns", ns.getId());
-            query.setParameter("childName", childLocalName);
-            try {
-                Integer result = (Integer)query.getSingleResult();
-                nextSnsIndex = result != null ? result + 1 : 1; // SNS index is 1-based
-            } catch (NoResultException e) {
-            }
-
-            // Find the largest child index in the existing ChildEntity objects ...
-            query = entities.createNamedQuery("ChildEntity.findMaximumChildIndex");
-            query.setParameter("parentUuid", parent.uuid);
-            try {
-                Integer result = (Integer)query.getSingleResult();
-                nextIndexInParent = result != null ? result + 1 : 0; // index-in-parent is 0-based
-            } catch (NoResultException e) {
-            }
-        }
-
-        // Create the new ChildEntity ...
-        ChildId id = new ChildId(parent.uuid, childUuid);
-        ChildEntity entity = new ChildEntity(id, nextIndexInParent, ns, childName.getLocalName(), nextSnsIndex);
-        entities.persist(entity);
-
-        // Set the actual path, regardless of the supplied path...
-        Path path = pathFactory.create(parentPath, childName, nextSnsIndex);
-        Location actualLocation = new Location(path, UUID.fromString(childUuid));
-
-        // Finally, update the cache with the information we know ...
-        if (childrenOfParent != null) {
-            // Add to the cached list of children ...
-            childrenOfParent.add(actualLocation);
-        }
-        return actualLocation;
-    }
-
-    protected class NextChildIndexes {
-        protected final int nextIndexInParent;
-        protected final int nextSnsIndex;
-
-        protected NextChildIndexes( int nextIndexInParent,
-                                    int nextSnsIndex ) {
-            this.nextIndexInParent = nextIndexInParent;
-            this.nextSnsIndex = nextSnsIndex;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadNodeRequest)
-     */
-    @Override
-    public void process( ReadNodeRequest request ) {
-        logger.trace(request.toString());
-        Location actualLocation = null;
-        try {
-            Location location = request.at();
-            ActualLocation actual = getActualLocation(location);
-            String parentUuidString = actual.uuid;
-            actualLocation = actual.location;
-
-            // Record the UUID as a property, since it's not stored in the serialized properties...
-            request.addProperty(actualLocation.getIdProperty(DnaLexicon.UUID));
-
-            // Find the properties entity for this node ...
-            Query query = entities.createNamedQuery("PropertiesEntity.findByUuid");
-            query.setParameter("uuid", parentUuidString);
-            try {
-                PropertiesEntity entity = (PropertiesEntity)query.getSingleResult();
-
-                // Deserialize the properties ...
-                boolean compressed = entity.isCompressed();
-                Collection<Property> properties = new LinkedList<Property>();
-                byte[] data = entity.getData();
-                if (data != null) {
-                    LargeValueSerializer largeValues = new LargeValueSerializer(entity);
-                    ByteArrayInputStream bais = new ByteArrayInputStream(data);
-                    InputStream is = compressed ? new GZIPInputStream(bais) : bais;
-                    ObjectInputStream ois = new ObjectInputStream(is);
-                    try {
-                        serializer.deserializeAllProperties(ois, properties, largeValues);
-                        for (Property property : properties) {
-                            request.addProperty(property);
-                        }
-                    } finally {
-                        ois.close();
-                    }
-                }
-
-            } catch (NoResultException e) {
-                // No properties, but that's okay...
-            }
-
-            // Get the children for this node ...
-            for (Location childLocation : getAllChildren(actual)) {
-                request.addChild(childLocation);
-            }
-        } catch (NoResultException e) {
-            // there are no properties (probably not expected, but still okay) ...
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
-        setCacheableInfo(request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllChildrenRequest)
-     */
-    @Override
-    public void process( ReadAllChildrenRequest request ) {
-        logger.trace(request.toString());
-        Location actualLocation = null;
-        try {
-            Location location = request.of();
-            ActualLocation actual = getActualLocation(location);
-            actualLocation = actual.location;
-
-            // Get the children for this node ...
-            for (Location childLocation : getAllChildren(actual)) {
-                request.addChild(childLocation);
-            }
-        } catch (NoResultException e) {
-            // there are no properties (probably not expected, but still okay) ...
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
-        setCacheableInfo(request);
-    }
-
-    /**
-     * Utility method to obtain all of the children for a node, either from the cache (if all children are known to this
-     * processor) or by querying the database (and caching the list of children).
-     * 
-     * @param parent the actual location of the parent node; may not be null
-     * @return the list of child locations
-     */
-    protected LinkedList<Location> getAllChildren( ActualLocation parent ) {
-        assert parent != null;
-        Path parentPath = parent.location.getPath();
-        assert parentPath != null;
-        LinkedList<Location> cachedChildren = cache.getAllChildren(parentPath);
-        if (cachedChildren != null) {
-            // The cache has all of the children for the node ...
-            return cachedChildren;
-        }
-
-        // Not found in the cache, so query the database ...
-        Query query = entities.createNamedQuery("ChildEntity.findAllUnderParent");
-        query.setParameter("parentUuidString", parent.uuid);
-        LinkedList<Location> childLocations = new LinkedList<Location>();
-        @SuppressWarnings( "unchecked" )
-        List<ChildEntity> children = query.getResultList();
-        for (ChildEntity child : children) {
-            String namespaceUri = child.getChildNamespace().getUri();
-            String localName = child.getChildName();
-            Name childName = nameFactory.create(namespaceUri, localName);
-            int sns = child.getSameNameSiblingIndex();
-            Path childPath = pathFactory.create(parentPath, childName, sns);
-            String childUuidString = child.getId().getChildUuidString();
-            Location childLocation = new Location(childPath, UUID.fromString(childUuidString));
-            childLocations.add(childLocation);
-        }
-        // Update the cache ...
-        cache.setAllChildren(parentPath, childLocations);
-        return childLocations;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest)
-     */
-    @Override
-    public void process( ReadBlockOfChildrenRequest request ) {
-        logger.trace(request.toString());
-        Location actualLocation = null;
-        final int startingIndex = request.startingAtIndex();
-        try {
-            Location parentLocation = request.of();
-            ActualLocation actualParent = getActualLocation(parentLocation);
-            actualLocation = actualParent.location;
-
-            Path parentPath = actualParent.location.getPath();
-            assert parentPath != null;
-            LinkedList<Location> cachedChildren = cache.getAllChildren(parentPath);
-            if (cachedChildren != null) {
-                // The cache has all of the children for the node ...
-                if (startingIndex < cachedChildren.size()) {
-                    ListIterator<Location> iter = cachedChildren.listIterator(startingIndex);
-                    for (int i = 0; i != request.count() && iter.hasNext(); ++i) {
-                        Location child = iter.next();
-                        request.addChild(child);
-                    }
-                }
-            } else {
-                // Nothing was cached, so we need to search the database for the children ...
-                Query query = entities.createNamedQuery("ChildEntity.findRangeUnderParent");
-                query.setParameter("parentUuidString", actualParent.uuid);
-                query.setParameter("firstIndex", startingIndex);
-                query.setParameter("afterIndex", startingIndex + request.count());
-                @SuppressWarnings( "unchecked" )
-                List<ChildEntity> children = query.getResultList();
-                for (ChildEntity child : children) {
-                    String namespaceUri = child.getChildNamespace().getUri();
-                    String localName = child.getChildName();
-                    Name childName = nameFactory.create(namespaceUri, localName);
-                    int sns = child.getSameNameSiblingIndex();
-                    Path childPath = pathFactory.create(parentPath, childName, sns);
-                    String childUuidString = child.getId().getChildUuidString();
-                    Location childLocation = new Location(childPath, UUID.fromString(childUuidString));
-                    request.addChild(childLocation);
-                }
-                // Do not update the cache, since we don't know all of the children.
-            }
-
-        } catch (NoResultException e) {
-            // there are no properties (probably not expected, but still okay) ...
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
-        setCacheableInfo(request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadNextBlockOfChildrenRequest)
-     */
-    @Override
-    public void process( ReadNextBlockOfChildrenRequest request ) {
-        logger.trace(request.toString());
-        Location actualLocation = null;
-        final Location previousSibling = request.startingAfter();
-        final int count = request.count();
-        try {
-            ActualLocation actualSibling = getActualLocation(previousSibling);
-            actualLocation = actualSibling.location;
-            if (!actualLocation.getPath().isRoot()) {
-                // First look in the cache for the children of the parent ...
-                Path parentPath = actualSibling.location.getPath().getParent();
-                assert parentPath != null;
-                LinkedList<Location> cachedChildren = cache.getAllChildren(parentPath);
-                if (cachedChildren != null) {
-                    // The cache has all of the children for the node.
-                    // First find the location of the previous sibling ...
-                    boolean accumulate = false;
-                    int counter = 0;
-                    for (Location child : cachedChildren) {
-                        if (accumulate) {
-                            // We're accumulating children ...
-                            request.addChild(child);
-                            ++counter;
-                            if (counter <= count) continue;
-                            break;
-                        }
-                        // Haven't found the previous sibling yet ...
-                        if (child.isSame(previousSibling)) {
-                            accumulate = true;
-                        }
-                    }
-                } else {
-                    // The children were not found in the cache, so we have to search the database.
-                    // We don't know the UUID of the parent, so find the previous sibling and
-                    // then get the starting index and the parent UUID ...
-                    ChildEntity previousChild = actualSibling.childEntity;
-                    if (previousChild == null) {
-                        Query query = entities.createNamedQuery("ChildEntity.findByChildUuid");
-                        query.setParameter("childUuidString", actualSibling.uuid);
-                        previousChild = (ChildEntity)query.getSingleResult();
-                    }
-                    int startingIndex = previousChild.getIndexInParent() + 1;
-                    String parentUuid = previousChild.getId().getParentUuidString();
-
-                    // Now search the database for the children ...
-                    Query query = entities.createNamedQuery("ChildEntity.findRangeUnderParent");
-                    query.setParameter("parentUuidString", parentUuid);
-                    query.setParameter("firstIndex", startingIndex);
-                    query.setParameter("afterIndex", startingIndex + request.count());
-                    @SuppressWarnings( "unchecked" )
-                    List<ChildEntity> children = query.getResultList();
-                    LinkedList<Location> allChildren = null;
-                    if (startingIndex == 1 && children.size() < request.count()) {
-                        // The previous child was the first sibling, and we got fewer children than
-                        // the max count. This means we know all of the children, so accumulate the locations
-                        // so they can be cached ...
-                        allChildren = new LinkedList<Location>();
-                        allChildren.add(actualSibling.location);
-                    }
-                    for (ChildEntity child : children) {
-                        String namespaceUri = child.getChildNamespace().getUri();
-                        String localName = child.getChildName();
-                        Name childName = nameFactory.create(namespaceUri, localName);
-                        int sns = child.getSameNameSiblingIndex();
-                        Path childPath = pathFactory.create(parentPath, childName, sns);
-                        String childUuidString = child.getId().getChildUuidString();
-                        Location childLocation = new Location(childPath, UUID.fromString(childUuidString));
-                        request.addChild(childLocation);
-                        if (allChildren != null) {
-                            // We're going to cache the results, so add this child ...
-                            allChildren.add(childLocation);
-                        }
-                    }
-
-                    if (allChildren != null) {
-                        cache.setAllChildren(parentPath, allChildren);
-                    }
-                }
-            }
-
-        } catch (NoResultException e) {
-            // there are no properties (probably not expected, but still okay) ...
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        if (actualLocation != null) request.setActualLocationOfStartingAfterNode(actualLocation);
-        setCacheableInfo(request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllPropertiesRequest)
-     */
-    @Override
-    public void process( ReadAllPropertiesRequest request ) {
-        logger.trace(request.toString());
-        Location actualLocation = null;
-        try {
-            Location location = request.at();
-            ActualLocation actual = getActualLocation(location);
-            String uuidString = actual.uuid;
-            actualLocation = actual.location;
-
-            // Record the UUID as a property, since it's not stored in the serialized properties...
-            request.addProperty(actualLocation.getIdProperty(DnaLexicon.UUID));
-
-            // Find the properties entity for this node ...
-            Query query = entities.createNamedQuery("PropertiesEntity.findByUuid");
-            query.setParameter("uuid", uuidString);
-            PropertiesEntity entity = (PropertiesEntity)query.getSingleResult();
-
-            // Deserialize the properties ...
-            boolean compressed = entity.isCompressed();
-            int propertyCount = entity.getPropertyCount();
-            Collection<Property> properties = new ArrayList<Property>(propertyCount);
-            byte[] data = entity.getData();
-            if (data != null) {
-                LargeValueSerializer largeValues = new LargeValueSerializer(entity);
-                ByteArrayInputStream bais = new ByteArrayInputStream(data);
-                InputStream is = compressed ? new GZIPInputStream(bais) : bais;
-                ObjectInputStream ois = new ObjectInputStream(is);
-                try {
-                    serializer.deserializeAllProperties(ois, properties, largeValues);
-                    for (Property property : properties) {
-                        request.addProperty(property);
-                    }
-                } finally {
-                    ois.close();
-                }
-            }
-        } catch (NoResultException e) {
-            // there are no properties (probably not expected, but still okay) ...
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
-        setCacheableInfo(request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadPropertyRequest)
-     */
-    @Override
-    public void process( ReadPropertyRequest request ) {
-        logger.trace(request.toString());
-        // Small optimization ...
-        final Name propertyName = request.named();
-        if (DnaLexicon.UUID.equals(propertyName)) {
-            try {
-                // Just get the UUID ...
-                Location location = request.on();
-                ActualLocation actualLocation = getActualLocation(location);
-                UUID uuid = actualLocation.location.getUuid();
-                Property uuidProperty = getExecutionContext().getPropertyFactory().create(propertyName, uuid);
-                request.setProperty(uuidProperty);
-                request.setActualLocationOfNode(actualLocation.location);
-                setCacheableInfo(request);
-            } catch (Throwable e) { // Includes PathNotFoundException
-                request.setError(e);
-            }
-            return;
-        }
-        // Process the one property that's requested ...
-        Location actualLocation = null;
-        try {
-            Location location = request.on();
-            ActualLocation actual = getActualLocation(location);
-            String uuidString = actual.uuid;
-            actualLocation = actual.location;
-
-            // Find the properties entity for this node ...
-            Query query = entities.createNamedQuery("PropertiesEntity.findByUuid");
-            query.setParameter("uuid", uuidString);
-            PropertiesEntity entity = (PropertiesEntity)query.getSingleResult();
-
-            // Deserialize the stream of properties, but only materialize the one property ...
-            boolean compressed = entity.isCompressed();
-            int propertyCount = entity.getPropertyCount();
-            Collection<Property> properties = new ArrayList<Property>(propertyCount);
-            byte[] data = entity.getData();
-            if (data != null) {
-                LargeValueSerializer largeValues = new LargeValueSerializer(entity);
-                ByteArrayInputStream bais = new ByteArrayInputStream(data);
-                InputStream is = compressed ? new GZIPInputStream(bais) : bais;
-                ObjectInputStream ois = new ObjectInputStream(is);
-                try {
-                    Serializer.LargeValues skippedLargeValues = Serializer.NO_LARGE_VALUES;
-                    serializer.deserializeSomeProperties(ois, properties, largeValues, skippedLargeValues, propertyName);
-                    for (Property property : properties) {
-                        request.setProperty(property); // should be only one property
-                    }
-                } finally {
-                    ois.close();
-                }
-            }
-        } catch (NoResultException e) {
-            // there are no properties (probably not expected, but still okay) ...
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
-        setCacheableInfo(request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.UpdatePropertiesRequest)
-     */
-    @Override
-    public void process( UpdatePropertiesRequest request ) {
-        logger.trace(request.toString());
-        Location actualLocation = null;
-        try {
-            Location location = request.on();
-            ActualLocation actual = getActualLocation(location);
-            actualLocation = actual.location;
-
-            // Find the properties entity for this node ...
-            Query query = entities.createNamedQuery("PropertiesEntity.findByUuid");
-            query.setParameter("uuid", actual.uuid);
-            PropertiesEntity entity = null;
-            try {
-                entity = (PropertiesEntity)query.getSingleResult();
-
-                // Prepare the streams so we can deserialize all existing properties and reserialize the old and updated
-                // properties ...
-                boolean compressed = entity.isCompressed();
-                byte[] originalData = entity.getData();
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                OutputStream os = compressed ? new GZIPOutputStream(baos) : baos;
-                ObjectOutputStream oos = new ObjectOutputStream(os);
-                int numProps = 0;
-                LargeValueSerializer largeValues = null;
-                Collection<Property> props = request.properties();
-                References refs = enforceReferentialIntegrity ? new References() : null;
-                if (originalData == null) {
-                    largeValues = new LargeValueSerializer(entity);
-                    numProps = props.size();
-                    serializer.serializeProperties(oos, numProps, props, largeValues, refs);
-                } else {
-                    boolean hadLargeValues = !entity.getLargeValues().isEmpty();
-                    Set<String> largeValueHashesWritten = hadLargeValues ? new HashSet<String>() : null;
-                    largeValues = new LargeValueSerializer(entity, largeValueHashesWritten);
-                    ByteArrayInputStream bais = new ByteArrayInputStream(originalData);
-                    InputStream is = compressed ? new GZIPInputStream(bais) : bais;
-                    ObjectInputStream ois = new ObjectInputStream(is);
-                    SkippedLargeValues removedValues = new SkippedLargeValues(largeValues);
-                    try {
-                        Serializer.ReferenceValues refValues = refs != null ? refs : Serializer.NO_REFERENCES_VALUES;
-                        numProps = serializer.reserializeProperties(ois, oos, props, largeValues, removedValues, refValues);
-                    } finally {
-                        try {
-                            ois.close();
-                        } finally {
-                            oos.close();
-                        }
-                    }
-                    // The new large values were recorded and associated with the properties entity during reserialization.
-                    // However, any values no longer used now need to be removed ...
-                    if (hadLargeValues) {
-                        // Remove any large value from the 'skipped' list that was also written ...
-                        removedValues.skippedKeys.removeAll(largeValueHashesWritten);
-                        for (String oldHexKey : removedValues.skippedKeys) {
-                            LargeValueId id = new LargeValueId(oldHexKey);
-                            entity.getLargeValues().remove(id);
-                        }
-                    }
-
-                    if (refs != null) {
-                        // Remove any existing references ...
-                        if (refs.hasRemoved()) {
-                            for (Reference reference : refs.getRemoved()) {
-                                String toUuid = resolveToUuid(reference);
-                                if (toUuid != null) {
-                                    ReferenceId id = new ReferenceId(actual.uuid, toUuid);
-                                    ReferenceEntity refEntity = entities.find(ReferenceEntity.class, id);
-                                    if (refEntity != null) {
-                                        entities.remove(refEntity);
-                                        referencesChanged = true;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-                entity.setPropertyCount(numProps);
-                entity.setData(baos.toByteArray());
-                entity.setCompressed(compressData);
-
-                if (refs != null && refs.hasWritten()) {
-                    // If there were references from the updated node ...
-                    Set<Reference> newReferences = refs.getWritten();
-                    // Remove any reference that was written (and not removed) ...
-                    newReferences.removeAll(refs.getRead());
-                    if (newReferences.size() != 0) {
-                        // Now save the new references ...
-                        for (Reference reference : newReferences) {
-                            String toUuid = resolveToUuid(reference);
-                            if (toUuid != null) {
-                                ReferenceId id = new ReferenceId(actual.uuid, toUuid);
-                                ReferenceEntity refEntity = new ReferenceEntity(id);
-                                entities.persist(refEntity);
-                                referencesChanged = true;
-                            }
-                        }
-                    }
-                }
-            } catch (NoResultException e) {
-                // there are no properties yet ...
-                createProperties(actual.uuid, request.properties());
-            }
-
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadBranchRequest)
-     */
-    @Override
-    public void process( ReadBranchRequest request ) {
-        logger.trace(request.toString());
-        Location actualLocation = null;
-        try {
-            Location location = request.at();
-            ActualLocation actual = getActualLocation(location);
-            actualLocation = actual.location;
-            Path path = actualLocation.getPath();
-
-            // Record the location of each node by its UUID; we'll use this when processing the properties ...
-            Map<String, Location> locationsByUuid = new HashMap<String, Location>();
-            locationsByUuid.put(actual.uuid, location);
-
-            // Compute the subgraph, including the root ...
-            int maxDepth = request.maximumDepth();
-            SubgraphQuery query = SubgraphQuery.create(getExecutionContext(), entities, actualLocation.getUuid(), path, maxDepth);
-
-            try {
-                // Record all of the children ...
-                Path parent = path;
-                String parentUuid = actual.uuid;
-                Location parentLocation = actualLocation;
-                List<Location> children = new LinkedList<Location>();
-                Map<Location, List<Location>> childrenByParentLocation = new HashMap<Location, List<Location>>();
-                childrenByParentLocation.put(parentLocation, children);
-                boolean includeChildrenOfNodesAtMaxDepth = true;
-                for (ChildEntity child : query.getNodes(false, includeChildrenOfNodesAtMaxDepth)) {
-                    String namespaceUri = child.getChildNamespace().getUri();
-                    String localName = child.getChildName();
-                    Name childName = nameFactory.create(namespaceUri, localName);
-                    int sns = child.getSameNameSiblingIndex();
-                    // Figure out who the parent is ...
-                    String childParentUuid = child.getId().getParentUuidString();
-                    if (!parentUuid.equals(childParentUuid)) {
-                        // Find the correct parent ...
-                        parentLocation = locationsByUuid.get(childParentUuid);
-                        parent = parentLocation.getPath();
-                        parentUuid = childParentUuid;
-                        // See if there is already a list of children for this parent ...
-                        children = childrenByParentLocation.get(parentLocation);
-                        if (children == null) {
-                            children = new LinkedList<Location>();
-                            childrenByParentLocation.put(parentLocation, children);
-                        }
-                    }
-                    assert children != null;
-                    Path childPath = pathFactory.create(parent, childName, sns);
-                    String childUuidString = child.getId().getChildUuidString();
-                    Location childLocation = new Location(childPath, UUID.fromString(childUuidString));
-                    locationsByUuid.put(childUuidString, childLocation);
-                    children.add(childLocation);
-                }
-                // Now add the list of children to the results ...
-                for (Map.Entry<Location, List<Location>> entry : childrenByParentLocation.entrySet()) {
-                    // Don't add if there are no children ...
-                    if (!entry.getValue().isEmpty()) {
-                        request.setChildren(entry.getKey(), entry.getValue());
-                    }
-                }
-
-                // Note that we've found children for nodes that are at the maximum depth. This is so that the nodes
-                // in the subgraph all have the correct children. However, we don't want to store the properties for
-                // any node whose depth is greater than the maximum depth. Therefore, only get the properties that
-                // include nodes within the maximum depth...
-                includeChildrenOfNodesAtMaxDepth = false;
-
-                // Now record all of the properties ...
-                for (PropertiesEntity props : query.getProperties(true, includeChildrenOfNodesAtMaxDepth)) {
-                    boolean compressed = props.isCompressed();
-                    int propertyCount = props.getPropertyCount();
-                    Collection<Property> properties = new ArrayList<Property>(propertyCount);
-                    Location nodeLocation = locationsByUuid.get(props.getId().getUuidString());
-                    assert nodeLocation != null;
-                    // Record the UUID as a property, since it's not stored in the serialized properties...
-                    properties.add(actualLocation.getIdProperty(DnaLexicon.UUID));
-                    // Deserialize all the properties (except the UUID)...
-                    byte[] data = props.getData();
-                    if (data != null) {
-                        LargeValueSerializer largeValues = new LargeValueSerializer(props);
-                        ByteArrayInputStream bais = new ByteArrayInputStream(data);
-                        InputStream is = compressed ? new GZIPInputStream(bais) : bais;
-                        ObjectInputStream ois = new ObjectInputStream(is);
-                        try {
-                            serializer.deserializeAllProperties(ois, properties, largeValues);
-                            request.setProperties(nodeLocation, properties);
-                        } finally {
-                            ois.close();
-                        }
-                    }
-                }
-            } finally {
-                // Close and release the temporary data used for this operation ...
-                query.close();
-            }
-
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        request.setActualLocationOfNode(actualLocation);
-        setCacheableInfo(request);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CopyBranchRequest)
-     */
-    @Override
-    public void process( CopyBranchRequest request ) {
-        logger.trace(request.toString());
-        Location actualFromLocation = null;
-        Location actualToLocation = null;
-        try {
-            Location fromLocation = request.from();
-            ActualLocation actualFrom = getActualLocation(fromLocation);
-            actualFromLocation = actualFrom.location;
-            Path fromPath = actualFromLocation.getPath();
-
-            Location newParentLocation = request.into();
-            ActualLocation actualNewParent = getActualLocation(newParentLocation);
-            assert actualNewParent != null;
-
-            // Create a map that we'll use to record the new UUID for each of the original nodes ...
-            Map<String, String> originalToNewUuid = new HashMap<String, String>();
-
-            // Compute the subgraph, including the top node in the subgraph ...
-            SubgraphQuery query = SubgraphQuery.create(getExecutionContext(), entities, actualFromLocation.getUuid(), fromPath, 0);
-            try {
-                // Walk through the original nodes, creating new ChildEntity object (i.e., copy) for each original ...
-                List<ChildEntity> originalNodes = query.getNodes(true, true);
-                Iterator<ChildEntity> originalIter = originalNodes.iterator();
-
-                // Start with the original (top-level) node first, since we need to add it to the list of children ...
-                if (originalIter.hasNext()) {
-                    ChildEntity original = originalIter.next();
-
-                    // Create a new UUID for the copy ...
-                    String copyUuid = UUID.randomUUID().toString();
-                    originalToNewUuid.put(original.getId().getChildUuidString(), copyUuid);
-
-                    // Now add the new copy of the original ...
-                    Name childName = fromPath.getLastSegment().getName();
-                    actualToLocation = addNewChild(actualNewParent, copyUuid, childName);
-                }
-
-                // Now create copies of all children in the subgraph, assigning new UUIDs to each new child ...
-                while (originalIter.hasNext()) {
-                    ChildEntity original = originalIter.next();
-                    String newParentUuidOfCopy = originalToNewUuid.get(original.getId().getParentUuidString());
-                    assert newParentUuidOfCopy != null;
-
-                    // Create a new UUID for the copy ...
-                    String copyUuid = UUID.randomUUID().toString();
-                    originalToNewUuid.put(original.getId().getChildUuidString(), copyUuid);
-
-                    // Create the copy ...
-                    ChildEntity copy = new ChildEntity(new ChildId(newParentUuidOfCopy, copyUuid), original.getIndexInParent(),
-                                                       original.getChildNamespace(), original.getChildName(),
-                                                       original.getSameNameSiblingIndex());
-                    entities.persist(copy);
-                }
-                entities.flush();
-
-                // Now create copies of all the intra-subgraph references, replacing the UUIDs on both ends ...
-                Set<String> newNodesWithReferenceProperties = new HashSet<String>();
-                for (ReferenceEntity reference : query.getInternalReferences()) {
-                    String newFromUuid = originalToNewUuid.get(reference.getId().getFromUuidString());
-                    assert newFromUuid != null;
-                    String newToUuid = originalToNewUuid.get(reference.getId().getToUuidString());
-                    assert newToUuid != null;
-                    ReferenceEntity copy = new ReferenceEntity(new ReferenceId(newFromUuid, newToUuid));
-                    entities.persist(copy);
-                    newNodesWithReferenceProperties.add(newFromUuid);
-                }
-
-                // Now create copies of all the references owned by the subgraph but pointing to non-subgraph nodes,
-                // so we only replaced the 'from' UUID ...
-                for (ReferenceEntity reference : query.getOutwardReferences()) {
-                    String oldToUuid = reference.getId().getToUuidString();
-                    String newFromUuid = originalToNewUuid.get(reference.getId().getFromUuidString());
-                    assert newFromUuid != null;
-                    ReferenceEntity copy = new ReferenceEntity(new ReferenceId(newFromUuid, oldToUuid));
-                    entities.persist(copy);
-                    newNodesWithReferenceProperties.add(newFromUuid);
-                }
-
-                // Now process the properties, creating a copy (note references are not changed) ...
-                for (PropertiesEntity original : query.getProperties(true, true)) {
-                    // Find the UUID of the copy ...
-                    String copyUuid = originalToNewUuid.get(original.getId().getUuidString());
-                    assert copyUuid != null;
-
-                    // Create the copy ...
-                    boolean compressed = original.isCompressed();
-                    byte[] originalData = original.getData();
-                    PropertiesEntity copy = new PropertiesEntity(new NodeId(copyUuid));
-                    copy.setCompressed(compressed);
-                    if (newNodesWithReferenceProperties.contains(copyUuid)) {
-
-                        // This node has internal or outward references that must be adjusted ...
-                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                        OutputStream os = compressed ? new GZIPOutputStream(baos) : baos;
-                        ObjectOutputStream oos = new ObjectOutputStream(os);
-                        ByteArrayInputStream bais = new ByteArrayInputStream(originalData);
-                        InputStream is = compressed ? new GZIPInputStream(bais) : bais;
-                        ObjectInputStream ois = new ObjectInputStream(is);
-                        try {
-                            serializer.adjustReferenceProperties(ois, oos, originalToNewUuid);
-                        } finally {
-                            try {
-                                ois.close();
-                            } finally {
-                                oos.close();
-                            }
-                        }
-                        copy.setData(baos.toByteArray());
-                    } else {
-                        // No references to adjust, so just copy the original data ...
-                        copy.setData(originalData);
-                    }
-                    copy.setPropertyCount(original.getPropertyCount());
-                    copy.setReferentialIntegrityEnforced(original.isReferentialIntegrityEnforced());
-                    entities.persist(copy);
-                }
-                entities.flush();
-
-            } finally {
-                // Close and release the temporary data used for this operation ...
-                query.close();
-            }
-
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        request.setActualLocations(actualFromLocation, actualToLocation);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.DeleteBranchRequest)
-     */
-    @Override
-    public void process( DeleteBranchRequest request ) {
-        logger.trace(request.toString());
-        Location actualLocation = null;
-        try {
-            Location location = request.at();
-            ActualLocation actual = getActualLocation(location);
-            actualLocation = actual.location;
-            Path path = actualLocation.getPath();
-
-            // Compute the subgraph, including the top node in the subgraph ...
-            SubgraphQuery query = SubgraphQuery.create(getExecutionContext(), entities, actualLocation.getUuid(), path, 0);
-            try {
-                ChildEntity deleted = query.getNode();
-                String parentUuidString = deleted.getId().getParentUuidString();
-                String childName = deleted.getChildName();
-                long nsId = deleted.getChildNamespace().getId();
-                int indexInParent = deleted.getIndexInParent();
-
-                // Get the locations of all deleted nodes, which will be required by events ...
-                List<Location> deletedLocations = query.getNodeLocations(true, true);
-
-                // Now delete the subgraph ...
-                query.deleteSubgraph(true);
-
-                // Verify referential integrity: that none of the deleted nodes are referenced by nodes not being deleted.
-                List<ReferenceEntity> invalidReferences = query.getInwardReferences();
-                if (invalidReferences.size() > 0) {
-                    // Some of the references that remain will be invalid, since they point to nodes that
-                    // have just been deleted. Build up the information necessary to produce a useful exception ...
-                    ValueFactory<Reference> refFactory = getExecutionContext().getValueFactories().getReferenceFactory();
-                    Map<Location, List<Reference>> invalidRefs = new HashMap<Location, List<Reference>>();
-                    for (ReferenceEntity entity : invalidReferences) {
-                        UUID fromUuid = UUID.fromString(entity.getId().getFromUuidString());
-                        ActualLocation actualFromLocation = getActualLocation(new Location(fromUuid));
-                        Location fromLocation = actualFromLocation.location;
-                        List<Reference> refs = invalidRefs.get(fromLocation);
-                        if (refs == null) {
-                            refs = new ArrayList<Reference>();
-                            invalidRefs.put(fromLocation, refs);
-                        }
-                        UUID toUuid = UUID.fromString(entity.getId().getToUuidString());
-                        refs.add(refFactory.create(toUuid));
-                    }
-                    String msg = JpaConnectorI18n.unableToDeleteBecauseOfReferences.text();
-                    throw new ReferentialIntegrityException(invalidRefs, msg);
-                }
-
-                // And adjust the SNS index and indexes ...
-                ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities, parentUuidString, childName, nsId, indexInParent);
-                entities.flush();
-
-                // Remove from the cache of children locations all entries for deleted nodes ...
-                cache.removeBranch(deletedLocations);
-            } finally {
-                // Close and release the temporary data used for this operation ...
-                query.close();
-            }
-
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        request.setActualLocationOfNode(actualLocation);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.MoveBranchRequest)
-     */
-    @Override
-    public void process( MoveBranchRequest request ) {
-        logger.trace(request.toString());
-        Location actualOldLocation = null;
-        Location actualNewLocation = null;
-        try {
-            Location fromLocation = request.from();
-            ActualLocation actualLocation = getActualLocation(fromLocation);
-            String fromUuidString = actualLocation.uuid;
-            actualOldLocation = actualLocation.location;
-            Path oldPath = actualOldLocation.getPath();
-
-            // It's not possible to move the root node
-            if (oldPath.isRoot()) {
-                String msg = JpaConnectorI18n.unableToMoveRootNode.text(getSourceName());
-                throw new InvalidRequestException(msg);
-            }
-
-            // Find the ChildEntity of the existing 'from' node ...
-            ChildEntity fromEntity = actualLocation.childEntity;
-            final String oldParentUuid = fromEntity.getId().getParentUuidString();
-
-            // Find the actual new location ...
-            Location toLocation = request.into();
-            String toUuidString = null;
-            if (request.hasNoEffect()) {
-                actualNewLocation = actualOldLocation;
-            } else {
-                // We have to proceed as normal ...
-                ActualLocation actualIntoLocation = getActualLocation(toLocation);
-                toUuidString = actualIntoLocation.uuid;
-                if (!toUuidString.equals(oldParentUuid)) {
-                    // Now we know that the new parent is not the existing parent ...
-                    final int oldIndex = fromEntity.getIndexInParent();
-
-                    // Find the largest SNS index in the existing ChildEntity objects with the same name ...
-                    String childLocalName = fromEntity.getChildName();
-                    NamespaceEntity ns = fromEntity.getChildNamespace();
-                    Query query = entities.createNamedQuery("ChildEntity.findMaximumSnsIndex");
-                    query.setParameter("parentUuidString", toUuidString);
-                    query.setParameter("ns", ns.getId());
-                    query.setParameter("childName", childLocalName);
-                    int nextSnsIndex = 1;
-                    try {
-                        nextSnsIndex = (Integer)query.getSingleResult();
-                    } catch (NoResultException e) {
-                    }
-
-                    // Find the largest child index in the existing ChildEntity objects ...
-                    query = entities.createNamedQuery("ChildEntity.findMaximumChildIndex");
-                    query.setParameter("parentUuidString", toUuidString);
-                    int nextIndexInParent = 1;
-                    try {
-                        nextIndexInParent = (Integer)query.getSingleResult() + 1;
-                    } catch (NoResultException e) {
-                    }
-
-                    // Move the child entity to be under the new parent ...
-                    fromEntity.setId(new ChildId(toUuidString, fromUuidString));
-                    fromEntity.setIndexInParent(nextIndexInParent);
-                    fromEntity.setSameNameSiblingIndex(nextSnsIndex);
-
-                    // Flush the entities to the database ...
-                    entities.flush();
-
-                    // Determine the new location ...
-                    Path newParentPath = actualIntoLocation.location.getPath();
-                    Name childName = oldPath.getLastSegment().getName();
-                    Path newPath = pathFactory.create(newParentPath, childName, nextSnsIndex);
-                    actualNewLocation = actualOldLocation.with(newPath);
-
-                    // And adjust the SNS index and indexes ...
-                    ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities,
-                                                                        oldParentUuid,
-                                                                        childLocalName,
-                                                                        ns.getId(),
-                                                                        oldIndex);
-
-                    // Update the cache ...
-                    cache.moveNode(actualOldLocation, oldIndex, actualNewLocation);
-
-                }
-
-            }
-
-        } catch (Throwable e) { // Includes PathNotFoundException
-            request.setError(e);
-            return;
-        }
-        request.setActualLocations(actualOldLocation, actualNewLocation);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#close()
-     */
-    @Override
-    public void close() {
-        // Verify that the references are valid so far ...
-        verifyReferences();
-
-        // Now commit the transaction ...
-        EntityTransaction txn = entities.getTransaction();
-        if (txn != null) txn.commit();
-        super.close();
-    }
-
-    /**
-     * {@link ReferenceEntity Reference entities} are added and removed in the appropriate <code>process(...)</code> methods.
-     * However, this method is typically called in {@link BasicRequestProcessor#close()} and performs the following steps:
-     * <ol>
-     * <li>Remove all references that have a "from" node that is under the versions branch.</li>
-     * <li>Verify that all remaining references have a valid and existing "to" node</li>
-     * </ol>
-     */
-    protected void verifyReferences() {
-        if (!enforceReferentialIntegrity) return;
-        if (referencesChanged) {
-
-            // Remove all references that have a "from" node that doesn't support referential integrity ...
-            ReferenceEntity.deleteUnenforcedReferences(entities);
-
-            // Verify that all references are resolved to existing nodes ...
-            int numUnresolved = ReferenceEntity.countAllReferencesResolved(entities);
-            if (numUnresolved != 0) {
-                List<ReferenceEntity> references = ReferenceEntity.verifyAllReferencesResolved(entities);
-                ValueFactory<Reference> refFactory = getExecutionContext().getValueFactories().getReferenceFactory();
-                Map<Location, List<Reference>> invalidRefs = new HashMap<Location, List<Reference>>();
-                for (ReferenceEntity entity : references) {
-                    UUID fromUuid = UUID.fromString(entity.getId().getFromUuidString());
-                    Location location = new Location(fromUuid);
-                    location = getActualLocation(location).location;
-                    List<Reference> refs = invalidRefs.get(location);
-                    if (refs == null) {
-                        refs = new ArrayList<Reference>();
-                        invalidRefs.put(location, refs);
-                    }
-                    UUID toUuid = UUID.fromString(entity.getId().getToUuidString());
-                    refs.add(refFactory.create(toUuid));
-                }
-                String msg = JpaConnectorI18n.invalidReferences.text(getSourceName());
-                throw new ReferentialIntegrityException(invalidRefs, msg);
-            }
-
-            referencesChanged = false;
-        }
-    }
-
-    protected String createProperties( String uuidString,
-                                       Collection<Property> properties ) throws IOException {
-        assert uuidString != null;
-
-        // Create the PropertiesEntity ...
-        NodeId nodeId = new NodeId(uuidString);
-        PropertiesEntity props = new PropertiesEntity(nodeId);
-
-        // If there are properties ...
-        boolean processProperties = true;
-        if (properties.isEmpty()) processProperties = false;
-        else if (properties.size() == 1 && properties.iterator().next().getName().equals(JcrLexicon.NAME)) processProperties = false;
-
-        if (processProperties) {
-            References refs = enforceReferentialIntegrity ? new References() : null;
-            LargeValueSerializer largeValues = new LargeValueSerializer(props);
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            OutputStream os = compressData ? new GZIPOutputStream(baos) : baos;
-            ObjectOutputStream oos = new ObjectOutputStream(os);
-            int numProperties = properties.size();
-            try {
-                Serializer.ReferenceValues refValues = refs != null ? refs : Serializer.NO_REFERENCES_VALUES;
-                serializer.serializeProperties(oos, numProperties, properties, largeValues, refValues);
-            } finally {
-                oos.close();
-            }
-
-            props.setData(baos.toByteArray());
-            props.setPropertyCount(numProperties);
-
-            // Record the changes to the references ...
-            if (refs != null && refs.hasWritten()) {
-                for (Reference reference : refs.getWritten()) {
-                    String toUuid = resolveToUuid(reference);
-                    if (toUuid != null) {
-                        ReferenceId id = new ReferenceId(uuidString, toUuid);
-                        ReferenceEntity refEntity = new ReferenceEntity(id);
-                        entities.persist(refEntity);
-                        referencesChanged = true;
-                    }
-                }
-            }
-        } else {
-            props.setData(null);
-            props.setPropertyCount(0);
-        }
-        props.setCompressed(compressData);
-        props.setReferentialIntegrityEnforced(true);
-
-        entities.persist(props);
-
-        // References will be persisted in the commit ...
-        return uuidString;
-    }
-
-    /**
-     * Attempt to resolve the reference.
-     * 
-     * @param reference the reference
-     * @return the UUID of the node to which the reference points, or null if the reference could not be resolved
-     */
-    protected String resolveToUuid( Reference reference ) {
-        // See if the reference is by UUID ...
-        try {
-            UUID uuid = uuidFactory.create(reference);
-            ActualLocation actualLocation = getActualLocation(new Location(uuid));
-            return actualLocation.uuid;
-        } catch (ValueFormatException e) {
-            // Unknown kind of reference, which we don't track
-        } catch (PathNotFoundException e) {
-            // Unable to resolve reference ...
-        }
-        // Unable to resolve reference ...
-        return null;
-    }
-
-    /**
-     * Utility method to look up the actual information given a supplied location. This method verifies that the location actually
-     * represents an existing node, or it throws a {@link PathNotFoundException}. In all cases, the resulting information contains
-     * the correct path and the correct UUID.
-     * <p>
-     * Note that this method sometimes performs "unnecessary" work when the location contains both a path to a node and the node's
-     * corresponding UUID. Strictly speaking, this method would need to do very little. However, in such cases, this method does
-     * verify that the information is still correct (ensuring that calls to use the {@link ChildEntity} will be correct). So,
-     * while this work <i>may</i> be unnecessary, it does ensure that the location is consistent and correct (something that is
-     * not unnecessary).
-     * </p>
-     * <p>
-     * There are cases when a request containing a Path and a UUID are no longer correct. The node may have been just moved by
-     * another request (perhaps from a different client), or there may be an error in the component making the request. In these
-     * cases, this method assumes that the path is incorrect (since paths may change) and finds the <i>correct path</i> given the
-     * UUID.
-     * </p>
-     * <p>
-     * This method will also find the path when the location contains just the UUID.
-     * </p>
-     * 
-     * @param original the original location; may not be null
-     * @return the actual location, which includes the verified location and additional information needed by this method that may
-     *         be usable after this method is called
-     * @throws PathNotFoundException if the location does not represent a location that could be found
-     */
-    protected ActualLocation getActualLocation( Location original ) throws PathNotFoundException {
-        assert original != null;
-
-        // Look for the UUID in the original ...
-        Property uuidProperty = original.getIdProperty(DnaLexicon.UUID);
-        String uuidString = uuidProperty != null && !uuidProperty.isEmpty() ? stringFactory.create(uuidProperty.getFirstValue()) : null;
-
-        Path path = original.getPath();
-        if (path != null) {
-            // See if the location is already in the cache ...
-            Location cached = cache.getLocationFor(path);
-            if (cached != null) {
-                return new ActualLocation(cached, cached.getUuid().toString(), null);
-            }
-        }
-
-        // If the original location has a UUID, then use that to find the child entity that represents the location ...
-        if (uuidString != null) {
-            // The original has a UUID, so use that to find the child entity.
-            // Then walk up the ancestors and build the path.
-            String nodeUuidString = uuidString;
-            LinkedList<Path.Segment> segments = new LinkedList<Path.Segment>();
-            ChildEntity entity = null;
-            ChildEntity originalEntity = null;
-            while (uuidString != null && !uuidString.equals(this.rootNodeUuidString)) {
-                Query query = entities.createNamedQuery("ChildEntity.findByChildUuid");
-                query.setParameter("childUuidString", uuidString);
-                try {
-                    // Find the parent of the UUID ...
-                    entity = (ChildEntity)query.getSingleResult();
-                    if (originalEntity == null) originalEntity = entity;
-                    String localName = entity.getChildName();
-                    String uri = entity.getChildNamespace().getUri();
-                    int sns = entity.getSameNameSiblingIndex();
-                    Name name = nameFactory.create(uri, localName);
-                    segments.addFirst(pathFactory.createSegment(name, sns));
-                    uuidString = entity.getId().getParentUuidString();
-                } catch (NoResultException e) {
-                    uuidString = null;
-                }
-            }
-            Path fullPath = pathFactory.createAbsolutePath(segments);
-            Location newLocation = new Location(fullPath, uuidProperty);
-            cache.addNewNode(newLocation);
-            return new ActualLocation(newLocation, nodeUuidString, originalEntity);
-        }
-
-        // There is no UUID, so look for a path ...
-        if (path == null) {
-            String propName = DnaLexicon.UUID.getString(getExecutionContext().getNamespaceRegistry());
-            String msg = JpaConnectorI18n.locationShouldHavePathAndOrProperty.text(getSourceName(), propName);
-            throw new PathNotFoundException(original, pathFactory.createRootPath(), msg);
-        }
-
-        // Walk the child entities, starting at the root, down the to the path ...
-        if (path.isRoot()) {
-            Location newLocation = original.with(rootNodeUuid);
-            cache.addNewNode(newLocation);
-            return new ActualLocation(newLocation, rootNodeUuidString, null);
-        }
-        // See if the parent location is known in the cache ...
-        Location cachedParent = cache.getLocationFor(path.getParent());
-        if (cachedParent != null) {
-            // We know the UUID of the parent, so we can find the child a little faster ...
-            ChildEntity child = findByPathSegment(cachedParent.getUuid().toString(), path.getLastSegment());
-            uuidString = child.getId().getChildUuidString();
-            Location newLocation = original.with(UUID.fromString(uuidString));
-            cache.addNewNode(newLocation);
-            return new ActualLocation(newLocation, uuidString, child);
-        }
-
-        // We couldn't find the parent, so we need to search by path ...
-        String parentUuid = this.rootNodeUuidString;
-        ChildEntity child = null;
-        for (Path.Segment segment : path) {
-            child = findByPathSegment(parentUuid, segment);
-            if (child == null) {
-                // Unable to complete the path, so prepare the exception by determining the lowest path that exists ...
-                Path lowest = path;
-                while (lowest.getLastSegment() != segment) {
-                    lowest = lowest.getParent();
-                }
-                lowest = lowest.getParent();
-                throw new PathNotFoundException(original, lowest);
-            }
-            parentUuid = child.getId().getChildUuidString();
-        }
-        assert child != null;
-        uuidString = child.getId().getChildUuidString();
-        Location newLocation = original.with(UUID.fromString(uuidString));
-        cache.addNewNode(newLocation);
-        return new ActualLocation(newLocation, uuidString, child);
-    }
-
-    /**
-     * Find the node with the supplied path segment that is a child of the supplied parent.
-     * 
-     * @param parentUuid the UUID of the parent node, in string form
-     * @param pathSegment the path segment of the child
-     * @return the existing namespace, or null if one does not exist
-     * @throws IllegalArgumentException if the manager or URI are null
-     */
-    protected ChildEntity findByPathSegment( String parentUuid,
-                                             Path.Segment pathSegment ) {
-        assert namespaces != null;
-        assert parentUuid != null;
-        assert pathSegment != null;
-        Name name = pathSegment.getName();
-        String localName = name.getLocalName();
-        String nsUri = name.getNamespaceUri();
-        NamespaceEntity ns = namespaces.get(nsUri, false);
-        if (ns == null) {
-            // The namespace can't be found, then certainly the node won't be found ...
-            return null;
-        }
-        int snsIndex = pathSegment.hasIndex() ? pathSegment.getIndex() : 1;
-        Query query = entities.createNamedQuery("ChildEntity.findByPathSegment");
-        query.setParameter("parentUuidString", parentUuid);
-        query.setParameter("ns", ns.getId());
-        query.setParameter("childName", localName);
-        query.setParameter("sns", snsIndex);
-        try {
-            return (ChildEntity)query.getSingleResult();
-        } catch (NoResultException e) {
-            return null;
-        }
-    }
-
-    protected String createHexValuesString( Collection<String> hexValues ) {
-        if (hexValues == null || hexValues.isEmpty()) return null;
-        StringBuilder sb = new StringBuilder();
-        boolean first = true;
-        for (String hexValue : hexValues) {
-            if (first) {
-                first = false;
-            } else {
-                sb.append(',');
-            }
-            sb.append(hexValue);
-        }
-        return sb.toString();
-    }
-
-    protected Collection<String> createHexValues( String hexValuesString ) {
-        return Arrays.asList(hexValuesString.split(","));
-    }
-
-    protected class LargeValueSerializer implements LargeValues {
-        private final PropertiesEntity properties;
-        private Set<String> written;
-
-        public LargeValueSerializer( PropertiesEntity entity ) {
-            this.properties = entity;
-            this.written = null;
-        }
-
-        public LargeValueSerializer( PropertiesEntity entity,
-                                     Set<String> written ) {
-            this.properties = entity;
-            this.written = written;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#getMinimumSize()
-         */
-        public long getMinimumSize() {
-            return largeValueMinimumSizeInBytes;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.properties.ValueFactories,
-         *      byte[], long)
-         */
-        public Object read( ValueFactories valueFactories,
-                            byte[] hash,
-                            long length ) throws IOException {
-            String hashStr = StringUtil.getHexString(hash);
-            // Find the large value ...
-            LargeValueId largeValueId = new LargeValueId(hashStr);
-            LargeValueEntity entity = entities.find(LargeValueEntity.class, largeValueId);
-            if (entity != null) {
-                // Find the large value from the existing property entity ...
-                byte[] data = entity.getData();
-                if (entity.isCompressed()) {
-                    InputStream stream = new GZIPInputStream(new ByteArrayInputStream(data));
-                    try {
-                        data = IoUtil.readBytes(stream);
-                    } finally {
-                        stream.close();
-                    }
-                }
-                return valueFactories.getValueFactory(entity.getType()).create(data);
-            }
-            throw new IOException(JpaConnectorI18n.unableToReadLargeValue.text(getSourceName(), hashStr));
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#write(byte[], long,
-         *      org.jboss.dna.graph.properties.PropertyType, java.lang.Object)
-         */
-        public void write( byte[] hash,
-                           long length,
-                           PropertyType type,
-                           Object value ) throws IOException {
-            if (value == null) return;
-            String hashStr = StringUtil.getHexString(hash);
-            if (written != null) written.add(hashStr);
-
-            // Look for an existing value in the collection ...
-            final LargeValueId id = new LargeValueId(hashStr);
-            for (LargeValueId existing : properties.getLargeValues()) {
-                if (existing.equals(id)) {
-                    // Already associated with this properties entity
-                    return;
-                }
-            }
-            LargeValueEntity entity = entities.find(LargeValueEntity.class, id);
-            if (entity == null) {
-                // We have to create the large value entity ...
-                entity = new LargeValueEntity();
-                entity.setCompressed(true);
-                entity.setId(id);
-                entity.setLength(length);
-                entity.setType(type);
-                ValueFactories factories = getExecutionContext().getValueFactories();
-                byte[] bytes = null;
-                switch (type) {
-                    case BINARY:
-                        Binary binary = factories.getBinaryFactory().create(value);
-                        InputStream stream = null;
-                        try {
-                            binary.acquire();
-                            stream = binary.getStream();
-                            if (compressData) stream = new GZIPInputStream(stream);
-                            bytes = IoUtil.readBytes(stream);
-                        } finally {
-                            try {
-                                if (stream != null) stream.close();
-                            } finally {
-                                binary.release();
-                            }
-                        }
-                        break;
-                    case URI:
-                        // This will be treated as a string ...
-                    default:
-                        String str = factories.getStringFactory().create(value);
-                        if (compressData) {
-                            ByteArrayOutputStream bs = new ByteArrayOutputStream();
-                            OutputStream strStream = new GZIPOutputStream(bs);
-                            try {
-                                IoUtil.write(str, strStream);
-                            } finally {
-                                strStream.close();
-                            }
-                            bytes = bs.toByteArray();
-                        } else {
-                            bytes = str.getBytes();
-                        }
-                        break;
-                }
-                entity.setData(bytes);
-                entities.persist(entity);
-            }
-            // Now associate the large value with the properties entity ...
-            assert id.getHash() != null;
-            properties.getLargeValues().add(id);
-        }
-
-    }
-
-    protected class RecordingLargeValues implements LargeValues {
-        protected final Collection<String> readKeys = new HashSet<String>();
-        protected final Collection<String> writtenKeys = new HashSet<String>();
-        protected final LargeValues delegate;
-
-        RecordingLargeValues( LargeValues delegate ) {
-            assert delegate != null;
-            this.delegate = delegate;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#getMinimumSize()
-         */
-        public long getMinimumSize() {
-            return delegate.getMinimumSize();
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.properties.ValueFactories,
-         *      byte[], long)
-         */
-        public Object read( ValueFactories valueFactories,
-                            byte[] hash,
-                            long length ) throws IOException {
-            String key = StringUtil.getHexString(hash);
-            readKeys.add(key);
-            return delegate.read(valueFactories, hash, length);
-        }
-
-        public void write( byte[] hash,
-                           long length,
-                           PropertyType type,
-                           Object value ) throws IOException {
-            String key = StringUtil.getHexString(hash);
-            writtenKeys.add(key);
-            delegate.write(hash, length, type, value);
-        }
-    }
-
-    protected class SkippedLargeValues implements LargeValues {
-        protected Collection<String> skippedKeys = new HashSet<String>();
-        protected final LargeValues delegate;
-
-        SkippedLargeValues( LargeValues delegate ) {
-            assert delegate != null;
-            this.delegate = delegate;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#getMinimumSize()
-         */
-        public long getMinimumSize() {
-            return delegate.getMinimumSize();
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.properties.ValueFactories,
-         *      byte[], long)
-         */
-        public Object read( ValueFactories valueFactories,
-                            byte[] hash,
-                            long length ) throws IOException {
-            String key = StringUtil.getHexString(hash);
-            skippedKeys.add(key);
-            return null;
-        }
-
-        public void write( byte[] hash,
-                           long length,
-                           PropertyType type,
-                           Object value ) {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    @Immutable
-    protected static class ActualLocation {
-        /** The actual location */
-        protected final Location location;
-        /** The string-form of the UUID, supplied as a convenience. */
-        protected final String uuid;
-        /** The ChildEntity that represents the location, which may be null if the location represents the root node */
-        protected final ChildEntity childEntity;
-
-        protected ActualLocation( Location location,
-                                  String uuid,
-                                  ChildEntity childEntity ) {
-            assert location != null;
-            assert uuid != null;
-            this.location = location;
-            this.uuid = uuid;
-            this.childEntity = childEntity;
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see java.lang.Object#toString()
-         */
-        @Override
-        public String toString() {
-            return this.location.toString() + " (uuid=" + uuid + ") " + childEntity;
-        }
-    }
-
-    protected class References implements Serializer.ReferenceValues {
-        private Set<Reference> read;
-        private Set<Reference> removed;
-        private Set<Reference> written;
-
-        protected References() {
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.ReferenceValues#read(org.jboss.dna.graph.properties.Reference)
-         */
-        public void read( Reference reference ) {
-            if (read == null) read = new HashSet<Reference>();
-            read.add(reference);
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.ReferenceValues#remove(org.jboss.dna.graph.properties.Reference)
-         */
-        public void remove( Reference reference ) {
-            if (removed == null) removed = new HashSet<Reference>();
-            removed.add(reference);
-        }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.ReferenceValues#write(org.jboss.dna.graph.properties.Reference)
-         */
-        public void write( Reference reference ) {
-            if (written == null) written = new HashSet<Reference>();
-            written.add(reference);
-        }
-
-        public boolean hasRead() {
-            return read != null;
-        }
-
-        public boolean hasRemoved() {
-            return removed != null;
-        }
-
-        public boolean hasWritten() {
-            return written != null;
-        }
-
-        /**
-         * @return read
-         */
-        public Set<Reference> getRead() {
-            if (read != null) return read;
-            return Collections.emptySet();
-        }
-
-        /**
-         * @return removed
-         */
-        public Set<Reference> getRemoved() {
-            if (removed != null) return removed;
-            return Collections.emptySet();
-        }
-
-        /**
-         * @return written
-         */
-        public Set<Reference> getWritten() {
-            if (written != null) return written;
-            return Collections.emptySet();
-        }
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicRequestProcessor.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,1845 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import net.jcip.annotations.Immutable;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.IoUtil;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.connector.store.jpa.JpaConnectorI18n;
+import org.jboss.dna.connector.store.jpa.model.common.NamespaceEntity;
+import org.jboss.dna.connector.store.jpa.util.Namespaces;
+import org.jboss.dna.connector.store.jpa.util.RequestProcessorCache;
+import org.jboss.dna.connector.store.jpa.util.Serializer;
+import org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.JcrLexicon;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ReferentialIntegrityException;
+import org.jboss.dna.graph.property.UuidFactory;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.InvalidRequestException;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadBranchRequest;
+import org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
+import org.jboss.dna.graph.request.ReadPropertyRequest;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
+
+/**
+ * @author Randall Hauch
+ */
+ at NotThreadSafe
+public class BasicRequestProcessor extends RequestProcessor {
+
+    protected final EntityManager entities;
+    protected final ValueFactory<String> stringFactory;
+    protected final PathFactory pathFactory;
+    protected final NameFactory nameFactory;
+    protected final UuidFactory uuidFactory;
+    protected final Namespaces namespaces;
+    protected final UUID rootNodeUuid;
+    protected final String rootNodeUuidString;
+    protected final Serializer serializer;
+    protected final long largeValueMinimumSizeInBytes;
+    protected final boolean compressData;
+    protected final Logger logger;
+    protected final RequestProcessorCache cache;
+    protected final boolean enforceReferentialIntegrity;
+    private boolean referencesChanged;
+
+    /**
+     * @param sourceName
+     * @param context
+     * @param entityManager
+     * @param rootNodeUuid
+     * @param largeValueMinimumSizeInBytes
+     * @param compressData
+     * @param enforceReferentialIntegrity
+     */
+    public BasicRequestProcessor( String sourceName,
+                                  ExecutionContext context,
+                                  EntityManager entityManager,
+                                  UUID rootNodeUuid,
+                                  long largeValueMinimumSizeInBytes,
+                                  boolean compressData,
+                                  boolean enforceReferentialIntegrity ) {
+        super(sourceName, context);
+        assert entityManager != null;
+        assert rootNodeUuid != null;
+        this.entities = entityManager;
+        ValueFactories valuesFactory = context.getValueFactories();
+        this.stringFactory = valuesFactory.getStringFactory();
+        this.pathFactory = valuesFactory.getPathFactory();
+        this.nameFactory = valuesFactory.getNameFactory();
+        this.uuidFactory = valuesFactory.getUuidFactory();
+        this.namespaces = new Namespaces(entityManager);
+        this.rootNodeUuid = rootNodeUuid;
+        this.rootNodeUuidString = this.rootNodeUuid.toString();
+        this.largeValueMinimumSizeInBytes = largeValueMinimumSizeInBytes;
+        this.compressData = compressData;
+        this.enforceReferentialIntegrity = enforceReferentialIntegrity;
+        this.serializer = new Serializer(context, true);
+        this.logger = getExecutionContext().getLogger(getClass());
+        this.cache = new RequestProcessorCache(this.pathFactory);
+
+        // Start the transaction ...
+        this.entities.getTransaction().begin();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CreateNodeRequest)
+     */
+    @Override
+    public void process( CreateNodeRequest request ) {
+        logger.trace(request.toString());
+        Location actualLocation = null;
+        try {
+            // Create nodes have to be defined via a path ...
+            Location parentLocation = request.under();
+            ActualLocation actual = getActualLocation(parentLocation);
+            String parentUuidString = actual.uuid;
+            assert parentUuidString != null;
+
+            // We need to look for an existing UUID property in the request,
+            // so since we have to iterate through the properties, go ahead an serialize them right away ...
+            String uuidString = null;
+            for (Property property : request.properties()) {
+                if (property.getName().equals(DnaLexicon.UUID)) {
+                    uuidString = stringFactory.create(property.getFirstValue());
+                    break;
+                }
+            }
+            if (uuidString == null) uuidString = UUID.randomUUID().toString();
+            assert uuidString != null;
+            createProperties(uuidString, request.properties());
+
+            // Find or create the namespace for the child ...
+            Name childName = request.named();
+            String childNsUri = childName.getNamespaceUri();
+            NamespaceEntity ns = namespaces.get(childNsUri, true);
+            assert ns != null;
+            final Path parentPath = actual.location.getPath();
+            assert parentPath != null;
+
+            // Figure out the next SNS index and index-in-parent for this new child ...
+            actualLocation = addNewChild(actual, uuidString, childName);
+
+            // Since we've just created this node, we know about all the children (actually, there are none).
+            cache.setAllChildren(actualLocation.getPath(), new LinkedList<Location>());
+
+            // Flush the entities ...
+            // entities.flush();
+
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            logger.trace(e, "Problem " + request);
+            return;
+        }
+        request.setActualLocationOfNode(actualLocation);
+    }
+
+    protected Location addNewChild( ActualLocation parent,
+                                    String childUuid,
+                                    Name childName ) {
+        int nextSnsIndex = 1; // SNS index is 1-based
+        int nextIndexInParent = 0; // index-in-parent is 0-based
+        String childNsUri = childName.getNamespaceUri();
+        NamespaceEntity ns = namespaces.get(childNsUri, true);
+        assert ns != null;
+
+        final Path parentPath = parent.location.getPath();
+        assert parentPath != null;
+
+        // Look in the cache for the children of the parent node.
+        LinkedList<Location> childrenOfParent = cache.getAllChildren(parentPath);
+        if (childrenOfParent != null) {
+            // The cache had the complete list of children for the parent node, which means
+            // we know about all of the children and can walk the children to figure out the next indexes.
+            nextIndexInParent = childrenOfParent.size();
+            if (nextIndexInParent > 1) {
+                // Since we want the last indexes, process the list backwards ...
+                ListIterator<Location> iter = childrenOfParent.listIterator(childrenOfParent.size());
+                while (iter.hasPrevious()) {
+                    Location existing = iter.previous();
+                    Path.Segment segment = existing.getPath().getLastSegment();
+                    if (!segment.getName().equals(childName)) continue;
+                    // Otherwise the name matched, so get the indexes ...
+                    nextSnsIndex = segment.getIndex() + 1;
+                }
+            }
+        } else {
+            // The cache did not have the complete list of children for the parent node,
+            // so we need to look the values up by querying the database ...
+
+            // Find the largest SNS index in the existing ChildEntity objects with the same name ...
+            String childLocalName = childName.getLocalName();
+            Query query = entities.createNamedQuery("ChildEntity.findMaximumSnsIndex");
+            query.setParameter("parentUuid", parent.uuid);
+            query.setParameter("ns", ns.getId());
+            query.setParameter("childName", childLocalName);
+            try {
+                Integer result = (Integer)query.getSingleResult();
+                nextSnsIndex = result != null ? result + 1 : 1; // SNS index is 1-based
+            } catch (NoResultException e) {
+            }
+
+            // Find the largest child index in the existing ChildEntity objects ...
+            query = entities.createNamedQuery("ChildEntity.findMaximumChildIndex");
+            query.setParameter("parentUuid", parent.uuid);
+            try {
+                Integer result = (Integer)query.getSingleResult();
+                nextIndexInParent = result != null ? result + 1 : 0; // index-in-parent is 0-based
+            } catch (NoResultException e) {
+            }
+        }
+
+        // Create the new ChildEntity ...
+        ChildId id = new ChildId(parent.uuid, childUuid);
+        ChildEntity entity = new ChildEntity(id, nextIndexInParent, ns, childName.getLocalName(), nextSnsIndex);
+        entities.persist(entity);
+
+        // Set the actual path, regardless of the supplied path...
+        Path path = pathFactory.create(parentPath, childName, nextSnsIndex);
+        Location actualLocation = new Location(path, UUID.fromString(childUuid));
+
+        // Finally, update the cache with the information we know ...
+        if (childrenOfParent != null) {
+            // Add to the cached list of children ...
+            childrenOfParent.add(actualLocation);
+        }
+        return actualLocation;
+    }
+
+    protected class NextChildIndexes {
+        protected final int nextIndexInParent;
+        protected final int nextSnsIndex;
+
+        protected NextChildIndexes( int nextIndexInParent,
+                                    int nextSnsIndex ) {
+            this.nextIndexInParent = nextIndexInParent;
+            this.nextSnsIndex = nextSnsIndex;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadNodeRequest)
+     */
+    @Override
+    public void process( ReadNodeRequest request ) {
+        logger.trace(request.toString());
+        Location actualLocation = null;
+        try {
+            Location location = request.at();
+            ActualLocation actual = getActualLocation(location);
+            String parentUuidString = actual.uuid;
+            actualLocation = actual.location;
+
+            // Record the UUID as a property, since it's not stored in the serialized properties...
+            request.addProperty(actualLocation.getIdProperty(DnaLexicon.UUID));
+
+            // Find the properties entity for this node ...
+            Query query = entities.createNamedQuery("PropertiesEntity.findByUuid");
+            query.setParameter("uuid", parentUuidString);
+            try {
+                PropertiesEntity entity = (PropertiesEntity)query.getSingleResult();
+
+                // Deserialize the properties ...
+                boolean compressed = entity.isCompressed();
+                Collection<Property> properties = new LinkedList<Property>();
+                byte[] data = entity.getData();
+                if (data != null) {
+                    LargeValueSerializer largeValues = new LargeValueSerializer(entity);
+                    ByteArrayInputStream bais = new ByteArrayInputStream(data);
+                    InputStream is = compressed ? new GZIPInputStream(bais) : bais;
+                    ObjectInputStream ois = new ObjectInputStream(is);
+                    try {
+                        serializer.deserializeAllProperties(ois, properties, largeValues);
+                        for (Property property : properties) {
+                            request.addProperty(property);
+                        }
+                    } finally {
+                        ois.close();
+                    }
+                }
+
+            } catch (NoResultException e) {
+                // No properties, but that's okay...
+            }
+
+            // Get the children for this node ...
+            for (Location childLocation : getAllChildren(actual)) {
+                request.addChild(childLocation);
+            }
+        } catch (NoResultException e) {
+            // there are no properties (probably not expected, but still okay) ...
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
+        setCacheableInfo(request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
+     */
+    @Override
+    public void process( ReadAllChildrenRequest request ) {
+        logger.trace(request.toString());
+        Location actualLocation = null;
+        try {
+            Location location = request.of();
+            ActualLocation actual = getActualLocation(location);
+            actualLocation = actual.location;
+
+            // Get the children for this node ...
+            for (Location childLocation : getAllChildren(actual)) {
+                request.addChild(childLocation);
+            }
+        } catch (NoResultException e) {
+            // there are no properties (probably not expected, but still okay) ...
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
+        setCacheableInfo(request);
+    }
+
+    /**
+     * Utility method to obtain all of the children for a node, either from the cache (if all children are known to this
+     * processor) or by querying the database (and caching the list of children).
+     * 
+     * @param parent the actual location of the parent node; may not be null
+     * @return the list of child locations
+     */
+    protected LinkedList<Location> getAllChildren( ActualLocation parent ) {
+        assert parent != null;
+        Path parentPath = parent.location.getPath();
+        assert parentPath != null;
+        LinkedList<Location> cachedChildren = cache.getAllChildren(parentPath);
+        if (cachedChildren != null) {
+            // The cache has all of the children for the node ...
+            return cachedChildren;
+        }
+
+        // Not found in the cache, so query the database ...
+        Query query = entities.createNamedQuery("ChildEntity.findAllUnderParent");
+        query.setParameter("parentUuidString", parent.uuid);
+        LinkedList<Location> childLocations = new LinkedList<Location>();
+        @SuppressWarnings( "unchecked" )
+        List<ChildEntity> children = query.getResultList();
+        for (ChildEntity child : children) {
+            String namespaceUri = child.getChildNamespace().getUri();
+            String localName = child.getChildName();
+            Name childName = nameFactory.create(namespaceUri, localName);
+            int sns = child.getSameNameSiblingIndex();
+            Path childPath = pathFactory.create(parentPath, childName, sns);
+            String childUuidString = child.getId().getChildUuidString();
+            Location childLocation = new Location(childPath, UUID.fromString(childUuidString));
+            childLocations.add(childLocation);
+        }
+        // Update the cache ...
+        cache.setAllChildren(parentPath, childLocations);
+        return childLocations;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadBlockOfChildrenRequest)
+     */
+    @Override
+    public void process( ReadBlockOfChildrenRequest request ) {
+        logger.trace(request.toString());
+        Location actualLocation = null;
+        final int startingIndex = request.startingAtIndex();
+        try {
+            Location parentLocation = request.of();
+            ActualLocation actualParent = getActualLocation(parentLocation);
+            actualLocation = actualParent.location;
+
+            Path parentPath = actualParent.location.getPath();
+            assert parentPath != null;
+            LinkedList<Location> cachedChildren = cache.getAllChildren(parentPath);
+            if (cachedChildren != null) {
+                // The cache has all of the children for the node ...
+                if (startingIndex < cachedChildren.size()) {
+                    ListIterator<Location> iter = cachedChildren.listIterator(startingIndex);
+                    for (int i = 0; i != request.count() && iter.hasNext(); ++i) {
+                        Location child = iter.next();
+                        request.addChild(child);
+                    }
+                }
+            } else {
+                // Nothing was cached, so we need to search the database for the children ...
+                Query query = entities.createNamedQuery("ChildEntity.findRangeUnderParent");
+                query.setParameter("parentUuidString", actualParent.uuid);
+                query.setParameter("firstIndex", startingIndex);
+                query.setParameter("afterIndex", startingIndex + request.count());
+                @SuppressWarnings( "unchecked" )
+                List<ChildEntity> children = query.getResultList();
+                for (ChildEntity child : children) {
+                    String namespaceUri = child.getChildNamespace().getUri();
+                    String localName = child.getChildName();
+                    Name childName = nameFactory.create(namespaceUri, localName);
+                    int sns = child.getSameNameSiblingIndex();
+                    Path childPath = pathFactory.create(parentPath, childName, sns);
+                    String childUuidString = child.getId().getChildUuidString();
+                    Location childLocation = new Location(childPath, UUID.fromString(childUuidString));
+                    request.addChild(childLocation);
+                }
+                // Do not update the cache, since we don't know all of the children.
+            }
+
+        } catch (NoResultException e) {
+            // there are no properties (probably not expected, but still okay) ...
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
+        setCacheableInfo(request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest)
+     */
+    @Override
+    public void process( ReadNextBlockOfChildrenRequest request ) {
+        logger.trace(request.toString());
+        Location actualLocation = null;
+        final Location previousSibling = request.startingAfter();
+        final int count = request.count();
+        try {
+            ActualLocation actualSibling = getActualLocation(previousSibling);
+            actualLocation = actualSibling.location;
+            if (!actualLocation.getPath().isRoot()) {
+                // First look in the cache for the children of the parent ...
+                Path parentPath = actualSibling.location.getPath().getParent();
+                assert parentPath != null;
+                LinkedList<Location> cachedChildren = cache.getAllChildren(parentPath);
+                if (cachedChildren != null) {
+                    // The cache has all of the children for the node.
+                    // First find the location of the previous sibling ...
+                    boolean accumulate = false;
+                    int counter = 0;
+                    for (Location child : cachedChildren) {
+                        if (accumulate) {
+                            // We're accumulating children ...
+                            request.addChild(child);
+                            ++counter;
+                            if (counter <= count) continue;
+                            break;
+                        }
+                        // Haven't found the previous sibling yet ...
+                        if (child.isSame(previousSibling)) {
+                            accumulate = true;
+                        }
+                    }
+                } else {
+                    // The children were not found in the cache, so we have to search the database.
+                    // We don't know the UUID of the parent, so find the previous sibling and
+                    // then get the starting index and the parent UUID ...
+                    ChildEntity previousChild = actualSibling.childEntity;
+                    if (previousChild == null) {
+                        Query query = entities.createNamedQuery("ChildEntity.findByChildUuid");
+                        query.setParameter("childUuidString", actualSibling.uuid);
+                        previousChild = (ChildEntity)query.getSingleResult();
+                    }
+                    int startingIndex = previousChild.getIndexInParent() + 1;
+                    String parentUuid = previousChild.getId().getParentUuidString();
+
+                    // Now search the database for the children ...
+                    Query query = entities.createNamedQuery("ChildEntity.findRangeUnderParent");
+                    query.setParameter("parentUuidString", parentUuid);
+                    query.setParameter("firstIndex", startingIndex);
+                    query.setParameter("afterIndex", startingIndex + request.count());
+                    @SuppressWarnings( "unchecked" )
+                    List<ChildEntity> children = query.getResultList();
+                    LinkedList<Location> allChildren = null;
+                    if (startingIndex == 1 && children.size() < request.count()) {
+                        // The previous child was the first sibling, and we got fewer children than
+                        // the max count. This means we know all of the children, so accumulate the locations
+                        // so they can be cached ...
+                        allChildren = new LinkedList<Location>();
+                        allChildren.add(actualSibling.location);
+                    }
+                    for (ChildEntity child : children) {
+                        String namespaceUri = child.getChildNamespace().getUri();
+                        String localName = child.getChildName();
+                        Name childName = nameFactory.create(namespaceUri, localName);
+                        int sns = child.getSameNameSiblingIndex();
+                        Path childPath = pathFactory.create(parentPath, childName, sns);
+                        String childUuidString = child.getId().getChildUuidString();
+                        Location childLocation = new Location(childPath, UUID.fromString(childUuidString));
+                        request.addChild(childLocation);
+                        if (allChildren != null) {
+                            // We're going to cache the results, so add this child ...
+                            allChildren.add(childLocation);
+                        }
+                    }
+
+                    if (allChildren != null) {
+                        cache.setAllChildren(parentPath, allChildren);
+                    }
+                }
+            }
+
+        } catch (NoResultException e) {
+            // there are no properties (probably not expected, but still okay) ...
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        if (actualLocation != null) request.setActualLocationOfStartingAfterNode(actualLocation);
+        setCacheableInfo(request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllPropertiesRequest)
+     */
+    @Override
+    public void process( ReadAllPropertiesRequest request ) {
+        logger.trace(request.toString());
+        Location actualLocation = null;
+        try {
+            Location location = request.at();
+            ActualLocation actual = getActualLocation(location);
+            String uuidString = actual.uuid;
+            actualLocation = actual.location;
+
+            // Record the UUID as a property, since it's not stored in the serialized properties...
+            request.addProperty(actualLocation.getIdProperty(DnaLexicon.UUID));
+
+            // Find the properties entity for this node ...
+            Query query = entities.createNamedQuery("PropertiesEntity.findByUuid");
+            query.setParameter("uuid", uuidString);
+            PropertiesEntity entity = (PropertiesEntity)query.getSingleResult();
+
+            // Deserialize the properties ...
+            boolean compressed = entity.isCompressed();
+            int propertyCount = entity.getPropertyCount();
+            Collection<Property> properties = new ArrayList<Property>(propertyCount);
+            byte[] data = entity.getData();
+            if (data != null) {
+                LargeValueSerializer largeValues = new LargeValueSerializer(entity);
+                ByteArrayInputStream bais = new ByteArrayInputStream(data);
+                InputStream is = compressed ? new GZIPInputStream(bais) : bais;
+                ObjectInputStream ois = new ObjectInputStream(is);
+                try {
+                    serializer.deserializeAllProperties(ois, properties, largeValues);
+                    for (Property property : properties) {
+                        request.addProperty(property);
+                    }
+                } finally {
+                    ois.close();
+                }
+            }
+        } catch (NoResultException e) {
+            // there are no properties (probably not expected, but still okay) ...
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
+        setCacheableInfo(request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadPropertyRequest)
+     */
+    @Override
+    public void process( ReadPropertyRequest request ) {
+        logger.trace(request.toString());
+        // Small optimization ...
+        final Name propertyName = request.named();
+        if (DnaLexicon.UUID.equals(propertyName)) {
+            try {
+                // Just get the UUID ...
+                Location location = request.on();
+                ActualLocation actualLocation = getActualLocation(location);
+                UUID uuid = actualLocation.location.getUuid();
+                Property uuidProperty = getExecutionContext().getPropertyFactory().create(propertyName, uuid);
+                request.setProperty(uuidProperty);
+                request.setActualLocationOfNode(actualLocation.location);
+                setCacheableInfo(request);
+            } catch (Throwable e) { // Includes PathNotFoundException
+                request.setError(e);
+            }
+            return;
+        }
+        // Process the one property that's requested ...
+        Location actualLocation = null;
+        try {
+            Location location = request.on();
+            ActualLocation actual = getActualLocation(location);
+            String uuidString = actual.uuid;
+            actualLocation = actual.location;
+
+            // Find the properties entity for this node ...
+            Query query = entities.createNamedQuery("PropertiesEntity.findByUuid");
+            query.setParameter("uuid", uuidString);
+            PropertiesEntity entity = (PropertiesEntity)query.getSingleResult();
+
+            // Deserialize the stream of properties, but only materialize the one property ...
+            boolean compressed = entity.isCompressed();
+            int propertyCount = entity.getPropertyCount();
+            Collection<Property> properties = new ArrayList<Property>(propertyCount);
+            byte[] data = entity.getData();
+            if (data != null) {
+                LargeValueSerializer largeValues = new LargeValueSerializer(entity);
+                ByteArrayInputStream bais = new ByteArrayInputStream(data);
+                InputStream is = compressed ? new GZIPInputStream(bais) : bais;
+                ObjectInputStream ois = new ObjectInputStream(is);
+                try {
+                    Serializer.LargeValues skippedLargeValues = Serializer.NO_LARGE_VALUES;
+                    serializer.deserializeSomeProperties(ois, properties, largeValues, skippedLargeValues, propertyName);
+                    for (Property property : properties) {
+                        request.setProperty(property); // should be only one property
+                    }
+                } finally {
+                    ois.close();
+                }
+            }
+        } catch (NoResultException e) {
+            // there are no properties (probably not expected, but still okay) ...
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
+        setCacheableInfo(request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.UpdatePropertiesRequest)
+     */
+    @Override
+    public void process( UpdatePropertiesRequest request ) {
+        logger.trace(request.toString());
+        Location actualLocation = null;
+        try {
+            Location location = request.on();
+            ActualLocation actual = getActualLocation(location);
+            actualLocation = actual.location;
+
+            // Find the properties entity for this node ...
+            Query query = entities.createNamedQuery("PropertiesEntity.findByUuid");
+            query.setParameter("uuid", actual.uuid);
+            PropertiesEntity entity = null;
+            try {
+                entity = (PropertiesEntity)query.getSingleResult();
+
+                // Prepare the streams so we can deserialize all existing properties and reserialize the old and updated
+                // properties ...
+                boolean compressed = entity.isCompressed();
+                byte[] originalData = entity.getData();
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                OutputStream os = compressed ? new GZIPOutputStream(baos) : baos;
+                ObjectOutputStream oos = new ObjectOutputStream(os);
+                int numProps = 0;
+                LargeValueSerializer largeValues = null;
+                Collection<Property> props = request.properties();
+                References refs = enforceReferentialIntegrity ? new References() : null;
+                if (originalData == null) {
+                    largeValues = new LargeValueSerializer(entity);
+                    numProps = props.size();
+                    serializer.serializeProperties(oos, numProps, props, largeValues, refs);
+                } else {
+                    boolean hadLargeValues = !entity.getLargeValues().isEmpty();
+                    Set<String> largeValueHashesWritten = hadLargeValues ? new HashSet<String>() : null;
+                    largeValues = new LargeValueSerializer(entity, largeValueHashesWritten);
+                    ByteArrayInputStream bais = new ByteArrayInputStream(originalData);
+                    InputStream is = compressed ? new GZIPInputStream(bais) : bais;
+                    ObjectInputStream ois = new ObjectInputStream(is);
+                    SkippedLargeValues removedValues = new SkippedLargeValues(largeValues);
+                    try {
+                        Serializer.ReferenceValues refValues = refs != null ? refs : Serializer.NO_REFERENCES_VALUES;
+                        numProps = serializer.reserializeProperties(ois, oos, props, largeValues, removedValues, refValues);
+                    } finally {
+                        try {
+                            ois.close();
+                        } finally {
+                            oos.close();
+                        }
+                    }
+                    // The new large values were recorded and associated with the properties entity during reserialization.
+                    // However, any values no longer used now need to be removed ...
+                    if (hadLargeValues) {
+                        // Remove any large value from the 'skipped' list that was also written ...
+                        removedValues.skippedKeys.removeAll(largeValueHashesWritten);
+                        for (String oldHexKey : removedValues.skippedKeys) {
+                            LargeValueId id = new LargeValueId(oldHexKey);
+                            entity.getLargeValues().remove(id);
+                        }
+                    }
+
+                    if (refs != null) {
+                        // Remove any existing references ...
+                        if (refs.hasRemoved()) {
+                            for (Reference reference : refs.getRemoved()) {
+                                String toUuid = resolveToUuid(reference);
+                                if (toUuid != null) {
+                                    ReferenceId id = new ReferenceId(actual.uuid, toUuid);
+                                    ReferenceEntity refEntity = entities.find(ReferenceEntity.class, id);
+                                    if (refEntity != null) {
+                                        entities.remove(refEntity);
+                                        referencesChanged = true;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                entity.setPropertyCount(numProps);
+                entity.setData(baos.toByteArray());
+                entity.setCompressed(compressData);
+
+                if (refs != null && refs.hasWritten()) {
+                    // If there were references from the updated node ...
+                    Set<Reference> newReferences = refs.getWritten();
+                    // Remove any reference that was written (and not removed) ...
+                    newReferences.removeAll(refs.getRead());
+                    if (newReferences.size() != 0) {
+                        // Now save the new references ...
+                        for (Reference reference : newReferences) {
+                            String toUuid = resolveToUuid(reference);
+                            if (toUuid != null) {
+                                ReferenceId id = new ReferenceId(actual.uuid, toUuid);
+                                ReferenceEntity refEntity = new ReferenceEntity(id);
+                                entities.persist(refEntity);
+                                referencesChanged = true;
+                            }
+                        }
+                    }
+                }
+            } catch (NoResultException e) {
+                // there are no properties yet ...
+                createProperties(actual.uuid, request.properties());
+            }
+
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        if (actualLocation != null) request.setActualLocationOfNode(actualLocation);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadBranchRequest)
+     */
+    @Override
+    public void process( ReadBranchRequest request ) {
+        logger.trace(request.toString());
+        Location actualLocation = null;
+        try {
+            Location location = request.at();
+            ActualLocation actual = getActualLocation(location);
+            actualLocation = actual.location;
+            Path path = actualLocation.getPath();
+
+            // Record the location of each node by its UUID; we'll use this when processing the properties ...
+            Map<String, Location> locationsByUuid = new HashMap<String, Location>();
+            locationsByUuid.put(actual.uuid, location);
+
+            // Compute the subgraph, including the root ...
+            int maxDepth = request.maximumDepth();
+            SubgraphQuery query = SubgraphQuery.create(getExecutionContext(), entities, actualLocation.getUuid(), path, maxDepth);
+
+            try {
+                // Record all of the children ...
+                Path parent = path;
+                String parentUuid = actual.uuid;
+                Location parentLocation = actualLocation;
+                List<Location> children = new LinkedList<Location>();
+                Map<Location, List<Location>> childrenByParentLocation = new HashMap<Location, List<Location>>();
+                childrenByParentLocation.put(parentLocation, children);
+                boolean includeChildrenOfNodesAtMaxDepth = true;
+                for (ChildEntity child : query.getNodes(false, includeChildrenOfNodesAtMaxDepth)) {
+                    String namespaceUri = child.getChildNamespace().getUri();
+                    String localName = child.getChildName();
+                    Name childName = nameFactory.create(namespaceUri, localName);
+                    int sns = child.getSameNameSiblingIndex();
+                    // Figure out who the parent is ...
+                    String childParentUuid = child.getId().getParentUuidString();
+                    if (!parentUuid.equals(childParentUuid)) {
+                        // Find the correct parent ...
+                        parentLocation = locationsByUuid.get(childParentUuid);
+                        parent = parentLocation.getPath();
+                        parentUuid = childParentUuid;
+                        // See if there is already a list of children for this parent ...
+                        children = childrenByParentLocation.get(parentLocation);
+                        if (children == null) {
+                            children = new LinkedList<Location>();
+                            childrenByParentLocation.put(parentLocation, children);
+                        }
+                    }
+                    assert children != null;
+                    Path childPath = pathFactory.create(parent, childName, sns);
+                    String childUuidString = child.getId().getChildUuidString();
+                    Location childLocation = new Location(childPath, UUID.fromString(childUuidString));
+                    locationsByUuid.put(childUuidString, childLocation);
+                    children.add(childLocation);
+                }
+                // Now add the list of children to the results ...
+                for (Map.Entry<Location, List<Location>> entry : childrenByParentLocation.entrySet()) {
+                    // Don't add if there are no children ...
+                    if (!entry.getValue().isEmpty()) {
+                        request.setChildren(entry.getKey(), entry.getValue());
+                    }
+                }
+
+                // Note that we've found children for nodes that are at the maximum depth. This is so that the nodes
+                // in the subgraph all have the correct children. However, we don't want to store the properties for
+                // any node whose depth is greater than the maximum depth. Therefore, only get the properties that
+                // include nodes within the maximum depth...
+                includeChildrenOfNodesAtMaxDepth = false;
+
+                // Now record all of the properties ...
+                for (PropertiesEntity props : query.getProperties(true, includeChildrenOfNodesAtMaxDepth)) {
+                    boolean compressed = props.isCompressed();
+                    int propertyCount = props.getPropertyCount();
+                    Collection<Property> properties = new ArrayList<Property>(propertyCount);
+                    Location nodeLocation = locationsByUuid.get(props.getId().getUuidString());
+                    assert nodeLocation != null;
+                    // Record the UUID as a property, since it's not stored in the serialized properties...
+                    properties.add(actualLocation.getIdProperty(DnaLexicon.UUID));
+                    // Deserialize all the properties (except the UUID)...
+                    byte[] data = props.getData();
+                    if (data != null) {
+                        LargeValueSerializer largeValues = new LargeValueSerializer(props);
+                        ByteArrayInputStream bais = new ByteArrayInputStream(data);
+                        InputStream is = compressed ? new GZIPInputStream(bais) : bais;
+                        ObjectInputStream ois = new ObjectInputStream(is);
+                        try {
+                            serializer.deserializeAllProperties(ois, properties, largeValues);
+                            request.setProperties(nodeLocation, properties);
+                        } finally {
+                            ois.close();
+                        }
+                    }
+                }
+            } finally {
+                // Close and release the temporary data used for this operation ...
+                query.close();
+            }
+
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        request.setActualLocationOfNode(actualLocation);
+        setCacheableInfo(request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CopyBranchRequest)
+     */
+    @Override
+    public void process( CopyBranchRequest request ) {
+        logger.trace(request.toString());
+        Location actualFromLocation = null;
+        Location actualToLocation = null;
+        try {
+            Location fromLocation = request.from();
+            ActualLocation actualFrom = getActualLocation(fromLocation);
+            actualFromLocation = actualFrom.location;
+            Path fromPath = actualFromLocation.getPath();
+
+            Location newParentLocation = request.into();
+            ActualLocation actualNewParent = getActualLocation(newParentLocation);
+            assert actualNewParent != null;
+
+            // Create a map that we'll use to record the new UUID for each of the original nodes ...
+            Map<String, String> originalToNewUuid = new HashMap<String, String>();
+
+            // Compute the subgraph, including the top node in the subgraph ...
+            SubgraphQuery query = SubgraphQuery.create(getExecutionContext(), entities, actualFromLocation.getUuid(), fromPath, 0);
+            try {
+                // Walk through the original nodes, creating new ChildEntity object (i.e., copy) for each original ...
+                List<ChildEntity> originalNodes = query.getNodes(true, true);
+                Iterator<ChildEntity> originalIter = originalNodes.iterator();
+
+                // Start with the original (top-level) node first, since we need to add it to the list of children ...
+                if (originalIter.hasNext()) {
+                    ChildEntity original = originalIter.next();
+
+                    // Create a new UUID for the copy ...
+                    String copyUuid = UUID.randomUUID().toString();
+                    originalToNewUuid.put(original.getId().getChildUuidString(), copyUuid);
+
+                    // Now add the new copy of the original ...
+                    Name childName = fromPath.getLastSegment().getName();
+                    actualToLocation = addNewChild(actualNewParent, copyUuid, childName);
+                }
+
+                // Now create copies of all children in the subgraph, assigning new UUIDs to each new child ...
+                while (originalIter.hasNext()) {
+                    ChildEntity original = originalIter.next();
+                    String newParentUuidOfCopy = originalToNewUuid.get(original.getId().getParentUuidString());
+                    assert newParentUuidOfCopy != null;
+
+                    // Create a new UUID for the copy ...
+                    String copyUuid = UUID.randomUUID().toString();
+                    originalToNewUuid.put(original.getId().getChildUuidString(), copyUuid);
+
+                    // Create the copy ...
+                    ChildEntity copy = new ChildEntity(new ChildId(newParentUuidOfCopy, copyUuid), original.getIndexInParent(),
+                                                       original.getChildNamespace(), original.getChildName(),
+                                                       original.getSameNameSiblingIndex());
+                    entities.persist(copy);
+                }
+                entities.flush();
+
+                // Now create copies of all the intra-subgraph references, replacing the UUIDs on both ends ...
+                Set<String> newNodesWithReferenceProperties = new HashSet<String>();
+                for (ReferenceEntity reference : query.getInternalReferences()) {
+                    String newFromUuid = originalToNewUuid.get(reference.getId().getFromUuidString());
+                    assert newFromUuid != null;
+                    String newToUuid = originalToNewUuid.get(reference.getId().getToUuidString());
+                    assert newToUuid != null;
+                    ReferenceEntity copy = new ReferenceEntity(new ReferenceId(newFromUuid, newToUuid));
+                    entities.persist(copy);
+                    newNodesWithReferenceProperties.add(newFromUuid);
+                }
+
+                // Now create copies of all the references owned by the subgraph but pointing to non-subgraph nodes,
+                // so we only replaced the 'from' UUID ...
+                for (ReferenceEntity reference : query.getOutwardReferences()) {
+                    String oldToUuid = reference.getId().getToUuidString();
+                    String newFromUuid = originalToNewUuid.get(reference.getId().getFromUuidString());
+                    assert newFromUuid != null;
+                    ReferenceEntity copy = new ReferenceEntity(new ReferenceId(newFromUuid, oldToUuid));
+                    entities.persist(copy);
+                    newNodesWithReferenceProperties.add(newFromUuid);
+                }
+
+                // Now process the properties, creating a copy (note references are not changed) ...
+                for (PropertiesEntity original : query.getProperties(true, true)) {
+                    // Find the UUID of the copy ...
+                    String copyUuid = originalToNewUuid.get(original.getId().getUuidString());
+                    assert copyUuid != null;
+
+                    // Create the copy ...
+                    boolean compressed = original.isCompressed();
+                    byte[] originalData = original.getData();
+                    PropertiesEntity copy = new PropertiesEntity(new NodeId(copyUuid));
+                    copy.setCompressed(compressed);
+                    if (newNodesWithReferenceProperties.contains(copyUuid)) {
+
+                        // This node has internal or outward references that must be adjusted ...
+                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                        OutputStream os = compressed ? new GZIPOutputStream(baos) : baos;
+                        ObjectOutputStream oos = new ObjectOutputStream(os);
+                        ByteArrayInputStream bais = new ByteArrayInputStream(originalData);
+                        InputStream is = compressed ? new GZIPInputStream(bais) : bais;
+                        ObjectInputStream ois = new ObjectInputStream(is);
+                        try {
+                            serializer.adjustReferenceProperties(ois, oos, originalToNewUuid);
+                        } finally {
+                            try {
+                                ois.close();
+                            } finally {
+                                oos.close();
+                            }
+                        }
+                        copy.setData(baos.toByteArray());
+                    } else {
+                        // No references to adjust, so just copy the original data ...
+                        copy.setData(originalData);
+                    }
+                    copy.setPropertyCount(original.getPropertyCount());
+                    copy.setReferentialIntegrityEnforced(original.isReferentialIntegrityEnforced());
+                    entities.persist(copy);
+                }
+                entities.flush();
+
+            } finally {
+                // Close and release the temporary data used for this operation ...
+                query.close();
+            }
+
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        request.setActualLocations(actualFromLocation, actualToLocation);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.DeleteBranchRequest)
+     */
+    @Override
+    public void process( DeleteBranchRequest request ) {
+        logger.trace(request.toString());
+        Location actualLocation = null;
+        try {
+            Location location = request.at();
+            ActualLocation actual = getActualLocation(location);
+            actualLocation = actual.location;
+            Path path = actualLocation.getPath();
+
+            // Compute the subgraph, including the top node in the subgraph ...
+            SubgraphQuery query = SubgraphQuery.create(getExecutionContext(), entities, actualLocation.getUuid(), path, 0);
+            try {
+                ChildEntity deleted = query.getNode();
+                String parentUuidString = deleted.getId().getParentUuidString();
+                String childName = deleted.getChildName();
+                long nsId = deleted.getChildNamespace().getId();
+                int indexInParent = deleted.getIndexInParent();
+
+                // Get the locations of all deleted nodes, which will be required by events ...
+                List<Location> deletedLocations = query.getNodeLocations(true, true);
+
+                // Now delete the subgraph ...
+                query.deleteSubgraph(true);
+
+                // Verify referential integrity: that none of the deleted nodes are referenced by nodes not being deleted.
+                List<ReferenceEntity> invalidReferences = query.getInwardReferences();
+                if (invalidReferences.size() > 0) {
+                    // Some of the references that remain will be invalid, since they point to nodes that
+                    // have just been deleted. Build up the information necessary to produce a useful exception ...
+                    ValueFactory<Reference> refFactory = getExecutionContext().getValueFactories().getReferenceFactory();
+                    Map<Location, List<Reference>> invalidRefs = new HashMap<Location, List<Reference>>();
+                    for (ReferenceEntity entity : invalidReferences) {
+                        UUID fromUuid = UUID.fromString(entity.getId().getFromUuidString());
+                        ActualLocation actualFromLocation = getActualLocation(new Location(fromUuid));
+                        Location fromLocation = actualFromLocation.location;
+                        List<Reference> refs = invalidRefs.get(fromLocation);
+                        if (refs == null) {
+                            refs = new ArrayList<Reference>();
+                            invalidRefs.put(fromLocation, refs);
+                        }
+                        UUID toUuid = UUID.fromString(entity.getId().getToUuidString());
+                        refs.add(refFactory.create(toUuid));
+                    }
+                    String msg = JpaConnectorI18n.unableToDeleteBecauseOfReferences.text();
+                    throw new ReferentialIntegrityException(invalidRefs, msg);
+                }
+
+                // And adjust the SNS index and indexes ...
+                ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities, parentUuidString, childName, nsId, indexInParent);
+                entities.flush();
+
+                // Remove from the cache of children locations all entries for deleted nodes ...
+                cache.removeBranch(deletedLocations);
+            } finally {
+                // Close and release the temporary data used for this operation ...
+                query.close();
+            }
+
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        request.setActualLocationOfNode(actualLocation);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.MoveBranchRequest)
+     */
+    @Override
+    public void process( MoveBranchRequest request ) {
+        logger.trace(request.toString());
+        Location actualOldLocation = null;
+        Location actualNewLocation = null;
+        try {
+            Location fromLocation = request.from();
+            ActualLocation actualLocation = getActualLocation(fromLocation);
+            String fromUuidString = actualLocation.uuid;
+            actualOldLocation = actualLocation.location;
+            Path oldPath = actualOldLocation.getPath();
+
+            // It's not possible to move the root node
+            if (oldPath.isRoot()) {
+                String msg = JpaConnectorI18n.unableToMoveRootNode.text(getSourceName());
+                throw new InvalidRequestException(msg);
+            }
+
+            // Find the ChildEntity of the existing 'from' node ...
+            ChildEntity fromEntity = actualLocation.childEntity;
+            final String oldParentUuid = fromEntity.getId().getParentUuidString();
+
+            // Find the actual new location ...
+            Location toLocation = request.into();
+            String toUuidString = null;
+            if (request.hasNoEffect()) {
+                actualNewLocation = actualOldLocation;
+            } else {
+                // We have to proceed as normal ...
+                ActualLocation actualIntoLocation = getActualLocation(toLocation);
+                toUuidString = actualIntoLocation.uuid;
+                if (!toUuidString.equals(oldParentUuid)) {
+                    // Now we know that the new parent is not the existing parent ...
+                    final int oldIndex = fromEntity.getIndexInParent();
+
+                    // Find the largest SNS index in the existing ChildEntity objects with the same name ...
+                    String childLocalName = fromEntity.getChildName();
+                    NamespaceEntity ns = fromEntity.getChildNamespace();
+                    Query query = entities.createNamedQuery("ChildEntity.findMaximumSnsIndex");
+                    query.setParameter("parentUuidString", toUuidString);
+                    query.setParameter("ns", ns.getId());
+                    query.setParameter("childName", childLocalName);
+                    int nextSnsIndex = 1;
+                    try {
+                        nextSnsIndex = (Integer)query.getSingleResult();
+                    } catch (NoResultException e) {
+                    }
+
+                    // Find the largest child index in the existing ChildEntity objects ...
+                    query = entities.createNamedQuery("ChildEntity.findMaximumChildIndex");
+                    query.setParameter("parentUuidString", toUuidString);
+                    int nextIndexInParent = 1;
+                    try {
+                        nextIndexInParent = (Integer)query.getSingleResult() + 1;
+                    } catch (NoResultException e) {
+                    }
+
+                    // Move the child entity to be under the new parent ...
+                    fromEntity.setId(new ChildId(toUuidString, fromUuidString));
+                    fromEntity.setIndexInParent(nextIndexInParent);
+                    fromEntity.setSameNameSiblingIndex(nextSnsIndex);
+
+                    // Flush the entities to the database ...
+                    entities.flush();
+
+                    // Determine the new location ...
+                    Path newParentPath = actualIntoLocation.location.getPath();
+                    Name childName = oldPath.getLastSegment().getName();
+                    Path newPath = pathFactory.create(newParentPath, childName, nextSnsIndex);
+                    actualNewLocation = actualOldLocation.with(newPath);
+
+                    // And adjust the SNS index and indexes ...
+                    ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities,
+                                                                        oldParentUuid,
+                                                                        childLocalName,
+                                                                        ns.getId(),
+                                                                        oldIndex);
+
+                    // Update the cache ...
+                    cache.moveNode(actualOldLocation, oldIndex, actualNewLocation);
+
+                }
+
+            }
+
+        } catch (Throwable e) { // Includes PathNotFoundException
+            request.setError(e);
+            return;
+        }
+        request.setActualLocations(actualOldLocation, actualNewLocation);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#close()
+     */
+    @Override
+    public void close() {
+        // Verify that the references are valid so far ...
+        verifyReferences();
+
+        // Now commit the transaction ...
+        EntityTransaction txn = entities.getTransaction();
+        if (txn != null) txn.commit();
+        super.close();
+    }
+
+    /**
+     * {@link ReferenceEntity Reference entities} are added and removed in the appropriate <code>process(...)</code> methods.
+     * However, this method is typically called in {@link BasicRequestProcessor#close()} and performs the following steps:
+     * <ol>
+     * <li>Remove all references that have a "from" node that is under the versions branch.</li>
+     * <li>Verify that all remaining references have a valid and existing "to" node</li>
+     * </ol>
+     */
+    protected void verifyReferences() {
+        if (!enforceReferentialIntegrity) return;
+        if (referencesChanged) {
+
+            // Remove all references that have a "from" node that doesn't support referential integrity ...
+            ReferenceEntity.deleteUnenforcedReferences(entities);
+
+            // Verify that all references are resolved to existing nodes ...
+            int numUnresolved = ReferenceEntity.countAllReferencesResolved(entities);
+            if (numUnresolved != 0) {
+                List<ReferenceEntity> references = ReferenceEntity.verifyAllReferencesResolved(entities);
+                ValueFactory<Reference> refFactory = getExecutionContext().getValueFactories().getReferenceFactory();
+                Map<Location, List<Reference>> invalidRefs = new HashMap<Location, List<Reference>>();
+                for (ReferenceEntity entity : references) {
+                    UUID fromUuid = UUID.fromString(entity.getId().getFromUuidString());
+                    Location location = new Location(fromUuid);
+                    location = getActualLocation(location).location;
+                    List<Reference> refs = invalidRefs.get(location);
+                    if (refs == null) {
+                        refs = new ArrayList<Reference>();
+                        invalidRefs.put(location, refs);
+                    }
+                    UUID toUuid = UUID.fromString(entity.getId().getToUuidString());
+                    refs.add(refFactory.create(toUuid));
+                }
+                String msg = JpaConnectorI18n.invalidReferences.text(getSourceName());
+                throw new ReferentialIntegrityException(invalidRefs, msg);
+            }
+
+            referencesChanged = false;
+        }
+    }
+
+    protected String createProperties( String uuidString,
+                                       Collection<Property> properties ) throws IOException {
+        assert uuidString != null;
+
+        // Create the PropertiesEntity ...
+        NodeId nodeId = new NodeId(uuidString);
+        PropertiesEntity props = new PropertiesEntity(nodeId);
+
+        // If there are properties ...
+        boolean processProperties = true;
+        if (properties.isEmpty()) processProperties = false;
+        else if (properties.size() == 1 && properties.iterator().next().getName().equals(JcrLexicon.NAME)) processProperties = false;
+
+        if (processProperties) {
+            References refs = enforceReferentialIntegrity ? new References() : null;
+            LargeValueSerializer largeValues = new LargeValueSerializer(props);
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            OutputStream os = compressData ? new GZIPOutputStream(baos) : baos;
+            ObjectOutputStream oos = new ObjectOutputStream(os);
+            int numProperties = properties.size();
+            try {
+                Serializer.ReferenceValues refValues = refs != null ? refs : Serializer.NO_REFERENCES_VALUES;
+                serializer.serializeProperties(oos, numProperties, properties, largeValues, refValues);
+            } finally {
+                oos.close();
+            }
+
+            props.setData(baos.toByteArray());
+            props.setPropertyCount(numProperties);
+
+            // Record the changes to the references ...
+            if (refs != null && refs.hasWritten()) {
+                for (Reference reference : refs.getWritten()) {
+                    String toUuid = resolveToUuid(reference);
+                    if (toUuid != null) {
+                        ReferenceId id = new ReferenceId(uuidString, toUuid);
+                        ReferenceEntity refEntity = new ReferenceEntity(id);
+                        entities.persist(refEntity);
+                        referencesChanged = true;
+                    }
+                }
+            }
+        } else {
+            props.setData(null);
+            props.setPropertyCount(0);
+        }
+        props.setCompressed(compressData);
+        props.setReferentialIntegrityEnforced(true);
+
+        entities.persist(props);
+
+        // References will be persisted in the commit ...
+        return uuidString;
+    }
+
+    /**
+     * Attempt to resolve the reference.
+     * 
+     * @param reference the reference
+     * @return the UUID of the node to which the reference points, or null if the reference could not be resolved
+     */
+    protected String resolveToUuid( Reference reference ) {
+        // See if the reference is by UUID ...
+        try {
+            UUID uuid = uuidFactory.create(reference);
+            ActualLocation actualLocation = getActualLocation(new Location(uuid));
+            return actualLocation.uuid;
+        } catch (ValueFormatException e) {
+            // Unknown kind of reference, which we don't track
+        } catch (PathNotFoundException e) {
+            // Unable to resolve reference ...
+        }
+        // Unable to resolve reference ...
+        return null;
+    }
+
+    /**
+     * Utility method to look up the actual information given a supplied location. This method verifies that the location actually
+     * represents an existing node, or it throws a {@link PathNotFoundException}. In all cases, the resulting information contains
+     * the correct path and the correct UUID.
+     * <p>
+     * Note that this method sometimes performs "unnecessary" work when the location contains both a path to a node and the node's
+     * corresponding UUID. Strictly speaking, this method would need to do very little. However, in such cases, this method does
+     * verify that the information is still correct (ensuring that calls to use the {@link ChildEntity} will be correct). So,
+     * while this work <i>may</i> be unnecessary, it does ensure that the location is consistent and correct (something that is
+     * not unnecessary).
+     * </p>
+     * <p>
+     * There are cases when a request containing a Path and a UUID are no longer correct. The node may have been just moved by
+     * another request (perhaps from a different client), or there may be an error in the component making the request. In these
+     * cases, this method assumes that the path is incorrect (since paths may change) and finds the <i>correct path</i> given the
+     * UUID.
+     * </p>
+     * <p>
+     * This method will also find the path when the location contains just the UUID.
+     * </p>
+     * 
+     * @param original the original location; may not be null
+     * @return the actual location, which includes the verified location and additional information needed by this method that may
+     *         be usable after this method is called
+     * @throws PathNotFoundException if the location does not represent a location that could be found
+     */
+    protected ActualLocation getActualLocation( Location original ) throws PathNotFoundException {
+        assert original != null;
+
+        // Look for the UUID in the original ...
+        Property uuidProperty = original.getIdProperty(DnaLexicon.UUID);
+        String uuidString = uuidProperty != null && !uuidProperty.isEmpty() ? stringFactory.create(uuidProperty.getFirstValue()) : null;
+
+        Path path = original.getPath();
+        if (path != null) {
+            // See if the location is already in the cache ...
+            Location cached = cache.getLocationFor(path);
+            if (cached != null) {
+                return new ActualLocation(cached, cached.getUuid().toString(), null);
+            }
+        }
+
+        // If the original location has a UUID, then use that to find the child entity that represents the location ...
+        if (uuidString != null) {
+            // The original has a UUID, so use that to find the child entity.
+            // Then walk up the ancestors and build the path.
+            String nodeUuidString = uuidString;
+            LinkedList<Path.Segment> segments = new LinkedList<Path.Segment>();
+            ChildEntity entity = null;
+            ChildEntity originalEntity = null;
+            while (uuidString != null && !uuidString.equals(this.rootNodeUuidString)) {
+                Query query = entities.createNamedQuery("ChildEntity.findByChildUuid");
+                query.setParameter("childUuidString", uuidString);
+                try {
+                    // Find the parent of the UUID ...
+                    entity = (ChildEntity)query.getSingleResult();
+                    if (originalEntity == null) originalEntity = entity;
+                    String localName = entity.getChildName();
+                    String uri = entity.getChildNamespace().getUri();
+                    int sns = entity.getSameNameSiblingIndex();
+                    Name name = nameFactory.create(uri, localName);
+                    segments.addFirst(pathFactory.createSegment(name, sns));
+                    uuidString = entity.getId().getParentUuidString();
+                } catch (NoResultException e) {
+                    uuidString = null;
+                }
+            }
+            Path fullPath = pathFactory.createAbsolutePath(segments);
+            Location newLocation = new Location(fullPath, uuidProperty);
+            cache.addNewNode(newLocation);
+            return new ActualLocation(newLocation, nodeUuidString, originalEntity);
+        }
+
+        // There is no UUID, so look for a path ...
+        if (path == null) {
+            String propName = DnaLexicon.UUID.getString(getExecutionContext().getNamespaceRegistry());
+            String msg = JpaConnectorI18n.locationShouldHavePathAndOrProperty.text(getSourceName(), propName);
+            throw new PathNotFoundException(original, pathFactory.createRootPath(), msg);
+        }
+
+        // Walk the child entities, starting at the root, down the to the path ...
+        if (path.isRoot()) {
+            Location newLocation = original.with(rootNodeUuid);
+            cache.addNewNode(newLocation);
+            return new ActualLocation(newLocation, rootNodeUuidString, null);
+        }
+        // See if the parent location is known in the cache ...
+        Location cachedParent = cache.getLocationFor(path.getParent());
+        if (cachedParent != null) {
+            // We know the UUID of the parent, so we can find the child a little faster ...
+            ChildEntity child = findByPathSegment(cachedParent.getUuid().toString(), path.getLastSegment());
+            uuidString = child.getId().getChildUuidString();
+            Location newLocation = original.with(UUID.fromString(uuidString));
+            cache.addNewNode(newLocation);
+            return new ActualLocation(newLocation, uuidString, child);
+        }
+
+        // We couldn't find the parent, so we need to search by path ...
+        String parentUuid = this.rootNodeUuidString;
+        ChildEntity child = null;
+        for (Path.Segment segment : path) {
+            child = findByPathSegment(parentUuid, segment);
+            if (child == null) {
+                // Unable to complete the path, so prepare the exception by determining the lowest path that exists ...
+                Path lowest = path;
+                while (lowest.getLastSegment() != segment) {
+                    lowest = lowest.getParent();
+                }
+                lowest = lowest.getParent();
+                throw new PathNotFoundException(original, lowest);
+            }
+            parentUuid = child.getId().getChildUuidString();
+        }
+        assert child != null;
+        uuidString = child.getId().getChildUuidString();
+        Location newLocation = original.with(UUID.fromString(uuidString));
+        cache.addNewNode(newLocation);
+        return new ActualLocation(newLocation, uuidString, child);
+    }
+
+    /**
+     * Find the node with the supplied path segment that is a child of the supplied parent.
+     * 
+     * @param parentUuid the UUID of the parent node, in string form
+     * @param pathSegment the path segment of the child
+     * @return the existing namespace, or null if one does not exist
+     * @throws IllegalArgumentException if the manager or URI are null
+     */
+    protected ChildEntity findByPathSegment( String parentUuid,
+                                             Path.Segment pathSegment ) {
+        assert namespaces != null;
+        assert parentUuid != null;
+        assert pathSegment != null;
+        Name name = pathSegment.getName();
+        String localName = name.getLocalName();
+        String nsUri = name.getNamespaceUri();
+        NamespaceEntity ns = namespaces.get(nsUri, false);
+        if (ns == null) {
+            // The namespace can't be found, then certainly the node won't be found ...
+            return null;
+        }
+        int snsIndex = pathSegment.hasIndex() ? pathSegment.getIndex() : 1;
+        Query query = entities.createNamedQuery("ChildEntity.findByPathSegment");
+        query.setParameter("parentUuidString", parentUuid);
+        query.setParameter("ns", ns.getId());
+        query.setParameter("childName", localName);
+        query.setParameter("sns", snsIndex);
+        try {
+            return (ChildEntity)query.getSingleResult();
+        } catch (NoResultException e) {
+            return null;
+        }
+    }
+
+    protected String createHexValuesString( Collection<String> hexValues ) {
+        if (hexValues == null || hexValues.isEmpty()) return null;
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (String hexValue : hexValues) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(',');
+            }
+            sb.append(hexValue);
+        }
+        return sb.toString();
+    }
+
+    protected Collection<String> createHexValues( String hexValuesString ) {
+        return Arrays.asList(hexValuesString.split(","));
+    }
+
+    protected class LargeValueSerializer implements LargeValues {
+        private final PropertiesEntity properties;
+        private Set<String> written;
+
+        public LargeValueSerializer( PropertiesEntity entity ) {
+            this.properties = entity;
+            this.written = null;
+        }
+
+        public LargeValueSerializer( PropertiesEntity entity,
+                                     Set<String> written ) {
+            this.properties = entity;
+            this.written = written;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#getMinimumSize()
+         */
+        public long getMinimumSize() {
+            return largeValueMinimumSizeInBytes;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.property.ValueFactories,
+         *      byte[], long)
+         */
+        public Object read( ValueFactories valueFactories,
+                            byte[] hash,
+                            long length ) throws IOException {
+            String hashStr = StringUtil.getHexString(hash);
+            // Find the large value ...
+            LargeValueId largeValueId = new LargeValueId(hashStr);
+            LargeValueEntity entity = entities.find(LargeValueEntity.class, largeValueId);
+            if (entity != null) {
+                // Find the large value from the existing property entity ...
+                byte[] data = entity.getData();
+                if (entity.isCompressed()) {
+                    InputStream stream = new GZIPInputStream(new ByteArrayInputStream(data));
+                    try {
+                        data = IoUtil.readBytes(stream);
+                    } finally {
+                        stream.close();
+                    }
+                }
+                return valueFactories.getValueFactory(entity.getType()).create(data);
+            }
+            throw new IOException(JpaConnectorI18n.unableToReadLargeValue.text(getSourceName(), hashStr));
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#write(byte[], long,
+         *      org.jboss.dna.graph.property.PropertyType, java.lang.Object)
+         */
+        public void write( byte[] hash,
+                           long length,
+                           PropertyType type,
+                           Object value ) throws IOException {
+            if (value == null) return;
+            String hashStr = StringUtil.getHexString(hash);
+            if (written != null) written.add(hashStr);
+
+            // Look for an existing value in the collection ...
+            final LargeValueId id = new LargeValueId(hashStr);
+            for (LargeValueId existing : properties.getLargeValues()) {
+                if (existing.equals(id)) {
+                    // Already associated with this properties entity
+                    return;
+                }
+            }
+            LargeValueEntity entity = entities.find(LargeValueEntity.class, id);
+            if (entity == null) {
+                // We have to create the large value entity ...
+                entity = new LargeValueEntity();
+                entity.setCompressed(true);
+                entity.setId(id);
+                entity.setLength(length);
+                entity.setType(type);
+                ValueFactories factories = getExecutionContext().getValueFactories();
+                byte[] bytes = null;
+                switch (type) {
+                    case BINARY:
+                        Binary binary = factories.getBinaryFactory().create(value);
+                        InputStream stream = null;
+                        try {
+                            binary.acquire();
+                            stream = binary.getStream();
+                            if (compressData) stream = new GZIPInputStream(stream);
+                            bytes = IoUtil.readBytes(stream);
+                        } finally {
+                            try {
+                                if (stream != null) stream.close();
+                            } finally {
+                                binary.release();
+                            }
+                        }
+                        break;
+                    case URI:
+                        // This will be treated as a string ...
+                    default:
+                        String str = factories.getStringFactory().create(value);
+                        if (compressData) {
+                            ByteArrayOutputStream bs = new ByteArrayOutputStream();
+                            OutputStream strStream = new GZIPOutputStream(bs);
+                            try {
+                                IoUtil.write(str, strStream);
+                            } finally {
+                                strStream.close();
+                            }
+                            bytes = bs.toByteArray();
+                        } else {
+                            bytes = str.getBytes();
+                        }
+                        break;
+                }
+                entity.setData(bytes);
+                entities.persist(entity);
+            }
+            // Now associate the large value with the properties entity ...
+            assert id.getHash() != null;
+            properties.getLargeValues().add(id);
+        }
+
+    }
+
+    protected class RecordingLargeValues implements LargeValues {
+        protected final Collection<String> readKeys = new HashSet<String>();
+        protected final Collection<String> writtenKeys = new HashSet<String>();
+        protected final LargeValues delegate;
+
+        RecordingLargeValues( LargeValues delegate ) {
+            assert delegate != null;
+            this.delegate = delegate;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#getMinimumSize()
+         */
+        public long getMinimumSize() {
+            return delegate.getMinimumSize();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.property.ValueFactories,
+         *      byte[], long)
+         */
+        public Object read( ValueFactories valueFactories,
+                            byte[] hash,
+                            long length ) throws IOException {
+            String key = StringUtil.getHexString(hash);
+            readKeys.add(key);
+            return delegate.read(valueFactories, hash, length);
+        }
+
+        public void write( byte[] hash,
+                           long length,
+                           PropertyType type,
+                           Object value ) throws IOException {
+            String key = StringUtil.getHexString(hash);
+            writtenKeys.add(key);
+            delegate.write(hash, length, type, value);
+        }
+    }
+
+    protected class SkippedLargeValues implements LargeValues {
+        protected Collection<String> skippedKeys = new HashSet<String>();
+        protected final LargeValues delegate;
+
+        SkippedLargeValues( LargeValues delegate ) {
+            assert delegate != null;
+            this.delegate = delegate;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#getMinimumSize()
+         */
+        public long getMinimumSize() {
+            return delegate.getMinimumSize();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.property.ValueFactories,
+         *      byte[], long)
+         */
+        public Object read( ValueFactories valueFactories,
+                            byte[] hash,
+                            long length ) throws IOException {
+            String key = StringUtil.getHexString(hash);
+            skippedKeys.add(key);
+            return null;
+        }
+
+        public void write( byte[] hash,
+                           long length,
+                           PropertyType type,
+                           Object value ) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Immutable
+    protected static class ActualLocation {
+        /** The actual location */
+        protected final Location location;
+        /** The string-form of the UUID, supplied as a convenience. */
+        protected final String uuid;
+        /** The ChildEntity that represents the location, which may be null if the location represents the root node */
+        protected final ChildEntity childEntity;
+
+        protected ActualLocation( Location location,
+                                  String uuid,
+                                  ChildEntity childEntity ) {
+            assert location != null;
+            assert uuid != null;
+            this.location = location;
+            this.uuid = uuid;
+            this.childEntity = childEntity;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.lang.Object#toString()
+         */
+        @Override
+        public String toString() {
+            return this.location.toString() + " (uuid=" + uuid + ") " + childEntity;
+        }
+    }
+
+    protected class References implements Serializer.ReferenceValues {
+        private Set<Reference> read;
+        private Set<Reference> removed;
+        private Set<Reference> written;
+
+        protected References() {
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.ReferenceValues#read(org.jboss.dna.graph.property.Reference)
+         */
+        public void read( Reference reference ) {
+            if (read == null) read = new HashSet<Reference>();
+            read.add(reference);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.ReferenceValues#remove(org.jboss.dna.graph.property.Reference)
+         */
+        public void remove( Reference reference ) {
+            if (removed == null) removed = new HashSet<Reference>();
+            removed.add(reference);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.ReferenceValues#write(org.jboss.dna.graph.property.Reference)
+         */
+        public void write( Reference reference ) {
+            if (written == null) written = new HashSet<Reference>();
+            written.add(reference);
+        }
+
+        public boolean hasRead() {
+            return read != null;
+        }
+
+        public boolean hasRemoved() {
+            return removed != null;
+        }
+
+        public boolean hasWritten() {
+            return written != null;
+        }
+
+        /**
+         * @return read
+         */
+        public Set<Reference> getRead() {
+            if (read != null) return read;
+            return Collections.emptySet();
+        }
+
+        /**
+         * @return removed
+         */
+        public Set<Reference> getRemoved() {
+            if (removed != null) return removed;
+            return Collections.emptySet();
+        }
+
+        /**
+         * @return written
+         */
+        public Set<Reference> getWritten() {
+            if (written != null) return written;
+            return Collections.emptySet();
+        }
+    }
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntity.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,259 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.util.List;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EntityManager;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Query;
-import javax.persistence.Table;
-import org.hibernate.annotations.Index;
-import org.jboss.dna.common.text.Inflector;
-import org.jboss.dna.common.util.HashCode;
-import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
-
-/**
- * An entity representing the parent-child relationship between two nodes. In addition to the references to the parent and child
- * nodes, this entity also maintains the indexInParent of the indexInParent within the parent node's list of all children, the
- * child's name ( {@link #getChildName() local part} and {@link #getChildNamespace() namespace}), and the same-name-sibiling
- * indexInParent (if there is one).
- * 
- * @author Randall Hauch
- */
- at Entity
- at Table( name = "DNA_BASIC_CHILDREN" )
- at org.hibernate.annotations.Table( appliesTo = "DNA_BASIC_CHILDREN", indexes = {
-    @Index( name = "CHILDINDEX_INX", columnNames = {"PARENT_UUID", "CHILD_INDEX"} ),
-    @Index( name = "CHILDUUID_INX", columnNames = {"CHILD_UUID"} ),
-    @Index( name = "CHILDNAME_INX", columnNames = {"PARENT_UUID", "CHILD_NAME_NS_ID", "CHILD_NAME_LOCAL", "SNS_INDEX"} )} )
- at NamedQueries( {
-    @NamedQuery( name = "ChildEntity.findByPathSegment", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString AND child.childNamespace.id = :ns AND child.childName = :childName AND child.sameNameSiblingIndex = :sns" ),
-    @NamedQuery( name = "ChildEntity.findAllUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString order by child.indexInParent" ),
-    @NamedQuery( name = "ChildEntity.findRangeUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString and child.indexInParent >= :firstIndex and child.indexInParent < :afterIndex order by child.indexInParent" ),
-    @NamedQuery( name = "ChildEntity.findChildrenAfterIndexUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString and child.indexInParent >= :afterIndex order by child.indexInParent" ),
-    @NamedQuery( name = "ChildEntity.findByChildUuid", query = "select child from ChildEntity as child where child.id.childUuidString = :childUuidString" ),
-    @NamedQuery( name = "ChildEntity.findMaximumSnsIndex", query = "select max(child.sameNameSiblingIndex) from ChildEntity as child where child.id.parentUuidString = :parentUuid AND child.childNamespace.id = :ns AND child.childName = :childName" ),
-    @NamedQuery( name = "ChildEntity.findMaximumChildIndex", query = "select max(child.indexInParent) from ChildEntity as child where child.id.parentUuidString = :parentUuid" )} )
-public class ChildEntity {
-
-    @Id
-    private ChildId id;
-
-    /** The zero-based index */
-    @Column( name = "CHILD_INDEX", nullable = false, unique = false )
-    private int indexInParent;
-
-    @ManyToOne
-    @JoinColumn( name = "CHILD_NAME_NS_ID", nullable = false )
-    private NamespaceEntity childNamespace;
-
-    @Column( name = "CHILD_NAME_LOCAL", nullable = false, unique = false, length = 512 )
-    private String childName;
-
-    @Column( name = "SNS_INDEX", nullable = false, unique = false )
-    private int sameNameSiblingIndex;
-
-    public ChildEntity() {
-    }
-
-    public ChildEntity( ChildId id,
-                        int indexInParent,
-                        NamespaceEntity ns,
-                        String name ) {
-        this.id = id;
-        this.indexInParent = indexInParent;
-        this.childNamespace = ns;
-        this.childName = name;
-        this.sameNameSiblingIndex = 1;
-    }
-
-    public ChildEntity( ChildId id,
-                        int indexInParent,
-                        NamespaceEntity ns,
-                        String name,
-                        int sameNameSiblingIndex ) {
-        this.id = id;
-        this.indexInParent = indexInParent;
-        this.childNamespace = ns;
-        this.childName = name;
-        this.sameNameSiblingIndex = sameNameSiblingIndex;
-    }
-
-    /**
-     * @return parent
-     */
-    public ChildId getId() {
-        return id;
-    }
-
-    /**
-     * @param childId Sets parent to the specified value.
-     */
-    public void setId( ChildId childId ) {
-        this.id = childId;
-    }
-
-    /**
-     * Get the zero-based index of this child within the parent's list of children
-     * 
-     * @return the zero-based index of this child
-     */
-    public int getIndexInParent() {
-        return indexInParent;
-    }
-
-    /**
-     * @param index Sets indexInParent to the specified value.
-     */
-    public void setIndexInParent( int index ) {
-        this.indexInParent = index;
-    }
-
-    /**
-     * @return childName
-     */
-    public String getChildName() {
-        return childName;
-    }
-
-    /**
-     * @param childName Sets childName to the specified value.
-     */
-    public void setChildName( String childName ) {
-        this.childName = childName;
-    }
-
-    /**
-     * @return childNamespace
-     */
-    public NamespaceEntity getChildNamespace() {
-        return childNamespace;
-    }
-
-    /**
-     * @param childNamespace Sets childNamespace to the specified value.
-     */
-    public void setChildNamespace( NamespaceEntity childNamespace ) {
-        this.childNamespace = childNamespace;
-    }
-
-    /**
-     * @return sameNameSiblingIndex
-     */
-    public int getSameNameSiblingIndex() {
-        return sameNameSiblingIndex;
-    }
-
-    /**
-     * @param sameNameSiblingIndex Sets sameNameSiblingIndex to the specified value.
-     */
-    public void setSameNameSiblingIndex( int sameNameSiblingIndex ) {
-        this.sameNameSiblingIndex = sameNameSiblingIndex;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return HashCode.compute(id);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof ChildEntity) {
-            ChildEntity that = (ChildEntity)obj;
-            if (this.id == null) {
-                if (that.id != null) return false;
-            } else {
-                if (!this.id.equals(that.id)) return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        if (childNamespace != null) {
-            sb.append('{').append(childNamespace).append("}:");
-        }
-        sb.append(childName);
-        if (sameNameSiblingIndex > 1) {
-            sb.append('[').append(sameNameSiblingIndex).append(']');
-        }
-        if (id != null) {
-            sb.append(" (id=").append(id.getChildUuidString()).append(")");
-            String parentId = id.getParentUuidString();
-            if (parentId != null) {
-                sb.append(" is ");
-                sb.append(Inflector.getInstance().ordinalize(indexInParent));
-                sb.append(" child of ");
-                sb.append(parentId);
-            } else {
-                sb.append(" is root");
-            }
-        }
-        return sb.toString();
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public static void adjustSnsIndexesAndIndexesAfterRemoving( EntityManager entities,
-                                                                String uuidParent,
-                                                                String childName,
-                                                                long childNamespaceIndex,
-                                                                int childIndex ) {
-        // Decrement the 'indexInParent' index values for all nodes above the previously removed sibling ...
-        Query query = entities.createNamedQuery("ChildEntity.findChildrenAfterIndexUnderParent");
-        query.setParameter("parentUuidString", uuidParent);
-        query.setParameter("afterIndex", childIndex);
-        for (ChildEntity entity : (List<ChildEntity>)query.getResultList()) {
-            // Decrement the index in parent ...
-            entity.setIndexInParent(entity.getIndexInParent() - 1);
-            if (entity.getChildName().equals(childName) && entity.getChildNamespace().getId() == childNamespaceIndex) {
-                // The name matches, so decrement the SNS index ...
-                entity.setSameNameSiblingIndex(entity.getSameNameSiblingIndex() - 1);
-            }
-        }
-    }
-
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntity.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,259 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.util.List;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityManager;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Query;
+import javax.persistence.Table;
+import org.hibernate.annotations.Index;
+import org.jboss.dna.common.text.Inflector;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.connector.store.jpa.model.common.NamespaceEntity;
+
+/**
+ * An entity representing the parent-child relationship between two nodes. In addition to the references to the parent and child
+ * nodes, this entity also maintains the indexInParent of the indexInParent within the parent node's list of all children, the
+ * child's name ( {@link #getChildName() local part} and {@link #getChildNamespace() namespace}), and the same-name-sibiling
+ * indexInParent (if there is one).
+ * 
+ * @author Randall Hauch
+ */
+ at Entity
+ at Table( name = "DNA_BASIC_CHILDREN" )
+ at org.hibernate.annotations.Table( appliesTo = "DNA_BASIC_CHILDREN", indexes = {
+    @Index( name = "CHILDINDEX_INX", columnNames = {"PARENT_UUID", "CHILD_INDEX"} ),
+    @Index( name = "CHILDUUID_INX", columnNames = {"CHILD_UUID"} ),
+    @Index( name = "CHILDNAME_INX", columnNames = {"PARENT_UUID", "CHILD_NAME_NS_ID", "CHILD_NAME_LOCAL", "SNS_INDEX"} )} )
+ at NamedQueries( {
+    @NamedQuery( name = "ChildEntity.findByPathSegment", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString AND child.childNamespace.id = :ns AND child.childName = :childName AND child.sameNameSiblingIndex = :sns" ),
+    @NamedQuery( name = "ChildEntity.findAllUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString order by child.indexInParent" ),
+    @NamedQuery( name = "ChildEntity.findRangeUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString and child.indexInParent >= :firstIndex and child.indexInParent < :afterIndex order by child.indexInParent" ),
+    @NamedQuery( name = "ChildEntity.findChildrenAfterIndexUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString and child.indexInParent >= :afterIndex order by child.indexInParent" ),
+    @NamedQuery( name = "ChildEntity.findByChildUuid", query = "select child from ChildEntity as child where child.id.childUuidString = :childUuidString" ),
+    @NamedQuery( name = "ChildEntity.findMaximumSnsIndex", query = "select max(child.sameNameSiblingIndex) from ChildEntity as child where child.id.parentUuidString = :parentUuid AND child.childNamespace.id = :ns AND child.childName = :childName" ),
+    @NamedQuery( name = "ChildEntity.findMaximumChildIndex", query = "select max(child.indexInParent) from ChildEntity as child where child.id.parentUuidString = :parentUuid" )} )
+public class ChildEntity {
+
+    @Id
+    private ChildId id;
+
+    /** The zero-based index */
+    @Column( name = "CHILD_INDEX", nullable = false, unique = false )
+    private int indexInParent;
+
+    @ManyToOne
+    @JoinColumn( name = "CHILD_NAME_NS_ID", nullable = false )
+    private NamespaceEntity childNamespace;
+
+    @Column( name = "CHILD_NAME_LOCAL", nullable = false, unique = false, length = 512 )
+    private String childName;
+
+    @Column( name = "SNS_INDEX", nullable = false, unique = false )
+    private int sameNameSiblingIndex;
+
+    public ChildEntity() {
+    }
+
+    public ChildEntity( ChildId id,
+                        int indexInParent,
+                        NamespaceEntity ns,
+                        String name ) {
+        this.id = id;
+        this.indexInParent = indexInParent;
+        this.childNamespace = ns;
+        this.childName = name;
+        this.sameNameSiblingIndex = 1;
+    }
+
+    public ChildEntity( ChildId id,
+                        int indexInParent,
+                        NamespaceEntity ns,
+                        String name,
+                        int sameNameSiblingIndex ) {
+        this.id = id;
+        this.indexInParent = indexInParent;
+        this.childNamespace = ns;
+        this.childName = name;
+        this.sameNameSiblingIndex = sameNameSiblingIndex;
+    }
+
+    /**
+     * @return parent
+     */
+    public ChildId getId() {
+        return id;
+    }
+
+    /**
+     * @param childId Sets parent to the specified value.
+     */
+    public void setId( ChildId childId ) {
+        this.id = childId;
+    }
+
+    /**
+     * Get the zero-based index of this child within the parent's list of children
+     * 
+     * @return the zero-based index of this child
+     */
+    public int getIndexInParent() {
+        return indexInParent;
+    }
+
+    /**
+     * @param index Sets indexInParent to the specified value.
+     */
+    public void setIndexInParent( int index ) {
+        this.indexInParent = index;
+    }
+
+    /**
+     * @return childName
+     */
+    public String getChildName() {
+        return childName;
+    }
+
+    /**
+     * @param childName Sets childName to the specified value.
+     */
+    public void setChildName( String childName ) {
+        this.childName = childName;
+    }
+
+    /**
+     * @return childNamespace
+     */
+    public NamespaceEntity getChildNamespace() {
+        return childNamespace;
+    }
+
+    /**
+     * @param childNamespace Sets childNamespace to the specified value.
+     */
+    public void setChildNamespace( NamespaceEntity childNamespace ) {
+        this.childNamespace = childNamespace;
+    }
+
+    /**
+     * @return sameNameSiblingIndex
+     */
+    public int getSameNameSiblingIndex() {
+        return sameNameSiblingIndex;
+    }
+
+    /**
+     * @param sameNameSiblingIndex Sets sameNameSiblingIndex to the specified value.
+     */
+    public void setSameNameSiblingIndex( int sameNameSiblingIndex ) {
+        this.sameNameSiblingIndex = sameNameSiblingIndex;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return HashCode.compute(id);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof ChildEntity) {
+            ChildEntity that = (ChildEntity)obj;
+            if (this.id == null) {
+                if (that.id != null) return false;
+            } else {
+                if (!this.id.equals(that.id)) return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        if (childNamespace != null) {
+            sb.append('{').append(childNamespace).append("}:");
+        }
+        sb.append(childName);
+        if (sameNameSiblingIndex > 1) {
+            sb.append('[').append(sameNameSiblingIndex).append(']');
+        }
+        if (id != null) {
+            sb.append(" (id=").append(id.getChildUuidString()).append(")");
+            String parentId = id.getParentUuidString();
+            if (parentId != null) {
+                sb.append(" is ");
+                sb.append(Inflector.getInstance().ordinalize(indexInParent));
+                sb.append(" child of ");
+                sb.append(parentId);
+            } else {
+                sb.append(" is root");
+            }
+        }
+        return sb.toString();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public static void adjustSnsIndexesAndIndexesAfterRemoving( EntityManager entities,
+                                                                String uuidParent,
+                                                                String childName,
+                                                                long childNamespaceIndex,
+                                                                int childIndex ) {
+        // Decrement the 'indexInParent' index values for all nodes above the previously removed sibling ...
+        Query query = entities.createNamedQuery("ChildEntity.findChildrenAfterIndexUnderParent");
+        query.setParameter("parentUuidString", uuidParent);
+        query.setParameter("afterIndex", childIndex);
+        for (ChildEntity entity : (List<ChildEntity>)query.getResultList()) {
+            // Decrement the index in parent ...
+            entity.setIndexInParent(entity.getIndexInParent() - 1);
+            if (entity.getChildName().equals(childName) && entity.getChildNamespace().getId() == childNamespaceIndex) {
+                // The name matches, so decrement the SNS index ...
+                entity.setSameNameSiblingIndex(entity.getSameNameSiblingIndex() - 1);
+            }
+        }
+    }
+
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildId.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ChildId.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildId.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,125 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.io.Serializable;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.HashCode;
-
-/**
- * A unique identifer for a parent-child relationship.
- * 
- * @author Randall Hauch
- */
- at Embeddable
- at Immutable
- at org.hibernate.annotations.Immutable
-public class ChildId implements Serializable {
-
-    /**
-     * Version {@value}
-     */
-    private static final long serialVersionUID = 1L;
-
-    @Column( name = "PARENT_UUID", nullable = false, length = 36 )
-    private String parentUuidString;
-
-    @Column( name = "CHILD_UUID", nullable = false, length = 36 )
-    private String childUuidString;
-
-    public ChildId() {
-    }
-
-    public ChildId( NodeId parentId,
-                    NodeId childId ) {
-        if (parentId != null) this.parentUuidString = parentId.getUuidString();
-        if (childId != null) this.childUuidString = childId.getUuidString();
-    }
-
-    public ChildId( String parentUuid,
-                    String childUuid ) {
-        this.parentUuidString = parentUuid;
-        this.childUuidString = childUuid;
-    }
-
-    /**
-     * @return parentUuidString
-     */
-    public String getParentUuidString() {
-        return parentUuidString;
-    }
-
-    /**
-     * @return childUuidString
-     */
-    public String getChildUuidString() {
-        return childUuidString;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return HashCode.compute(parentUuidString, childUuidString);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof ChildId) {
-            ChildId that = (ChildId)obj;
-            if (this.parentUuidString == null) {
-                if (that.parentUuidString != null) return false;
-            } else {
-                if (!this.parentUuidString.equals(that.parentUuidString)) return false;
-            }
-            if (this.childUuidString == null) {
-                if (that.childUuidString != null) return false;
-            } else {
-                if (!this.childUuidString.equals(that.childUuidString)) return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "Child " + childUuidString + " of " + parentUuidString;
-    }
-
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildId.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ChildId.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildId.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildId.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.HashCode;
+
+/**
+ * A unique identifer for a parent-child relationship.
+ * 
+ * @author Randall Hauch
+ */
+ at Embeddable
+ at Immutable
+ at org.hibernate.annotations.Immutable
+public class ChildId implements Serializable {
+
+    /**
+     * Version {@value}
+     */
+    private static final long serialVersionUID = 1L;
+
+    @Column( name = "PARENT_UUID", nullable = false, length = 36 )
+    private String parentUuidString;
+
+    @Column( name = "CHILD_UUID", nullable = false, length = 36 )
+    private String childUuidString;
+
+    public ChildId() {
+    }
+
+    public ChildId( NodeId parentId,
+                    NodeId childId ) {
+        if (parentId != null) this.parentUuidString = parentId.getUuidString();
+        if (childId != null) this.childUuidString = childId.getUuidString();
+    }
+
+    public ChildId( String parentUuid,
+                    String childUuid ) {
+        this.parentUuidString = parentUuid;
+        this.childUuidString = childUuid;
+    }
+
+    /**
+     * @return parentUuidString
+     */
+    public String getParentUuidString() {
+        return parentUuidString;
+    }
+
+    /**
+     * @return childUuidString
+     */
+    public String getChildUuidString() {
+        return childUuidString;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return HashCode.compute(parentUuidString, childUuidString);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof ChildId) {
+            ChildId that = (ChildId)obj;
+            if (this.parentUuidString == null) {
+                if (that.parentUuidString != null) return false;
+            } else {
+                if (!this.parentUuidString.equals(that.parentUuidString)) return false;
+            }
+            if (this.childUuidString == null) {
+                if (that.childUuidString != null) return false;
+            } else {
+                if (!this.childUuidString.equals(that.childUuidString)) return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "Child " + childUuidString + " of " + parentUuidString;
+    }
+
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/LargeValueEntity.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,195 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EntityManager;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.Id;
-import javax.persistence.Lob;
-import javax.persistence.NamedQuery;
-import javax.persistence.Query;
-import javax.persistence.Table;
-import org.jboss.dna.graph.properties.PropertyType;
-
-/**
- * A single property value that is too large to be stored on the individual node, and which will be shared among all properties
- * that have the same value.
- * 
- * @author Randall Hauch
- */
- at Entity
- at Table( name = "DNA_BASIC_LARGE_VALUES" )
- at NamedQuery( name = "LargeValueEntity.deleteUnused", query = "delete LargeValueEntity value where value.id not in (select values.hash from PropertiesEntity prop join prop.largeValues values)" )
-public class LargeValueEntity {
-
-    @Id
-    private LargeValueId id;
-
-    /**
-     * The property type for this value. Typically, this is {@link PropertyType#STRING} or {@link PropertyType#BINARY}, although
-     * technically it could be any type.
-     */
-    @Enumerated( value = EnumType.STRING )
-    @Column( name = "TYPE", nullable = false )
-    private PropertyType type;
-
-    /**
-     * The number of bytes in this value.
-     */
-    @Column( name = "LENGTH", nullable = false )
-    private long length;
-
-    /**
-     * Flag specifying whether the binary data is stored in a compressed format.
-     */
-    @Column( name = "COMPRESSED", nullable = true )
-    private Boolean compressed;
-
-    /**
-     * Lazily-fetched value
-     */
-    @Lob
-    @Column( name = "DATA", nullable = false )
-    private byte[] data;
-
-    /**
-     * @return id
-     */
-    public LargeValueId getId() {
-        return id;
-    }
-
-    /**
-     * @param id Sets id to the specified value.
-     */
-    public void setId( LargeValueId id ) {
-        this.id = id;
-    }
-
-    /**
-     * @return length
-     */
-    public long getLength() {
-        return length;
-    }
-
-    /**
-     * @param length Sets length to the specified value.
-     */
-    public void setLength( long length ) {
-        this.length = length;
-    }
-
-    /**
-     * @return type
-     */
-    public PropertyType getType() {
-        return type;
-    }
-
-    /**
-     * @param type Sets type to the specified value.
-     */
-    public void setType( PropertyType type ) {
-        this.type = type;
-    }
-
-    /**
-     * @return data
-     */
-    public byte[] getData() {
-        return data;
-    }
-
-    /**
-     * @param data Sets data to the specified value.
-     */
-    public void setData( byte[] data ) {
-        this.data = data;
-    }
-
-    /**
-     * @return compressed
-     */
-    public boolean isCompressed() {
-        return compressed != null && compressed.booleanValue();
-    }
-
-    /**
-     * @param compressed Sets compressed to the specified value.
-     */
-    public void setCompressed( boolean compressed ) {
-        this.compressed = Boolean.valueOf(compressed);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof LargeValueEntity) {
-            LargeValueEntity that = (LargeValueEntity)obj;
-            if (this.getId().equals(that.getId())) return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "Large " + this.type + " value (hash=" + this.getId().getHash() + ",compressed=" + isCompressed() + ")";
-    }
-
-    /**
-     * Delete all unused large value entities.
-     * 
-     * @param manager the manager; never null
-     * @return the number of deleted large values
-     */
-    public static int deleteUnused( EntityManager manager ) {
-        assert manager != null;
-        Query delete = manager.createNamedQuery("LargeValueEntity.deleteUnused");
-        int result = delete.executeUpdate();
-        manager.flush();
-        return result;
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueEntity.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/LargeValueEntity.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueEntity.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,195 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityManager;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import javax.persistence.NamedQuery;
+import javax.persistence.Query;
+import javax.persistence.Table;
+import org.jboss.dna.graph.property.PropertyType;
+
+/**
+ * A single property value that is too large to be stored on the individual node, and which will be shared among all properties
+ * that have the same value.
+ * 
+ * @author Randall Hauch
+ */
+ at Entity
+ at Table( name = "DNA_BASIC_LARGE_VALUES" )
+ at NamedQuery( name = "LargeValueEntity.deleteUnused", query = "delete LargeValueEntity value where value.id not in (select values.hash from PropertiesEntity prop join prop.largeValues values)" )
+public class LargeValueEntity {
+
+    @Id
+    private LargeValueId id;
+
+    /**
+     * The property type for this value. Typically, this is {@link PropertyType#STRING} or {@link PropertyType#BINARY}, although
+     * technically it could be any type.
+     */
+    @Enumerated( value = EnumType.STRING )
+    @Column( name = "TYPE", nullable = false )
+    private PropertyType type;
+
+    /**
+     * The number of bytes in this value.
+     */
+    @Column( name = "LENGTH", nullable = false )
+    private long length;
+
+    /**
+     * Flag specifying whether the binary data is stored in a compressed format.
+     */
+    @Column( name = "COMPRESSED", nullable = true )
+    private Boolean compressed;
+
+    /**
+     * Lazily-fetched value
+     */
+    @Lob
+    @Column( name = "DATA", nullable = false )
+    private byte[] data;
+
+    /**
+     * @return id
+     */
+    public LargeValueId getId() {
+        return id;
+    }
+
+    /**
+     * @param id Sets id to the specified value.
+     */
+    public void setId( LargeValueId id ) {
+        this.id = id;
+    }
+
+    /**
+     * @return length
+     */
+    public long getLength() {
+        return length;
+    }
+
+    /**
+     * @param length Sets length to the specified value.
+     */
+    public void setLength( long length ) {
+        this.length = length;
+    }
+
+    /**
+     * @return type
+     */
+    public PropertyType getType() {
+        return type;
+    }
+
+    /**
+     * @param type Sets type to the specified value.
+     */
+    public void setType( PropertyType type ) {
+        this.type = type;
+    }
+
+    /**
+     * @return data
+     */
+    public byte[] getData() {
+        return data;
+    }
+
+    /**
+     * @param data Sets data to the specified value.
+     */
+    public void setData( byte[] data ) {
+        this.data = data;
+    }
+
+    /**
+     * @return compressed
+     */
+    public boolean isCompressed() {
+        return compressed != null && compressed.booleanValue();
+    }
+
+    /**
+     * @param compressed Sets compressed to the specified value.
+     */
+    public void setCompressed( boolean compressed ) {
+        this.compressed = Boolean.valueOf(compressed);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof LargeValueEntity) {
+            LargeValueEntity that = (LargeValueEntity)obj;
+            if (this.getId().equals(that.getId())) return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "Large " + this.type + " value (hash=" + this.getId().getHash() + ",compressed=" + isCompressed() + ")";
+    }
+
+    /**
+     * Delete all unused large value entities.
+     * 
+     * @param manager the manager; never null
+     * @return the number of deleted large values
+     */
+    public static int deleteUnused( EntityManager manager ) {
+        assert manager != null;
+        Query delete = manager.createNamedQuery("LargeValueEntity.deleteUnused");
+        int result = delete.executeUpdate();
+        manager.flush();
+        return result;
+    }
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueId.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/LargeValueId.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueId.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,98 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.io.Serializable;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import net.jcip.annotations.Immutable;
-
-/**
- * A unique identifer for a large value, which is the 160-bit SHA-1 hash of this value, in hex form (40-bytes). The SHA-1
- * algorithm is fast and has not yet proven to have any duplicates. Even if SHA-2 and SHA-3 are better for cryptographically
- * secure purposes, it is doubtful whether a repository needs more than SHA-1 for identity purposes.
- * 
- * @author Randall Hauch
- */
- at Embeddable
- at Immutable
- at org.hibernate.annotations.Immutable
-public class LargeValueId implements Serializable {
-
-    /**
-     * Version {@value}
-     */
-    private static final long serialVersionUID = 1L;
-
-    @Column( name = "SHA1", nullable = false, length = 40 )
-    private String hash;
-
-    public LargeValueId() {
-    }
-
-    public LargeValueId( String hash ) {
-        this.hash = hash;
-    }
-
-    /**
-     * @return hash
-     */
-    public String getHash() {
-        return hash;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return hash.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof LargeValueId) {
-            LargeValueId that = (LargeValueId)obj;
-            return this.hash.equals(that.hash);
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "Large value " + hash;
-    }
-
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueId.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/LargeValueId.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueId.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/LargeValueId.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,98 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import net.jcip.annotations.Immutable;
+
+/**
+ * A unique identifer for a large value, which is the 160-bit SHA-1 hash of this value, in hex form (40-bytes). The SHA-1
+ * algorithm is fast and has not yet proven to have any duplicates. Even if SHA-2 and SHA-3 are better for cryptographically
+ * secure purposes, it is doubtful whether a repository needs more than SHA-1 for identity purposes.
+ * 
+ * @author Randall Hauch
+ */
+ at Embeddable
+ at Immutable
+ at org.hibernate.annotations.Immutable
+public class LargeValueId implements Serializable {
+
+    /**
+     * Version {@value}
+     */
+    private static final long serialVersionUID = 1L;
+
+    @Column( name = "SHA1", nullable = false, length = 40 )
+    private String hash;
+
+    public LargeValueId() {
+    }
+
+    public LargeValueId( String hash ) {
+        this.hash = hash;
+    }
+
+    /**
+     * @return hash
+     */
+    public String getHash() {
+        return hash;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return hash.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof LargeValueId) {
+            LargeValueId that = (LargeValueId)obj;
+            return this.hash.equals(that.hash);
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "Large value " + hash;
+    }
+
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/NodeId.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/NodeId.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/NodeId.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,110 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.io.Serializable;
-import java.util.UUID;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import net.jcip.annotations.Immutable;
-
-/**
- * An identifier for a node, comprised of a single {@link UUID}, and {@link Embeddable embeddable} in a persistent entity. The
- * identifier takes the form of two <code>long</code> columns: one for the UUID's {@link UUID#getMostSignificantBits() most
- * significant bits} and one for its {@link UUID#getLeastSignificantBits() least significant bits}.
- * 
- * @author Randall Hauch
- */
- at Embeddable
- at Immutable
- at org.hibernate.annotations.Immutable
-public class NodeId implements Serializable {
-
-    /**
-     * Version {@value}
-     */
-    private static final long serialVersionUID = 1L;
-
-    @Column( name = "UUID", nullable = true )
-    private String uuidString;
-
-    public NodeId() {
-    }
-
-    public NodeId( String uuidString ) {
-        this.uuidString = uuidString;
-    }
-
-    /**
-     * @return uuidString
-     */
-    public String getUuidString() {
-        return uuidString;
-    }
-
-    /**
-     * @param uuidString Sets uuidString to the specified value.
-     */
-    public void setUuidString( String uuidString ) {
-        this.uuidString = uuidString;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return uuidString.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof NodeId) {
-            NodeId that = (NodeId)obj;
-            if (this.uuidString == null) {
-                if (that.uuidString != null) return false;
-            } else {
-                if (!this.uuidString.equals(that.uuidString)) return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return uuidString;
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/NodeId.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/NodeId.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/NodeId.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/NodeId.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,110 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.io.Serializable;
+import java.util.UUID;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import net.jcip.annotations.Immutable;
+
+/**
+ * An identifier for a node, comprised of a single {@link UUID}, and {@link Embeddable embeddable} in a persistent entity. The
+ * identifier takes the form of two <code>long</code> columns: one for the UUID's {@link UUID#getMostSignificantBits() most
+ * significant bits} and one for its {@link UUID#getLeastSignificantBits() least significant bits}.
+ * 
+ * @author Randall Hauch
+ */
+ at Embeddable
+ at Immutable
+ at org.hibernate.annotations.Immutable
+public class NodeId implements Serializable {
+
+    /**
+     * Version {@value}
+     */
+    private static final long serialVersionUID = 1L;
+
+    @Column( name = "UUID", nullable = true )
+    private String uuidString;
+
+    public NodeId() {
+    }
+
+    public NodeId( String uuidString ) {
+        this.uuidString = uuidString;
+    }
+
+    /**
+     * @return uuidString
+     */
+    public String getUuidString() {
+        return uuidString;
+    }
+
+    /**
+     * @param uuidString Sets uuidString to the specified value.
+     */
+    public void setUuidString( String uuidString ) {
+        this.uuidString = uuidString;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return uuidString.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof NodeId) {
+            NodeId that = (NodeId)obj;
+            if (this.uuidString == null) {
+                if (that.uuidString != null) return false;
+            } else {
+                if (!this.uuidString.equals(that.uuidString)) return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return uuidString;
+    }
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/PropertiesEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/PropertiesEntity.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/PropertiesEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,204 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.util.Collection;
-import java.util.HashSet;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.Lob;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import org.jboss.dna.connector.store.jpa.util.Serializer;
-
-/**
- * Represents the packed properties of a single node. Node that the object has the node's identifier and the packed properties,
- * but nothing else. The PropertiesEntity doesn't even have the name. This is because this class is used to read, modify, and save
- * the properties of a node. Finding a node by its name or working with the children, however, requires working with the
- * {@link ChildEntity node children}.
- * 
- * @author Randall Hauch
- */
- at Entity
- at Table( name = "DNA_BASIC_NODEPROPS" )
- at NamedQueries( {
-    @NamedQuery( name = "PropertiesEntity.findByUuid", query = "select prop from PropertiesEntity as prop where prop.id.uuidString = :uuid" ),
-    @NamedQuery( name = "PropertiesEntity.deleteByUuid", query = "delete PropertiesEntity prop where prop.id.uuidString = :uuid" )} )
-public class PropertiesEntity {
-    @Id
-    private NodeId id;
-
-    @Lob
-    @Column( name = "DATA", nullable = true, unique = false )
-    private byte[] data;
-
-    @Column( name = "NUM_PROPS", nullable = false )
-    private int propertyCount;
-
-    /**
-     * Flag specifying whether the binary data is stored in a compressed format.
-     */
-    @Column( name = "COMPRESSED", nullable = true )
-    private Boolean compressed;
-
-    /**
-     * Flag specifying whether the binary data is stored in a compressed format.
-     */
-    @Column( name = "ENFORCEREFINTEG", nullable = false )
-    private boolean referentialIntegrityEnforced = true;
-
-    @org.hibernate.annotations.CollectionOfElements( fetch = FetchType.LAZY )
-    @JoinTable( name = "DNA_LARGEVALUE_USAGES", joinColumns = @JoinColumn( name = "NODE_UUID" ) )
-    private Collection<LargeValueId> largeValues = new HashSet<LargeValueId>();
-
-    public PropertiesEntity() {
-    }
-
-    public PropertiesEntity( NodeId id ) {
-        setId(id);
-    }
-
-    /**
-     * Get the node's identifier.
-     * 
-     * @return the node's identifier
-     */
-    public NodeId getId() {
-        return id;
-    }
-
-    /**
-     * Set the node's identifier.
-     * 
-     * @param id the new identifier for the node
-     */
-    public void setId( NodeId id ) {
-        this.id = id;
-    }
-
-    /**
-     * Get the data that represents the {@link Serializer packed} properties.
-     * 
-     * @return the raw data representing the properties
-     */
-    public byte[] getData() {
-        return data;
-    }
-
-    /**
-     * Set the data that represents the {@link Serializer packed} properties.
-     * 
-     * @param data the raw data representing the properties
-     */
-    public void setData( byte[] data ) {
-        this.data = data;
-    }
-
-    /**
-     * @return propertyCount
-     */
-    public int getPropertyCount() {
-        return propertyCount;
-    }
-
-    /**
-     * @param propertyCount Sets propertyCount to the specified value.
-     */
-    public void setPropertyCount( int propertyCount ) {
-        this.propertyCount = propertyCount;
-    }
-
-    /**
-     * @return compressed
-     */
-    public boolean isCompressed() {
-        return compressed != null && compressed.booleanValue();
-    }
-
-    /**
-     * @param compressed Sets compressed to the specified value.
-     */
-    public void setCompressed( boolean compressed ) {
-        this.compressed = Boolean.valueOf(compressed);
-    }
-
-    /**
-     * @return largeValues
-     */
-    public Collection<LargeValueId> getLargeValues() {
-        return largeValues;
-    }
-
-    /**
-     * @return referentialIntegrityEnforced
-     */
-    public boolean isReferentialIntegrityEnforced() {
-        return referentialIntegrityEnforced;
-    }
-
-    /**
-     * @param referentialIntegrityEnforced Sets referentialIntegrityEnforced to the specified value.
-     */
-    public void setReferentialIntegrityEnforced( boolean referentialIntegrityEnforced ) {
-        this.referentialIntegrityEnforced = referentialIntegrityEnforced;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof PropertiesEntity) {
-            PropertiesEntity that = (PropertiesEntity)obj;
-            if (this.getId().equals(that.getId())) return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "Properties for " + this.id;
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/PropertiesEntity.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/PropertiesEntity.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/PropertiesEntity.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/PropertiesEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,204 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.util.Collection;
+import java.util.HashSet;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.Lob;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import org.jboss.dna.connector.store.jpa.util.Serializer;
+
+/**
+ * Represents the packed properties of a single node. Node that the object has the node's identifier and the packed properties,
+ * but nothing else. The PropertiesEntity doesn't even have the name. This is because this class is used to read, modify, and save
+ * the properties of a node. Finding a node by its name or working with the children, however, requires working with the
+ * {@link ChildEntity node children}.
+ * 
+ * @author Randall Hauch
+ */
+ at Entity
+ at Table( name = "DNA_BASIC_NODEPROPS" )
+ at NamedQueries( {
+    @NamedQuery( name = "PropertiesEntity.findByUuid", query = "select prop from PropertiesEntity as prop where prop.id.uuidString = :uuid" ),
+    @NamedQuery( name = "PropertiesEntity.deleteByUuid", query = "delete PropertiesEntity prop where prop.id.uuidString = :uuid" )} )
+public class PropertiesEntity {
+    @Id
+    private NodeId id;
+
+    @Lob
+    @Column( name = "DATA", nullable = true, unique = false )
+    private byte[] data;
+
+    @Column( name = "NUM_PROPS", nullable = false )
+    private int propertyCount;
+
+    /**
+     * Flag specifying whether the binary data is stored in a compressed format.
+     */
+    @Column( name = "COMPRESSED", nullable = true )
+    private Boolean compressed;
+
+    /**
+     * Flag specifying whether the binary data is stored in a compressed format.
+     */
+    @Column( name = "ENFORCEREFINTEG", nullable = false )
+    private boolean referentialIntegrityEnforced = true;
+
+    @org.hibernate.annotations.CollectionOfElements( fetch = FetchType.LAZY )
+    @JoinTable( name = "DNA_LARGEVALUE_USAGES", joinColumns = @JoinColumn( name = "NODE_UUID" ) )
+    private Collection<LargeValueId> largeValues = new HashSet<LargeValueId>();
+
+    public PropertiesEntity() {
+    }
+
+    public PropertiesEntity( NodeId id ) {
+        setId(id);
+    }
+
+    /**
+     * Get the node's identifier.
+     * 
+     * @return the node's identifier
+     */
+    public NodeId getId() {
+        return id;
+    }
+
+    /**
+     * Set the node's identifier.
+     * 
+     * @param id the new identifier for the node
+     */
+    public void setId( NodeId id ) {
+        this.id = id;
+    }
+
+    /**
+     * Get the data that represents the {@link Serializer packed} properties.
+     * 
+     * @return the raw data representing the properties
+     */
+    public byte[] getData() {
+        return data;
+    }
+
+    /**
+     * Set the data that represents the {@link Serializer packed} properties.
+     * 
+     * @param data the raw data representing the properties
+     */
+    public void setData( byte[] data ) {
+        this.data = data;
+    }
+
+    /**
+     * @return propertyCount
+     */
+    public int getPropertyCount() {
+        return propertyCount;
+    }
+
+    /**
+     * @param propertyCount Sets propertyCount to the specified value.
+     */
+    public void setPropertyCount( int propertyCount ) {
+        this.propertyCount = propertyCount;
+    }
+
+    /**
+     * @return compressed
+     */
+    public boolean isCompressed() {
+        return compressed != null && compressed.booleanValue();
+    }
+
+    /**
+     * @param compressed Sets compressed to the specified value.
+     */
+    public void setCompressed( boolean compressed ) {
+        this.compressed = Boolean.valueOf(compressed);
+    }
+
+    /**
+     * @return largeValues
+     */
+    public Collection<LargeValueId> getLargeValues() {
+        return largeValues;
+    }
+
+    /**
+     * @return referentialIntegrityEnforced
+     */
+    public boolean isReferentialIntegrityEnforced() {
+        return referentialIntegrityEnforced;
+    }
+
+    /**
+     * @param referentialIntegrityEnforced Sets referentialIntegrityEnforced to the specified value.
+     */
+    public void setReferentialIntegrityEnforced( boolean referentialIntegrityEnforced ) {
+        this.referentialIntegrityEnforced = referentialIntegrityEnforced;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof PropertiesEntity) {
+            PropertiesEntity that = (PropertiesEntity)obj;
+            if (this.getId().equals(that.getId())) return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "Properties for " + this.id;
+    }
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ReferenceEntity.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,176 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.util.List;
-import javax.persistence.Entity;
-import javax.persistence.EntityManager;
-import javax.persistence.Id;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.NoResultException;
-import javax.persistence.Query;
-import javax.persistence.Table;
-import org.hibernate.annotations.Index;
-
-/**
- * A record of a reference from one node to another.
- * 
- * @author Randall Hauch
- */
- at Entity
- at Table( name = "DNA_BASIC_REFERENCES" )
- at org.hibernate.annotations.Table( appliesTo = "DNA_BASIC_REFERENCES", indexes = {
-    @Index( name = "REFINDEX_INX", columnNames = {"FROM_UUID", "TO_UUID"} ),
-    @Index( name = "REFTOUUID_INX", columnNames = {"TO_UUID"} )} )
- at NamedQueries( {
-    @NamedQuery( name = "ReferenceEntity.removeReferencesFrom", query = "delete ReferenceEntity where id.fromUuidString = :fromUuid" ),
-    @NamedQuery( name = "ReferenceEntity.removeNonEnforcedReferences", query = "delete ReferenceEntity as ref where ref.id.fromUuidString not in ( select props.id.uuidString from PropertiesEntity props where props.referentialIntegrityEnforced = true )" ),
-    @NamedQuery( name = "ReferenceEntity.countUnresolveReferences", query = "select count(*) from ReferenceEntity as ref where ref.id.toUuidString not in ( select props.id.uuidString from PropertiesEntity props where props.referentialIntegrityEnforced = true )" ),
-    @NamedQuery( name = "ReferenceEntity.getUnresolveReferences", query = "select ref from ReferenceEntity as ref where ref.id.toUuidString not in ( select props.id.uuidString from PropertiesEntity props where props.referentialIntegrityEnforced = true )" )} )
-public class ReferenceEntity {
-
-    @Id
-    private ReferenceId id;
-
-    /**
-     * 
-     */
-    public ReferenceEntity() {
-    }
-
-    /**
-     * @param id the id
-     */
-    public ReferenceEntity( ReferenceId id ) {
-        this.id = id;
-    }
-
-    /**
-     * @return id
-     */
-    public ReferenceId getId() {
-        return id;
-    }
-
-    /**
-     * @param id Sets id to the specified value.
-     */
-    public void setId( ReferenceId id ) {
-        this.id = id;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof ReferenceEntity) {
-            ReferenceEntity that = (ReferenceEntity)obj;
-            if (this.getId().equals(that.getId())) return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return this.id.toString();
-    }
-
-    /**
-     * Delete all references that start from the node with the supplied UUID.
-     * 
-     * @param uuid the UUID of the node from which the references start
-     * @param manager the manager; may not be null
-     * @return the number of deleted references
-     */
-    public static int deleteReferencesFrom( String uuid,
-                                            EntityManager manager ) {
-        assert manager != null;
-        Query delete = manager.createNamedQuery("ReferenceEntity.removeReferencesFrom");
-        delete.setParameter("fromUuid", uuid);
-        int result = delete.executeUpdate();
-        manager.flush();
-        return result;
-    }
-
-    /**
-     * Delete all references that start from nodes that do not support enforced referential integrity.
-     * 
-     * @param manager the manager; may not be null
-     * @return the number of deleted references
-     */
-    public static int deleteUnenforcedReferences( EntityManager manager ) {
-        assert manager != null;
-        Query delete = manager.createNamedQuery("ReferenceEntity.removeNonEnforcedReferences");
-        int result = delete.executeUpdate();
-        manager.flush();
-        return result;
-    }
-
-    /**
-     * Delete all references that start from nodes that do not support enforced referential integrity.
-     * 
-     * @param manager the manager; may not be null
-     * @return the number of deleted references
-     */
-    public static int countAllReferencesResolved( EntityManager manager ) {
-        assert manager != null;
-        Query query = manager.createNamedQuery("ReferenceEntity.getUnresolveReferences");
-        try {
-            return (Integer)query.getSingleResult();
-        } catch (NoResultException e) {
-            return 0;
-        }
-    }
-
-    /**
-     * Delete all references that start from nodes that do not support enforced referential integrity.
-     * 
-     * @param manager the manager; may not be null
-     * @return the number of deleted references
-     */
-    @SuppressWarnings( "unchecked" )
-    public static List<ReferenceEntity> verifyAllReferencesResolved( EntityManager manager ) {
-        assert manager != null;
-        Query query = manager.createNamedQuery("ReferenceEntity.getUnresolveReferences");
-        return query.getResultList();
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceEntity.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ReferenceEntity.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceEntity.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,176 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.util.List;
+import javax.persistence.Entity;
+import javax.persistence.EntityManager;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import javax.persistence.Table;
+import org.hibernate.annotations.Index;
+
+/**
+ * A record of a reference from one node to another.
+ * 
+ * @author Randall Hauch
+ */
+ at Entity
+ at Table( name = "DNA_BASIC_REFERENCES" )
+ at org.hibernate.annotations.Table( appliesTo = "DNA_BASIC_REFERENCES", indexes = {
+    @Index( name = "REFINDEX_INX", columnNames = {"FROM_UUID", "TO_UUID"} ),
+    @Index( name = "REFTOUUID_INX", columnNames = {"TO_UUID"} )} )
+ at NamedQueries( {
+    @NamedQuery( name = "ReferenceEntity.removeReferencesFrom", query = "delete ReferenceEntity where id.fromUuidString = :fromUuid" ),
+    @NamedQuery( name = "ReferenceEntity.removeNonEnforcedReferences", query = "delete ReferenceEntity as ref where ref.id.fromUuidString not in ( select props.id.uuidString from PropertiesEntity props where props.referentialIntegrityEnforced = true )" ),
+    @NamedQuery( name = "ReferenceEntity.countUnresolveReferences", query = "select count(*) from ReferenceEntity as ref where ref.id.toUuidString not in ( select props.id.uuidString from PropertiesEntity props where props.referentialIntegrityEnforced = true )" ),
+    @NamedQuery( name = "ReferenceEntity.getUnresolveReferences", query = "select ref from ReferenceEntity as ref where ref.id.toUuidString not in ( select props.id.uuidString from PropertiesEntity props where props.referentialIntegrityEnforced = true )" )} )
+public class ReferenceEntity {
+
+    @Id
+    private ReferenceId id;
+
+    /**
+     * 
+     */
+    public ReferenceEntity() {
+    }
+
+    /**
+     * @param id the id
+     */
+    public ReferenceEntity( ReferenceId id ) {
+        this.id = id;
+    }
+
+    /**
+     * @return id
+     */
+    public ReferenceId getId() {
+        return id;
+    }
+
+    /**
+     * @param id Sets id to the specified value.
+     */
+    public void setId( ReferenceId id ) {
+        this.id = id;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof ReferenceEntity) {
+            ReferenceEntity that = (ReferenceEntity)obj;
+            if (this.getId().equals(that.getId())) return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return this.id.toString();
+    }
+
+    /**
+     * Delete all references that start from the node with the supplied UUID.
+     * 
+     * @param uuid the UUID of the node from which the references start
+     * @param manager the manager; may not be null
+     * @return the number of deleted references
+     */
+    public static int deleteReferencesFrom( String uuid,
+                                            EntityManager manager ) {
+        assert manager != null;
+        Query delete = manager.createNamedQuery("ReferenceEntity.removeReferencesFrom");
+        delete.setParameter("fromUuid", uuid);
+        int result = delete.executeUpdate();
+        manager.flush();
+        return result;
+    }
+
+    /**
+     * Delete all references that start from nodes that do not support enforced referential integrity.
+     * 
+     * @param manager the manager; may not be null
+     * @return the number of deleted references
+     */
+    public static int deleteUnenforcedReferences( EntityManager manager ) {
+        assert manager != null;
+        Query delete = manager.createNamedQuery("ReferenceEntity.removeNonEnforcedReferences");
+        int result = delete.executeUpdate();
+        manager.flush();
+        return result;
+    }
+
+    /**
+     * Delete all references that start from nodes that do not support enforced referential integrity.
+     * 
+     * @param manager the manager; may not be null
+     * @return the number of deleted references
+     */
+    public static int countAllReferencesResolved( EntityManager manager ) {
+        assert manager != null;
+        Query query = manager.createNamedQuery("ReferenceEntity.getUnresolveReferences");
+        try {
+            return (Integer)query.getSingleResult();
+        } catch (NoResultException e) {
+            return 0;
+        }
+    }
+
+    /**
+     * Delete all references that start from nodes that do not support enforced referential integrity.
+     * 
+     * @param manager the manager; may not be null
+     * @return the number of deleted references
+     */
+    @SuppressWarnings( "unchecked" )
+    public static List<ReferenceEntity> verifyAllReferencesResolved( EntityManager manager ) {
+        assert manager != null;
+        Query query = manager.createNamedQuery("ReferenceEntity.getUnresolveReferences");
+        return query.getResultList();
+    }
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceId.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ReferenceId.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceId.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,120 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.io.Serializable;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.HashCode;
-
-/**
- * An identifier for a reference, comprised of a single {@link NodeId} of the node containing the reference and a single
- * {@link NodeId} of the node being referenced.
- * 
- * @author Randall Hauch
- */
- at Embeddable
- at Immutable
- at org.hibernate.annotations.Immutable
-public class ReferenceId implements Serializable {
-
-    /**
-     * Version {@value}
-     */
-    private static final long serialVersionUID = 1L;
-
-    @Column( name = "FROM_UUID", nullable = false, updatable = false, length = 36 )
-    private String fromUuidString;
-
-    @Column( name = "TO_UUID", nullable = false, updatable = false, length = 36 )
-    private String toUuidString;
-
-    public ReferenceId() {
-    }
-
-    public ReferenceId( String fromUuid,
-                        String toUuid ) {
-        this.fromUuidString = fromUuid;
-        this.toUuidString = toUuid;
-    }
-
-    /**
-     * @return fromUuidString
-     */
-    public String getFromUuidString() {
-        return fromUuidString;
-    }
-
-    /**
-     * @return toUuidString
-     */
-    public String getToUuidString() {
-        return toUuidString;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return HashCode.compute(fromUuidString, toUuidString);
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof ReferenceId) {
-            ReferenceId that = (ReferenceId)obj;
-            if (this.fromUuidString == null) {
-                if (that.fromUuidString != null) return false;
-            } else {
-                if (!this.fromUuidString.equals(that.fromUuidString)) return false;
-            }
-            if (this.toUuidString == null) {
-                if (that.toUuidString != null) return false;
-            } else {
-                if (!this.toUuidString.equals(that.toUuidString)) return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "Reference from " + fromUuidString + " to " + toUuidString;
-    }
-
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceId.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ReferenceId.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceId.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ReferenceId.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,120 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.HashCode;
+
+/**
+ * An identifier for a reference, comprised of a single {@link NodeId} of the node containing the reference and a single
+ * {@link NodeId} of the node being referenced.
+ * 
+ * @author Randall Hauch
+ */
+ at Embeddable
+ at Immutable
+ at org.hibernate.annotations.Immutable
+public class ReferenceId implements Serializable {
+
+    /**
+     * Version {@value}
+     */
+    private static final long serialVersionUID = 1L;
+
+    @Column( name = "FROM_UUID", nullable = false, updatable = false, length = 36 )
+    private String fromUuidString;
+
+    @Column( name = "TO_UUID", nullable = false, updatable = false, length = 36 )
+    private String toUuidString;
+
+    public ReferenceId() {
+    }
+
+    public ReferenceId( String fromUuid,
+                        String toUuid ) {
+        this.fromUuidString = fromUuid;
+        this.toUuidString = toUuid;
+    }
+
+    /**
+     * @return fromUuidString
+     */
+    public String getFromUuidString() {
+        return fromUuidString;
+    }
+
+    /**
+     * @return toUuidString
+     */
+    public String getToUuidString() {
+        return toUuidString;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return HashCode.compute(fromUuidString, toUuidString);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof ReferenceId) {
+            ReferenceId that = (ReferenceId)obj;
+            if (this.fromUuidString == null) {
+                if (that.fromUuidString != null) return false;
+            } else {
+                if (!this.fromUuidString.equals(that.fromUuidString)) return false;
+            }
+            if (this.toUuidString == null) {
+                if (that.toUuidString != null) return false;
+            } else {
+                if (!this.toUuidString.equals(that.toUuidString)) return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "Reference from " + fromUuidString + " to " + toUuidString;
+    }
+
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphNodeEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphNodeEntity.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphNodeEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,167 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import org.hibernate.annotations.Index;
-
-/**
- * Represents a single node that appears in a subgraph.
- * 
- * @author Randall Hauch
- * @see SubgraphQueryEntity
- */
- at Entity
- at Table( name = "DNA_SUBGRAPH_NODES" )
- at org.hibernate.annotations.Table( appliesTo = "DNA_SUBGRAPH_NODES", indexes = @Index( name = "QUERYID_INX", columnNames = {
-    "QUERY_ID", "UUID"} ) )
- at NamedQueries( {
-    @NamedQuery( name = "SubgraphNodeEntity.insertChildren", query = "insert into SubgraphNodeEntity(queryId,nodeUuid,depth,parentIndexInParent,indexInParent) select parentNode.queryId, child.id.childUuidString, parentNode.depth+1, parentNode.indexInParent, child.indexInParent from ChildEntity child, SubgraphNodeEntity parentNode where child.id.parentUuidString = parentNode.nodeUuid and parentNode.queryId = :queryId and parentNode.depth = :parentDepth" ),
-    @NamedQuery( name = "SubgraphNodeEntity.getCount", query = "select count(*) from SubgraphNodeEntity where queryId = :queryId" ),
-    @NamedQuery( name = "SubgraphNodeEntity.getPropertiesEntities", query = "select props from PropertiesEntity props, SubgraphNodeEntity node where props.id.uuidString = node.nodeUuid and node.queryId = :queryId and node.depth >= :depth and node.depth <= :maxDepth order by node.depth, node.parentIndexInParent, node.indexInParent" ),
-    @NamedQuery( name = "SubgraphNodeEntity.getPropertiesEntitiesWithLargeValues", query = "select props from PropertiesEntity props, SubgraphNodeEntity node where props.id.uuidString = node.nodeUuid and node.queryId = :queryId and node.depth >= :depth and size(props.largeValues) > 0" ),
-    @NamedQuery( name = "SubgraphNodeEntity.getChildEntities", query = "select child from ChildEntity child, SubgraphNodeEntity node where child.id.childUuidString = node.nodeUuid and node.queryId = :queryId and node.depth >= :depth and node.depth <= :maxDepth order by node.depth, node.parentIndexInParent, node.indexInParent" ),
-    @NamedQuery( name = "SubgraphNodeEntity.getInternalReferences", query = "select ref from ReferenceEntity as ref where ref.id.toUuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId) and ref.id.fromUuidString in (select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId)" ),
-    @NamedQuery( name = "SubgraphNodeEntity.getOutwardReferences", query = "select ref from ReferenceEntity as ref where ref.id.toUuidString not in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId) and ref.id.fromUuidString in (select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId)" ),
-    @NamedQuery( name = "SubgraphNodeEntity.getInwardReferences", query = "select ref from ReferenceEntity as ref where ref.id.toUuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId) and ref.id.fromUuidString not in (select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId)" ),
-    @NamedQuery( name = "SubgraphNodeEntity.deletePropertiesEntities", query = "delete PropertiesEntity props where props.id.uuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId )" ),
-    @NamedQuery( name = "SubgraphNodeEntity.deleteChildEntities", query = "delete ChildEntity child where child.id.childUuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId )" ),
-    @NamedQuery( name = "SubgraphNodeEntity.deleteReferences", query = "delete ReferenceEntity as ref where ref.id.fromUuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId )" ),
-    @NamedQuery( name = "SubgraphNodeEntity.deleteByQueryId", query = "delete SubgraphNodeEntity where queryId = :queryId" )} )
-public class SubgraphNodeEntity {
-
-    @Id
-    @Column( name = "ID" )
-    @GeneratedValue( strategy = GenerationType.AUTO )
-    private Long id;
-
-    @Column( name = "QUERY_ID", nullable = false, unique = false, updatable = false )
-    private Long queryId;
-
-    @Column( name = "UUID", updatable = false, nullable = false, length = 36 )
-    private String nodeUuid;
-
-    @Column( name = "DEPTH", updatable = false, nullable = false )
-    private int depth;
-
-    @Column( name = "PARENT_NUM", updatable = false, nullable = false )
-    private int parentIndexInParent;
-
-    @Column( name = "CHILD_NUM", updatable = false, nullable = false )
-    private int indexInParent;
-
-    public SubgraphNodeEntity() {
-    }
-
-    public SubgraphNodeEntity( Long queryId,
-                               String nodeUuid,
-                               int depth ) {
-        this.queryId = queryId;
-        this.nodeUuid = nodeUuid;
-        this.depth = depth;
-    }
-
-    /**
-     * @return id
-     */
-    public Long getId() {
-        return id;
-    }
-
-    /**
-     * @return depth
-     */
-    public int getDepth() {
-        return depth;
-    }
-
-    /**
-     * @return nodeUuid
-     */
-    public String getNodeUuid() {
-        return nodeUuid;
-    }
-
-    /**
-     * @return queryId
-     */
-    public Long getQueryId() {
-        return queryId;
-    }
-
-    /**
-     * @return indexInParent
-     */
-    public int getIndexInParent() {
-        return indexInParent;
-    }
-
-    /**
-     * @return parentIndexInParent
-     */
-    public int getParentIndexInParent() {
-        return parentIndexInParent;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return id != null ? id.intValue() : 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof SubgraphNodeEntity) {
-            SubgraphNodeEntity that = (SubgraphNodeEntity)obj;
-            if (this.id.equals(that.id)) return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "" + id + " - Query " + queryId + "; depth=" + depth + "; node=" + nodeUuid + " at index " + indexInParent;
-    }
-
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphNodeEntity.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphNodeEntity.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphNodeEntity.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphNodeEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,167 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import org.hibernate.annotations.Index;
+
+/**
+ * Represents a single node that appears in a subgraph.
+ * 
+ * @author Randall Hauch
+ * @see SubgraphQueryEntity
+ */
+ at Entity
+ at Table( name = "DNA_SUBGRAPH_NODES" )
+ at org.hibernate.annotations.Table( appliesTo = "DNA_SUBGRAPH_NODES", indexes = @Index( name = "QUERYID_INX", columnNames = {
+    "QUERY_ID", "UUID"} ) )
+ at NamedQueries( {
+    @NamedQuery( name = "SubgraphNodeEntity.insertChildren", query = "insert into SubgraphNodeEntity(queryId,nodeUuid,depth,parentIndexInParent,indexInParent) select parentNode.queryId, child.id.childUuidString, parentNode.depth+1, parentNode.indexInParent, child.indexInParent from ChildEntity child, SubgraphNodeEntity parentNode where child.id.parentUuidString = parentNode.nodeUuid and parentNode.queryId = :queryId and parentNode.depth = :parentDepth" ),
+    @NamedQuery( name = "SubgraphNodeEntity.getCount", query = "select count(*) from SubgraphNodeEntity where queryId = :queryId" ),
+    @NamedQuery( name = "SubgraphNodeEntity.getPropertiesEntities", query = "select props from PropertiesEntity props, SubgraphNodeEntity node where props.id.uuidString = node.nodeUuid and node.queryId = :queryId and node.depth >= :depth and node.depth <= :maxDepth order by node.depth, node.parentIndexInParent, node.indexInParent" ),
+    @NamedQuery( name = "SubgraphNodeEntity.getPropertiesEntitiesWithLargeValues", query = "select props from PropertiesEntity props, SubgraphNodeEntity node where props.id.uuidString = node.nodeUuid and node.queryId = :queryId and node.depth >= :depth and size(props.largeValues) > 0" ),
+    @NamedQuery( name = "SubgraphNodeEntity.getChildEntities", query = "select child from ChildEntity child, SubgraphNodeEntity node where child.id.childUuidString = node.nodeUuid and node.queryId = :queryId and node.depth >= :depth and node.depth <= :maxDepth order by node.depth, node.parentIndexInParent, node.indexInParent" ),
+    @NamedQuery( name = "SubgraphNodeEntity.getInternalReferences", query = "select ref from ReferenceEntity as ref where ref.id.toUuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId) and ref.id.fromUuidString in (select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId)" ),
+    @NamedQuery( name = "SubgraphNodeEntity.getOutwardReferences", query = "select ref from ReferenceEntity as ref where ref.id.toUuidString not in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId) and ref.id.fromUuidString in (select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId)" ),
+    @NamedQuery( name = "SubgraphNodeEntity.getInwardReferences", query = "select ref from ReferenceEntity as ref where ref.id.toUuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId) and ref.id.fromUuidString not in (select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId)" ),
+    @NamedQuery( name = "SubgraphNodeEntity.deletePropertiesEntities", query = "delete PropertiesEntity props where props.id.uuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId )" ),
+    @NamedQuery( name = "SubgraphNodeEntity.deleteChildEntities", query = "delete ChildEntity child where child.id.childUuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId )" ),
+    @NamedQuery( name = "SubgraphNodeEntity.deleteReferences", query = "delete ReferenceEntity as ref where ref.id.fromUuidString in ( select node.nodeUuid from SubgraphNodeEntity node where node.queryId = :queryId )" ),
+    @NamedQuery( name = "SubgraphNodeEntity.deleteByQueryId", query = "delete SubgraphNodeEntity where queryId = :queryId" )} )
+public class SubgraphNodeEntity {
+
+    @Id
+    @Column( name = "ID" )
+    @GeneratedValue( strategy = GenerationType.AUTO )
+    private Long id;
+
+    @Column( name = "QUERY_ID", nullable = false, unique = false, updatable = false )
+    private Long queryId;
+
+    @Column( name = "UUID", updatable = false, nullable = false, length = 36 )
+    private String nodeUuid;
+
+    @Column( name = "DEPTH", updatable = false, nullable = false )
+    private int depth;
+
+    @Column( name = "PARENT_NUM", updatable = false, nullable = false )
+    private int parentIndexInParent;
+
+    @Column( name = "CHILD_NUM", updatable = false, nullable = false )
+    private int indexInParent;
+
+    public SubgraphNodeEntity() {
+    }
+
+    public SubgraphNodeEntity( Long queryId,
+                               String nodeUuid,
+                               int depth ) {
+        this.queryId = queryId;
+        this.nodeUuid = nodeUuid;
+        this.depth = depth;
+    }
+
+    /**
+     * @return id
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * @return depth
+     */
+    public int getDepth() {
+        return depth;
+    }
+
+    /**
+     * @return nodeUuid
+     */
+    public String getNodeUuid() {
+        return nodeUuid;
+    }
+
+    /**
+     * @return queryId
+     */
+    public Long getQueryId() {
+        return queryId;
+    }
+
+    /**
+     * @return indexInParent
+     */
+    public int getIndexInParent() {
+        return indexInParent;
+    }
+
+    /**
+     * @return parentIndexInParent
+     */
+    public int getParentIndexInParent() {
+        return parentIndexInParent;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return id != null ? id.intValue() : 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof SubgraphNodeEntity) {
+            SubgraphNodeEntity that = (SubgraphNodeEntity)obj;
+            if (this.id.equals(that.id)) return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "" + id + " - Query " + queryId + "; depth=" + depth + "; node=" + nodeUuid + " at index " + indexInParent;
+    }
+
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQuery.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQuery.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQuery.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,397 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.Query;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-
-/**
- * Represents a temporary working area for a query that efficiently retrieves the nodes in a subgraph. This class uses the
- * database to build up the content of the subgraph, and therefore requires write privilege on the database. The benefit is that
- * it minimizes the amount of memory required to process the subgraph, plus the set of nodes that make up the subgraph can be
- * produced with database joins.
- * <p>
- * The use of database joins also produces another benefit: the number of SQL statements necessary to build the set of nodes in a
- * subgraph is equal to the depth of the subgraph, regardless of the number of child nodes at any level.
- * </p>
- * 
- * @author Randall Hauch
- */
-public class SubgraphQuery {
-
-    /**
-     * Create a query that returns a subgraph at and below the node with the supplied path and the supplied UUID.
-     * 
-     * @param context the execution context; may not be null
-     * @param entities the entity manager; may not be null
-     * @param subgraphRootUuid the UUID (in string form) of the root node in the subgraph
-     * @param subgraphRootPath the path of the root node in the subgraph
-     * @param maxDepth the maximum depth of the subgraph, or 0 if there is no maximum depth
-     * @return the object representing the subgraph
-     */
-    public static SubgraphQuery create( ExecutionContext context,
-                                        EntityManager entities,
-                                        UUID subgraphRootUuid,
-                                        Path subgraphRootPath,
-                                        int maxDepth ) {
-        assert entities != null;
-        assert subgraphRootUuid != null;
-        assert maxDepth >= 0;
-        if (maxDepth == 0) maxDepth = Integer.MAX_VALUE;
-        final String subgraphRootUuidString = subgraphRootUuid.toString();
-        // Create a new subgraph query, and add a child for the root ...
-        SubgraphQueryEntity query = new SubgraphQueryEntity(subgraphRootUuidString);
-        entities.persist(query);
-        Long queryId = query.getId();
-
-        try {
-            // Insert a node for the root (this will be the starting point for the recursive operation) ...
-            SubgraphNodeEntity root = new SubgraphNodeEntity(queryId, subgraphRootUuidString, 0);
-            entities.persist(root);
-
-            // Now add the children by inserting the children, one level at a time.
-            // Note that we do this for the root, and for each level until 1 BEYOND
-            // the max depth (so that we can get the children for the nodes that are
-            // at the maximum depth)...
-            Query statement = entities.createNamedQuery("SubgraphNodeEntity.insertChildren");
-            int numChildrenInserted = 0;
-            int parentLevel = 0;
-            while (parentLevel <= maxDepth) {
-                // Insert the children of the next level by inserting via a select (join) of the children
-                statement.setParameter("queryId", queryId);
-                statement.setParameter("parentDepth", parentLevel);
-                numChildrenInserted = statement.executeUpdate();
-                if (numChildrenInserted == 0) break;
-                parentLevel = parentLevel + 1;
-            }
-        } catch (RuntimeException t) {
-            // Clean up the search and results ...
-            try {
-                Query search = entities.createNamedQuery("SubgraphNodeEntity.deleteByQueryId");
-                search.setParameter("queryId", query.getId());
-                search.executeUpdate();
-            } finally {
-                entities.remove(query);
-            }
-            throw t;
-        }
-        return new SubgraphQuery(context, entities, query, subgraphRootPath, maxDepth);
-    }
-
-    private final ExecutionContext context;
-    private final EntityManager manager;
-    private SubgraphQueryEntity query;
-    private final int maxDepth;
-    private final Path subgraphRootPath;
-
-    protected SubgraphQuery( ExecutionContext context,
-                             EntityManager manager,
-                             SubgraphQueryEntity query,
-                             Path subgraphRootPath,
-                             int maxDepth ) {
-        assert manager != null;
-        assert query != null;
-        assert context != null;
-        assert subgraphRootPath != null;
-        this.context = context;
-        this.manager = manager;
-        this.query = query;
-        this.maxDepth = maxDepth;
-        this.subgraphRootPath = subgraphRootPath;
-    }
-
-    /**
-     * @return maxDepth
-     */
-    public int getMaxDepth() {
-        return maxDepth;
-    }
-
-    /**
-     * @return manager
-     */
-    public EntityManager getEntityManager() {
-        return manager;
-    }
-
-    /**
-     * @return subgraphRootPath
-     */
-    public Path getSubgraphRootPath() {
-        return subgraphRootPath;
-    }
-
-    /**
-     * @return query
-     */
-    public SubgraphQueryEntity getSubgraphQueryEntity() {
-        if (query == null) throw new IllegalStateException();
-        return query;
-    }
-
-    public int getNodeCount( boolean includeRoot ) {
-        if (query == null) throw new IllegalStateException();
-        // Now query for all the nodes and put into a list ...
-        Query search = manager.createNamedQuery("SubgraphNodeEntity.getCount");
-        search.setParameter("queryId", query.getId());
-
-        // Now process the nodes below the subgraph's root ...
-        try {
-            return (Integer)search.getSingleResult() - (includeRoot ? 0 : 1);
-        } catch (NoResultException e) {
-            return 0;
-        }
-    }
-
-    /**
-     * Get the {@link ChildEntity root node} of the subgraph. This must be called before the query is {@link #close() closed}.
-     * 
-     * @return the subgraph's root nodes
-     */
-    public ChildEntity getNode() {
-        // Now query for all the nodes and put into a list ...
-        Query search = manager.createNamedQuery("SubgraphNodeEntity.getChildEntities");
-        search.setParameter("queryId", query.getId());
-        search.setParameter("depth", 0);
-        search.setParameter("maxDepth", 0);
-
-        // Now process the nodes below the subgraph's root ...
-        return (ChildEntity)search.getSingleResult();
-    }
-
-    /**
-     * Get the {@link ChildEntity nodes} in the subgraph. This must be called before the query is {@link #close() closed}.
-     * 
-     * @param includeRoot true if the subgraph's root node is to be included, or false otherwise
-     * @param includeChildrenOfMaxDepthNodes true if the method is to include nodes that are children of nodes that are at the
-     *        maximum depth, or false if only nodes up to the maximum depth are to be included
-     * @return the list of nodes, in breadth-first order
-     */
-    @SuppressWarnings( "unchecked" )
-    public List<ChildEntity> getNodes( boolean includeRoot,
-                                       boolean includeChildrenOfMaxDepthNodes ) {
-        if (query == null) throw new IllegalStateException();
-        // Now query for all the nodes and put into a list ...
-        Query search = manager.createNamedQuery("SubgraphNodeEntity.getChildEntities");
-        search.setParameter("queryId", query.getId());
-        search.setParameter("depth", includeRoot ? 0 : 1);
-        search.setParameter("maxDepth", includeChildrenOfMaxDepthNodes ? maxDepth : maxDepth - 1);
-
-        // Now process the nodes below the subgraph's root ...
-        return search.getResultList();
-    }
-
-    /**
-     * Get the {@link PropertiesEntity properties} for each of the nodes in the subgraph. This must be called before the query is
-     * {@link #close() closed}.
-     * 
-     * @param includeRoot true if the properties for the subgraph's root node are to be included, or false otherwise
-     * @param includeChildrenOfMaxDepthNodes true if the method is to include nodes that are children of nodes that are at the
-     *        maximum depth, or false if only nodes up to the maximum depth are to be included
-     * @return the list of properties for each of the nodes, in breadth-first order
-     */
-    @SuppressWarnings( "unchecked" )
-    public List<PropertiesEntity> getProperties( boolean includeRoot,
-                                                 boolean includeChildrenOfMaxDepthNodes ) {
-        if (query == null) throw new IllegalStateException();
-        // Now query for all the nodes and put into a list ...
-        Query search = manager.createNamedQuery("SubgraphNodeEntity.getPropertiesEntities");
-        search.setParameter("queryId", query.getId());
-        search.setParameter("depth", includeRoot ? 0 : 1);
-        search.setParameter("maxDepth", includeChildrenOfMaxDepthNodes ? maxDepth : maxDepth - 1);
-
-        // Now process the nodes below the subgraph's root ...
-        return search.getResultList();
-    }
-
-    /**
-     * Get the {@link Location} for each of the nodes in the subgraph. This must be called before the query is {@link #close()
-     * closed}.
-     * <p>
-     * This method calls {@link #getNodes(boolean,boolean)}. Therefore, calling {@link #getNodes(boolean,boolean)} and this method
-     * for the same subgraph is not efficient; consider just calling {@link #getNodes(boolean,boolean)} alone.
-     * </p>
-     * 
-     * @param includeRoot true if the properties for the subgraph's root node are to be included, or false otherwise
-     * @param includeChildrenOfMaxDepthNodes true if the method is to include nodes that are children of nodes that are at the
-     *        maximum depth, or false if only nodes up to the maximum depth are to be included
-     * @return the list of {@link Location locations}, one for each of the nodes in the subgraph, in breadth-first order
-     */
-    public List<Location> getNodeLocations( boolean includeRoot,
-                                            boolean includeChildrenOfMaxDepthNodes ) {
-        if (query == null) throw new IllegalStateException();
-        // Set up a map of the paths to the nodes, keyed by UUIDs. This saves us from having to build
-        // the paths every time ...
-        Map<String, Path> pathByUuid = new HashMap<String, Path>();
-        LinkedList<Location> locations = new LinkedList<Location>();
-        String subgraphRootUuid = query.getRootUuid();
-        pathByUuid.put(subgraphRootUuid, subgraphRootPath);
-        UUID uuid = UUID.fromString(subgraphRootUuid);
-        if (includeRoot) {
-            locations.add(new Location(subgraphRootPath, uuid));
-        }
-
-        // Now iterate over the child nodes in the subgraph (we've already included the root) ...
-        final PathFactory pathFactory = context.getValueFactories().getPathFactory();
-        final NameFactory nameFactory = context.getValueFactories().getNameFactory();
-        for (ChildEntity entity : getNodes(false, includeChildrenOfMaxDepthNodes)) {
-            String parentUuid = entity.getId().getParentUuidString();
-            Path parentPath = pathByUuid.get(parentUuid);
-            assert parentPath != null;
-            String nsUri = entity.getChildNamespace().getUri();
-            String localName = entity.getChildName();
-            int sns = entity.getSameNameSiblingIndex();
-            Name childName = nameFactory.create(nsUri, localName);
-            Path childPath = pathFactory.create(parentPath, childName, sns);
-            String childUuid = entity.getId().getChildUuidString();
-            pathByUuid.put(childUuid, childPath);
-            uuid = UUID.fromString(childUuid);
-            locations.add(new Location(childPath, uuid));
-
-        }
-        return locations;
-    }
-
-    /**
-     * Get the list of references that are owned by nodes within the subgraph and that point to other nodes <i>in this same
-     * subgraph</i>. This set of references is important in copying a subgraph, since all intra-subgraph references in the
-     * original subgraph must also be intra-subgraph references in the copy.
-     * 
-     * @return the list of references completely contained by this subgraphs
-     */
-    @SuppressWarnings( "unchecked" )
-    public List<ReferenceEntity> getInternalReferences() {
-        Query references = manager.createNamedQuery("SubgraphNodeEntity.getInternalReferences");
-        references.setParameter("queryId", query.getId());
-        return references.getResultList();
-    }
-
-    /**
-     * Get the list of references that are owned by nodes within the subgraph and that point to nodes <i>not in this same
-     * subgraph</i>. This set of references is important in copying a subgraph.
-     * 
-     * @return the list of references that are owned by the subgraph but that point to nodes outside of the subgraph
-     */
-    @SuppressWarnings( "unchecked" )
-    public List<ReferenceEntity> getOutwardReferences() {
-        Query references = manager.createNamedQuery("SubgraphNodeEntity.getOutwardReferences");
-        references.setParameter("queryId", query.getId());
-        return references.getResultList();
-    }
-
-    /**
-     * Get the list of references that are owned by nodes <i>outside</i> of the subgraph that point to nodes <i>in this
-     * subgraph</i>. This set of references is important in deleting nodes, since such references prevent the deletion of the
-     * subgraph.
-     * 
-     * @return the list of references that are no longer valid
-     */
-    @SuppressWarnings( "unchecked" )
-    public List<ReferenceEntity> getInwardReferences() {
-        // Verify referential integrity: that none of the deleted nodes are referenced by nodes not being deleted.
-        Query references = manager.createNamedQuery("SubgraphNodeEntity.getInwardReferences");
-        references.setParameter("queryId", query.getId());
-        return references.getResultList();
-    }
-
-    /**
-     * Delete the nodes in the subgraph. This method first does not check for referential integrity (see
-     * {@link #getInwardReferences()}).
-     * 
-     * @param includeRoot true if the root node should also be deleted
-     */
-    @SuppressWarnings( "unchecked" )
-    public void deleteSubgraph( boolean includeRoot ) {
-        if (query == null) throw new IllegalStateException();
-
-        // Delete the PropertiesEntities ...
-        //
-        // Right now, Hibernate is not able to support deleting PropertiesEntity in bulk because of the
-        // large value association (and there's no way to clear the association in bulk).
-        // Therefore, the only way to do this with Hibernate is to load each PropertiesEntity that has
-        // large values and clear them. (Theoretically, fewer PropertiesEntity objects will have large values
-        // than the total number in the subgraph.)
-        // Then we can delete the properties.
-        Query withLargeValues = manager.createNamedQuery("SubgraphNodeEntity.getPropertiesEntitiesWithLargeValues");
-        withLargeValues.setParameter("queryId", query.getId());
-        withLargeValues.setParameter("depth", includeRoot ? 0 : 1);
-        List<PropertiesEntity> propertiesWithLargeValues = withLargeValues.getResultList();
-        if (propertiesWithLargeValues.size() != 0) {
-            for (PropertiesEntity props : propertiesWithLargeValues) {
-                props.getLargeValues().clear();
-            }
-            manager.flush();
-        }
-
-        // Delete the PropertiesEntities, none of which will have large values ...
-        Query delete = manager.createNamedQuery("SubgraphNodeEntity.deletePropertiesEntities");
-        delete.setParameter("queryId", query.getId());
-        delete.executeUpdate();
-
-        // Delete the ChildEntities ...
-        delete = manager.createNamedQuery("SubgraphNodeEntity.deleteChildEntities");
-        delete.setParameter("queryId", query.getId());
-        delete.executeUpdate();
-
-        // Delete references ...
-        delete = manager.createNamedQuery("SubgraphNodeEntity.deleteReferences");
-        delete.setParameter("queryId", query.getId());
-        delete.executeUpdate();
-
-        // Delete unused large values ...
-        LargeValueEntity.deleteUnused(manager);
-
-        manager.flush();
-    }
-
-    /**
-     * Close this query object and clean up all in-database records associated with this query. This method <i>must</i> be called
-     * when this query is no longer needed, and once it is called, this subgraph query is no longer usable.
-     */
-    public void close() {
-        if (query == null) return;
-        // Clean up the search and results ...
-        try {
-            Query search = manager.createNamedQuery("SubgraphNodeEntity.deleteByQueryId");
-            search.setParameter("queryId", query.getId());
-            search.executeUpdate();
-        } finally {
-            try {
-                manager.remove(query);
-            } finally {
-                query = null;
-            }
-        }
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQuery.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQuery.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQuery.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQuery.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,397 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+
+/**
+ * Represents a temporary working area for a query that efficiently retrieves the nodes in a subgraph. This class uses the
+ * database to build up the content of the subgraph, and therefore requires write privilege on the database. The benefit is that
+ * it minimizes the amount of memory required to process the subgraph, plus the set of nodes that make up the subgraph can be
+ * produced with database joins.
+ * <p>
+ * The use of database joins also produces another benefit: the number of SQL statements necessary to build the set of nodes in a
+ * subgraph is equal to the depth of the subgraph, regardless of the number of child nodes at any level.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+public class SubgraphQuery {
+
+    /**
+     * Create a query that returns a subgraph at and below the node with the supplied path and the supplied UUID.
+     * 
+     * @param context the execution context; may not be null
+     * @param entities the entity manager; may not be null
+     * @param subgraphRootUuid the UUID (in string form) of the root node in the subgraph
+     * @param subgraphRootPath the path of the root node in the subgraph
+     * @param maxDepth the maximum depth of the subgraph, or 0 if there is no maximum depth
+     * @return the object representing the subgraph
+     */
+    public static SubgraphQuery create( ExecutionContext context,
+                                        EntityManager entities,
+                                        UUID subgraphRootUuid,
+                                        Path subgraphRootPath,
+                                        int maxDepth ) {
+        assert entities != null;
+        assert subgraphRootUuid != null;
+        assert maxDepth >= 0;
+        if (maxDepth == 0) maxDepth = Integer.MAX_VALUE;
+        final String subgraphRootUuidString = subgraphRootUuid.toString();
+        // Create a new subgraph query, and add a child for the root ...
+        SubgraphQueryEntity query = new SubgraphQueryEntity(subgraphRootUuidString);
+        entities.persist(query);
+        Long queryId = query.getId();
+
+        try {
+            // Insert a node for the root (this will be the starting point for the recursive operation) ...
+            SubgraphNodeEntity root = new SubgraphNodeEntity(queryId, subgraphRootUuidString, 0);
+            entities.persist(root);
+
+            // Now add the children by inserting the children, one level at a time.
+            // Note that we do this for the root, and for each level until 1 BEYOND
+            // the max depth (so that we can get the children for the nodes that are
+            // at the maximum depth)...
+            Query statement = entities.createNamedQuery("SubgraphNodeEntity.insertChildren");
+            int numChildrenInserted = 0;
+            int parentLevel = 0;
+            while (parentLevel <= maxDepth) {
+                // Insert the children of the next level by inserting via a select (join) of the children
+                statement.setParameter("queryId", queryId);
+                statement.setParameter("parentDepth", parentLevel);
+                numChildrenInserted = statement.executeUpdate();
+                if (numChildrenInserted == 0) break;
+                parentLevel = parentLevel + 1;
+            }
+        } catch (RuntimeException t) {
+            // Clean up the search and results ...
+            try {
+                Query search = entities.createNamedQuery("SubgraphNodeEntity.deleteByQueryId");
+                search.setParameter("queryId", query.getId());
+                search.executeUpdate();
+            } finally {
+                entities.remove(query);
+            }
+            throw t;
+        }
+        return new SubgraphQuery(context, entities, query, subgraphRootPath, maxDepth);
+    }
+
+    private final ExecutionContext context;
+    private final EntityManager manager;
+    private SubgraphQueryEntity query;
+    private final int maxDepth;
+    private final Path subgraphRootPath;
+
+    protected SubgraphQuery( ExecutionContext context,
+                             EntityManager manager,
+                             SubgraphQueryEntity query,
+                             Path subgraphRootPath,
+                             int maxDepth ) {
+        assert manager != null;
+        assert query != null;
+        assert context != null;
+        assert subgraphRootPath != null;
+        this.context = context;
+        this.manager = manager;
+        this.query = query;
+        this.maxDepth = maxDepth;
+        this.subgraphRootPath = subgraphRootPath;
+    }
+
+    /**
+     * @return maxDepth
+     */
+    public int getMaxDepth() {
+        return maxDepth;
+    }
+
+    /**
+     * @return manager
+     */
+    public EntityManager getEntityManager() {
+        return manager;
+    }
+
+    /**
+     * @return subgraphRootPath
+     */
+    public Path getSubgraphRootPath() {
+        return subgraphRootPath;
+    }
+
+    /**
+     * @return query
+     */
+    public SubgraphQueryEntity getSubgraphQueryEntity() {
+        if (query == null) throw new IllegalStateException();
+        return query;
+    }
+
+    public int getNodeCount( boolean includeRoot ) {
+        if (query == null) throw new IllegalStateException();
+        // Now query for all the nodes and put into a list ...
+        Query search = manager.createNamedQuery("SubgraphNodeEntity.getCount");
+        search.setParameter("queryId", query.getId());
+
+        // Now process the nodes below the subgraph's root ...
+        try {
+            return (Integer)search.getSingleResult() - (includeRoot ? 0 : 1);
+        } catch (NoResultException e) {
+            return 0;
+        }
+    }
+
+    /**
+     * Get the {@link ChildEntity root node} of the subgraph. This must be called before the query is {@link #close() closed}.
+     * 
+     * @return the subgraph's root nodes
+     */
+    public ChildEntity getNode() {
+        // Now query for all the nodes and put into a list ...
+        Query search = manager.createNamedQuery("SubgraphNodeEntity.getChildEntities");
+        search.setParameter("queryId", query.getId());
+        search.setParameter("depth", 0);
+        search.setParameter("maxDepth", 0);
+
+        // Now process the nodes below the subgraph's root ...
+        return (ChildEntity)search.getSingleResult();
+    }
+
+    /**
+     * Get the {@link ChildEntity nodes} in the subgraph. This must be called before the query is {@link #close() closed}.
+     * 
+     * @param includeRoot true if the subgraph's root node is to be included, or false otherwise
+     * @param includeChildrenOfMaxDepthNodes true if the method is to include nodes that are children of nodes that are at the
+     *        maximum depth, or false if only nodes up to the maximum depth are to be included
+     * @return the list of nodes, in breadth-first order
+     */
+    @SuppressWarnings( "unchecked" )
+    public List<ChildEntity> getNodes( boolean includeRoot,
+                                       boolean includeChildrenOfMaxDepthNodes ) {
+        if (query == null) throw new IllegalStateException();
+        // Now query for all the nodes and put into a list ...
+        Query search = manager.createNamedQuery("SubgraphNodeEntity.getChildEntities");
+        search.setParameter("queryId", query.getId());
+        search.setParameter("depth", includeRoot ? 0 : 1);
+        search.setParameter("maxDepth", includeChildrenOfMaxDepthNodes ? maxDepth : maxDepth - 1);
+
+        // Now process the nodes below the subgraph's root ...
+        return search.getResultList();
+    }
+
+    /**
+     * Get the {@link PropertiesEntity properties} for each of the nodes in the subgraph. This must be called before the query is
+     * {@link #close() closed}.
+     * 
+     * @param includeRoot true if the properties for the subgraph's root node are to be included, or false otherwise
+     * @param includeChildrenOfMaxDepthNodes true if the method is to include nodes that are children of nodes that are at the
+     *        maximum depth, or false if only nodes up to the maximum depth are to be included
+     * @return the list of properties for each of the nodes, in breadth-first order
+     */
+    @SuppressWarnings( "unchecked" )
+    public List<PropertiesEntity> getProperties( boolean includeRoot,
+                                                 boolean includeChildrenOfMaxDepthNodes ) {
+        if (query == null) throw new IllegalStateException();
+        // Now query for all the nodes and put into a list ...
+        Query search = manager.createNamedQuery("SubgraphNodeEntity.getPropertiesEntities");
+        search.setParameter("queryId", query.getId());
+        search.setParameter("depth", includeRoot ? 0 : 1);
+        search.setParameter("maxDepth", includeChildrenOfMaxDepthNodes ? maxDepth : maxDepth - 1);
+
+        // Now process the nodes below the subgraph's root ...
+        return search.getResultList();
+    }
+
+    /**
+     * Get the {@link Location} for each of the nodes in the subgraph. This must be called before the query is {@link #close()
+     * closed}.
+     * <p>
+     * This method calls {@link #getNodes(boolean,boolean)}. Therefore, calling {@link #getNodes(boolean,boolean)} and this method
+     * for the same subgraph is not efficient; consider just calling {@link #getNodes(boolean,boolean)} alone.
+     * </p>
+     * 
+     * @param includeRoot true if the properties for the subgraph's root node are to be included, or false otherwise
+     * @param includeChildrenOfMaxDepthNodes true if the method is to include nodes that are children of nodes that are at the
+     *        maximum depth, or false if only nodes up to the maximum depth are to be included
+     * @return the list of {@link Location locations}, one for each of the nodes in the subgraph, in breadth-first order
+     */
+    public List<Location> getNodeLocations( boolean includeRoot,
+                                            boolean includeChildrenOfMaxDepthNodes ) {
+        if (query == null) throw new IllegalStateException();
+        // Set up a map of the paths to the nodes, keyed by UUIDs. This saves us from having to build
+        // the paths every time ...
+        Map<String, Path> pathByUuid = new HashMap<String, Path>();
+        LinkedList<Location> locations = new LinkedList<Location>();
+        String subgraphRootUuid = query.getRootUuid();
+        pathByUuid.put(subgraphRootUuid, subgraphRootPath);
+        UUID uuid = UUID.fromString(subgraphRootUuid);
+        if (includeRoot) {
+            locations.add(new Location(subgraphRootPath, uuid));
+        }
+
+        // Now iterate over the child nodes in the subgraph (we've already included the root) ...
+        final PathFactory pathFactory = context.getValueFactories().getPathFactory();
+        final NameFactory nameFactory = context.getValueFactories().getNameFactory();
+        for (ChildEntity entity : getNodes(false, includeChildrenOfMaxDepthNodes)) {
+            String parentUuid = entity.getId().getParentUuidString();
+            Path parentPath = pathByUuid.get(parentUuid);
+            assert parentPath != null;
+            String nsUri = entity.getChildNamespace().getUri();
+            String localName = entity.getChildName();
+            int sns = entity.getSameNameSiblingIndex();
+            Name childName = nameFactory.create(nsUri, localName);
+            Path childPath = pathFactory.create(parentPath, childName, sns);
+            String childUuid = entity.getId().getChildUuidString();
+            pathByUuid.put(childUuid, childPath);
+            uuid = UUID.fromString(childUuid);
+            locations.add(new Location(childPath, uuid));
+
+        }
+        return locations;
+    }
+
+    /**
+     * Get the list of references that are owned by nodes within the subgraph and that point to other nodes <i>in this same
+     * subgraph</i>. This set of references is important in copying a subgraph, since all intra-subgraph references in the
+     * original subgraph must also be intra-subgraph references in the copy.
+     * 
+     * @return the list of references completely contained by this subgraphs
+     */
+    @SuppressWarnings( "unchecked" )
+    public List<ReferenceEntity> getInternalReferences() {
+        Query references = manager.createNamedQuery("SubgraphNodeEntity.getInternalReferences");
+        references.setParameter("queryId", query.getId());
+        return references.getResultList();
+    }
+
+    /**
+     * Get the list of references that are owned by nodes within the subgraph and that point to nodes <i>not in this same
+     * subgraph</i>. This set of references is important in copying a subgraph.
+     * 
+     * @return the list of references that are owned by the subgraph but that point to nodes outside of the subgraph
+     */
+    @SuppressWarnings( "unchecked" )
+    public List<ReferenceEntity> getOutwardReferences() {
+        Query references = manager.createNamedQuery("SubgraphNodeEntity.getOutwardReferences");
+        references.setParameter("queryId", query.getId());
+        return references.getResultList();
+    }
+
+    /**
+     * Get the list of references that are owned by nodes <i>outside</i> of the subgraph that point to nodes <i>in this
+     * subgraph</i>. This set of references is important in deleting nodes, since such references prevent the deletion of the
+     * subgraph.
+     * 
+     * @return the list of references that are no longer valid
+     */
+    @SuppressWarnings( "unchecked" )
+    public List<ReferenceEntity> getInwardReferences() {
+        // Verify referential integrity: that none of the deleted nodes are referenced by nodes not being deleted.
+        Query references = manager.createNamedQuery("SubgraphNodeEntity.getInwardReferences");
+        references.setParameter("queryId", query.getId());
+        return references.getResultList();
+    }
+
+    /**
+     * Delete the nodes in the subgraph. This method first does not check for referential integrity (see
+     * {@link #getInwardReferences()}).
+     * 
+     * @param includeRoot true if the root node should also be deleted
+     */
+    @SuppressWarnings( "unchecked" )
+    public void deleteSubgraph( boolean includeRoot ) {
+        if (query == null) throw new IllegalStateException();
+
+        // Delete the PropertiesEntities ...
+        //
+        // Right now, Hibernate is not able to support deleting PropertiesEntity in bulk because of the
+        // large value association (and there's no way to clear the association in bulk).
+        // Therefore, the only way to do this with Hibernate is to load each PropertiesEntity that has
+        // large values and clear them. (Theoretically, fewer PropertiesEntity objects will have large values
+        // than the total number in the subgraph.)
+        // Then we can delete the properties.
+        Query withLargeValues = manager.createNamedQuery("SubgraphNodeEntity.getPropertiesEntitiesWithLargeValues");
+        withLargeValues.setParameter("queryId", query.getId());
+        withLargeValues.setParameter("depth", includeRoot ? 0 : 1);
+        List<PropertiesEntity> propertiesWithLargeValues = withLargeValues.getResultList();
+        if (propertiesWithLargeValues.size() != 0) {
+            for (PropertiesEntity props : propertiesWithLargeValues) {
+                props.getLargeValues().clear();
+            }
+            manager.flush();
+        }
+
+        // Delete the PropertiesEntities, none of which will have large values ...
+        Query delete = manager.createNamedQuery("SubgraphNodeEntity.deletePropertiesEntities");
+        delete.setParameter("queryId", query.getId());
+        delete.executeUpdate();
+
+        // Delete the ChildEntities ...
+        delete = manager.createNamedQuery("SubgraphNodeEntity.deleteChildEntities");
+        delete.setParameter("queryId", query.getId());
+        delete.executeUpdate();
+
+        // Delete references ...
+        delete = manager.createNamedQuery("SubgraphNodeEntity.deleteReferences");
+        delete.setParameter("queryId", query.getId());
+        delete.executeUpdate();
+
+        // Delete unused large values ...
+        LargeValueEntity.deleteUnused(manager);
+
+        manager.flush();
+    }
+
+    /**
+     * Close this query object and clean up all in-database records associated with this query. This method <i>must</i> be called
+     * when this query is no longer needed, and once it is called, this subgraph query is no longer usable.
+     */
+    public void close() {
+        if (query == null) return;
+        // Clean up the search and results ...
+        try {
+            Query search = manager.createNamedQuery("SubgraphNodeEntity.deleteByQueryId");
+            search.setParameter("queryId", query.getId());
+            search.executeUpdate();
+        } finally {
+            try {
+                manager.remove(query);
+            } finally {
+                query = null;
+            }
+        }
+    }
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQueryEntity.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,63 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-
-/**
- * Represents a temporary working area for a query that retrieves the nodes in a subgraph.
- * 
- * @author Randall Hauch
- */
- at Entity( name = "DNA_SUBGRAPH_QUERIES" )
-public class SubgraphQueryEntity {
-
-    @Id
-    @GeneratedValue( strategy = GenerationType.AUTO )
-    @Column( name = "ID", updatable = false )
-    private Long id;
-
-    @Column( name = "ROOT_UUID", updatable = false, nullable = false, length = 36 )
-    private String rootUuid;
-
-    public SubgraphQueryEntity( String rootUuid ) {
-        this.rootUuid = rootUuid;
-    }
-
-    /**
-     * @return id
-     */
-    public Long getId() {
-        return id;
-    }
-
-    /**
-     * @return rootUuid
-     */
-    public String getRootUuid() {
-        return rootUuid;
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryEntity.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQueryEntity.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryEntity.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+/**
+ * Represents a temporary working area for a query that retrieves the nodes in a subgraph.
+ * 
+ * @author Randall Hauch
+ */
+ at Entity( name = "DNA_SUBGRAPH_QUERIES" )
+public class SubgraphQueryEntity {
+
+    @Id
+    @GeneratedValue( strategy = GenerationType.AUTO )
+    @Column( name = "ID", updatable = false )
+    private Long id;
+
+    @Column( name = "ROOT_UUID", updatable = false, nullable = false, length = 36 )
+    private String rootUuid;
+
+    public SubgraphQueryEntity( String rootUuid ) {
+        this.rootUuid = rootUuid;
+    }
+
+    /**
+     * @return id
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * @return rootUuid
+     */
+    public String getRootUuid() {
+        return rootUuid;
+    }
+}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common (from rev 705, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common)

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/ChangeLogEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/ChangeLogEntity.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/ChangeLogEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,148 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.common;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Lob;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import org.hibernate.annotations.Index;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.basic.JodaDateTime;
-
-/**
- * Represents a record of the changes that have been made to the repository. The actual change events are serialized and stored in
- * a binary (and compressed) format.
- * 
- * @author Randall Hauch
- */
- at Entity
- at Table( name = "DNA_CHANGELOG" )
- at org.hibernate.annotations.Table( appliesTo = "DNA_CHANGELOG", indexes = @Index( name = "NS_CHANGE_TS_INX", columnNames = {"UTC_TIMESTAMP"} ) )
- at NamedQueries( {
-    @NamedQuery( name = "ChangeLogEntity.findBetween", query = "select entry from ChangeLogEntity as entry where entry.timestampInUtc >= :start and entry.timestampInUtc <= :end" ),
-    @NamedQuery( name = "ChangeLogEntity.deleteBefore", query = "delete ChangeLogEntity entry where entry.timestampInUtc < :timestamp" )} )
-public class ChangeLogEntity {
-
-    @Id
-    @GeneratedValue( strategy = GenerationType.AUTO )
-    @Column( name = "ID", updatable = false )
-    private Long id;
-
-    @Column( name = "USERNAME", updatable = false, nullable = false, length = 64, unique = false )
-    private String username;
-
-    @Column( name = "UTC_TIMESTAMP", updatable = false, nullable = false, unique = false )
-    private long timestampInUtc;
-
-    @Column( name = "CHANGE_COUNT", updatable = false, nullable = false, unique = false )
-    private int numChanges;
-
-    @Lob
-    @Column( name = "CHANGES", updatable = false, nullable = false, unique = false )
-    private byte[] changes;
-
-    public ChangeLogEntity( String username,
-                            DateTime timestamp,
-                            int numChanges,
-                            byte[] changes ) {
-        this.username = username;
-        this.timestampInUtc = timestamp.toUtcTimeZone().getMilliseconds();
-        this.numChanges = numChanges;
-        this.changes = changes;
-    }
-
-    /**
-     * @return id
-     */
-    public Long getId() {
-        return id;
-    }
-
-    /**
-     * @return username
-     */
-    public String getUsername() {
-        return username;
-    }
-
-    /**
-     * @return timestampInUtc
-     */
-    public long getTimestampInUtc() {
-        return timestampInUtc;
-    }
-
-    /**
-     * @return changes
-     */
-    public byte[] getChanges() {
-        return changes;
-    }
-
-    /**
-     * @return numChanges
-     */
-    public int getNumChanges() {
-        return numChanges;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof ChangeLogEntity) {
-            ChangeLogEntity that = (ChangeLogEntity)obj;
-            return id.equals(that.id);
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "" + numChanges + " changes by " + username + " at " + new JodaDateTime(timestampInUtc);
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/ChangeLogEntity.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/ChangeLogEntity.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/ChangeLogEntity.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/ChangeLogEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,148 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.common;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import org.hibernate.annotations.Index;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.basic.JodaDateTime;
+
+/**
+ * Represents a record of the changes that have been made to the repository. The actual change events are serialized and stored in
+ * a binary (and compressed) format.
+ * 
+ * @author Randall Hauch
+ */
+ at Entity
+ at Table( name = "DNA_CHANGELOG" )
+ at org.hibernate.annotations.Table( appliesTo = "DNA_CHANGELOG", indexes = @Index( name = "NS_CHANGE_TS_INX", columnNames = {"UTC_TIMESTAMP"} ) )
+ at NamedQueries( {
+    @NamedQuery( name = "ChangeLogEntity.findBetween", query = "select entry from ChangeLogEntity as entry where entry.timestampInUtc >= :start and entry.timestampInUtc <= :end" ),
+    @NamedQuery( name = "ChangeLogEntity.deleteBefore", query = "delete ChangeLogEntity entry where entry.timestampInUtc < :timestamp" )} )
+public class ChangeLogEntity {
+
+    @Id
+    @GeneratedValue( strategy = GenerationType.AUTO )
+    @Column( name = "ID", updatable = false )
+    private Long id;
+
+    @Column( name = "USERNAME", updatable = false, nullable = false, length = 64, unique = false )
+    private String username;
+
+    @Column( name = "UTC_TIMESTAMP", updatable = false, nullable = false, unique = false )
+    private long timestampInUtc;
+
+    @Column( name = "CHANGE_COUNT", updatable = false, nullable = false, unique = false )
+    private int numChanges;
+
+    @Lob
+    @Column( name = "CHANGES", updatable = false, nullable = false, unique = false )
+    private byte[] changes;
+
+    public ChangeLogEntity( String username,
+                            DateTime timestamp,
+                            int numChanges,
+                            byte[] changes ) {
+        this.username = username;
+        this.timestampInUtc = timestamp.toUtcTimeZone().getMilliseconds();
+        this.numChanges = numChanges;
+        this.changes = changes;
+    }
+
+    /**
+     * @return id
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * @return username
+     */
+    public String getUsername() {
+        return username;
+    }
+
+    /**
+     * @return timestampInUtc
+     */
+    public long getTimestampInUtc() {
+        return timestampInUtc;
+    }
+
+    /**
+     * @return changes
+     */
+    public byte[] getChanges() {
+        return changes;
+    }
+
+    /**
+     * @return numChanges
+     */
+    public int getNumChanges() {
+        return numChanges;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof ChangeLogEntity) {
+            ChangeLogEntity that = (ChangeLogEntity)obj;
+            return id.equals(that.id);
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "" + numChanges + " changes by " + username + " at " + new JodaDateTime(timestampInUtc);
+    }
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/NamespaceEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/NamespaceEntity.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/NamespaceEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,174 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.common;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EntityManager;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.NoResultException;
-import javax.persistence.Query;
-import javax.persistence.Table;
-import org.hibernate.annotations.Index;
-import org.jboss.dna.common.util.CheckArg;
-
-/**
- * A NamespaceEntity represents a namespace that has been used in the store. NamespaceEntity records are immutable and shared by
- * one or more enities.
- * 
- * @author Randall Hauch
- */
- at Entity
- at Table( name = "DNA_NAMESPACES" )
- at org.hibernate.annotations.Table( appliesTo = "DNA_NAMESPACES", indexes = @Index( name = "NS_URI_INX", columnNames = {"URI"} ) )
- at NamedQueries( {@NamedQuery( name = "NamespaceEntity.findAll", query = "select ns from NamespaceEntity as ns" ),
-    @NamedQuery( name = "NamespaceEntity.findByUri", query = "select ns from NamespaceEntity as ns where ns.uri = ?1" )} )
-public class NamespaceEntity {
-
-    @Id
-    @GeneratedValue( strategy = GenerationType.AUTO )
-    private Long id;
-
-    @Column( name = "URI", nullable = false, unique = false, length = 512, updatable = false )
-    private String uri;
-
-    /**
-     * 
-     */
-    public NamespaceEntity() {
-    }
-
-    /**
-     * @param uri the namespace URI
-     */
-    public NamespaceEntity( String uri ) {
-        setUri(uri);
-    }
-
-    /**
-     * @return id
-     */
-    public Long getId() {
-        return id;
-    }
-
-    /**
-     * @param id Sets id to the specified value.
-     */
-    public void setId( Long id ) {
-        this.id = id;
-    }
-
-    /**
-     * @return uri
-     */
-    public String getUri() {
-        return uri;
-    }
-
-    /**
-     * @param uri Sets uri to the specified value.
-     */
-    public void setUri( String uri ) {
-        this.uri = uri;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals( Object obj ) {
-        if (obj == this) return true;
-        if (obj instanceof NamespaceEntity) {
-            NamespaceEntity that = (NamespaceEntity)obj;
-            if (!this.id.equals(that.id)) return false;
-            if (!this.uri.equals(that.uri)) return false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return uri;
-    }
-
-    /**
-     * Find an existing namespace by its URI, or create and return one if it does not already exist.
-     * 
-     * @param manager the entity manager
-     * @param uri the URI
-     * @return the existing namespace, or null if one does not exist
-     * @throws IllegalArgumentException if the manager or URI are null
-     */
-    public static NamespaceEntity findByUri( EntityManager manager,
-                                             String uri ) {
-        return findByUri(manager, uri, true);
-    }
-
-    /**
-     * Find an existing namespace by its URI.
-     * 
-     * @param manager the entity manager
-     * @param uri the URI
-     * @param createIfRequired if the namespace should be persisted if it does not yet exist
-     * @return the existing namespace, or null if one does not exist
-     * @throws IllegalArgumentException if the manager or URI are null
-     */
-    public static NamespaceEntity findByUri( EntityManager manager,
-                                             String uri,
-                                             boolean createIfRequired ) {
-        CheckArg.isNotNull(manager, "manager");
-        CheckArg.isNotNull(uri, "uri");
-        Query query = manager.createNamedQuery("NamespaceEntity.findByUri");
-        query.setParameter(1, uri);
-        try {
-            return (NamespaceEntity)query.getSingleResult();
-        } catch (NoResultException e) {
-            if (!createIfRequired) return null;
-            NamespaceEntity namespace = new NamespaceEntity(uri);
-            manager.persist(namespace);
-            return namespace;
-        }
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/NamespaceEntity.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/NamespaceEntity.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/NamespaceEntity.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/common/NamespaceEntity.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.common;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityManager;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import javax.persistence.Table;
+import org.hibernate.annotations.Index;
+import org.jboss.dna.common.util.CheckArg;
+
+/**
+ * A NamespaceEntity represents a namespace that has been used in the store. NamespaceEntity records are immutable and shared by
+ * one or more enities.
+ * 
+ * @author Randall Hauch
+ */
+ at Entity
+ at Table( name = "DNA_NAMESPACES" )
+ at org.hibernate.annotations.Table( appliesTo = "DNA_NAMESPACES", indexes = @Index( name = "NS_URI_INX", columnNames = {"URI"} ) )
+ at NamedQueries( {@NamedQuery( name = "NamespaceEntity.findAll", query = "select ns from NamespaceEntity as ns" ),
+    @NamedQuery( name = "NamespaceEntity.findByUri", query = "select ns from NamespaceEntity as ns where ns.uri = ?1" )} )
+public class NamespaceEntity {
+
+    @Id
+    @GeneratedValue( strategy = GenerationType.AUTO )
+    private Long id;
+
+    @Column( name = "URI", nullable = false, unique = false, length = 512, updatable = false )
+    private String uri;
+
+    /**
+     * 
+     */
+    public NamespaceEntity() {
+    }
+
+    /**
+     * @param uri the namespace URI
+     */
+    public NamespaceEntity( String uri ) {
+        setUri(uri);
+    }
+
+    /**
+     * @return id
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * @param id Sets id to the specified value.
+     */
+    public void setId( Long id ) {
+        this.id = id;
+    }
+
+    /**
+     * @return uri
+     */
+    public String getUri() {
+        return uri;
+    }
+
+    /**
+     * @param uri Sets uri to the specified value.
+     */
+    public void setUri( String uri ) {
+        this.uri = uri;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof NamespaceEntity) {
+            NamespaceEntity that = (NamespaceEntity)obj;
+            if (!this.id.equals(that.id)) return false;
+            if (!this.uri.equals(that.uri)) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return uri;
+    }
+
+    /**
+     * Find an existing namespace by its URI, or create and return one if it does not already exist.
+     * 
+     * @param manager the entity manager
+     * @param uri the URI
+     * @return the existing namespace, or null if one does not exist
+     * @throws IllegalArgumentException if the manager or URI are null
+     */
+    public static NamespaceEntity findByUri( EntityManager manager,
+                                             String uri ) {
+        return findByUri(manager, uri, true);
+    }
+
+    /**
+     * Find an existing namespace by its URI.
+     * 
+     * @param manager the entity manager
+     * @param uri the URI
+     * @param createIfRequired if the namespace should be persisted if it does not yet exist
+     * @return the existing namespace, or null if one does not exist
+     * @throws IllegalArgumentException if the manager or URI are null
+     */
+    public static NamespaceEntity findByUri( EntityManager manager,
+                                             String uri,
+                                             boolean createIfRequired ) {
+        CheckArg.isNotNull(manager, "manager");
+        CheckArg.isNotNull(uri, "uri");
+        Query query = manager.createNamedQuery("NamespaceEntity.findByUri");
+        query.setParameter(1, uri);
+        try {
+            return (NamespaceEntity)query.getSingleResult();
+        } catch (NoResultException e) {
+            if (!createIfRequired) return null;
+            NamespaceEntity namespace = new NamespaceEntity(uri);
+            manager.persist(namespace);
+            return namespace;
+        }
+    }
+}

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Namespaces.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Namespaces.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Namespaces.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,7 +24,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import javax.persistence.EntityManager;
-import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
+import org.jboss.dna.connector.store.jpa.model.common.NamespaceEntity;
 
 /**
  * @author Randall Hauch

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/RequestProcessorCache.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/RequestProcessorCache.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/RequestProcessorCache.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -33,10 +33,10 @@
 import java.util.Set;
 import org.jboss.dna.common.util.StringUtil;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
 
 /**
  * Represents a cache of the known node information, including a node's actual {@link Location} and the complete set of children.

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -36,22 +36,22 @@
 import java.util.UUID;
 import org.jboss.dna.common.SystemFailureException;
 import org.jboss.dna.common.util.SecureHash;
-import org.jboss.dna.connector.store.jpa.models.basic.LargeValueEntity;
+import org.jboss.dna.connector.store.jpa.model.basic.LargeValueEntity;
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.BinaryFactory;
-import org.jboss.dna.graph.properties.DateTime;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.UuidFactory;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.BinaryFactory;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.UuidFactory;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
 
 /**
  * @author Randall Hauch

Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorReadingTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorReadingTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorReadingTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,10 +21,10 @@
  */
 package org.jboss.dna.connector.store.jpa;
 
-import org.jboss.dna.common.stats.Stopwatch;
+import org.jboss.dna.common.statistic.Stopwatch;
 import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.test.ReadableConnectorTest;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.test.ReadableConnectorTest;
 
 /**
  * @author Randall Hauch
@@ -34,7 +34,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.test.AbstractConnectorTest#setUpSource()
+     * @see org.jboss.dna.graph.connector.test.AbstractConnectorTest#setUpSource()
      */
     @Override
     protected RepositorySource setUpSource() {
@@ -58,7 +58,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.test.AbstractConnectorTest#initializeContent(org.jboss.dna.graph.Graph)
+     * @see org.jboss.dna.graph.connector.test.AbstractConnectorTest#initializeContent(org.jboss.dna.graph.Graph)
      */
     @Override
     protected void initializeContent( Graph graph ) {

Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -22,8 +22,8 @@
 package org.jboss.dna.connector.store.jpa;
 
 import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.test.WritableConnectorTest;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.test.WritableConnectorTest;
 
 /**
  * @author Randall Hauch
@@ -33,7 +33,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.test.AbstractConnectorTest#setUpSource()
+     * @see org.jboss.dna.graph.connector.test.AbstractConnectorTest#setUpSource()
      */
     @Override
     protected RepositorySource setUpSource() {
@@ -58,7 +58,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.test.AbstractConnectorTest#initializeContent(org.jboss.dna.graph.Graph)
+     * @see org.jboss.dna.graph.connector.test.AbstractConnectorTest#initializeContent(org.jboss.dna.graph.Graph)
      */
     @Override
     protected void initializeContent( Graph graph ) {

Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -27,8 +27,8 @@
 import static org.junit.Assert.assertThat;
 import java.util.ArrayList;
 import java.util.List;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/ModelTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/ModelTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/ModelTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -29,7 +29,7 @@
 import org.hibernate.ejb.Ejb3Configuration;
 import org.jboss.dna.common.i18n.I18n;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;

Copied: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic (from rev 705, trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic)

Deleted: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModelTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModelTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModelTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,360 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
-import java.io.UnsupportedEncodingException;
-import java.security.NoSuchAlgorithmException;
-import java.util.Locale;
-import java.util.UUID;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.EntityTransaction;
-import org.hibernate.ejb.Ejb3Configuration;
-import org.jboss.dna.common.util.SecureHash;
-import org.jboss.dna.common.util.StringUtil;
-import org.jboss.dna.connector.store.jpa.JpaConnectorI18n;
-import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
-import org.jboss.dna.graph.BasicExecutionContext;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * This test not only verifies the (minimal) functionality of the {@link BasicModel} class, but it also verifies that the entity
- * classes used by the {@link BasicModel#configure(Ejb3Configuration) configuration} are consistent and error-free. In other
- * words, if there are any problems with any of the entity annotations, they will be found when the {@link EntityManager} is
- * {@link #startEntityManager() started}.
- * 
- * @author Randall Hauch
- */
-public class BasicModelTest {
-
-    private EntityManagerFactory factory;
-    private EntityManager manager;
-    private BasicModel model;
-    private ExecutionContext context;
-
-    @BeforeClass
-    public static void beforeAll() throws Exception {
-    }
-
-    @Before
-    public void beforeEach() throws Exception {
-        model = new BasicModel();
-        context = new BasicExecutionContext();
-    }
-
-    @After
-    public void afterEach() throws Exception {
-        try {
-            if (manager != null) manager.close();
-        } finally {
-            manager = null;
-            if (factory != null) {
-                try {
-                    factory.close();
-                } finally {
-                    factory = null;
-                }
-            }
-        }
-    }
-
-    protected EntityManager startEntityManager() {
-        if (manager == null) {
-            // Connect to the database ...
-            Ejb3Configuration configurator = new Ejb3Configuration();
-            model.configure(configurator);
-            configurator.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
-            configurator.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
-            configurator.setProperty("hibernate.connection.username", "sa");
-            configurator.setProperty("hibernate.connection.password", "");
-            configurator.setProperty("hibernate.connection.url", "jdbc:hsqldb:.");
-            configurator.setProperty("hibernate.show_sql", "false");
-            configurator.setProperty("hibernate.format_sql", "true");
-            configurator.setProperty("hibernate.use_sql_comments", "true");
-            configurator.setProperty("hibernate.hbm2ddl.auto", "create");
-            factory = configurator.buildEntityManagerFactory();
-            manager = factory.createEntityManager();
-        }
-        return manager;
-    }
-
-    @Test
-    public void shouldHaveName() {
-        assertThat(model.getName(), is("Basic"));
-    }
-
-    @Test
-    public void shouldHaveDescription() {
-        assertThat(model.getDescription(), is(JpaConnectorI18n.basicModelDescription.text()));
-        assertThat(model.getDescription(Locale.US), is(JpaConnectorI18n.basicModelDescription.text()));
-    }
-
-    @Test
-    public void shouldCreateRequestProcessor() {
-        EntityManager manager = mock(EntityManager.class);
-        EntityTransaction txn = mock(EntityTransaction.class);
-        stub(manager.getTransaction()).toReturn(txn);
-        RequestProcessor proc = model.createRequestProcessor("test source",
-                                                             context,
-                                                             manager,
-                                                             UUID.randomUUID(),
-                                                             100,
-                                                             false,
-                                                             false);
-        assertThat(proc, is(notNullValue()));
-    }
-
-    @Test
-    public void shouldPersistPropertyEntityWithCompressedFlagAndNoChildren() {
-        startEntityManager();
-        NodeId nodeId = new NodeId(UUID.randomUUID().toString());
-        PropertiesEntity prop = new PropertiesEntity();
-        prop.setCompressed(true);
-        prop.setData("Hello, World".getBytes());
-        prop.setId(nodeId);
-        manager.getTransaction().begin();
-        try {
-            // Save a properties entity (with compressed data) ...
-            manager.persist(prop);
-            manager.getTransaction().commit();
-        } catch (RuntimeException t) {
-            manager.getTransaction().rollback();
-            throw t;
-        }
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            PropertiesEntity prop2 = manager.find(PropertiesEntity.class, nodeId);
-            assertThat(prop2.isCompressed(), is(prop.isCompressed()));
-            assertThat(prop2.getId(), is(prop.getId()));
-            assertThat(prop2.getData(), is(prop.getData()));
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @Test
-    public void shouldPersistPropertyEntityWithUncompressedFlagAndNoChildren() {
-        startEntityManager();
-        NodeId nodeId = new NodeId(UUID.randomUUID().toString());
-        PropertiesEntity prop = new PropertiesEntity();
-        prop.setData("Hello, World".getBytes());
-        prop.setId(nodeId);
-        manager.getTransaction().begin();
-        try {
-            // Save a properties entity (with compressed data) ...
-            manager.persist(prop);
-            manager.getTransaction().commit();
-        } catch (RuntimeException t) {
-            manager.getTransaction().rollback();
-            throw t;
-        }
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            PropertiesEntity prop2 = manager.find(PropertiesEntity.class, nodeId);
-            assertThat(prop2.isCompressed(), is(prop.isCompressed()));
-            assertThat(prop2.getId(), is(prop.getId()));
-            assertThat(prop2.getData(), is(prop.getData()));
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @Test
-    public void shouldPersistLargeValueEntityWithCompressedFlag() throws UnsupportedEncodingException, NoSuchAlgorithmException {
-        startEntityManager();
-        byte[] content = "Jack and Jill went up the hill to grab a pail of water.".getBytes();
-        String hash = StringUtil.getHexString(SecureHash.getHash(SecureHash.Algorithm.SHA_1, content));
-        LargeValueId id = new LargeValueId(hash);
-        LargeValueEntity entity = new LargeValueEntity();
-        entity.setCompressed(true);
-        entity.setId(id);
-        entity.setLength(content.length);
-        entity.setData(content);
-        entity.setType(PropertyType.STRING);
-        manager.getTransaction().begin();
-        try {
-            // Save the entity ...
-            manager.persist(entity);
-            manager.getTransaction().commit();
-        } catch (RuntimeException t) {
-            manager.getTransaction().rollback();
-            throw t;
-        }
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            LargeValueEntity entity2 = manager.find(LargeValueEntity.class, id);
-            assertThat(entity2.isCompressed(), is(entity.isCompressed()));
-            assertThat(entity2.getId(), is(id));
-            assertThat(entity2.getData(), is(entity.getData()));
-            assertThat(entity2.getLength(), is(entity.getLength()));
-            assertThat(entity2.getType(), is(entity.getType()));
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @Test
-    public void shouldPersistLargeValueEntityWithUncompressedFlag() throws UnsupportedEncodingException, NoSuchAlgorithmException {
-        startEntityManager();
-        byte[] content = "Jack and Jill went up the hill to grab a pail of water.".getBytes();
-        String hash = StringUtil.getHexString(SecureHash.getHash(SecureHash.Algorithm.SHA_1, content));
-        LargeValueId id = new LargeValueId(hash);
-        LargeValueEntity entity = new LargeValueEntity();
-        // entity.setCompressed(false);
-        entity.setId(id);
-        entity.setLength(content.length);
-        entity.setData(content);
-        entity.setType(PropertyType.STRING);
-        manager.getTransaction().begin();
-        try {
-            // Save the entity ...
-            manager.persist(entity);
-            manager.getTransaction().commit();
-        } catch (RuntimeException t) {
-            manager.getTransaction().rollback();
-            throw t;
-        }
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            LargeValueEntity entity2 = manager.find(LargeValueEntity.class, id);
-            assertThat(entity2.isCompressed(), is(entity.isCompressed()));
-            assertThat(entity2.getId(), is(entity.getId()));
-            assertThat(entity2.getData(), is(entity.getData()));
-            assertThat(entity2.getLength(), is(entity.getLength()));
-            assertThat(entity2.getType(), is(entity.getType()));
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @Test
-    public void shouldPersistNamespaceEntity() {
-        startEntityManager();
-        String uri = "http://www.example.com";
-        NamespaceEntity namespace = new NamespaceEntity(uri);
-        manager.getTransaction().begin();
-        try {
-            // Save a namespace entity ...
-            manager.persist(namespace);
-            manager.getTransaction().commit();
-        } catch (RuntimeException t) {
-            manager.getTransaction().rollback();
-            throw t;
-        }
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            NamespaceEntity ns2 = manager.find(NamespaceEntity.class, namespace.getId());
-            assertThat(ns2.getUri(), is(namespace.getUri()));
-            assertThat(ns2.getId(), is(namespace.getId()));
-        } finally {
-            manager.getTransaction().rollback();
-        }
-        // Look up by namespace ...
-        manager.getTransaction().begin();
-        try {
-            NamespaceEntity ns2 = NamespaceEntity.findByUri(manager, uri);
-            assertThat(ns2.getUri(), is(namespace.getUri()));
-            assertThat(ns2.getId(), is(namespace.getId()));
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @Test
-    public void shouldPersistChildEntity() {
-        startEntityManager();
-        UUID parentId = UUID.randomUUID();
-
-        // Create UUIDs for several children ...
-        ChildId childId1 = new ChildId(parentId.toString(), UUID.randomUUID().toString());
-        ChildId childId2 = new ChildId(parentId.toString(), UUID.randomUUID().toString());
-        ChildId childId3 = new ChildId(parentId.toString(), UUID.randomUUID().toString());
-        assertThat(childId1, is(not(childId2)));
-        assertThat(childId1, is(not(childId3)));
-        assertThat(childId2, is(not(childId3)));
-
-        manager.getTransaction().begin();
-        try {
-            NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
-
-            // Create the child entities ...
-            ChildEntity child1 = new ChildEntity(childId1, 1, ns, "child1");
-            ChildEntity child2 = new ChildEntity(childId2, 2, ns, "child2");
-            ChildEntity child3 = new ChildEntity(childId3, 3, ns, "child3", 1);
-
-            // Save a properties entities ...
-            manager.persist(child1);
-            manager.persist(child2);
-            manager.persist(child3);
-            manager.getTransaction().commit();
-        } catch (RuntimeException t) {
-            // manager.getTransaction().rollback();
-            throw t;
-        }
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
-
-            ChildEntity child1a = manager.find(ChildEntity.class, childId1);
-            ChildEntity child2a = manager.find(ChildEntity.class, childId2);
-            ChildEntity child3a = manager.find(ChildEntity.class, childId3);
-
-            assertThat(child1a.getId(), is(childId1));
-            assertThat(child1a.getIndexInParent(), is(1));
-            assertThat(child1a.getChildName(), is("child1"));
-            assertThat(child1a.getChildNamespace(), is(ns));
-            assertThat(child1a.getSameNameSiblingIndex(), is(1));
-
-            assertThat(child2a.getId(), is(childId2));
-            assertThat(child2a.getIndexInParent(), is(2));
-            assertThat(child2a.getChildName(), is("child2"));
-            assertThat(child2a.getChildNamespace(), is(ns));
-            assertThat(child2a.getSameNameSiblingIndex(), is(1));
-
-            assertThat(child3a.getId(), is(childId3));
-            assertThat(child3a.getIndexInParent(), is(3));
-            assertThat(child3a.getChildName(), is("child3"));
-            assertThat(child3a.getChildNamespace(), is(ns));
-            assertThat(child3a.getSameNameSiblingIndex(), is(1));
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModelTest.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModelTest.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModelTest.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/BasicModelTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,366 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Locale;
+import java.util.UUID;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.jboss.dna.common.util.SecureHash;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.connector.store.jpa.JpaConnectorI18n;
+import org.jboss.dna.connector.store.jpa.model.basic.BasicModel;
+import org.jboss.dna.connector.store.jpa.model.basic.ChildEntity;
+import org.jboss.dna.connector.store.jpa.model.basic.ChildId;
+import org.jboss.dna.connector.store.jpa.model.basic.LargeValueEntity;
+import org.jboss.dna.connector.store.jpa.model.basic.LargeValueId;
+import org.jboss.dna.connector.store.jpa.model.basic.NodeId;
+import org.jboss.dna.connector.store.jpa.model.basic.PropertiesEntity;
+import org.jboss.dna.connector.store.jpa.model.common.NamespaceEntity;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test not only verifies the (minimal) functionality of the {@link BasicModel} class, but it also verifies that the entity
+ * classes used by the {@link BasicModel#configure(Ejb3Configuration) configuration} are consistent and error-free. In other
+ * words, if there are any problems with any of the entity annotations, they will be found when the {@link EntityManager} is
+ * {@link #startEntityManager() started}.
+ * 
+ * @author Randall Hauch
+ */
+public class BasicModelTest {
+
+    private EntityManagerFactory factory;
+    private EntityManager manager;
+    private BasicModel model;
+    private ExecutionContext context;
+
+    @BeforeClass
+    public static void beforeAll() throws Exception {
+    }
+
+    @Before
+    public void beforeEach() throws Exception {
+        model = new BasicModel();
+        context = new ExecutionContext();
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        try {
+            if (manager != null) manager.close();
+        } finally {
+            manager = null;
+            if (factory != null) {
+                try {
+                    factory.close();
+                } finally {
+                    factory = null;
+                }
+            }
+        }
+    }
+
+    protected EntityManager startEntityManager() {
+        if (manager == null) {
+            // Connect to the database ...
+            Ejb3Configuration configurator = new Ejb3Configuration();
+            model.configure(configurator);
+            configurator.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+            configurator.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
+            configurator.setProperty("hibernate.connection.username", "sa");
+            configurator.setProperty("hibernate.connection.password", "");
+            configurator.setProperty("hibernate.connection.url", "jdbc:hsqldb:.");
+            configurator.setProperty("hibernate.show_sql", "false");
+            configurator.setProperty("hibernate.format_sql", "true");
+            configurator.setProperty("hibernate.use_sql_comments", "true");
+            configurator.setProperty("hibernate.hbm2ddl.auto", "create");
+            factory = configurator.buildEntityManagerFactory();
+            manager = factory.createEntityManager();
+        }
+        return manager;
+    }
+
+    @Test
+    public void shouldHaveName() {
+        assertThat(model.getName(), is("Basic"));
+    }
+
+    @Test
+    public void shouldHaveDescription() {
+        assertThat(model.getDescription(), is(JpaConnectorI18n.basicModelDescription.text()));
+        assertThat(model.getDescription(Locale.US), is(JpaConnectorI18n.basicModelDescription.text()));
+    }
+
+    @Test
+    public void shouldCreateRequestProcessor() {
+        EntityManager manager = mock(EntityManager.class);
+        EntityTransaction txn = mock(EntityTransaction.class);
+        stub(manager.getTransaction()).toReturn(txn);
+        RequestProcessor proc = model.createRequestProcessor("test source",
+                                                             context,
+                                                             manager,
+                                                             UUID.randomUUID(),
+                                                             100,
+                                                             false,
+                                                             false);
+        assertThat(proc, is(notNullValue()));
+    }
+
+    @Test
+    public void shouldPersistPropertyEntityWithCompressedFlagAndNoChildren() {
+        startEntityManager();
+        NodeId nodeId = new NodeId(UUID.randomUUID().toString());
+        PropertiesEntity prop = new PropertiesEntity();
+        prop.setCompressed(true);
+        prop.setData("Hello, World".getBytes());
+        prop.setId(nodeId);
+        manager.getTransaction().begin();
+        try {
+            // Save a properties entity (with compressed data) ...
+            manager.persist(prop);
+            manager.getTransaction().commit();
+        } catch (RuntimeException t) {
+            manager.getTransaction().rollback();
+            throw t;
+        }
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            PropertiesEntity prop2 = manager.find(PropertiesEntity.class, nodeId);
+            assertThat(prop2.isCompressed(), is(prop.isCompressed()));
+            assertThat(prop2.getId(), is(prop.getId()));
+            assertThat(prop2.getData(), is(prop.getData()));
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @Test
+    public void shouldPersistPropertyEntityWithUncompressedFlagAndNoChildren() {
+        startEntityManager();
+        NodeId nodeId = new NodeId(UUID.randomUUID().toString());
+        PropertiesEntity prop = new PropertiesEntity();
+        prop.setData("Hello, World".getBytes());
+        prop.setId(nodeId);
+        manager.getTransaction().begin();
+        try {
+            // Save a properties entity (with compressed data) ...
+            manager.persist(prop);
+            manager.getTransaction().commit();
+        } catch (RuntimeException t) {
+            manager.getTransaction().rollback();
+            throw t;
+        }
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            PropertiesEntity prop2 = manager.find(PropertiesEntity.class, nodeId);
+            assertThat(prop2.isCompressed(), is(prop.isCompressed()));
+            assertThat(prop2.getId(), is(prop.getId()));
+            assertThat(prop2.getData(), is(prop.getData()));
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @Test
+    public void shouldPersistLargeValueEntityWithCompressedFlag() throws UnsupportedEncodingException, NoSuchAlgorithmException {
+        startEntityManager();
+        byte[] content = "Jack and Jill went up the hill to grab a pail of water.".getBytes();
+        String hash = StringUtil.getHexString(SecureHash.getHash(SecureHash.Algorithm.SHA_1, content));
+        LargeValueId id = new LargeValueId(hash);
+        LargeValueEntity entity = new LargeValueEntity();
+        entity.setCompressed(true);
+        entity.setId(id);
+        entity.setLength(content.length);
+        entity.setData(content);
+        entity.setType(PropertyType.STRING);
+        manager.getTransaction().begin();
+        try {
+            // Save the entity ...
+            manager.persist(entity);
+            manager.getTransaction().commit();
+        } catch (RuntimeException t) {
+            manager.getTransaction().rollback();
+            throw t;
+        }
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            LargeValueEntity entity2 = manager.find(LargeValueEntity.class, id);
+            assertThat(entity2.isCompressed(), is(entity.isCompressed()));
+            assertThat(entity2.getId(), is(id));
+            assertThat(entity2.getData(), is(entity.getData()));
+            assertThat(entity2.getLength(), is(entity.getLength()));
+            assertThat(entity2.getType(), is(entity.getType()));
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @Test
+    public void shouldPersistLargeValueEntityWithUncompressedFlag() throws UnsupportedEncodingException, NoSuchAlgorithmException {
+        startEntityManager();
+        byte[] content = "Jack and Jill went up the hill to grab a pail of water.".getBytes();
+        String hash = StringUtil.getHexString(SecureHash.getHash(SecureHash.Algorithm.SHA_1, content));
+        LargeValueId id = new LargeValueId(hash);
+        LargeValueEntity entity = new LargeValueEntity();
+        // entity.setCompressed(false);
+        entity.setId(id);
+        entity.setLength(content.length);
+        entity.setData(content);
+        entity.setType(PropertyType.STRING);
+        manager.getTransaction().begin();
+        try {
+            // Save the entity ...
+            manager.persist(entity);
+            manager.getTransaction().commit();
+        } catch (RuntimeException t) {
+            manager.getTransaction().rollback();
+            throw t;
+        }
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            LargeValueEntity entity2 = manager.find(LargeValueEntity.class, id);
+            assertThat(entity2.isCompressed(), is(entity.isCompressed()));
+            assertThat(entity2.getId(), is(entity.getId()));
+            assertThat(entity2.getData(), is(entity.getData()));
+            assertThat(entity2.getLength(), is(entity.getLength()));
+            assertThat(entity2.getType(), is(entity.getType()));
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @Test
+    public void shouldPersistNamespaceEntity() {
+        startEntityManager();
+        String uri = "http://www.example.com";
+        NamespaceEntity namespace = new NamespaceEntity(uri);
+        manager.getTransaction().begin();
+        try {
+            // Save a namespace entity ...
+            manager.persist(namespace);
+            manager.getTransaction().commit();
+        } catch (RuntimeException t) {
+            manager.getTransaction().rollback();
+            throw t;
+        }
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            NamespaceEntity ns2 = manager.find(NamespaceEntity.class, namespace.getId());
+            assertThat(ns2.getUri(), is(namespace.getUri()));
+            assertThat(ns2.getId(), is(namespace.getId()));
+        } finally {
+            manager.getTransaction().rollback();
+        }
+        // Look up by namespace ...
+        manager.getTransaction().begin();
+        try {
+            NamespaceEntity ns2 = NamespaceEntity.findByUri(manager, uri);
+            assertThat(ns2.getUri(), is(namespace.getUri()));
+            assertThat(ns2.getId(), is(namespace.getId()));
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @Test
+    public void shouldPersistChildEntity() {
+        startEntityManager();
+        UUID parentId = UUID.randomUUID();
+
+        // Create UUIDs for several children ...
+        ChildId childId1 = new ChildId(parentId.toString(), UUID.randomUUID().toString());
+        ChildId childId2 = new ChildId(parentId.toString(), UUID.randomUUID().toString());
+        ChildId childId3 = new ChildId(parentId.toString(), UUID.randomUUID().toString());
+        assertThat(childId1, is(not(childId2)));
+        assertThat(childId1, is(not(childId3)));
+        assertThat(childId2, is(not(childId3)));
+
+        manager.getTransaction().begin();
+        try {
+            NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+
+            // Create the child entities ...
+            ChildEntity child1 = new ChildEntity(childId1, 1, ns, "child1");
+            ChildEntity child2 = new ChildEntity(childId2, 2, ns, "child2");
+            ChildEntity child3 = new ChildEntity(childId3, 3, ns, "child3", 1);
+
+            // Save a properties entities ...
+            manager.persist(child1);
+            manager.persist(child2);
+            manager.persist(child3);
+            manager.getTransaction().commit();
+        } catch (RuntimeException t) {
+            // manager.getTransaction().rollback();
+            throw t;
+        }
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+
+            ChildEntity child1a = manager.find(ChildEntity.class, childId1);
+            ChildEntity child2a = manager.find(ChildEntity.class, childId2);
+            ChildEntity child3a = manager.find(ChildEntity.class, childId3);
+
+            assertThat(child1a.getId(), is(childId1));
+            assertThat(child1a.getIndexInParent(), is(1));
+            assertThat(child1a.getChildName(), is("child1"));
+            assertThat(child1a.getChildNamespace(), is(ns));
+            assertThat(child1a.getSameNameSiblingIndex(), is(1));
+
+            assertThat(child2a.getId(), is(childId2));
+            assertThat(child2a.getIndexInParent(), is(2));
+            assertThat(child2a.getChildName(), is("child2"));
+            assertThat(child2a.getChildNamespace(), is(ns));
+            assertThat(child2a.getSameNameSiblingIndex(), is(1));
+
+            assertThat(child3a.getId(), is(childId3));
+            assertThat(child3a.getIndexInParent(), is(3));
+            assertThat(child3a.getChildName(), is("child3"));
+            assertThat(child3a.getChildNamespace(), is(ns));
+            assertThat(child3a.getSameNameSiblingIndex(), is(1));
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntityTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntityTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntityTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,404 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import java.util.List;
-import java.util.UUID;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.Query;
-import org.hibernate.ejb.Ejb3Configuration;
-import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
-import org.jboss.dna.graph.BasicExecutionContext;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Path;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class ChildEntityTest {
-
-    private EntityManagerFactory factory;
-    private EntityManager manager;
-    private BasicModel model;
-    private ExecutionContext context;
-
-    @Before
-    public void beforeEach() throws Exception {
-        model = new BasicModel();
-        context = new BasicExecutionContext();
-        // Connect to the database ...
-        Ejb3Configuration configurator = new Ejb3Configuration();
-        model.configure(configurator);
-        configurator.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
-        configurator.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
-        configurator.setProperty("hibernate.connection.username", "sa");
-        configurator.setProperty("hibernate.connection.password", "");
-        configurator.setProperty("hibernate.connection.url", "jdbc:hsqldb:.");
-        configurator.setProperty("hibernate.show_sql", "false");
-        configurator.setProperty("hibernate.format_sql", "true");
-        configurator.setProperty("hibernate.use_sql_comments", "true");
-        configurator.setProperty("hibernate.hbm2ddl.auto", "create");
-        factory = configurator.buildEntityManagerFactory();
-        manager = factory.createEntityManager();
-    }
-
-    @After
-    public void afterEach() throws Exception {
-        try {
-            if (manager != null) manager.close();
-        } finally {
-            manager = null;
-            if (factory != null) {
-                try {
-                    factory.close();
-                } finally {
-                    factory = null;
-                }
-            }
-        }
-    }
-
-    protected ChildId[] createChildren( UUID parentUuid,
-                                        NamespaceEntity ns,
-                                        int startingIndex,
-                                        int numChildren,
-                                        String localName,
-                                        boolean useSns ) {
-
-        ChildId[] result = new ChildId[numChildren];
-        manager.getTransaction().begin();
-        try {
-            // Create the child entities ...
-            for (int i = 0; i != numChildren; ++i) {
-                int indexInParent = i + startingIndex;
-                ChildId id = new ChildId(parentUuid.toString(), UUID.randomUUID().toString());
-                ChildEntity child = null;
-                if (useSns) {
-                    child = new ChildEntity(id, indexInParent, ns, localName, i + 1);
-                } else {
-                    String name = numChildren == 1 ? localName : localName + indexInParent;
-                    child = new ChildEntity(id, indexInParent, ns, name);
-                }
-                result[i] = id;
-                manager.persist(child);
-            }
-            manager.getTransaction().commit();
-        } catch (RuntimeException t) {
-            // manager.getTransaction().rollback();
-            throw t;
-        }
-        return result;
-    }
-
-    protected ChildId[] createMixtureOfChildren( UUID parentUuid,
-                                                 NamespaceEntity ns ) {
-        ChildId[] ids1 = createChildren(parentUuid, ns, 1, 10, "child", false);
-        ChildId[] ids2 = createChildren(parentUuid, ns, 11, 10, "childWithSameName", true);
-        ChildId[] ids3 = createChildren(parentUuid, ns, 21, 1, "anotherChild", false);
-        ChildId[] ids4 = createChildren(parentUuid, ns, 22, 1, "nextToLastChild", false);
-        ChildId[] ids5 = createChildren(parentUuid, ns, 23, 1, "lastChild", false);
-        ChildId[][] ids = new ChildId[][] {ids1, ids2, ids3, ids4, ids5};
-        ChildId[] results = new ChildId[ids1.length + ids2.length + ids3.length + ids4.length + ids5.length];
-        int i = 0;
-        for (ChildId[] idArray : ids) {
-            for (ChildId id : idArray)
-                results[i++] = id;
-        }
-        return results;
-    }
-
-    protected ChildEntity getChild( String childUuid ) {
-        Query query = manager.createNamedQuery("ChildEntity.findByChildUuid");
-        query.setParameter("childUuidString", childUuid);
-        return (ChildEntity)query.getSingleResult();
-    }
-
-    @Test
-    public void shouldCreateChildrenWithDifferentNames() {
-        UUID parentUuid = UUID.randomUUID();
-        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
-        ChildId[] ids = createChildren(parentUuid, ns, 1, 10, "child", false);
-
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            int index = 1;
-            for (ChildId id : ids) {
-                ChildEntity child = manager.find(ChildEntity.class, id);
-                assertThat(child.getId(), is(id));
-                assertThat(child.getIndexInParent(), is(index));
-                assertThat(child.getChildName(), is("child" + index));
-                assertThat(child.getChildNamespace(), is(ns));
-                assertThat(child.getSameNameSiblingIndex(), is(1));
-                ++index;
-            }
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @Test
-    public void shouldCreateChildrenWithSameNameSiblingIndex() {
-        UUID parentUuid = UUID.randomUUID();
-        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
-        ChildId[] ids = createChildren(parentUuid, ns, 1, 10, "child", true);
-
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            int index = 1;
-            for (ChildId id : ids) {
-                ChildEntity child = manager.find(ChildEntity.class, id);
-                assertThat(child.getId(), is(id));
-                assertThat(child.getIndexInParent(), is(index));
-                assertThat(child.getChildName(), is("child"));
-                assertThat(child.getChildNamespace(), is(ns));
-                assertThat(child.getSameNameSiblingIndex(), is(index));
-                ++index;
-            }
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    @Test
-    public void shouldCreateMixtureOfChildrenWithDifferentNamesAndSameNameSiblingIndexes() {
-        UUID parentUuid = UUID.randomUUID();
-        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
-        createChildren(parentUuid, ns, 1, 10, "child", false);
-        createChildren(parentUuid, ns, 11, 10, "childWithSameName", true);
-        createChildren(parentUuid, ns, 21, 1, "anotherChild", false);
-        createChildren(parentUuid, ns, 22, 1, "nextToLastChild", false);
-        createChildren(parentUuid, ns, 23, 1, "lastChild", false);
-
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
-            query.setParameter("parentUuidString", parentUuid.toString());
-            List<ChildEntity> children = query.getResultList();
-            int index = 1;
-            assertThat(children.size(), is(23));
-            for (ChildEntity child : children) {
-                assertThat(child.getIndexInParent(), is(index++));
-            }
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    @Test
-    public void shouldCreateMixtureOfChildrenWithDifferentNamesAndSameNameSiblingIndexesMethod2() {
-        UUID parentUuid = UUID.randomUUID();
-        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
-        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
-        assertThat(ids.length, is(23));
-
-        // Look up the object ...
-        manager.getTransaction().begin();
-        try {
-            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
-            query.setParameter("parentUuidString", parentUuid.toString());
-            List<ChildEntity> children = query.getResultList();
-            int index = 1;
-            assertThat(children.size(), is(23));
-            for (ChildEntity child : children) {
-                assertThat(child.getIndexInParent(), is(index++));
-            }
-
-            index = 1;
-            for (ChildId id : ids) {
-                ChildEntity entity = getChild(id.getChildUuidString());
-                assertThat(entity.getIndexInParent(), is(index++));
-            }
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    @Test
-    public void shouldFindEntitiesInIndexRange() {
-        UUID parentUuid = UUID.randomUUID();
-        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
-        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
-        assertThat(ids.length, is(23));
-
-        // Look up the objects ...
-        manager.getTransaction().begin();
-        try {
-            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
-            query.setParameter("parentUuidString", parentUuid.toString());
-            List<ChildEntity> children = query.getResultList();
-            int index = 1;
-            assertThat(children.size(), is(23));
-            for (ChildEntity child : children) {
-                assertThat(child.getIndexInParent(), is(index++));
-            }
-
-            query = manager.createNamedQuery("ChildEntity.findRangeUnderParent");
-            query.setParameter("parentUuidString", parentUuid.toString());
-            query.setParameter("firstIndex", 3);
-            query.setParameter("afterIndex", 6);
-            children = query.getResultList();
-            assertThat(children.size(), is(3));
-            assertThat(children.get(0).getIndexInParent(), is(3));
-            assertThat(children.get(1).getIndexInParent(), is(4));
-            assertThat(children.get(2).getIndexInParent(), is(5));
-
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    @Test
-    public void shouldFindEntitiesAfterIndex() {
-        UUID parentUuid = UUID.randomUUID();
-        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
-        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
-        assertThat(ids.length, is(23));
-
-        // Look up the objects ...
-        manager.getTransaction().begin();
-        try {
-            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
-            query.setParameter("parentUuidString", parentUuid.toString());
-            List<ChildEntity> children = query.getResultList();
-            int index = 1;
-            assertThat(children.size(), is(23));
-            for (ChildEntity child : children) {
-                assertThat(child.getIndexInParent(), is(index++));
-            }
-
-            query = manager.createNamedQuery("ChildEntity.findChildrenAfterIndexUnderParent");
-            query.setParameter("parentUuidString", parentUuid.toString());
-            query.setParameter("afterIndex", 18);
-            children = query.getResultList();
-            assertThat(children.size(), is(6));
-            assertThat(children.get(0).getIndexInParent(), is(18));
-            assertThat(children.get(1).getIndexInParent(), is(19));
-            assertThat(children.get(2).getIndexInParent(), is(20));
-            assertThat(children.get(3).getIndexInParent(), is(21));
-            assertThat(children.get(4).getIndexInParent(), is(22));
-            assertThat(children.get(5).getIndexInParent(), is(23));
-
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    @Test
-    public void shouldFindAdjustChildIndexesAfterRemovalOfFirstSibling() {
-        UUID parentUuid = UUID.randomUUID();
-        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
-        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
-        assertThat(ids.length, is(23));
-
-        // Look up the objects ...
-        manager.getTransaction().begin();
-        try {
-            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
-            query.setParameter("parentUuidString", parentUuid.toString());
-            List<ChildEntity> children = query.getResultList();
-            int index = 1;
-            assertThat(children.size(), is(23));
-            for (ChildEntity child : children) {
-                assertThat(child.getIndexInParent(), is(index++));
-            }
-
-            // Remove the first child ...
-            ChildEntity child = getChild(ids[0].getChildUuidString());
-            assertThat(child, is(notNullValue()));
-            String childName = child.getChildName();
-            manager.remove(child);
-
-            ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(manager, parentUuid.toString(), childName, ns.getId(), 0);
-
-            assertChildren(parentUuid.toString(),
-            // "child1",
-                           "child2",
-                           "child3",
-                           "child4",
-                           "child5",
-                           "child6",
-                           "child7",
-                           "child8",
-                           "child9",
-                           "child10",
-                           "childWithSameName[1]",
-                           "childWithSameName[2]",
-                           "childWithSameName[3]",
-                           "childWithSameName[4]",
-                           "childWithSameName[5]",
-                           "childWithSameName[6]",
-                           "childWithSameName[7]",
-                           "childWithSameName[8]",
-                           "childWithSameName[9]",
-                           "childWithSameName[10]",
-                           "anotherChild",
-                           "nextToLastChild",
-                           "lastChild");
-
-        } finally {
-            manager.getTransaction().rollback();
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    protected void assertChildren( String parentUuid,
-                                   String... childNames ) {
-        Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
-        query.setParameter("parentUuidString", parentUuid.toString());
-        List<ChildEntity> children = query.getResultList();
-        int index = 0;
-        for (ChildEntity child : children) {
-            // System.out.println("found " + child);
-            String childName = childNames[index++];
-            Path.Segment segment = context.getValueFactories().getPathFactory().createSegment(childName);
-            assertThat(child.getChildName(), is(segment.getName().getLocalName()));
-            assertThat(child.getSameNameSiblingIndex(), is(segment.hasIndex() ? segment.getIndex() : 1));
-            assertThat(child.getIndexInParent(), is(index)); // index is incremented
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    protected void printChildren( String parentUuid ) {
-        Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
-        query.setParameter("parentUuidString", parentUuid.toString());
-        List<ChildEntity> children = query.getResultList();
-        for (ChildEntity child : children) {
-            System.out.println("found " + child);
-        }
-
-    }
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntityTest.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntityTest.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntityTest.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntityTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,406 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.util.List;
+import java.util.UUID;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Query;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.jboss.dna.connector.store.jpa.model.basic.BasicModel;
+import org.jboss.dna.connector.store.jpa.model.basic.ChildEntity;
+import org.jboss.dna.connector.store.jpa.model.basic.ChildId;
+import org.jboss.dna.connector.store.jpa.model.common.NamespaceEntity;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.Path;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ChildEntityTest {
+
+    private EntityManagerFactory factory;
+    private EntityManager manager;
+    private BasicModel model;
+    private ExecutionContext context;
+
+    @Before
+    public void beforeEach() throws Exception {
+        model = new BasicModel();
+        context = new ExecutionContext();
+        // Connect to the database ...
+        Ejb3Configuration configurator = new Ejb3Configuration();
+        model.configure(configurator);
+        configurator.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+        configurator.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
+        configurator.setProperty("hibernate.connection.username", "sa");
+        configurator.setProperty("hibernate.connection.password", "");
+        configurator.setProperty("hibernate.connection.url", "jdbc:hsqldb:.");
+        configurator.setProperty("hibernate.show_sql", "false");
+        configurator.setProperty("hibernate.format_sql", "true");
+        configurator.setProperty("hibernate.use_sql_comments", "true");
+        configurator.setProperty("hibernate.hbm2ddl.auto", "create");
+        factory = configurator.buildEntityManagerFactory();
+        manager = factory.createEntityManager();
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        try {
+            if (manager != null) manager.close();
+        } finally {
+            manager = null;
+            if (factory != null) {
+                try {
+                    factory.close();
+                } finally {
+                    factory = null;
+                }
+            }
+        }
+    }
+
+    protected ChildId[] createChildren( UUID parentUuid,
+                                        NamespaceEntity ns,
+                                        int startingIndex,
+                                        int numChildren,
+                                        String localName,
+                                        boolean useSns ) {
+
+        ChildId[] result = new ChildId[numChildren];
+        manager.getTransaction().begin();
+        try {
+            // Create the child entities ...
+            for (int i = 0; i != numChildren; ++i) {
+                int indexInParent = i + startingIndex;
+                ChildId id = new ChildId(parentUuid.toString(), UUID.randomUUID().toString());
+                ChildEntity child = null;
+                if (useSns) {
+                    child = new ChildEntity(id, indexInParent, ns, localName, i + 1);
+                } else {
+                    String name = numChildren == 1 ? localName : localName + indexInParent;
+                    child = new ChildEntity(id, indexInParent, ns, name);
+                }
+                result[i] = id;
+                manager.persist(child);
+            }
+            manager.getTransaction().commit();
+        } catch (RuntimeException t) {
+            // manager.getTransaction().rollback();
+            throw t;
+        }
+        return result;
+    }
+
+    protected ChildId[] createMixtureOfChildren( UUID parentUuid,
+                                                 NamespaceEntity ns ) {
+        ChildId[] ids1 = createChildren(parentUuid, ns, 1, 10, "child", false);
+        ChildId[] ids2 = createChildren(parentUuid, ns, 11, 10, "childWithSameName", true);
+        ChildId[] ids3 = createChildren(parentUuid, ns, 21, 1, "anotherChild", false);
+        ChildId[] ids4 = createChildren(parentUuid, ns, 22, 1, "nextToLastChild", false);
+        ChildId[] ids5 = createChildren(parentUuid, ns, 23, 1, "lastChild", false);
+        ChildId[][] ids = new ChildId[][] {ids1, ids2, ids3, ids4, ids5};
+        ChildId[] results = new ChildId[ids1.length + ids2.length + ids3.length + ids4.length + ids5.length];
+        int i = 0;
+        for (ChildId[] idArray : ids) {
+            for (ChildId id : idArray)
+                results[i++] = id;
+        }
+        return results;
+    }
+
+    protected ChildEntity getChild( String childUuid ) {
+        Query query = manager.createNamedQuery("ChildEntity.findByChildUuid");
+        query.setParameter("childUuidString", childUuid);
+        return (ChildEntity)query.getSingleResult();
+    }
+
+    @Test
+    public void shouldCreateChildrenWithDifferentNames() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createChildren(parentUuid, ns, 1, 10, "child", false);
+
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            int index = 1;
+            for (ChildId id : ids) {
+                ChildEntity child = manager.find(ChildEntity.class, id);
+                assertThat(child.getId(), is(id));
+                assertThat(child.getIndexInParent(), is(index));
+                assertThat(child.getChildName(), is("child" + index));
+                assertThat(child.getChildNamespace(), is(ns));
+                assertThat(child.getSameNameSiblingIndex(), is(1));
+                ++index;
+            }
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @Test
+    public void shouldCreateChildrenWithSameNameSiblingIndex() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createChildren(parentUuid, ns, 1, 10, "child", true);
+
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            int index = 1;
+            for (ChildId id : ids) {
+                ChildEntity child = manager.find(ChildEntity.class, id);
+                assertThat(child.getId(), is(id));
+                assertThat(child.getIndexInParent(), is(index));
+                assertThat(child.getChildName(), is("child"));
+                assertThat(child.getChildNamespace(), is(ns));
+                assertThat(child.getSameNameSiblingIndex(), is(index));
+                ++index;
+            }
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldCreateMixtureOfChildrenWithDifferentNamesAndSameNameSiblingIndexes() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        createChildren(parentUuid, ns, 1, 10, "child", false);
+        createChildren(parentUuid, ns, 11, 10, "childWithSameName", true);
+        createChildren(parentUuid, ns, 21, 1, "anotherChild", false);
+        createChildren(parentUuid, ns, 22, 1, "nextToLastChild", false);
+        createChildren(parentUuid, ns, 23, 1, "lastChild", false);
+
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldCreateMixtureOfChildrenWithDifferentNamesAndSameNameSiblingIndexesMethod2() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
+        assertThat(ids.length, is(23));
+
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+
+            index = 1;
+            for (ChildId id : ids) {
+                ChildEntity entity = getChild(id.getChildUuidString());
+                assertThat(entity.getIndexInParent(), is(index++));
+            }
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldFindEntitiesInIndexRange() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
+        assertThat(ids.length, is(23));
+
+        // Look up the objects ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+
+            query = manager.createNamedQuery("ChildEntity.findRangeUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            query.setParameter("firstIndex", 3);
+            query.setParameter("afterIndex", 6);
+            children = query.getResultList();
+            assertThat(children.size(), is(3));
+            assertThat(children.get(0).getIndexInParent(), is(3));
+            assertThat(children.get(1).getIndexInParent(), is(4));
+            assertThat(children.get(2).getIndexInParent(), is(5));
+
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldFindEntitiesAfterIndex() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
+        assertThat(ids.length, is(23));
+
+        // Look up the objects ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+
+            query = manager.createNamedQuery("ChildEntity.findChildrenAfterIndexUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            query.setParameter("afterIndex", 18);
+            children = query.getResultList();
+            assertThat(children.size(), is(6));
+            assertThat(children.get(0).getIndexInParent(), is(18));
+            assertThat(children.get(1).getIndexInParent(), is(19));
+            assertThat(children.get(2).getIndexInParent(), is(20));
+            assertThat(children.get(3).getIndexInParent(), is(21));
+            assertThat(children.get(4).getIndexInParent(), is(22));
+            assertThat(children.get(5).getIndexInParent(), is(23));
+
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldFindAdjustChildIndexesAfterRemovalOfFirstSibling() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
+        assertThat(ids.length, is(23));
+
+        // Look up the objects ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+
+            // Remove the first child ...
+            ChildEntity child = getChild(ids[0].getChildUuidString());
+            assertThat(child, is(notNullValue()));
+            String childName = child.getChildName();
+            manager.remove(child);
+
+            ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(manager, parentUuid.toString(), childName, ns.getId(), 0);
+
+            assertChildren(parentUuid.toString(),
+            // "child1",
+                           "child2",
+                           "child3",
+                           "child4",
+                           "child5",
+                           "child6",
+                           "child7",
+                           "child8",
+                           "child9",
+                           "child10",
+                           "childWithSameName[1]",
+                           "childWithSameName[2]",
+                           "childWithSameName[3]",
+                           "childWithSameName[4]",
+                           "childWithSameName[5]",
+                           "childWithSameName[6]",
+                           "childWithSameName[7]",
+                           "childWithSameName[8]",
+                           "childWithSameName[9]",
+                           "childWithSameName[10]",
+                           "anotherChild",
+                           "nextToLastChild",
+                           "lastChild");
+
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected void assertChildren( String parentUuid,
+                                   String... childNames ) {
+        Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+        query.setParameter("parentUuidString", parentUuid.toString());
+        List<ChildEntity> children = query.getResultList();
+        int index = 0;
+        for (ChildEntity child : children) {
+            // System.out.println("found " + child);
+            String childName = childNames[index++];
+            Path.Segment segment = context.getValueFactories().getPathFactory().createSegment(childName);
+            assertThat(child.getChildName(), is(segment.getName().getLocalName()));
+            assertThat(child.getSameNameSiblingIndex(), is(segment.hasIndex() ? segment.getIndex() : 1));
+            assertThat(child.getIndexInParent(), is(index)); // index is incremented
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected void printChildren( String parentUuid ) {
+        Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+        query.setParameter("parentUuidString", parentUuid.toString());
+        List<ChildEntity> children = query.getResultList();
+        for (ChildEntity child : children) {
+            System.out.println("found " + child);
+        }
+
+    }
+}

Deleted: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQueryTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,653 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.connector.store.jpa.models.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.IsCollectionContaining.hasItems;
-import java.io.UnsupportedEncodingException;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.Query;
-import org.hibernate.ejb.Ejb3Configuration;
-import org.jboss.dna.common.util.IoUtil;
-import org.jboss.dna.common.util.SecureHash;
-import org.jboss.dna.common.util.StringUtil;
-import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
-import org.jboss.dna.connector.store.jpa.util.Namespaces;
-import org.jboss.dna.graph.BasicExecutionContext;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class SubgraphQueryTest {
-
-    private EntityManagerFactory factory;
-    private EntityManager manager;
-    private BasicModel model;
-    private ExecutionContext context;
-    private Map<Path, UUID> uuidByPath;
-    private Namespaces namespaces;
-    private List<Location> locations;
-    private String[] validLargeValues;
-    private SubgraphQuery query;
-
-    @BeforeClass
-    public static void beforeAll() throws Exception {
-    }
-
-    @Before
-    public void beforeEach() throws Exception {
-        model = new BasicModel();
-        context = new BasicExecutionContext();
-
-        // Load in the large value ...
-        validLargeValues = new String[] {IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum1.txt")),
-            IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum2.txt")),
-            IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum3.txt"))};
-
-        // Connect to the database ...
-        Ejb3Configuration configurator = new Ejb3Configuration();
-        model.configure(configurator);
-        configurator.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
-        configurator.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
-        configurator.setProperty("hibernate.connection.username", "sa");
-        configurator.setProperty("hibernate.connection.password", "");
-        configurator.setProperty("hibernate.connection.url", "jdbc:hsqldb:.");
-        configurator.setProperty("hibernate.show_sql", "false");
-        configurator.setProperty("hibernate.format_sql", "true");
-        configurator.setProperty("hibernate.use_sql_comments", "true");
-        configurator.setProperty("hibernate.hbm2ddl.auto", "create");
-        factory = configurator.buildEntityManagerFactory();
-        manager = factory.createEntityManager();
-        namespaces = new Namespaces(manager);
-
-        manager.getTransaction().begin();
-
-        // Now populate a graph of nodes ...
-        uuidByPath = new HashMap<Path, UUID>();
-        uuidByPath.put(path("/"), UUID.randomUUID());
-        create("/a");
-        create("/a/a1");
-        create("/a/a1/a1");
-        create("/a/a1/a2");
-        create("/a/a1/a3");
-        create("/a/a2");
-        create("/a/a2/a1");
-        create("/a/a2/a1/a1");
-        create("/a/a2/a1/a1/a1");
-        create("/a/a2/a1/a1/a2");
-        create("/a/a2/a1/a2");
-        create("/a/a2/a2");
-        create("/a/a2/a3");
-        create("/a/a2/a4");
-        setLargeValue("/a/a1", "prop1", validLargeValues[0]);
-        setLargeValue("/a/a1", "prop1", validLargeValues[1]); // the only node that uses #1
-        setLargeValue("/a/a2", "prop1", validLargeValues[0]);
-        setLargeValue("/a/a2", "prop2", validLargeValues[2]);
-        setLargeValue("/a/a2/a1", "prop2", validLargeValues[0]);
-        setLargeValue("/a/a2/a1", "prop3", validLargeValues[2]);
-        manager.getTransaction().commit();
-        manager.getTransaction().begin();
-    }
-
-    @After
-    public void afterEach() throws Exception {
-        if (query != null) {
-            try {
-                query.close();
-            } catch (Throwable t) {
-                t.printStackTrace();
-            }
-        }
-        try {
-            manager.close();
-        } finally {
-            factory.close();
-        }
-    }
-
-    protected Path path( String path ) {
-        return context.getValueFactories().getPathFactory().create(path);
-    }
-
-    protected void create( String pathStr ) {
-        Path path = path(pathStr);
-        if (uuidByPath.containsKey(path)) return;
-        if (path.isRoot()) return;
-        Path parent = path.getParent();
-        // Look up the parent ...
-        UUID parentUuid = uuidByPath.get(parent);
-        assert parentUuid != null;
-        // Calculate the child index by walking the existing nodes ...
-        int numChildren = 0;
-        for (Path existing : uuidByPath.keySet()) {
-            if (parent.equals(existing.getParent())) {
-                ++numChildren;
-            }
-        }
-
-        // Create the child entity ...
-        Name childName = path.getLastSegment().getName();
-        int snsIndex = path.getLastSegment().getIndex();
-        NamespaceEntity namespace = namespaces.get(childName.getNamespaceUri(), true);
-        UUID childUuid = UUID.randomUUID();
-        ChildId id = new ChildId(parentUuid.toString(), childUuid.toString());
-        ChildEntity entity = new ChildEntity(id, ++numChildren, namespace, childName.getLocalName(), snsIndex);
-        manager.persist(entity);
-
-        // Create the properties ...
-        NodeId nodeId = new NodeId(childUuid.toString());
-        PropertiesEntity props = new PropertiesEntity(nodeId);
-        props.setData("bogus data".getBytes());
-        props.setPropertyCount(1);
-        props.setCompressed(false);
-        manager.persist(props);
-
-        uuidByPath.put(path, childUuid);
-    }
-
-    protected ReferenceEntity createReferenceBetween( String fromPathStr,
-                                                      String toPathStr ) {
-        Path fromPath = path(fromPathStr);
-        Path toPath = path(toPathStr);
-
-        // Look up the UUIDs ...
-        UUID fromUuid = uuidByPath.get(fromPath);
-        UUID toUuid = uuidByPath.get(toPath);
-        assert fromUuid != null;
-        assert toUuid != null;
-
-        // Now create a reference entity ...
-        ReferenceEntity entity = new ReferenceEntity(new ReferenceId(fromUuid.toString(), toUuid.toString()));
-        manager.persist(entity);
-        return entity;
-    }
-
-    protected UUID uuidForPath( String pathStr ) {
-        Path path = path(pathStr);
-        return uuidByPath.get(path);
-    }
-
-    protected void setLargeValue( String pathStr,
-                                  String propertyName,
-                                  String largeValue ) throws UnsupportedEncodingException, NoSuchAlgorithmException {
-        Path path = path(pathStr);
-        UUID nodeUuid = uuidByPath.get(path);
-        assertThat(nodeUuid, is(notNullValue()));
-
-        // Find or create the large value object ...
-        LargeValueId id = largeValueId(largeValue);
-        LargeValueEntity entity = manager.find(LargeValueEntity.class, id);
-        if (entity == null) {
-            entity = new LargeValueEntity();
-            entity.setId(id);
-            entity.setLength(largeValue.length());
-            entity.setCompressed(false);
-            entity.setData(largeValue.getBytes());
-            entity.setType(PropertyType.STRING);
-            manager.persist(entity);
-        }
-
-        // Load the PropertiesEntity ...
-        NodeId nodeId = new NodeId(nodeUuid.toString());
-        PropertiesEntity props = manager.find(PropertiesEntity.class, nodeId);
-        assertThat(props, is(notNullValue()));
-
-        // Add the large value ...
-        props.getLargeValues().add(id);
-    }
-
-    protected LargeValueId largeValueId( String value ) throws UnsupportedEncodingException, NoSuchAlgorithmException {
-        return new LargeValueId(StringUtil.getHexString(SecureHash.getHash(SecureHash.Algorithm.SHA_1, value.getBytes())));
-    }
-
-    protected PropertiesEntity getProperties( String pathStr ) {
-        Path path = path(pathStr);
-        UUID nodeUuid = uuidByPath.get(path);
-        assertThat(nodeUuid, is(notNullValue()));
-
-        NodeId nodeId = new NodeId(nodeUuid.toString());
-        return manager.find(PropertiesEntity.class, nodeId);
-    }
-
-    protected void verifyNextLocationIs( String path ) {
-        Path pathObj = path(path);
-        UUID uuid = uuidByPath.get(pathObj);
-        Location next = locations.remove(0);
-        assertThat(next, is(notNullValue()));
-        assertThat(next.getPath(), is(pathObj));
-        assertThat(next.getUuid(), is(uuid));
-    }
-
-    protected void verifyNoMoreLocations() {
-        assertThat(locations.isEmpty(), is(true));
-    }
-
-    @SuppressWarnings( "unchecked" )
-    protected void verifyNodesHaveLargeValues( String... paths ) {
-        if (paths == null || paths.length == 0) return;
-        // Build the set of UUIDs for the nodes that should have large values ...
-        String[] expectedNodeUuids = new String[paths.length];
-        for (int i = 0; i != paths.length; ++i) {
-            String pathStr = paths[i];
-            expectedNodeUuids[i] = uuidForPath(pathStr).toString();
-        }
-        // Load the PropertiesEntity for the nodes that have large properties ...
-        Query queryProps = manager.createQuery("select prop from PropertiesEntity as prop where size(prop.largeValues) > 0");
-        Set<String> actualNodeUuids = new HashSet<String>();
-        List<PropertiesEntity> propsWithLargeValues = queryProps.getResultList();
-        for (PropertiesEntity entity : propsWithLargeValues) {
-            String uuidStr = entity.getId().getUuidString();
-            actualNodeUuids.add(uuidStr);
-        }
-        assertThat(actualNodeUuids, hasItems(expectedNodeUuids));
-    }
-
-    @Test
-    public void shouldFindLargeValueContentFromFile() {
-        for (int i = 0; i != validLargeValues.length; ++i) {
-            assertThat(validLargeValues[i].startsWith((i + 1) + ". Lorem ipsum dolor sit amet"), is(true));
-        }
-    }
-
-    @Test
-    public void shouldPerformSubgraphQueryOfNodeWithChildrenAndNoGrandchildren() {
-        Path path = path("/a/a1");
-        UUID uuid = uuidByPath.get(path);
-        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNoMoreLocations();
-        query.close();
-    }
-
-    @Test
-    public void shouldPerformSubgraphQueryOfNodeWithChildrenAndGrandchildren() {
-        Path path = path("/a/a2");
-        UUID uuid = uuidByPath.get(path);
-        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a/a2");
-        verifyNextLocationIs("/a/a2/a1");
-        verifyNextLocationIs("/a/a2/a2");
-        verifyNextLocationIs("/a/a2/a3");
-        verifyNextLocationIs("/a/a2/a4");
-        verifyNextLocationIs("/a/a2/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a2");
-        verifyNextLocationIs("/a/a2/a1/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a1/a2");
-        verifyNoMoreLocations();
-        query.close();
-    }
-
-    @Test
-    public void shouldPerformSubgraphQueryOfNodeWithChildrenAndGrandchildrenAndGreatGranchildren() {
-        Path path = path("/a");
-        UUID uuid = uuidByPath.get(path);
-        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a");
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a2");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNextLocationIs("/a/a2/a1");
-        verifyNextLocationIs("/a/a2/a2");
-        verifyNextLocationIs("/a/a2/a3");
-        verifyNextLocationIs("/a/a2/a4");
-        verifyNextLocationIs("/a/a2/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a2");
-        verifyNextLocationIs("/a/a2/a1/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a1/a2");
-        verifyNoMoreLocations();
-        query.close();
-    }
-
-    @Test
-    public void shouldPerformMaxDepthSubgraphQueryOfNodeWithChildrenAndGrandchildrenAndGreatGranchildren() {
-        Path path = path("/a");
-        UUID uuid = uuidByPath.get(path);
-        query = SubgraphQuery.create(context, manager, uuid, path, 4);
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a");
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a2");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNextLocationIs("/a/a2/a1");
-        verifyNextLocationIs("/a/a2/a2");
-        verifyNextLocationIs("/a/a2/a3");
-        verifyNextLocationIs("/a/a2/a4");
-        verifyNextLocationIs("/a/a2/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a2");
-        verifyNextLocationIs("/a/a2/a1/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a1/a2");
-        verifyNoMoreLocations();
-
-        locations = query.getNodeLocations(true, false);
-        verifyNextLocationIs("/a");
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a2");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNextLocationIs("/a/a2/a1");
-        verifyNextLocationIs("/a/a2/a2");
-        verifyNextLocationIs("/a/a2/a3");
-        verifyNextLocationIs("/a/a2/a4");
-        verifyNextLocationIs("/a/a2/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a2");
-        verifyNoMoreLocations();
-        query.close();
-
-        query = SubgraphQuery.create(context, manager, uuid, path, 2);
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a");
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a2");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNextLocationIs("/a/a2/a1");
-        verifyNextLocationIs("/a/a2/a2");
-        verifyNextLocationIs("/a/a2/a3");
-        verifyNextLocationIs("/a/a2/a4");
-        verifyNoMoreLocations();
-
-        locations = query.getNodeLocations(true, false);
-        verifyNextLocationIs("/a");
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a2");
-        verifyNoMoreLocations();
-
-        query.close();
-
-        query = SubgraphQuery.create(context, manager, uuid, path, 3);
-        locations = query.getNodeLocations(true, false);
-        verifyNextLocationIs("/a");
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a2");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNextLocationIs("/a/a2/a1");
-        verifyNextLocationIs("/a/a2/a2");
-        verifyNextLocationIs("/a/a2/a3");
-        verifyNextLocationIs("/a/a2/a4");
-        verifyNoMoreLocations();
-
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a");
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a2");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNextLocationIs("/a/a2/a1");
-        verifyNextLocationIs("/a/a2/a2");
-        verifyNextLocationIs("/a/a2/a3");
-        verifyNextLocationIs("/a/a2/a4");
-        verifyNextLocationIs("/a/a2/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a2");
-        verifyNoMoreLocations();
-        query.close();
-    }
-
-    @Test
-    public void shouldDeleteSubgraph() throws Exception {
-        // Verify that all the nodes with large values do indeed have them ...
-        verifyNodesHaveLargeValues("/a/a1", "/a/a2", "/a/a2/a1");
-
-        // Count the number of objects ...
-        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(3L));
-        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(14L));
-        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(14L));
-
-        // Delete "/a/a1". Note that "/a/a1" has a large value that is shared by "/a/a2", but it's also the only
-        // user of large value #1.
-        Path path = path("/a/a1");
-        UUID uuid = uuidByPath.get(path);
-
-        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNoMoreLocations();
-        query.deleteSubgraph(true);
-        assertThat(query.getInwardReferences().isEmpty(), is(true));
-        query.close();
-
-        // Commit the transaction, and start another ...
-        manager.getTransaction().commit();
-        manager.getTransaction().begin();
-        manager.flush();
-
-        // Count the number of objects ...
-        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(2L));
-        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(10L));
-        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(10L));
-
-        // Verify the graph structure is correct ...
-        path = path("/a");
-        uuid = uuidByPath.get(path);
-        query = SubgraphQuery.create(context, manager, uuid, path, 4);
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a");
-        verifyNextLocationIs("/a/a2");
-        verifyNextLocationIs("/a/a2/a1");
-        verifyNextLocationIs("/a/a2/a2");
-        verifyNextLocationIs("/a/a2/a3");
-        verifyNextLocationIs("/a/a2/a4");
-        verifyNextLocationIs("/a/a2/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a2");
-        verifyNextLocationIs("/a/a2/a1/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a1/a2");
-        verifyNoMoreLocations();
-
-        locations = query.getNodeLocations(true, false);
-        verifyNextLocationIs("/a");
-        verifyNextLocationIs("/a/a2");
-        verifyNextLocationIs("/a/a2/a1");
-        verifyNextLocationIs("/a/a2/a2");
-        verifyNextLocationIs("/a/a2/a3");
-        verifyNextLocationIs("/a/a2/a4");
-        verifyNextLocationIs("/a/a2/a1/a1");
-        verifyNextLocationIs("/a/a2/a1/a2");
-        verifyNoMoreLocations();
-        query.close();
-
-        // Verify that all the nodes with large values do indeed have them ...
-        verifyNodesHaveLargeValues("/a/a2", "/a/a2/a1"); // "/a/a1" was deleted
-
-        // Now, load the one node remaining with
-    }
-
-    @Test
-    public void shouldNotDeleteSubgraphThatHasNodesReferencedByOtherNodesNotBeingDeleted() throws Exception {
-        // Verify that all the nodes with large values do indeed have them ...
-        verifyNodesHaveLargeValues("/a/a1", "/a/a2", "/a/a2/a1");
-
-        // Count the number of objects ...
-        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(3L));
-        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(14L));
-        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(14L));
-
-        // Create references from the "/a/a2" (not being deleted) branch, to the branch being deleted...
-        List<ReferenceEntity> expectedInvalidRefs = new ArrayList<ReferenceEntity>();
-        expectedInvalidRefs.add(createReferenceBetween("/a/a2", "/a/a1"));
-        expectedInvalidRefs.add(createReferenceBetween("/a/a2/a1", "/a/a1/a1"));
-        expectedInvalidRefs.add(createReferenceBetween("/a/a2/a2", "/a/a1/a2"));
-
-        // Create references between nodes in the branch being deleted (these shouldn't matter) ...
-        createReferenceBetween("/a/a1", "/a/a1/a1");
-        createReferenceBetween("/a/a1/a2", "/a/a1/a3");
-
-        // Delete "/a/a1". Note that "/a/a1" has a large value that is shared by "/a/a2", but it's also the only
-        // user of large value #1.
-        Path path = path("/a/a1");
-        UUID uuid = uuidByPath.get(path);
-
-        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNoMoreLocations();
-        query.deleteSubgraph(true);
-
-        // Now there should be invalid references ...
-        List<ReferenceEntity> invalidReferences = query.getInwardReferences();
-        assertThat(invalidReferences.size(), is(3));
-        invalidReferences.removeAll(invalidReferences);
-        assertThat(invalidReferences.size(), is(0));
-        query.close();
-    }
-
-    @SuppressWarnings( "unchecked" )
-    @Test
-    public void shouldDeleteSubgraphThatHasInternalReferences() throws Exception {
-        // Verify that all the nodes with large values do indeed have them ...
-        verifyNodesHaveLargeValues("/a/a1", "/a/a2", "/a/a2/a1");
-
-        // Count the number of objects ...
-        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(3L));
-        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(14L));
-        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(14L));
-
-        // Create references from the nodes that aren't being deleted (these won't matter, but will remain)...
-        List<ReferenceEntity> expectedValidRefs = new ArrayList<ReferenceEntity>();
-        expectedValidRefs.add(createReferenceBetween("/a/a2", "/a/a2/a1"));
-
-        // Create references between nodes in the branch being deleted (these shouldn't matter) ...
-        createReferenceBetween("/a/a1", "/a/a1/a1");
-        createReferenceBetween("/a/a1/a2", "/a/a1/a3");
-
-        // Delete "/a/a1". Note that "/a/a1" has a large value that is shared by "/a/a2", but it's also the only
-        // user of large value #1.
-        Path path = path("/a/a1");
-        UUID uuid = uuidByPath.get(path);
-
-        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
-        locations = query.getNodeLocations(true, true);
-        verifyNextLocationIs("/a/a1");
-        verifyNextLocationIs("/a/a1/a1");
-        verifyNextLocationIs("/a/a1/a2");
-        verifyNextLocationIs("/a/a1/a3");
-        verifyNoMoreLocations();
-        query.deleteSubgraph(true);
-
-        // Now there should be invalid references ...
-        List<ReferenceEntity> invalidReferences = query.getInwardReferences();
-        assertThat(invalidReferences.size(), is(0));
-        query.close();
-
-        // There should be no references any more ...
-        Query refQuery = manager.createQuery("select ref from ReferenceEntity as ref");
-        List<ReferenceEntity> remainingReferences = refQuery.getResultList();
-        assertThat(remainingReferences.size(), is(1));
-        remainingReferences.removeAll(expectedValidRefs);
-        assertThat(remainingReferences.size(), is(0));
-    }
-
-    @Test
-    public void shouldGetVariousReferencesRelatedToSubgraph() throws Exception {
-        // Verify that all the nodes with large values do indeed have them ...
-        verifyNodesHaveLargeValues("/a/a1", "/a/a2", "/a/a2/a1");
-
-        // Count the number of objects ...
-        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(3L));
-        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(14L));
-        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(14L));
-
-        // Create references from the nodes that aren't even part of the subgraph ...
-        List<ReferenceEntity> otherRefs = new ArrayList<ReferenceEntity>();
-        otherRefs.add(createReferenceBetween("/a/a2", "/a/a2/a1"));
-        otherRefs.add(createReferenceBetween("/a/a2/a1", "/a/a2/a2"));
-
-        // Create references between nodes in the subgraph ...
-        List<ReferenceEntity> internalRefs = new ArrayList<ReferenceEntity>();
-        internalRefs.add(createReferenceBetween("/a/a1", "/a/a1/a1"));
-        internalRefs.add(createReferenceBetween("/a/a1/a2", "/a/a1/a3"));
-
-        // Create references from nodes outside of the subgraph to nodes inside of the subgraph ...
-        List<ReferenceEntity> inwardRefs = new ArrayList<ReferenceEntity>();
-        inwardRefs.add(createReferenceBetween("/a/a2", "/a/a1/a1"));
-        inwardRefs.add(createReferenceBetween("/a/a2/a1", "/a/a1/a3"));
-
-        // Create references from nodes inside of the subgraph to nodes outside of the subgraph ...
-        List<ReferenceEntity> outwardRefs = new ArrayList<ReferenceEntity>();
-        outwardRefs.add(createReferenceBetween("/a/a1", "/a/a2"));
-        outwardRefs.add(createReferenceBetween("/a/a1/a1", "/a/a2/a1"));
-
-        // Create the query ...
-        Path path = path("/a/a1");
-        UUID uuid = uuidByPath.get(path);
-        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
-
-        // Check the various kinds of references ...
-        List<ReferenceEntity> actualInternal = query.getInternalReferences();
-        List<ReferenceEntity> actualInward = query.getInwardReferences();
-        List<ReferenceEntity> actualOutward = query.getOutwardReferences();
-
-        assertThat(actualInternal.size(), is(internalRefs.size()));
-        actualInternal.removeAll(internalRefs);
-        assertThat(actualInternal.size(), is(0));
-
-        assertThat(actualInward.size(), is(inwardRefs.size()));
-        actualInward.removeAll(inwardRefs);
-        assertThat(actualInward.size(), is(0));
-
-        assertThat(actualOutward.size(), is(outwardRefs.size()));
-        actualOutward.removeAll(outwardRefs);
-        assertThat(actualOutward.size(), is(0));
-
-        query.close();
-    }
-
-}

Copied: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryTest.java (from rev 706, trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQueryTest.java)
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryTest.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/model/basic/SubgraphQueryTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,662 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.model.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.IsCollectionContaining.hasItems;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Query;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.jboss.dna.common.util.IoUtil;
+import org.jboss.dna.common.util.SecureHash;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.connector.store.jpa.model.basic.BasicModel;
+import org.jboss.dna.connector.store.jpa.model.basic.ChildEntity;
+import org.jboss.dna.connector.store.jpa.model.basic.ChildId;
+import org.jboss.dna.connector.store.jpa.model.basic.LargeValueEntity;
+import org.jboss.dna.connector.store.jpa.model.basic.LargeValueId;
+import org.jboss.dna.connector.store.jpa.model.basic.NodeId;
+import org.jboss.dna.connector.store.jpa.model.basic.PropertiesEntity;
+import org.jboss.dna.connector.store.jpa.model.basic.ReferenceEntity;
+import org.jboss.dna.connector.store.jpa.model.basic.ReferenceId;
+import org.jboss.dna.connector.store.jpa.model.basic.SubgraphQuery;
+import org.jboss.dna.connector.store.jpa.model.common.NamespaceEntity;
+import org.jboss.dna.connector.store.jpa.util.Namespaces;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PropertyType;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class SubgraphQueryTest {
+
+    private EntityManagerFactory factory;
+    private EntityManager manager;
+    private BasicModel model;
+    private ExecutionContext context;
+    private Map<Path, UUID> uuidByPath;
+    private Namespaces namespaces;
+    private List<Location> locations;
+    private String[] validLargeValues;
+    private SubgraphQuery query;
+
+    @BeforeClass
+    public static void beforeAll() throws Exception {
+    }
+
+    @Before
+    public void beforeEach() throws Exception {
+        model = new BasicModel();
+        context = new ExecutionContext();
+
+        // Load in the large value ...
+        validLargeValues = new String[] {IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum1.txt")),
+            IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum2.txt")),
+            IoUtil.read(getClass().getClassLoader().getResourceAsStream("LoremIpsum3.txt"))};
+
+        // Connect to the database ...
+        Ejb3Configuration configurator = new Ejb3Configuration();
+        model.configure(configurator);
+        configurator.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+        configurator.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
+        configurator.setProperty("hibernate.connection.username", "sa");
+        configurator.setProperty("hibernate.connection.password", "");
+        configurator.setProperty("hibernate.connection.url", "jdbc:hsqldb:.");
+        configurator.setProperty("hibernate.show_sql", "false");
+        configurator.setProperty("hibernate.format_sql", "true");
+        configurator.setProperty("hibernate.use_sql_comments", "true");
+        configurator.setProperty("hibernate.hbm2ddl.auto", "create");
+        factory = configurator.buildEntityManagerFactory();
+        manager = factory.createEntityManager();
+        namespaces = new Namespaces(manager);
+
+        manager.getTransaction().begin();
+
+        // Now populate a graph of nodes ...
+        uuidByPath = new HashMap<Path, UUID>();
+        uuidByPath.put(path("/"), UUID.randomUUID());
+        create("/a");
+        create("/a/a1");
+        create("/a/a1/a1");
+        create("/a/a1/a2");
+        create("/a/a1/a3");
+        create("/a/a2");
+        create("/a/a2/a1");
+        create("/a/a2/a1/a1");
+        create("/a/a2/a1/a1/a1");
+        create("/a/a2/a1/a1/a2");
+        create("/a/a2/a1/a2");
+        create("/a/a2/a2");
+        create("/a/a2/a3");
+        create("/a/a2/a4");
+        setLargeValue("/a/a1", "prop1", validLargeValues[0]);
+        setLargeValue("/a/a1", "prop1", validLargeValues[1]); // the only node that uses #1
+        setLargeValue("/a/a2", "prop1", validLargeValues[0]);
+        setLargeValue("/a/a2", "prop2", validLargeValues[2]);
+        setLargeValue("/a/a2/a1", "prop2", validLargeValues[0]);
+        setLargeValue("/a/a2/a1", "prop3", validLargeValues[2]);
+        manager.getTransaction().commit();
+        manager.getTransaction().begin();
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        if (query != null) {
+            try {
+                query.close();
+            } catch (Throwable t) {
+                t.printStackTrace();
+            }
+        }
+        try {
+            manager.close();
+        } finally {
+            factory.close();
+        }
+    }
+
+    protected Path path( String path ) {
+        return context.getValueFactories().getPathFactory().create(path);
+    }
+
+    protected void create( String pathStr ) {
+        Path path = path(pathStr);
+        if (uuidByPath.containsKey(path)) return;
+        if (path.isRoot()) return;
+        Path parent = path.getParent();
+        // Look up the parent ...
+        UUID parentUuid = uuidByPath.get(parent);
+        assert parentUuid != null;
+        // Calculate the child index by walking the existing nodes ...
+        int numChildren = 0;
+        for (Path existing : uuidByPath.keySet()) {
+            if (parent.equals(existing.getParent())) {
+                ++numChildren;
+            }
+        }
+
+        // Create the child entity ...
+        Name childName = path.getLastSegment().getName();
+        int snsIndex = path.getLastSegment().getIndex();
+        NamespaceEntity namespace = namespaces.get(childName.getNamespaceUri(), true);
+        UUID childUuid = UUID.randomUUID();
+        ChildId id = new ChildId(parentUuid.toString(), childUuid.toString());
+        ChildEntity entity = new ChildEntity(id, ++numChildren, namespace, childName.getLocalName(), snsIndex);
+        manager.persist(entity);
+
+        // Create the properties ...
+        NodeId nodeId = new NodeId(childUuid.toString());
+        PropertiesEntity props = new PropertiesEntity(nodeId);
+        props.setData("bogus data".getBytes());
+        props.setPropertyCount(1);
+        props.setCompressed(false);
+        manager.persist(props);
+
+        uuidByPath.put(path, childUuid);
+    }
+
+    protected ReferenceEntity createReferenceBetween( String fromPathStr,
+                                                      String toPathStr ) {
+        Path fromPath = path(fromPathStr);
+        Path toPath = path(toPathStr);
+
+        // Look up the UUIDs ...
+        UUID fromUuid = uuidByPath.get(fromPath);
+        UUID toUuid = uuidByPath.get(toPath);
+        assert fromUuid != null;
+        assert toUuid != null;
+
+        // Now create a reference entity ...
+        ReferenceEntity entity = new ReferenceEntity(new ReferenceId(fromUuid.toString(), toUuid.toString()));
+        manager.persist(entity);
+        return entity;
+    }
+
+    protected UUID uuidForPath( String pathStr ) {
+        Path path = path(pathStr);
+        return uuidByPath.get(path);
+    }
+
+    protected void setLargeValue( String pathStr,
+                                  String propertyName,
+                                  String largeValue ) throws UnsupportedEncodingException, NoSuchAlgorithmException {
+        Path path = path(pathStr);
+        UUID nodeUuid = uuidByPath.get(path);
+        assertThat(nodeUuid, is(notNullValue()));
+
+        // Find or create the large value object ...
+        LargeValueId id = largeValueId(largeValue);
+        LargeValueEntity entity = manager.find(LargeValueEntity.class, id);
+        if (entity == null) {
+            entity = new LargeValueEntity();
+            entity.setId(id);
+            entity.setLength(largeValue.length());
+            entity.setCompressed(false);
+            entity.setData(largeValue.getBytes());
+            entity.setType(PropertyType.STRING);
+            manager.persist(entity);
+        }
+
+        // Load the PropertiesEntity ...
+        NodeId nodeId = new NodeId(nodeUuid.toString());
+        PropertiesEntity props = manager.find(PropertiesEntity.class, nodeId);
+        assertThat(props, is(notNullValue()));
+
+        // Add the large value ...
+        props.getLargeValues().add(id);
+    }
+
+    protected LargeValueId largeValueId( String value ) throws UnsupportedEncodingException, NoSuchAlgorithmException {
+        return new LargeValueId(StringUtil.getHexString(SecureHash.getHash(SecureHash.Algorithm.SHA_1, value.getBytes())));
+    }
+
+    protected PropertiesEntity getProperties( String pathStr ) {
+        Path path = path(pathStr);
+        UUID nodeUuid = uuidByPath.get(path);
+        assertThat(nodeUuid, is(notNullValue()));
+
+        NodeId nodeId = new NodeId(nodeUuid.toString());
+        return manager.find(PropertiesEntity.class, nodeId);
+    }
+
+    protected void verifyNextLocationIs( String path ) {
+        Path pathObj = path(path);
+        UUID uuid = uuidByPath.get(pathObj);
+        Location next = locations.remove(0);
+        assertThat(next, is(notNullValue()));
+        assertThat(next.getPath(), is(pathObj));
+        assertThat(next.getUuid(), is(uuid));
+    }
+
+    protected void verifyNoMoreLocations() {
+        assertThat(locations.isEmpty(), is(true));
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected void verifyNodesHaveLargeValues( String... paths ) {
+        if (paths == null || paths.length == 0) return;
+        // Build the set of UUIDs for the nodes that should have large values ...
+        String[] expectedNodeUuids = new String[paths.length];
+        for (int i = 0; i != paths.length; ++i) {
+            String pathStr = paths[i];
+            expectedNodeUuids[i] = uuidForPath(pathStr).toString();
+        }
+        // Load the PropertiesEntity for the nodes that have large properties ...
+        Query queryProps = manager.createQuery("select prop from PropertiesEntity as prop where size(prop.largeValues) > 0");
+        Set<String> actualNodeUuids = new HashSet<String>();
+        List<PropertiesEntity> propsWithLargeValues = queryProps.getResultList();
+        for (PropertiesEntity entity : propsWithLargeValues) {
+            String uuidStr = entity.getId().getUuidString();
+            actualNodeUuids.add(uuidStr);
+        }
+        assertThat(actualNodeUuids, hasItems(expectedNodeUuids));
+    }
+
+    @Test
+    public void shouldFindLargeValueContentFromFile() {
+        for (int i = 0; i != validLargeValues.length; ++i) {
+            assertThat(validLargeValues[i].startsWith((i + 1) + ". Lorem ipsum dolor sit amet"), is(true));
+        }
+    }
+
+    @Test
+    public void shouldPerformSubgraphQueryOfNodeWithChildrenAndNoGrandchildren() {
+        Path path = path("/a/a1");
+        UUID uuid = uuidByPath.get(path);
+        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNoMoreLocations();
+        query.close();
+    }
+
+    @Test
+    public void shouldPerformSubgraphQueryOfNodeWithChildrenAndGrandchildren() {
+        Path path = path("/a/a2");
+        UUID uuid = uuidByPath.get(path);
+        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a/a2");
+        verifyNextLocationIs("/a/a2/a1");
+        verifyNextLocationIs("/a/a2/a2");
+        verifyNextLocationIs("/a/a2/a3");
+        verifyNextLocationIs("/a/a2/a4");
+        verifyNextLocationIs("/a/a2/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a2");
+        verifyNextLocationIs("/a/a2/a1/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a1/a2");
+        verifyNoMoreLocations();
+        query.close();
+    }
+
+    @Test
+    public void shouldPerformSubgraphQueryOfNodeWithChildrenAndGrandchildrenAndGreatGranchildren() {
+        Path path = path("/a");
+        UUID uuid = uuidByPath.get(path);
+        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a");
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a2");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNextLocationIs("/a/a2/a1");
+        verifyNextLocationIs("/a/a2/a2");
+        verifyNextLocationIs("/a/a2/a3");
+        verifyNextLocationIs("/a/a2/a4");
+        verifyNextLocationIs("/a/a2/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a2");
+        verifyNextLocationIs("/a/a2/a1/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a1/a2");
+        verifyNoMoreLocations();
+        query.close();
+    }
+
+    @Test
+    public void shouldPerformMaxDepthSubgraphQueryOfNodeWithChildrenAndGrandchildrenAndGreatGranchildren() {
+        Path path = path("/a");
+        UUID uuid = uuidByPath.get(path);
+        query = SubgraphQuery.create(context, manager, uuid, path, 4);
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a");
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a2");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNextLocationIs("/a/a2/a1");
+        verifyNextLocationIs("/a/a2/a2");
+        verifyNextLocationIs("/a/a2/a3");
+        verifyNextLocationIs("/a/a2/a4");
+        verifyNextLocationIs("/a/a2/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a2");
+        verifyNextLocationIs("/a/a2/a1/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a1/a2");
+        verifyNoMoreLocations();
+
+        locations = query.getNodeLocations(true, false);
+        verifyNextLocationIs("/a");
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a2");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNextLocationIs("/a/a2/a1");
+        verifyNextLocationIs("/a/a2/a2");
+        verifyNextLocationIs("/a/a2/a3");
+        verifyNextLocationIs("/a/a2/a4");
+        verifyNextLocationIs("/a/a2/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a2");
+        verifyNoMoreLocations();
+        query.close();
+
+        query = SubgraphQuery.create(context, manager, uuid, path, 2);
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a");
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a2");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNextLocationIs("/a/a2/a1");
+        verifyNextLocationIs("/a/a2/a2");
+        verifyNextLocationIs("/a/a2/a3");
+        verifyNextLocationIs("/a/a2/a4");
+        verifyNoMoreLocations();
+
+        locations = query.getNodeLocations(true, false);
+        verifyNextLocationIs("/a");
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a2");
+        verifyNoMoreLocations();
+
+        query.close();
+
+        query = SubgraphQuery.create(context, manager, uuid, path, 3);
+        locations = query.getNodeLocations(true, false);
+        verifyNextLocationIs("/a");
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a2");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNextLocationIs("/a/a2/a1");
+        verifyNextLocationIs("/a/a2/a2");
+        verifyNextLocationIs("/a/a2/a3");
+        verifyNextLocationIs("/a/a2/a4");
+        verifyNoMoreLocations();
+
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a");
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a2");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNextLocationIs("/a/a2/a1");
+        verifyNextLocationIs("/a/a2/a2");
+        verifyNextLocationIs("/a/a2/a3");
+        verifyNextLocationIs("/a/a2/a4");
+        verifyNextLocationIs("/a/a2/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a2");
+        verifyNoMoreLocations();
+        query.close();
+    }
+
+    @Test
+    public void shouldDeleteSubgraph() throws Exception {
+        // Verify that all the nodes with large values do indeed have them ...
+        verifyNodesHaveLargeValues("/a/a1", "/a/a2", "/a/a2/a1");
+
+        // Count the number of objects ...
+        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(3L));
+        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(14L));
+        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(14L));
+
+        // Delete "/a/a1". Note that "/a/a1" has a large value that is shared by "/a/a2", but it's also the only
+        // user of large value #1.
+        Path path = path("/a/a1");
+        UUID uuid = uuidByPath.get(path);
+
+        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNoMoreLocations();
+        query.deleteSubgraph(true);
+        assertThat(query.getInwardReferences().isEmpty(), is(true));
+        query.close();
+
+        // Commit the transaction, and start another ...
+        manager.getTransaction().commit();
+        manager.getTransaction().begin();
+        manager.flush();
+
+        // Count the number of objects ...
+        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(2L));
+        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(10L));
+        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(10L));
+
+        // Verify the graph structure is correct ...
+        path = path("/a");
+        uuid = uuidByPath.get(path);
+        query = SubgraphQuery.create(context, manager, uuid, path, 4);
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a");
+        verifyNextLocationIs("/a/a2");
+        verifyNextLocationIs("/a/a2/a1");
+        verifyNextLocationIs("/a/a2/a2");
+        verifyNextLocationIs("/a/a2/a3");
+        verifyNextLocationIs("/a/a2/a4");
+        verifyNextLocationIs("/a/a2/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a2");
+        verifyNextLocationIs("/a/a2/a1/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a1/a2");
+        verifyNoMoreLocations();
+
+        locations = query.getNodeLocations(true, false);
+        verifyNextLocationIs("/a");
+        verifyNextLocationIs("/a/a2");
+        verifyNextLocationIs("/a/a2/a1");
+        verifyNextLocationIs("/a/a2/a2");
+        verifyNextLocationIs("/a/a2/a3");
+        verifyNextLocationIs("/a/a2/a4");
+        verifyNextLocationIs("/a/a2/a1/a1");
+        verifyNextLocationIs("/a/a2/a1/a2");
+        verifyNoMoreLocations();
+        query.close();
+
+        // Verify that all the nodes with large values do indeed have them ...
+        verifyNodesHaveLargeValues("/a/a2", "/a/a2/a1"); // "/a/a1" was deleted
+
+        // Now, load the one node remaining with
+    }
+
+    @Test
+    public void shouldNotDeleteSubgraphThatHasNodesReferencedByOtherNodesNotBeingDeleted() throws Exception {
+        // Verify that all the nodes with large values do indeed have them ...
+        verifyNodesHaveLargeValues("/a/a1", "/a/a2", "/a/a2/a1");
+
+        // Count the number of objects ...
+        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(3L));
+        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(14L));
+        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(14L));
+
+        // Create references from the "/a/a2" (not being deleted) branch, to the branch being deleted...
+        List<ReferenceEntity> expectedInvalidRefs = new ArrayList<ReferenceEntity>();
+        expectedInvalidRefs.add(createReferenceBetween("/a/a2", "/a/a1"));
+        expectedInvalidRefs.add(createReferenceBetween("/a/a2/a1", "/a/a1/a1"));
+        expectedInvalidRefs.add(createReferenceBetween("/a/a2/a2", "/a/a1/a2"));
+
+        // Create references between nodes in the branch being deleted (these shouldn't matter) ...
+        createReferenceBetween("/a/a1", "/a/a1/a1");
+        createReferenceBetween("/a/a1/a2", "/a/a1/a3");
+
+        // Delete "/a/a1". Note that "/a/a1" has a large value that is shared by "/a/a2", but it's also the only
+        // user of large value #1.
+        Path path = path("/a/a1");
+        UUID uuid = uuidByPath.get(path);
+
+        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNoMoreLocations();
+        query.deleteSubgraph(true);
+
+        // Now there should be invalid references ...
+        List<ReferenceEntity> invalidReferences = query.getInwardReferences();
+        assertThat(invalidReferences.size(), is(3));
+        invalidReferences.removeAll(invalidReferences);
+        assertThat(invalidReferences.size(), is(0));
+        query.close();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldDeleteSubgraphThatHasInternalReferences() throws Exception {
+        // Verify that all the nodes with large values do indeed have them ...
+        verifyNodesHaveLargeValues("/a/a1", "/a/a2", "/a/a2/a1");
+
+        // Count the number of objects ...
+        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(3L));
+        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(14L));
+        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(14L));
+
+        // Create references from the nodes that aren't being deleted (these won't matter, but will remain)...
+        List<ReferenceEntity> expectedValidRefs = new ArrayList<ReferenceEntity>();
+        expectedValidRefs.add(createReferenceBetween("/a/a2", "/a/a2/a1"));
+
+        // Create references between nodes in the branch being deleted (these shouldn't matter) ...
+        createReferenceBetween("/a/a1", "/a/a1/a1");
+        createReferenceBetween("/a/a1/a2", "/a/a1/a3");
+
+        // Delete "/a/a1". Note that "/a/a1" has a large value that is shared by "/a/a2", but it's also the only
+        // user of large value #1.
+        Path path = path("/a/a1");
+        UUID uuid = uuidByPath.get(path);
+
+        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
+        locations = query.getNodeLocations(true, true);
+        verifyNextLocationIs("/a/a1");
+        verifyNextLocationIs("/a/a1/a1");
+        verifyNextLocationIs("/a/a1/a2");
+        verifyNextLocationIs("/a/a1/a3");
+        verifyNoMoreLocations();
+        query.deleteSubgraph(true);
+
+        // Now there should be invalid references ...
+        List<ReferenceEntity> invalidReferences = query.getInwardReferences();
+        assertThat(invalidReferences.size(), is(0));
+        query.close();
+
+        // There should be no references any more ...
+        Query refQuery = manager.createQuery("select ref from ReferenceEntity as ref");
+        List<ReferenceEntity> remainingReferences = refQuery.getResultList();
+        assertThat(remainingReferences.size(), is(1));
+        remainingReferences.removeAll(expectedValidRefs);
+        assertThat(remainingReferences.size(), is(0));
+    }
+
+    @Test
+    public void shouldGetVariousReferencesRelatedToSubgraph() throws Exception {
+        // Verify that all the nodes with large values do indeed have them ...
+        verifyNodesHaveLargeValues("/a/a1", "/a/a2", "/a/a2/a1");
+
+        // Count the number of objects ...
+        assertThat((Long)manager.createQuery("select count(*) from LargeValueEntity").getSingleResult(), is(3L));
+        assertThat((Long)manager.createQuery("select count(*) from PropertiesEntity").getSingleResult(), is(14L));
+        assertThat((Long)manager.createQuery("select count(*) from ChildEntity").getSingleResult(), is(14L));
+
+        // Create references from the nodes that aren't even part of the subgraph ...
+        List<ReferenceEntity> otherRefs = new ArrayList<ReferenceEntity>();
+        otherRefs.add(createReferenceBetween("/a/a2", "/a/a2/a1"));
+        otherRefs.add(createReferenceBetween("/a/a2/a1", "/a/a2/a2"));
+
+        // Create references between nodes in the subgraph ...
+        List<ReferenceEntity> internalRefs = new ArrayList<ReferenceEntity>();
+        internalRefs.add(createReferenceBetween("/a/a1", "/a/a1/a1"));
+        internalRefs.add(createReferenceBetween("/a/a1/a2", "/a/a1/a3"));
+
+        // Create references from nodes outside of the subgraph to nodes inside of the subgraph ...
+        List<ReferenceEntity> inwardRefs = new ArrayList<ReferenceEntity>();
+        inwardRefs.add(createReferenceBetween("/a/a2", "/a/a1/a1"));
+        inwardRefs.add(createReferenceBetween("/a/a2/a1", "/a/a1/a3"));
+
+        // Create references from nodes inside of the subgraph to nodes outside of the subgraph ...
+        List<ReferenceEntity> outwardRefs = new ArrayList<ReferenceEntity>();
+        outwardRefs.add(createReferenceBetween("/a/a1", "/a/a2"));
+        outwardRefs.add(createReferenceBetween("/a/a1/a1", "/a/a2/a1"));
+
+        // Create the query ...
+        Path path = path("/a/a1");
+        UUID uuid = uuidByPath.get(path);
+        query = SubgraphQuery.create(context, manager, uuid, path, Integer.MAX_VALUE);
+
+        // Check the various kinds of references ...
+        List<ReferenceEntity> actualInternal = query.getInternalReferences();
+        List<ReferenceEntity> actualInward = query.getInwardReferences();
+        List<ReferenceEntity> actualOutward = query.getOutwardReferences();
+
+        assertThat(actualInternal.size(), is(internalRefs.size()));
+        actualInternal.removeAll(internalRefs);
+        assertThat(actualInternal.size(), is(0));
+
+        assertThat(actualInward.size(), is(inwardRefs.size()));
+        actualInward.removeAll(inwardRefs);
+        assertThat(actualInward.size(), is(0));
+
+        assertThat(actualOutward.size(), is(outwardRefs.size()));
+        actualOutward.removeAll(outwardRefs);
+        assertThat(actualOutward.size(), is(0));
+
+        query.close();
+    }
+
+}

Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/RequestProcessorCacheTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/RequestProcessorCacheTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/RequestProcessorCacheTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -31,11 +31,11 @@
 import java.util.UUID;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
 import org.junit.Before;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/SerializerTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/SerializerTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/SerializerTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -47,13 +47,13 @@
 import org.jboss.dna.common.util.StringUtil;
 import org.jboss.dna.connector.store.jpa.util.Serializer.ReferenceValues;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.PropertyType;
-import org.jboss.dna.graph.properties.Reference;
-import org.jboss.dna.graph.properties.ValueFactories;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.PropertyType;
+import org.jboss.dna.graph.property.Reference;
+import org.jboss.dna.graph.property.ValueFactories;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -475,7 +475,7 @@
         /**
          * {@inheritDoc}
          * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.properties.ValueFactories,
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.property.ValueFactories,
          *      byte[], long)
          */
         public Object read( ValueFactories valueFactories,
@@ -489,7 +489,7 @@
          * {@inheritDoc}
          * 
          * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#write(byte[], long,
-         *      org.jboss.dna.graph.properties.PropertyType, java.lang.Object)
+         *      org.jboss.dna.graph.property.PropertyType, java.lang.Object)
          */
         public void write( byte[] hash,
                            long length,
@@ -543,7 +543,7 @@
         /**
          * {@inheritDoc}
          * 
-         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.properties.ValueFactories,
+         * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#read(org.jboss.dna.graph.property.ValueFactories,
          *      byte[], long)
          */
         public Object read( ValueFactories valueFactories,
@@ -571,7 +571,7 @@
          * {@inheritDoc}
          * 
          * @see org.jboss.dna.connector.store.jpa.util.Serializer.LargeValues#write(byte[], long,
-         *      org.jboss.dna.graph.properties.PropertyType, java.lang.Object)
+         *      org.jboss.dna.graph.property.PropertyType, java.lang.Object)
          */
         public void write( byte[] hash,
                            long length,

Modified: trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryConnection.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryConnection.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryConnection.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -26,13 +26,13 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 import org.tmatesoft.svn.core.SVNErrorCode;
 import org.tmatesoft.svn.core.SVNErrorMessage;
 import org.tmatesoft.svn.core.SVNException;
@@ -148,7 +148,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#close()
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#close()
      */
     public void close() {
         // do not care about.
@@ -157,8 +157,8 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
-     *      org.jboss.dna.graph.requests.Request)
+     * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+     *      org.jboss.dna.graph.request.Request)
      */
     @SuppressWarnings( "unused" )
     public void execute( final ExecutionContext context,

Modified: trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryLexicon.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryLexicon.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryLexicon.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.connector.svn;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
 
 
 /**

Modified: trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -33,28 +33,28 @@
 import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.JcrNtLexicon;
 import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTimeFactory;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.requests.CopyBranchRequest;
-import org.jboss.dna.graph.requests.CreateNodeRequest;
-import org.jboss.dna.graph.requests.DeleteBranchRequest;
-import org.jboss.dna.graph.requests.MoveBranchRequest;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
-import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.requests.RemovePropertiesRequest;
-import org.jboss.dna.graph.requests.RenameNodeRequest;
-import org.jboss.dna.graph.requests.Request;
-import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.requests.processor.RequestProcessor;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTimeFactory;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.RemovePropertiesRequest;
+import org.jboss.dna.graph.request.RenameNodeRequest;
+import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.processor.RequestProcessor;
 import org.tmatesoft.svn.core.SVNDirEntry;
 import org.tmatesoft.svn.core.SVNException;
 import org.tmatesoft.svn.core.SVNNodeKind;
@@ -99,7 +99,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CopyBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CopyBranchRequest)
      */
     @Override
     public void process( CopyBranchRequest request ) {
@@ -111,7 +111,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.CreateNodeRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CreateNodeRequest)
      */
     @Override
     public void process( CreateNodeRequest request ) {
@@ -168,7 +168,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.DeleteBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.DeleteBranchRequest)
      */
     @Override
     public void process( DeleteBranchRequest request ) {
@@ -179,7 +179,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.MoveBranchRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.MoveBranchRequest)
      */
     @Override
     public void process( MoveBranchRequest request ) {
@@ -190,7 +190,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllChildrenRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
      */
     @SuppressWarnings( "unchecked" )
     @Override
@@ -251,7 +251,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadAllPropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllPropertiesRequest)
      */
     @Override
     public void process( ReadAllPropertiesRequest request ) {
@@ -329,7 +329,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.RemovePropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RemovePropertiesRequest)
      */
     @Override
     public void process( RemovePropertiesRequest request ) {
@@ -341,7 +341,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.RenameNodeRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RenameNodeRequest)
      */
     @Override
     public void process( RenameNodeRequest request ) {
@@ -353,7 +353,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.UpdatePropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.UpdatePropertiesRequest)
      */
     @Override
     public void process( UpdatePropertiesRequest request ) {

Modified: trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -44,11 +44,11 @@
 import org.jboss.dna.common.i18n.I18n;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceCapabilities;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryContext;
+import org.jboss.dna.graph.connector.RepositorySource;
+import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
+import org.jboss.dna.graph.connector.RepositorySourceException;
 import org.tmatesoft.svn.core.SVNException;
 import org.tmatesoft.svn.core.SVNURL;
 import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
@@ -125,7 +125,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getCapabilities()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
      */
     public RepositorySourceCapabilities getCapabilities() {
         return capabilities;
@@ -134,7 +134,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#initialize(org.jboss.dna.graph.connectors.RepositoryContext)
+     * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
      */
     public void initialize( RepositoryContext context ) throws RepositorySourceException {
         this.repositoryContext = context;
@@ -157,7 +157,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getRetryLimit()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
      */
     public int getRetryLimit() {
         return retryLimit.get();
@@ -166,7 +166,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#setRetryLimit(int)
+     * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
      */
     public void setRetryLimit( int limit ) {
         retryLimit.set(limit < 0 ? 0 : limit);
@@ -259,7 +259,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.connectors.RepositorySource#getConnection()
+     * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
      */
     public RepositoryConnection getConnection() throws RepositorySourceException {
         if (getName() == null) {

Modified: trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositoryConnectionTest.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositoryConnectionTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositoryConnectionTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -42,18 +42,18 @@
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.Node;
 import org.jboss.dna.graph.cache.CachePolicy;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
-import org.jboss.dna.graph.properties.Binary;
-import org.jboss.dna.graph.properties.DateTimeFactory;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PathNotFoundException;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueFactory;
-import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
+import org.jboss.dna.graph.connector.RepositorySourceListener;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTimeFactory;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositorySourceTest.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositorySourceTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositorySourceTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -39,7 +39,7 @@
 import javax.naming.Reference;
 import javax.naming.spi.ObjectFactory;
 import org.jboss.dna.graph.cache.BasicCachePolicy;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnection;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Deleted: trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/ApertureMimeTypeDetector.java
===================================================================
--- trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/ApertureMimeTypeDetector.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/ApertureMimeTypeDetector.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,56 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.mimetype;
-
-import java.io.IOException;
-import java.io.InputStream;
-import org.jboss.dna.graph.mimetype.MimeTypeDetector;
-import org.semanticdesktop.aperture.mime.identifier.MimeTypeIdentifier;
-import org.semanticdesktop.aperture.mime.identifier.magic.MagicMimeTypeIdentifier;
-import org.semanticdesktop.aperture.util.IOUtil;
-
-/**
- * @author jverhaeg
- */
-public class ApertureMimeTypeDetector implements MimeTypeDetector {
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @throws IOException
-     * @see org.jboss.dna.graph.mimetype.MimeTypeDetector#mimeTypeOf(java.lang.String, java.io.InputStream)
-     */
-    public String mimeTypeOf( String name,
-                              InputStream content ) throws IOException {
-        /*
-            MimeTypes identifier = TikaConfig.getDefaultConfig().getMimeRepository();
-            MimeTypeDetectors mimeType = identifier.getMimeType(path.getLastSegment().getName().getLocalName(), stream);
-            return mimeType == null ? null : mimeType.getName();
-        */
-        MimeTypeIdentifier identifier = new MagicMimeTypeIdentifier();
-        // Read as many bytes of the file as desired by the MIME-type identifier
-        int minimumArrayLength = identifier.getMinArrayLength();
-        byte[] bytes = IOUtil.readBytes(content, minimumArrayLength);
-        // let the MimeTypeIdentifier determine the MIME-type of this file
-        return identifier.identify(bytes, name, null);
-    }
-}

Copied: trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/aperture/ApertureMimeTypeDetector.java (from rev 705, trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/ApertureMimeTypeDetector.java)
===================================================================
--- trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/aperture/ApertureMimeTypeDetector.java	                        (rev 0)
+++ trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/aperture/ApertureMimeTypeDetector.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.mimetype.aperture;
+
+import java.io.IOException;
+import java.io.InputStream;
+import org.jboss.dna.graph.mimetype.MimeTypeDetector;
+import org.semanticdesktop.aperture.mime.identifier.MimeTypeIdentifier;
+import org.semanticdesktop.aperture.mime.identifier.magic.MagicMimeTypeIdentifier;
+import org.semanticdesktop.aperture.util.IOUtil;
+
+/**
+ * @author jverhaeg
+ */
+public class ApertureMimeTypeDetector implements MimeTypeDetector {
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @throws IOException
+     * @see org.jboss.dna.graph.mimetype.MimeTypeDetector#mimeTypeOf(java.lang.String, java.io.InputStream)
+     */
+    public String mimeTypeOf( String name,
+                              InputStream content ) throws IOException {
+        /*
+            MimeTypes identifier = TikaConfig.getDefaultConfig().getMimeRepository();
+            MimeTypeDetectors mimeType = identifier.getMimeType(path.getLastSegment().getName().getLocalName(), stream);
+            return mimeType == null ? null : mimeType.getName();
+        */
+        MimeTypeIdentifier identifier = new MagicMimeTypeIdentifier();
+        // Read as many bytes of the file as desired by the MIME-type identifier
+        int minimumArrayLength = identifier.getMinArrayLength();
+        byte[] bytes = IOUtil.readBytes(content, minimumArrayLength);
+        // let the MimeTypeIdentifier determine the MIME-type of this file
+        return identifier.identify(bytes, name, null);
+    }
+}


Property changes on: trunk/extensions/dna-mimetype-detector-aperture/src/main/java/org/jboss/dna/mimetype/aperture/ApertureMimeTypeDetector.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Deleted: trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/MimeTypeTest.java
===================================================================
--- trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/MimeTypeTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/MimeTypeTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,1661 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution For a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS For A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License For more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.mimetype;
-
-import java.io.FileNotFoundException;
-import org.jboss.dna.repository.mimetype.AbstractMimeTypeTest;
-import org.junit.Test;
-
-/**
- * @author jverhaeg
- */
-public class MimeTypeTest extends AbstractMimeTypeTest {
-
-    public MimeTypeTest() {
-        super(ApertureMimeTypeDetector.class);
-    }
-
-    @Override
-    protected String expectedMimeTypeForText_test_txt() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_ansi_txt()
-     */
-    @Override
-    protected String expectedMimeTypeForText_plain_text_ansi_txt() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_empty_txt()
-     */
-    @Override
-    protected String expectedMimeTypeForText_plain_text_empty_txt() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_txt()
-     */
-    @Override
-    protected String expectedMimeTypeForText_plain_text_txt() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_with_null_character_txt()
-     */
-    @Override
-    protected String expectedMimeTypeForText_plain_text_with_null_character_txt() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_utf16be_txt()
-     */
-    @Override
-    protected String expectedMimeTypeForText_plain_text_utf16be_txt() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_utf16le_txt()
-     */
-    @Override
-    protected String expectedMimeTypeForText_plain_text_utf16le_txt() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_utf8_txt()
-     */
-    @Override
-    protected String expectedMimeTypeForText_plain_text_utf8_txt() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_without_extension()
-     */
-    @Override
-    protected String expectedMimeTypeForText_plain_text_without_extension() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_rtf_staroffice_5_2_rtf()
-     */
-    @Override
-    protected String expectedMimeTypeForRtf_rtf_staroffice_5_2_rtf() {
-        return "text/rtf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_rtf_openoffice_2_0_rtf()
-     */
-    @Override
-    protected String expectedMimeTypeForRtf_rtf_openoffice_2_0_rtf() {
-        return "text/rtf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_rtf_word_2000_rtf()
-     */
-    @Override
-    protected String expectedMimeTypeForRtf_rtf_word_2000_rtf() {
-        return "text/rtf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_rtf_openoffice_1_1_5_rtf()
-     */
-    @Override
-    protected String expectedMimeTypeForRtf_rtf_openoffice_1_1_5_rtf() {
-        return "text/rtf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_test_rtf()
-     */
-    @Override
-    protected String expectedMimeTypeForRtf_test_rtf() {
-        return "text/rtf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_jingle3_mp3()
-     */
-    @Override
-    protected String expectedMimeTypeForMp3_jingle3_mp3() {
-        return "audio/mpeg";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_jingle1_mp3()
-     */
-    @Override
-    protected String expectedMimeTypeForMp3_jingle1_mp3() {
-        return "audio/mpeg";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_jingle2_mp3()
-     */
-    @Override
-    protected String expectedMimeTypeForMp3_jingle2_mp3() {
-        return "audio/mpeg";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_test_128_44_jstereo_mp3()
-     */
-    @Override
-    protected String expectedMimeTypeForMp3_test_128_44_jstereo_mp3() {
-        return "audio/mpeg";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_test_mp3()
-     */
-    @Override
-    protected String expectedMimeTypeForMp3_test_mp3() {
-        return "audio/mpeg";
-    }
-
-    @Override
-    public String expectedMimeTypeForWav() {
-        return "audio/x-wav";
-    }
-
-    @Override
-    public String expectedMimeTypeForBmp() {
-        return "image/bmp";
-    }
-
-    @Override
-    public String expectedMimeTypeForGif() {
-        return "image/gif";
-    }
-
-    @Override
-    public String expectedMimeTypeForIcon() {
-        return "image/x-icon";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_jpg_geotagged_jpg()
-     */
-    @Override
-    protected String expectedMimeTypeForJpeg_jpg_geotagged_jpg() {
-        return "image/jpeg";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_jpg_exif_zerolength_jpg()
-     */
-    @Override
-    protected String expectedMimeTypeForJpeg_jpg_exif_zerolength_jpg() {
-        return "image/jpeg";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_jpg_geotagged_ipanema_jpg()
-     */
-    @Override
-    protected String expectedMimeTypeForJpeg_jpg_geotagged_ipanema_jpg() {
-        return "image/jpeg";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_jpg_exif_img_9367_JPG()
-     */
-    @Override
-    protected String expectedMimeTypeForJpeg_jpg_exif_img_9367_JPG() {
-        return "image/jpeg";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_test_jpg()
-     */
-    @Override
-    protected String expectedMimeTypeForJpeg_test_jpg() {
-        return "image/jpeg";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPortablePixelMap_test_ppm()
-     */
-    @Override
-    protected String expectedMimeTypeForPortablePixelMap_test_ppm() {
-        return "image/x-portable-pixmap";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPortablePixelMap_test_pnm()
-     */
-    @Override
-    protected String expectedMimeTypeForPortablePixelMap_test_pnm() {
-        return "image/x-portable-pixmap";
-    }
-
-    @Override
-    public String expectedMimeTypeForPng() {
-        return "image/png";
-    }
-
-    @Override
-    public String expectedMimeTypeForTiff() {
-        return "image/tiff";
-    }
-
-    @Override
-    public String expectedMimeTypeForTga() {
-        return "image/x-tga";
-    }
-
-    @Override
-    public String expectedMimeTypeForWmf() {
-        return "image/wmf";
-    }
-
-    @Override
-    public String expectedMimeTypeForXcf() {
-        return "image/xcf";
-    }
-
-    @Override
-    public String expectedMimeTypeForXpm() {
-        return "image/xpm";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_utf8_bom()
-     */
-    @Override
-    protected String expectedMimeTypeForXml_xml_utf8_bom() {
-        return "text/xml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_CurrencyFormatterExample_mxml()
-     */
-    @Override
-    protected String expectedMimeTypeForXml_CurrencyFormatterExample_mxml() {
-        return "text/xml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_test_excel_spreadsheet_xml()
-     */
-    @Override
-    protected String expectedMimeTypeForXml_test_excel_spreadsheet_xml() {
-        return "text/xml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_test_xml()
-     */
-    @Override
-    protected String expectedMimeTypeForXml_test_xml() {
-        return "text/xml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_handwritten_xml()
-     */
-    @Override
-    protected String expectedMimeTypeForXml_xml_handwritten_xml() {
-        return "text/xml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_nonexistent_dtd_xml()
-     */
-    @Override
-    protected String expectedMimeTypeForXml_xml_nonexistent_dtd_xml() {
-        return "text/xml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_nonexistent_remote_dtd_xml()
-     */
-    @Override
-    protected String expectedMimeTypeForXml_xml_nonexistent_remote_dtd_xml() {
-        return "text/xml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_nonexistent_remote_xsd_xml()
-     */
-    @Override
-    protected String expectedMimeTypeForXml_xml_nonexistent_remote_xsd_xml() {
-        return "text/xml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_nonexistent_xsd_xml()
-     */
-    @Override
-    protected String expectedMimeTypeForXml_xml_nonexistent_xsd_xml() {
-        return "text/xml";
-    }
-
-    @Override
-    public String expectedMimeTypeForXsd() {
-        return "text/xml";
-    }
-
-    @Override
-    public String expectedMimeTypeForDtd() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_condenast_html()
-     */
-    @Override
-    protected String expectedMimeTypeForHtml_html_condenast_html() {
-        return "text/html";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_handwritten_html()
-     */
-    @Override
-    protected String expectedMimeTypeForHtml_html_handwritten_html() {
-        return "text/html";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_handwritten_with_wrong_file_extension_txt()
-     */
-    @Override
-    protected String expectedMimeTypeForHtml_html_handwritten_with_wrong_file_extension_txt() {
-        return "text/html";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_quelle_de_html()
-     */
-    @Override
-    protected String expectedMimeTypeForHtml_html_quelle_de_html() {
-        return "text/html";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_utf16_leading_whitespace_wrong_extension_doc()
-     */
-    @Override
-    protected String expectedMimeTypeForHtml_html_utf16_leading_whitespace_wrong_extension_doc() {
-        return "text/html";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_master_xml()
-     */
-    @Override
-    protected String expectedMimeTypeForHtml_master_xml() {
-        return "text/html";
-    }
-
-    @Override
-    public String expectedMimeTypeForJava() {
-        return "text/java";
-    }
-
-    @Override
-    public String expectedMimeTypeFor1_2Class() {
-        return "application/x-java-class";
-    }
-
-    @Override
-    public String expectedMimeTypeFor1_3Class() {
-        return "application/x-java-class";
-    }
-
-    @Override
-    public String expectedMimeTypeFor1_4Class() {
-        return "application/x-java-class";
-    }
-
-    @Override
-    public String expectedMimeTypeForPerl() {
-        return "text/plain";
-    }
-
-    @Override
-    public String expectedMimeTypeForPython() {
-        return "text/plain";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_test_pdf()
-     */
-    @Override
-    protected String expectedMimeTypeForPdf_test_pdf() {
-        return "application/pdf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_no_author_pdf()
-     */
-    @Override
-    protected String expectedMimeTypeForPdf_pdf_no_author_pdf() {
-        return "application/pdf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_openoffice_1_1_5_writer_pdf()
-     */
-    @Override
-    protected String expectedMimeTypeForPdf_pdf_openoffice_1_1_5_writer_pdf() {
-        return "application/pdf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_openoffice_2_0_writer_pdf()
-     */
-    @Override
-    protected String expectedMimeTypeForPdf_pdf_openoffice_2_0_writer_pdf() {
-        return "application/pdf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_word_2000_pdfcreator_0_8_0_pdf()
-     */
-    @Override
-    protected String expectedMimeTypeForPdf_pdf_word_2000_pdfcreator_0_8_0_pdf() {
-        return "application/pdf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_word_2000_pdfmaker_7_0_pdf()
-     */
-    @Override
-    protected String expectedMimeTypeForPdf_pdf_word_2000_pdfmaker_7_0_pdf() {
-        return "application/pdf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_word_2000_pdfwriter_7_0_pdf()
-     */
-    @Override
-    protected String expectedMimeTypeForPdf_pdf_word_2000_pdfwriter_7_0_pdf() {
-        return "application/pdf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_distiller_6_weirdchars_pdf()
-     */
-    @Override
-    protected String expectedMimeTypeForPdf_pdf_distiller_6_weirdchars_pdf() {
-        return "application/pdf";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPostscript_test_eps()
-     */
-    @Override
-    protected String expectedMimeTypeForPostscript_test_eps() {
-        return "application/postscript";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPostscript_test_ps()
-     */
-    @Override
-    protected String expectedMimeTypeForPostscript_test_ps() {
-        return "application/postscript";
-    }
-
-    @Override
-    public String expectedMimeTypeForJar() {
-        return "application/java-archive";
-    }
-
-    @Override
-    public String expectedMimeTypeForJavaManifest() {
-        return "application/x-java-manifest";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForGZip_test_tar_gz()
-     */
-    @Override
-    protected String expectedMimeTypeForGZip_test_tar_gz() {
-        return "application/gzip";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForGZip_test_txt_gz()
-     */
-    @Override
-    protected String expectedMimeTypeForGZip_test_txt_gz() {
-        return "application/gzip";
-    }
-
-    @Override
-    public String expectedMimeTypeForZip() {
-        return "application/zip";
-    }
-
-    @Override
-    public String expectedMimeTypeForBash() {
-        return "application/x-bash";
-    }
-
-    @Override
-    public String expectedMimeTypeForOgg() {
-        return "application/x-ogg";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenDocumentFormula() {
-        return "application/vnd.oasis.opendocument.formula";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenDocumentGraphics() {
-        return "application/vnd.oasis.opendocument.graphics";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenDocumentGraphicsTemplate() {
-        return "application/vnd.oasis.opendocument.graphics-template";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForOpenDocumentPresentation_openoffice_2_0_impress_odp()
-     */
-    @Override
-    protected String expectedMimeTypeForOpenDocumentPresentation_openoffice_2_0_impress_odp() {
-        return "application/vnd.oasis.opendocument.presentation";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForOpenDocumentPresentation_component_architecture_odp()
-     */
-    @Override
-    protected String expectedMimeTypeForOpenDocumentPresentation_component_architecture_odp() {
-        return "application/vnd.oasis.opendocument.presentation";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenDocumentPresentationTemplate() {
-        return "application/vnd.oasis.opendocument.presentation-template";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenDocumentSpreadsheet() {
-        return "application/vnd.oasis.opendocument.spreadsheet";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenDocumentSpreadsheetTemplate() {
-        return "application/vnd.oasis.opendocument.spreadsheet-template";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenDocumentText() {
-        return "application/vnd.oasis.opendocument.text";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenDocumentTextTemplate() {
-        return "application/vnd.oasis.opendocument.text-template";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenOfficeCalc() {
-        return "application/vnd.sun.xml.calc";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenOfficeCalcTemplate() {
-        return "application/vnd.sun.xml.calc.template";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenOfficeDraw() {
-        return "application/vnd.sun.xml.draw";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenOfficeDrawTemplate() {
-        return "application/vnd.sun.xml.draw.template";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenOfficeImpress() {
-        return "application/vnd.sun.xml.impress";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenOfficeImpressTemplate() {
-        return "application/vnd.sun.xml.impress.template";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenOfficeWriter() {
-        return "application/vnd.sun.xml.writer";
-    }
-
-    @Override
-    public String expectedMimeTypeForOpenOfficeWriterTemplate() {
-        return "application/vnd.sun.xml.writer.template";
-    }
-
-    @Override
-    public String expectedMimeTypeForStarOfficeCalc() {
-        return "application/vnd.stardivision.calc";
-    }
-
-    @Override
-    public String expectedMimeTypeForStarOfficeDraw() {
-        return "application/vnd.stardivision.draw";
-    }
-
-    @Override
-    public String expectedMimeTypeForStarOfficeImpress() {
-        return "application/vnd.stardivision.impress";
-    }
-
-    @Override
-    public String expectedMimeTypeForStarOfficeWriter() {
-        return "application/vnd.stardivision.writer";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForStarOfficeWriterTemplate()
-     */
-    @Override
-    protected String expectedMimeTypeForStarOfficeWriterTemplate() {
-        return "application/vnd.ms-office";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForStarOfficeCalcTemplate()
-     */
-    @Override
-    protected String expectedMimeTypeForStarOfficeCalcTemplate() {
-        return "application/vnd.ms-office";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForStarOfficeDrawTemplate()
-     */
-    @Override
-    protected String expectedMimeTypeForStarOfficeDrawTemplate() {
-        return "application/vnd.ms-office";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForStarOfficeImpressTemplate()
-     */
-    @Override
-    protected String expectedMimeTypeForStarOfficeImpressTemplate() {
-        return "application/vnd.ms-office";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_test_word_2000_doc()
-     */
-    @Override
-    protected String expectedMimeTypeForWord_test_word_2000_doc() {
-        return "application/vnd.ms-word";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_test_word_6_0_95_doc()
-     */
-    @Override
-    protected String expectedMimeTypeForWord_test_word_6_0_95_doc() {
-        return "application/vnd.ms-word";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2000_doc()
-     */
-    @Override
-    protected String expectedMimeTypeForWord_microsoft_word_2000_doc() {
-        return "application/vnd.ms-word";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2000_with_wrong_file_extension_pdf()
-     */
-    @Override
-    protected String expectedMimeTypeForWord_microsoft_word_2000_with_wrong_file_extension_pdf() {
-        return "application/vnd.ms-office";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2007beta2_dotx()
-     */
-    @Override
-    protected String expectedMimeTypeForWord_microsoft_word_2007beta2_dotx() {
-        return "application/vnd.openxmlformats-officedocument.wordprocessingml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2007beta2_docm()
-     */
-    @Override
-    protected String expectedMimeTypeForWord_microsoft_word_2007beta2_docm() {
-        return "application/vnd.openxmlformats-officedocument.wordprocessingml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2007beta2_docx()
-     */
-    @Override
-    protected String expectedMimeTypeForWord_microsoft_word_2007beta2_docx() {
-        return "application/vnd.openxmlformats-officedocument.wordprocessingml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2007beta2_dotm()
-     */
-    @Override
-    protected String expectedMimeTypeForWord_microsoft_word_2007beta2_dotm() {
-        return "application/vnd.openxmlformats-officedocument.wordprocessingml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_spreadsheet_4_0_2000_wks()
-     */
-    @Override
-    protected String expectedMimeTypeForWorks_microsoft_works_spreadsheet_4_0_2000_wks() {
-        return "application/vnd.ms-works";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_word_processor_7_0_wps()
-     */
-    @Override
-    protected String expectedMimeTypeForWorks_microsoft_works_word_processor_7_0_wps() {
-        return "application/vnd.ms-works";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_spreadsheet_7_0_xlr()
-     */
-    @Override
-    protected String expectedMimeTypeForWorks_microsoft_works_spreadsheet_7_0_xlr() {
-        return "application/vnd.ms-works";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_word_processor_2000_wps()
-     */
-    @Override
-    protected String expectedMimeTypeForWorks_microsoft_works_word_processor_2000_wps() {
-        return "application/vnd.ms-works";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_word_processor_4_0_wps()
-     */
-    @Override
-    protected String expectedMimeTypeForWorks_microsoft_works_word_processor_4_0_wps() {
-        return "application/vnd.ms-works";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_word_processor_3_0_wps()
-     */
-    @Override
-    protected String expectedMimeTypeForWorks_microsoft_works_word_processor_3_0_wps() {
-        return "application/vnd.ms-works";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorkbook_corel_quattro_pro_6_wb2()
-     */
-    @Override
-    protected String expectedMimeTypeForWorkbook_corel_quattro_pro_6_wb2() {
-        return "application/wb2";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorkbook_microsoft_works_spreadsheet_3_0_wks()
-     */
-    @Override
-    protected String expectedMimeTypeForWorkbook_microsoft_works_spreadsheet_3_0_wks() {
-        return "application/wb2";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_test_excel_2000_xls()
-     */
-    @Override
-    protected String expectedMimeTypeForExcel_test_excel_2000_xls() {
-        return "application/vnd.ms-excel";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xltx()
-     */
-    @Override
-    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xltx() {
-        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2000_xls()
-     */
-    @Override
-    protected String expectedMimeTypeForExcel_microsoft_excel_2000_xls() {
-        return "application/vnd.ms-excel";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlam()
-     */
-    @Override
-    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlam() {
-        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xltm()
-     */
-    @Override
-    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xltm() {
-        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsx()
-     */
-    @Override
-    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsx() {
-        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsb()
-     */
-    @Override
-    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsb() {
-        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsm()
-     */
-    @Override
-    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsm() {
-        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_potm()
-     */
-    @Override
-    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_potm() {
-        return "application/vnd.openxmlformats-officedocument.presentationml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_ppsm()
-     */
-    @Override
-    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_ppsm() {
-        return "application/vnd.openxmlformats-officedocument.presentationml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_pptm()
-     */
-    @Override
-    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_pptm() {
-        return "application/vnd.openxmlformats-officedocument.presentationml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_pptx()
-     */
-    @Override
-    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_pptx() {
-        return "application/vnd.openxmlformats-officedocument.presentationml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_potx()
-     */
-    @Override
-    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_potx() {
-        return "application/vnd.openxmlformats-officedocument.presentationml";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2000_ppt()
-     */
-    @Override
-    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2000_ppt() {
-        return "application/vnd.ms-powerpoint";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_test_ppt()
-     */
-    @Override
-    protected String expectedMimeTypeForPowerpoint_test_ppt() {
-        return "application/vnd.ms-powerpoint";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_ppsx()
-     */
-    @Override
-    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_ppsx() {
-        return "application/vnd.openxmlformats-officedocument.presentationml";
-    }
-
-    @Override
-    public String expectedMimeTypeForPublisher() {
-        return "application/x-mspublisher";
-    }
-
-    @Override
-    public String expectedMimeTypeForVisio() {
-        return "application/vnd.visio";
-    }
-
-    @Override
-    public String expectedMimeTypeForOutlook() {
-        return "application/vnd.ms-outlook";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForShw_corel_presentations_3_0_shw()
-     */
-    @Override
-    protected String expectedMimeTypeForShw_corel_presentations_3_0_shw() {
-        return "application/presentations";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForShw_corel_presentations_x3_shw()
-     */
-    @Override
-    protected String expectedMimeTypeForShw_corel_presentations_x3_shw() {
-        return "application/presentations";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPro_corel_quattro_pro_7_wb3()
-     */
-    @Override
-    protected String expectedMimeTypeForPro_corel_quattro_pro_7_wb3() {
-        return "application/x-quattropro";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPro_corel_quattro_pro_x3_qpw()
-     */
-    @Override
-    protected String expectedMimeTypeForPro_corel_quattro_pro_x3_qpw() {
-        return "application/x-quattropro";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_x3_wpd()
-     */
-    @Override
-    protected String expectedMimeTypeForWordperfect_corel_wordperfect_x3_wpd() {
-        return "application/vnd.wordperfect";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_4_2_wp()
-     */
-    @Override
-    protected String expectedMimeTypeForWordperfect_corel_wordperfect_4_2_wp() {
-        return "application/vnd.wordperfect";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_5_0_wp()
-     */
-    @Override
-    protected String expectedMimeTypeForWordperfect_corel_wordperfect_5_0_wp() {
-        return "application/vnd.wordperfect";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_5_1_far_east_wp()
-     */
-    @Override
-    protected String expectedMimeTypeForWordperfect_corel_wordperfect_5_1_far_east_wp() {
-        return "application/vnd.wordperfect";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_5_1_wp()
-     */
-    @Override
-    protected String expectedMimeTypeForWordperfect_corel_wordperfect_5_1_wp() {
-        return "application/vnd.wordperfect";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMail_test_excel_web_archive_mht()
-     */
-    @Override
-    protected String expectedMimeTypeForMail_test_excel_web_archive_mht() {
-        return "message/rfc822";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMail_mail_thunderbird_1_5_eml()
-     */
-    @Override
-    protected String expectedMimeTypeForMail_mail_thunderbird_1_5_eml() {
-        return "message/rfc822";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMail_mhtml_firefox_mht()
-     */
-    @Override
-    protected String expectedMimeTypeForMail_mhtml_firefox_mht() {
-        return "message/rfc822";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMail_mhtml_internet_explorer_mht()
-     */
-    @Override
-    protected String expectedMimeTypeForMail_mhtml_internet_explorer_mht() {
-        return "message/rfc822";
-    }
-
-    @Override
-    public String expectedMimeTypeForAddressBook() {
-        return "application/x-mozilla-addressbook";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_vCards_SAP_vcf()
-     */
-    @Override
-    protected String expectedMimeTypeForVCard_vcard_vCards_SAP_vcf() {
-        return "text/x-vcard";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_antoni_kontact_vcf()
-     */
-    @Override
-    protected String expectedMimeTypeForVCard_vcard_antoni_kontact_vcf() {
-        return "text/x-vcard";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_antoni_outlook2003_vcf()
-     */
-    @Override
-    protected String expectedMimeTypeForVCard_vcard_antoni_outlook2003_vcf() {
-        return "text/x-vcard";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_dirk_vcf()
-     */
-    @Override
-    protected String expectedMimeTypeForVCard_vcard_dirk_vcf() {
-        return "text/x-vcard";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_rfc2426_vcf()
-     */
-    @Override
-    protected String expectedMimeTypeForVCard_vcard_rfc2426_vcf() {
-        return "text/x-vcard";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_Todos1_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_Todos1_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_basicCalendar_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_basicCalendar_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_1_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_cal01_1_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_2_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_cal01_2_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_3_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_cal01_3_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_4_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_cal01_4_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_5_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_cal01_5_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_6_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_cal01_6_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_exrule_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_cal01_exrule_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_cal01_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_calconnect7_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_calconnect7_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_calconnect9_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_calconnect9_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_combined_multiplevcalendar_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_combined_multiplevcalendar_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_combined_onevcalendar_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_combined_onevcalendar_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_extendedCalendar_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_extendedCalendar_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_freebusy_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_freebusy_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_geol_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_geol_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_gkexample_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_gkexample_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_incoming_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_incoming_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_korganizer_jicaltest_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_korganizer_jicaltest_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_korganizer_jicaltest_vjournal_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_korganizer_jicaltest_vjournal_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_php_flp_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_php_flp_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_simplevevent_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_simplevevent_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_sunbird_sample_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_sunbird_sample_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_tag_bug_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_tag_bug_ics() {
-        return "text/calendar";
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_test_created_ics()
-     */
-    @Override
-    protected String expectedMimeTypeForCalendar_test_created_ics() {
-        return "text/calendar";
-    }
-
-    @Override
-    public String expectedMimeTypeForAu() {
-        return "application/octet-stream";
-    }
-
-    @Override
-    public String expectedMimeTypeForBin() {
-        return "application/octet-stream";
-    }
-
-    @Override
-    public String expectedMimeTypeForEmf() {
-        return "application/octet-stream";
-    }
-
-    @Override
-    public String expectedMimeTypeForFli() {
-        return "application/octet-stream";
-    }
-
-    @Override
-    public String expectedMimeTypeForPcx() {
-        return "application/octet-stream";
-    }
-
-    @Override
-    public String expectedMimeTypeForPict() {
-        return "application/octet-stream";
-    }
-
-    @Override
-    public String expectedMimeTypeForPsd() {
-        return "application/octet-stream";
-    }
-
-    @Override
-    public String expectedMimeTypeForTar() {
-        return "application/octet-stream";
-    }
-
-    @Test( expected = FileNotFoundException.class )
-    public void shouldFailIfFileNotFound() throws Exception {
-        testMimeType("missing.file", "");
-    }
-}

Copied: trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/aperture/MimeTypeTest.java (from rev 705, trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/MimeTypeTest.java)
===================================================================
--- trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/aperture/MimeTypeTest.java	                        (rev 0)
+++ trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/aperture/MimeTypeTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,1662 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution For a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS For A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License For more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.mimetype.aperture;
+
+import java.io.FileNotFoundException;
+import org.jboss.dna.mimetype.aperture.ApertureMimeTypeDetector;
+import org.jboss.dna.repository.mimetype.AbstractMimeTypeTest;
+import org.junit.Test;
+
+/**
+ * @author jverhaeg
+ */
+public class MimeTypeTest extends AbstractMimeTypeTest {
+
+    public MimeTypeTest() {
+        super(ApertureMimeTypeDetector.class);
+    }
+
+    @Override
+    protected String expectedMimeTypeForText_test_txt() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_ansi_txt()
+     */
+    @Override
+    protected String expectedMimeTypeForText_plain_text_ansi_txt() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_empty_txt()
+     */
+    @Override
+    protected String expectedMimeTypeForText_plain_text_empty_txt() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_txt()
+     */
+    @Override
+    protected String expectedMimeTypeForText_plain_text_txt() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_with_null_character_txt()
+     */
+    @Override
+    protected String expectedMimeTypeForText_plain_text_with_null_character_txt() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_utf16be_txt()
+     */
+    @Override
+    protected String expectedMimeTypeForText_plain_text_utf16be_txt() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_utf16le_txt()
+     */
+    @Override
+    protected String expectedMimeTypeForText_plain_text_utf16le_txt() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_utf8_txt()
+     */
+    @Override
+    protected String expectedMimeTypeForText_plain_text_utf8_txt() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForText_plain_text_without_extension()
+     */
+    @Override
+    protected String expectedMimeTypeForText_plain_text_without_extension() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_rtf_staroffice_5_2_rtf()
+     */
+    @Override
+    protected String expectedMimeTypeForRtf_rtf_staroffice_5_2_rtf() {
+        return "text/rtf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_rtf_openoffice_2_0_rtf()
+     */
+    @Override
+    protected String expectedMimeTypeForRtf_rtf_openoffice_2_0_rtf() {
+        return "text/rtf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_rtf_word_2000_rtf()
+     */
+    @Override
+    protected String expectedMimeTypeForRtf_rtf_word_2000_rtf() {
+        return "text/rtf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_rtf_openoffice_1_1_5_rtf()
+     */
+    @Override
+    protected String expectedMimeTypeForRtf_rtf_openoffice_1_1_5_rtf() {
+        return "text/rtf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForRtf_test_rtf()
+     */
+    @Override
+    protected String expectedMimeTypeForRtf_test_rtf() {
+        return "text/rtf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_jingle3_mp3()
+     */
+    @Override
+    protected String expectedMimeTypeForMp3_jingle3_mp3() {
+        return "audio/mpeg";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_jingle1_mp3()
+     */
+    @Override
+    protected String expectedMimeTypeForMp3_jingle1_mp3() {
+        return "audio/mpeg";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_jingle2_mp3()
+     */
+    @Override
+    protected String expectedMimeTypeForMp3_jingle2_mp3() {
+        return "audio/mpeg";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_test_128_44_jstereo_mp3()
+     */
+    @Override
+    protected String expectedMimeTypeForMp3_test_128_44_jstereo_mp3() {
+        return "audio/mpeg";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMp3_test_mp3()
+     */
+    @Override
+    protected String expectedMimeTypeForMp3_test_mp3() {
+        return "audio/mpeg";
+    }
+
+    @Override
+    public String expectedMimeTypeForWav() {
+        return "audio/x-wav";
+    }
+
+    @Override
+    public String expectedMimeTypeForBmp() {
+        return "image/bmp";
+    }
+
+    @Override
+    public String expectedMimeTypeForGif() {
+        return "image/gif";
+    }
+
+    @Override
+    public String expectedMimeTypeForIcon() {
+        return "image/x-icon";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_jpg_geotagged_jpg()
+     */
+    @Override
+    protected String expectedMimeTypeForJpeg_jpg_geotagged_jpg() {
+        return "image/jpeg";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_jpg_exif_zerolength_jpg()
+     */
+    @Override
+    protected String expectedMimeTypeForJpeg_jpg_exif_zerolength_jpg() {
+        return "image/jpeg";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_jpg_geotagged_ipanema_jpg()
+     */
+    @Override
+    protected String expectedMimeTypeForJpeg_jpg_geotagged_ipanema_jpg() {
+        return "image/jpeg";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_jpg_exif_img_9367_JPG()
+     */
+    @Override
+    protected String expectedMimeTypeForJpeg_jpg_exif_img_9367_JPG() {
+        return "image/jpeg";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForJpeg_test_jpg()
+     */
+    @Override
+    protected String expectedMimeTypeForJpeg_test_jpg() {
+        return "image/jpeg";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPortablePixelMap_test_ppm()
+     */
+    @Override
+    protected String expectedMimeTypeForPortablePixelMap_test_ppm() {
+        return "image/x-portable-pixmap";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPortablePixelMap_test_pnm()
+     */
+    @Override
+    protected String expectedMimeTypeForPortablePixelMap_test_pnm() {
+        return "image/x-portable-pixmap";
+    }
+
+    @Override
+    public String expectedMimeTypeForPng() {
+        return "image/png";
+    }
+
+    @Override
+    public String expectedMimeTypeForTiff() {
+        return "image/tiff";
+    }
+
+    @Override
+    public String expectedMimeTypeForTga() {
+        return "image/x-tga";
+    }
+
+    @Override
+    public String expectedMimeTypeForWmf() {
+        return "image/wmf";
+    }
+
+    @Override
+    public String expectedMimeTypeForXcf() {
+        return "image/xcf";
+    }
+
+    @Override
+    public String expectedMimeTypeForXpm() {
+        return "image/xpm";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_utf8_bom()
+     */
+    @Override
+    protected String expectedMimeTypeForXml_xml_utf8_bom() {
+        return "text/xml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_CurrencyFormatterExample_mxml()
+     */
+    @Override
+    protected String expectedMimeTypeForXml_CurrencyFormatterExample_mxml() {
+        return "text/xml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_test_excel_spreadsheet_xml()
+     */
+    @Override
+    protected String expectedMimeTypeForXml_test_excel_spreadsheet_xml() {
+        return "text/xml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_test_xml()
+     */
+    @Override
+    protected String expectedMimeTypeForXml_test_xml() {
+        return "text/xml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_handwritten_xml()
+     */
+    @Override
+    protected String expectedMimeTypeForXml_xml_handwritten_xml() {
+        return "text/xml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_nonexistent_dtd_xml()
+     */
+    @Override
+    protected String expectedMimeTypeForXml_xml_nonexistent_dtd_xml() {
+        return "text/xml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_nonexistent_remote_dtd_xml()
+     */
+    @Override
+    protected String expectedMimeTypeForXml_xml_nonexistent_remote_dtd_xml() {
+        return "text/xml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_nonexistent_remote_xsd_xml()
+     */
+    @Override
+    protected String expectedMimeTypeForXml_xml_nonexistent_remote_xsd_xml() {
+        return "text/xml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForXml_xml_nonexistent_xsd_xml()
+     */
+    @Override
+    protected String expectedMimeTypeForXml_xml_nonexistent_xsd_xml() {
+        return "text/xml";
+    }
+
+    @Override
+    public String expectedMimeTypeForXsd() {
+        return "text/xml";
+    }
+
+    @Override
+    public String expectedMimeTypeForDtd() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_condenast_html()
+     */
+    @Override
+    protected String expectedMimeTypeForHtml_html_condenast_html() {
+        return "text/html";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_handwritten_html()
+     */
+    @Override
+    protected String expectedMimeTypeForHtml_html_handwritten_html() {
+        return "text/html";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_handwritten_with_wrong_file_extension_txt()
+     */
+    @Override
+    protected String expectedMimeTypeForHtml_html_handwritten_with_wrong_file_extension_txt() {
+        return "text/html";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_quelle_de_html()
+     */
+    @Override
+    protected String expectedMimeTypeForHtml_html_quelle_de_html() {
+        return "text/html";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_html_utf16_leading_whitespace_wrong_extension_doc()
+     */
+    @Override
+    protected String expectedMimeTypeForHtml_html_utf16_leading_whitespace_wrong_extension_doc() {
+        return "text/html";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForHtml_master_xml()
+     */
+    @Override
+    protected String expectedMimeTypeForHtml_master_xml() {
+        return "text/html";
+    }
+
+    @Override
+    public String expectedMimeTypeForJava() {
+        return "text/java";
+    }
+
+    @Override
+    public String expectedMimeTypeFor1_2Class() {
+        return "application/x-java-class";
+    }
+
+    @Override
+    public String expectedMimeTypeFor1_3Class() {
+        return "application/x-java-class";
+    }
+
+    @Override
+    public String expectedMimeTypeFor1_4Class() {
+        return "application/x-java-class";
+    }
+
+    @Override
+    public String expectedMimeTypeForPerl() {
+        return "text/plain";
+    }
+
+    @Override
+    public String expectedMimeTypeForPython() {
+        return "text/plain";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_test_pdf()
+     */
+    @Override
+    protected String expectedMimeTypeForPdf_test_pdf() {
+        return "application/pdf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_no_author_pdf()
+     */
+    @Override
+    protected String expectedMimeTypeForPdf_pdf_no_author_pdf() {
+        return "application/pdf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_openoffice_1_1_5_writer_pdf()
+     */
+    @Override
+    protected String expectedMimeTypeForPdf_pdf_openoffice_1_1_5_writer_pdf() {
+        return "application/pdf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_openoffice_2_0_writer_pdf()
+     */
+    @Override
+    protected String expectedMimeTypeForPdf_pdf_openoffice_2_0_writer_pdf() {
+        return "application/pdf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_word_2000_pdfcreator_0_8_0_pdf()
+     */
+    @Override
+    protected String expectedMimeTypeForPdf_pdf_word_2000_pdfcreator_0_8_0_pdf() {
+        return "application/pdf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_word_2000_pdfmaker_7_0_pdf()
+     */
+    @Override
+    protected String expectedMimeTypeForPdf_pdf_word_2000_pdfmaker_7_0_pdf() {
+        return "application/pdf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_word_2000_pdfwriter_7_0_pdf()
+     */
+    @Override
+    protected String expectedMimeTypeForPdf_pdf_word_2000_pdfwriter_7_0_pdf() {
+        return "application/pdf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPdf_pdf_distiller_6_weirdchars_pdf()
+     */
+    @Override
+    protected String expectedMimeTypeForPdf_pdf_distiller_6_weirdchars_pdf() {
+        return "application/pdf";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPostscript_test_eps()
+     */
+    @Override
+    protected String expectedMimeTypeForPostscript_test_eps() {
+        return "application/postscript";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPostscript_test_ps()
+     */
+    @Override
+    protected String expectedMimeTypeForPostscript_test_ps() {
+        return "application/postscript";
+    }
+
+    @Override
+    public String expectedMimeTypeForJar() {
+        return "application/java-archive";
+    }
+
+    @Override
+    public String expectedMimeTypeForJavaManifest() {
+        return "application/x-java-manifest";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForGZip_test_tar_gz()
+     */
+    @Override
+    protected String expectedMimeTypeForGZip_test_tar_gz() {
+        return "application/gzip";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForGZip_test_txt_gz()
+     */
+    @Override
+    protected String expectedMimeTypeForGZip_test_txt_gz() {
+        return "application/gzip";
+    }
+
+    @Override
+    public String expectedMimeTypeForZip() {
+        return "application/zip";
+    }
+
+    @Override
+    public String expectedMimeTypeForBash() {
+        return "application/x-bash";
+    }
+
+    @Override
+    public String expectedMimeTypeForOgg() {
+        return "application/x-ogg";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenDocumentFormula() {
+        return "application/vnd.oasis.opendocument.formula";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenDocumentGraphics() {
+        return "application/vnd.oasis.opendocument.graphics";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenDocumentGraphicsTemplate() {
+        return "application/vnd.oasis.opendocument.graphics-template";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForOpenDocumentPresentation_openoffice_2_0_impress_odp()
+     */
+    @Override
+    protected String expectedMimeTypeForOpenDocumentPresentation_openoffice_2_0_impress_odp() {
+        return "application/vnd.oasis.opendocument.presentation";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForOpenDocumentPresentation_component_architecture_odp()
+     */
+    @Override
+    protected String expectedMimeTypeForOpenDocumentPresentation_component_architecture_odp() {
+        return "application/vnd.oasis.opendocument.presentation";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenDocumentPresentationTemplate() {
+        return "application/vnd.oasis.opendocument.presentation-template";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenDocumentSpreadsheet() {
+        return "application/vnd.oasis.opendocument.spreadsheet";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenDocumentSpreadsheetTemplate() {
+        return "application/vnd.oasis.opendocument.spreadsheet-template";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenDocumentText() {
+        return "application/vnd.oasis.opendocument.text";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenDocumentTextTemplate() {
+        return "application/vnd.oasis.opendocument.text-template";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenOfficeCalc() {
+        return "application/vnd.sun.xml.calc";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenOfficeCalcTemplate() {
+        return "application/vnd.sun.xml.calc.template";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenOfficeDraw() {
+        return "application/vnd.sun.xml.draw";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenOfficeDrawTemplate() {
+        return "application/vnd.sun.xml.draw.template";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenOfficeImpress() {
+        return "application/vnd.sun.xml.impress";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenOfficeImpressTemplate() {
+        return "application/vnd.sun.xml.impress.template";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenOfficeWriter() {
+        return "application/vnd.sun.xml.writer";
+    }
+
+    @Override
+    public String expectedMimeTypeForOpenOfficeWriterTemplate() {
+        return "application/vnd.sun.xml.writer.template";
+    }
+
+    @Override
+    public String expectedMimeTypeForStarOfficeCalc() {
+        return "application/vnd.stardivision.calc";
+    }
+
+    @Override
+    public String expectedMimeTypeForStarOfficeDraw() {
+        return "application/vnd.stardivision.draw";
+    }
+
+    @Override
+    public String expectedMimeTypeForStarOfficeImpress() {
+        return "application/vnd.stardivision.impress";
+    }
+
+    @Override
+    public String expectedMimeTypeForStarOfficeWriter() {
+        return "application/vnd.stardivision.writer";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForStarOfficeWriterTemplate()
+     */
+    @Override
+    protected String expectedMimeTypeForStarOfficeWriterTemplate() {
+        return "application/vnd.ms-office";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForStarOfficeCalcTemplate()
+     */
+    @Override
+    protected String expectedMimeTypeForStarOfficeCalcTemplate() {
+        return "application/vnd.ms-office";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForStarOfficeDrawTemplate()
+     */
+    @Override
+    protected String expectedMimeTypeForStarOfficeDrawTemplate() {
+        return "application/vnd.ms-office";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForStarOfficeImpressTemplate()
+     */
+    @Override
+    protected String expectedMimeTypeForStarOfficeImpressTemplate() {
+        return "application/vnd.ms-office";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_test_word_2000_doc()
+     */
+    @Override
+    protected String expectedMimeTypeForWord_test_word_2000_doc() {
+        return "application/vnd.ms-word";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_test_word_6_0_95_doc()
+     */
+    @Override
+    protected String expectedMimeTypeForWord_test_word_6_0_95_doc() {
+        return "application/vnd.ms-word";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2000_doc()
+     */
+    @Override
+    protected String expectedMimeTypeForWord_microsoft_word_2000_doc() {
+        return "application/vnd.ms-word";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2000_with_wrong_file_extension_pdf()
+     */
+    @Override
+    protected String expectedMimeTypeForWord_microsoft_word_2000_with_wrong_file_extension_pdf() {
+        return "application/vnd.ms-office";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2007beta2_dotx()
+     */
+    @Override
+    protected String expectedMimeTypeForWord_microsoft_word_2007beta2_dotx() {
+        return "application/vnd.openxmlformats-officedocument.wordprocessingml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2007beta2_docm()
+     */
+    @Override
+    protected String expectedMimeTypeForWord_microsoft_word_2007beta2_docm() {
+        return "application/vnd.openxmlformats-officedocument.wordprocessingml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2007beta2_docx()
+     */
+    @Override
+    protected String expectedMimeTypeForWord_microsoft_word_2007beta2_docx() {
+        return "application/vnd.openxmlformats-officedocument.wordprocessingml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWord_microsoft_word_2007beta2_dotm()
+     */
+    @Override
+    protected String expectedMimeTypeForWord_microsoft_word_2007beta2_dotm() {
+        return "application/vnd.openxmlformats-officedocument.wordprocessingml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_spreadsheet_4_0_2000_wks()
+     */
+    @Override
+    protected String expectedMimeTypeForWorks_microsoft_works_spreadsheet_4_0_2000_wks() {
+        return "application/vnd.ms-works";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_word_processor_7_0_wps()
+     */
+    @Override
+    protected String expectedMimeTypeForWorks_microsoft_works_word_processor_7_0_wps() {
+        return "application/vnd.ms-works";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_spreadsheet_7_0_xlr()
+     */
+    @Override
+    protected String expectedMimeTypeForWorks_microsoft_works_spreadsheet_7_0_xlr() {
+        return "application/vnd.ms-works";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_word_processor_2000_wps()
+     */
+    @Override
+    protected String expectedMimeTypeForWorks_microsoft_works_word_processor_2000_wps() {
+        return "application/vnd.ms-works";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_word_processor_4_0_wps()
+     */
+    @Override
+    protected String expectedMimeTypeForWorks_microsoft_works_word_processor_4_0_wps() {
+        return "application/vnd.ms-works";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorks_microsoft_works_word_processor_3_0_wps()
+     */
+    @Override
+    protected String expectedMimeTypeForWorks_microsoft_works_word_processor_3_0_wps() {
+        return "application/vnd.ms-works";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorkbook_corel_quattro_pro_6_wb2()
+     */
+    @Override
+    protected String expectedMimeTypeForWorkbook_corel_quattro_pro_6_wb2() {
+        return "application/wb2";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWorkbook_microsoft_works_spreadsheet_3_0_wks()
+     */
+    @Override
+    protected String expectedMimeTypeForWorkbook_microsoft_works_spreadsheet_3_0_wks() {
+        return "application/wb2";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_test_excel_2000_xls()
+     */
+    @Override
+    protected String expectedMimeTypeForExcel_test_excel_2000_xls() {
+        return "application/vnd.ms-excel";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xltx()
+     */
+    @Override
+    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xltx() {
+        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2000_xls()
+     */
+    @Override
+    protected String expectedMimeTypeForExcel_microsoft_excel_2000_xls() {
+        return "application/vnd.ms-excel";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlam()
+     */
+    @Override
+    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlam() {
+        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xltm()
+     */
+    @Override
+    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xltm() {
+        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsx()
+     */
+    @Override
+    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsx() {
+        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsb()
+     */
+    @Override
+    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsb() {
+        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsm()
+     */
+    @Override
+    protected String expectedMimeTypeForExcel_microsoft_excel_2007beta2_xlsm() {
+        return "application/vnd.openxmlformats-officedocument.spreadsheetml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_potm()
+     */
+    @Override
+    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_potm() {
+        return "application/vnd.openxmlformats-officedocument.presentationml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_ppsm()
+     */
+    @Override
+    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_ppsm() {
+        return "application/vnd.openxmlformats-officedocument.presentationml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_pptm()
+     */
+    @Override
+    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_pptm() {
+        return "application/vnd.openxmlformats-officedocument.presentationml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_pptx()
+     */
+    @Override
+    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_pptx() {
+        return "application/vnd.openxmlformats-officedocument.presentationml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_potx()
+     */
+    @Override
+    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_potx() {
+        return "application/vnd.openxmlformats-officedocument.presentationml";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2000_ppt()
+     */
+    @Override
+    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2000_ppt() {
+        return "application/vnd.ms-powerpoint";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_test_ppt()
+     */
+    @Override
+    protected String expectedMimeTypeForPowerpoint_test_ppt() {
+        return "application/vnd.ms-powerpoint";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_ppsx()
+     */
+    @Override
+    protected String expectedMimeTypeForPowerpoint_microsoft_powerpoint_2007beta2_ppsx() {
+        return "application/vnd.openxmlformats-officedocument.presentationml";
+    }
+
+    @Override
+    public String expectedMimeTypeForPublisher() {
+        return "application/x-mspublisher";
+    }
+
+    @Override
+    public String expectedMimeTypeForVisio() {
+        return "application/vnd.visio";
+    }
+
+    @Override
+    public String expectedMimeTypeForOutlook() {
+        return "application/vnd.ms-outlook";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForShw_corel_presentations_3_0_shw()
+     */
+    @Override
+    protected String expectedMimeTypeForShw_corel_presentations_3_0_shw() {
+        return "application/presentations";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForShw_corel_presentations_x3_shw()
+     */
+    @Override
+    protected String expectedMimeTypeForShw_corel_presentations_x3_shw() {
+        return "application/presentations";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPro_corel_quattro_pro_7_wb3()
+     */
+    @Override
+    protected String expectedMimeTypeForPro_corel_quattro_pro_7_wb3() {
+        return "application/x-quattropro";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForPro_corel_quattro_pro_x3_qpw()
+     */
+    @Override
+    protected String expectedMimeTypeForPro_corel_quattro_pro_x3_qpw() {
+        return "application/x-quattropro";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_x3_wpd()
+     */
+    @Override
+    protected String expectedMimeTypeForWordperfect_corel_wordperfect_x3_wpd() {
+        return "application/vnd.wordperfect";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_4_2_wp()
+     */
+    @Override
+    protected String expectedMimeTypeForWordperfect_corel_wordperfect_4_2_wp() {
+        return "application/vnd.wordperfect";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_5_0_wp()
+     */
+    @Override
+    protected String expectedMimeTypeForWordperfect_corel_wordperfect_5_0_wp() {
+        return "application/vnd.wordperfect";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_5_1_far_east_wp()
+     */
+    @Override
+    protected String expectedMimeTypeForWordperfect_corel_wordperfect_5_1_far_east_wp() {
+        return "application/vnd.wordperfect";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForWordperfect_corel_wordperfect_5_1_wp()
+     */
+    @Override
+    protected String expectedMimeTypeForWordperfect_corel_wordperfect_5_1_wp() {
+        return "application/vnd.wordperfect";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMail_test_excel_web_archive_mht()
+     */
+    @Override
+    protected String expectedMimeTypeForMail_test_excel_web_archive_mht() {
+        return "message/rfc822";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMail_mail_thunderbird_1_5_eml()
+     */
+    @Override
+    protected String expectedMimeTypeForMail_mail_thunderbird_1_5_eml() {
+        return "message/rfc822";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMail_mhtml_firefox_mht()
+     */
+    @Override
+    protected String expectedMimeTypeForMail_mhtml_firefox_mht() {
+        return "message/rfc822";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForMail_mhtml_internet_explorer_mht()
+     */
+    @Override
+    protected String expectedMimeTypeForMail_mhtml_internet_explorer_mht() {
+        return "message/rfc822";
+    }
+
+    @Override
+    public String expectedMimeTypeForAddressBook() {
+        return "application/x-mozilla-addressbook";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_vCards_SAP_vcf()
+     */
+    @Override
+    protected String expectedMimeTypeForVCard_vcard_vCards_SAP_vcf() {
+        return "text/x-vcard";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_antoni_kontact_vcf()
+     */
+    @Override
+    protected String expectedMimeTypeForVCard_vcard_antoni_kontact_vcf() {
+        return "text/x-vcard";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_antoni_outlook2003_vcf()
+     */
+    @Override
+    protected String expectedMimeTypeForVCard_vcard_antoni_outlook2003_vcf() {
+        return "text/x-vcard";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_dirk_vcf()
+     */
+    @Override
+    protected String expectedMimeTypeForVCard_vcard_dirk_vcf() {
+        return "text/x-vcard";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForVCard_vcard_rfc2426_vcf()
+     */
+    @Override
+    protected String expectedMimeTypeForVCard_vcard_rfc2426_vcf() {
+        return "text/x-vcard";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_Todos1_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_Todos1_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_basicCalendar_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_basicCalendar_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_1_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_cal01_1_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_2_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_cal01_2_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_3_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_cal01_3_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_4_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_cal01_4_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_5_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_cal01_5_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_6_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_cal01_6_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_exrule_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_cal01_exrule_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_cal01_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_cal01_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_calconnect7_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_calconnect7_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_calconnect9_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_calconnect9_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_combined_multiplevcalendar_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_combined_multiplevcalendar_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_combined_onevcalendar_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_combined_onevcalendar_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_extendedCalendar_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_extendedCalendar_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_freebusy_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_freebusy_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_geol_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_geol_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_gkexample_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_gkexample_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_incoming_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_incoming_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_korganizer_jicaltest_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_korganizer_jicaltest_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_korganizer_jicaltest_vjournal_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_korganizer_jicaltest_vjournal_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_php_flp_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_php_flp_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_simplevevent_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_simplevevent_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_sunbird_sample_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_sunbird_sample_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_tag_bug_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_tag_bug_ics() {
+        return "text/calendar";
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.mimetype.AbstractMimeTypeTest#expectedMimeTypeForCalendar_test_created_ics()
+     */
+    @Override
+    protected String expectedMimeTypeForCalendar_test_created_ics() {
+        return "text/calendar";
+    }
+
+    @Override
+    public String expectedMimeTypeForAu() {
+        return "application/octet-stream";
+    }
+
+    @Override
+    public String expectedMimeTypeForBin() {
+        return "application/octet-stream";
+    }
+
+    @Override
+    public String expectedMimeTypeForEmf() {
+        return "application/octet-stream";
+    }
+
+    @Override
+    public String expectedMimeTypeForFli() {
+        return "application/octet-stream";
+    }
+
+    @Override
+    public String expectedMimeTypeForPcx() {
+        return "application/octet-stream";
+    }
+
+    @Override
+    public String expectedMimeTypeForPict() {
+        return "application/octet-stream";
+    }
+
+    @Override
+    public String expectedMimeTypeForPsd() {
+        return "application/octet-stream";
+    }
+
+    @Override
+    public String expectedMimeTypeForTar() {
+        return "application/octet-stream";
+    }
+
+    @Test( expected = FileNotFoundException.class )
+    public void shouldFailIfFileNotFound() throws Exception {
+        testMimeType("missing.file", "");
+    }
+}


Property changes on: trunk/extensions/dna-mimetype-detector-aperture/src/test/java/org/jboss/dna/mimetype/aperture/MimeTypeTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Copied: trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image (from rev 705, trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/images)

Deleted: trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadata.java
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/images/ImageMetadata.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadata.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,1142 +0,0 @@
-/*
- * ImageInfo.java
- *
- * Version 1.9
- *
- * A Java class to determine image width, height and color depth for
- * a number of image file formats.
- *
- * Written by Marco Schmidt 
- *
- * Contributed to the Public Domain.
- */
-
-package org.jboss.dna.sequencer.images;
-
-import java.io.DataInput;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Vector;
-
-/**
- * Get file format, image resolution, number of bits per pixel and optionally number of images, comments and physical resolution
- * from JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM and PSD files (or input streams).
- * <p>
- * Use the class like this:
- * 
- * <pre>
- * ImageMetadata ii = new ImageMetadata();
- * ii.setInput(in); // in can be InputStream or RandomAccessFile
- * ii.setDetermineImageNumber(true); // default is false
- * ii.setCollectComments(true); // default is false
- * if (!ii.check()) {
- *     System.err.println(&quot;Not a supported image file format.&quot;);
- *     return;
- * }
- * System.out.println(ii.getFormatName() + &quot;, &quot; + ii.getMimeType() + &quot;, &quot; + ii.getWidth() + &quot; x &quot; + ii.getHeight() + &quot; pixels, &quot;
- *                    + ii.getBitsPerPixel() + &quot; bits per pixel, &quot; + ii.getNumberOfImages() + &quot; image(s), &quot;
- *                    + ii.getNumberOfComments() + &quot; comment(s).&quot;);
- * // there are other properties, check out the API documentation
- * </pre>
- * 
- * You can also use this class as a command line program. Call it with a number of image file names and URLs as parameters:
- * 
- * <pre>
- *   java ImageMetadata *.jpg *.png *.gif http://somesite.tld/image.jpg
- * </pre>
- * 
- * or call it without parameters and pipe data to it:
- * 
- * <pre>
- *   java ImageMetadata &lt; image.jpg  
- * </pre>
- * 
- * <p>
- * Known limitations:
- * <ul>
- * <li>When the determination of the number of images is turned off, GIF bits per pixel are only read from the global header. For
- * some GIFs, local palettes change this to a typically larger value. To be certain to get the correct color depth, call
- * setDetermineImageNumber(true) before calling check(). The complete scan over the GIF file will take additional time.</li>
- * <li>Transparency information is not included in the bits per pixel count. Actually, it was my decision not to include those
- * bits, so it's a feature! ;-)</li>
- * </ul>
- * <p>
- * Requirements:
- * <ul>
- * <li>Java 1.1 or higher</li>
- * </ul>
- * <p>
- * The latest version can be found at <a href="http://schmidt.devlib.org/image-info/">http://schmidt.devlib.org/image-info/</a>.
- * <p>
- * Written by Marco Schmidt.
- * <p>
- * This class is contributed to the Public Domain. Use it at your own risk.
- * <p>
- * <a name="history">History</a>:
- * <ul>
- * <li><strong>2001-08-24</strong> Initial version.</li>
- * <li><strong>2001-10-13</strong> Added support for the file formats BMP and PCX.</li>
- * <li><strong>2001-10-16</strong> Fixed bug in read(int[], int, int) that returned
- * <li><strong>2002-01-22</strong> Added support for file formats Amiga IFF and Sun Raster (RAS).</li>
- * <li><strong>2002-01-24</strong> Added support for file formats Portable Bitmap / Graymap / Pixmap (PBM, PGM, PPM) and Adobe
- * Photoshop (PSD). Added new method getMimeType() to return the MIME type associated with a particular file format.</li>
- * <li><strong>2002-03-15</strong> Added support to recognize number of images in file. Only works with GIF. Use
- * {@link #setDetermineImageNumber} with <code>true</code> as argument to identify animated GIFs ({@link #getNumberOfImages()}
- * will return a value larger than <code>1</code>).</li>
- * <li><strong>2002-04-10</strong> Fixed a bug in the feature 'determine number of images in animated GIF' introduced with
- * version 1.1. Thanks to Marcelo P. Lima for sending in the bug report. Released as 1.1.1.</li>
- * <li><strong>2002-04-18</strong> Added {@link #setCollectComments(boolean)}. That new method lets the user specify whether
- * textual comments are to be stored in an internal list when encountered in an input image file / stream. Added two methods to
- * return the physical width and height of the image in dpi: {@link #getPhysicalWidthDpi()} and {@link #getPhysicalHeightDpi()}.
- * If the physical resolution could not be retrieved, these methods return <code>-1</code>. </li>
- * <li><strong>2002-04-23</strong> Added support for the new properties physical resolution and comments for some formats.
- * Released as 1.2.</li>
- * <li><strong>2002-06-17</strong> Added support for SWF, sent in by Michael Aird. Changed checkJpeg() so that other APP markers
- * than APP0 will not lead to a failure anymore. Released as 1.3.</li>
- * <li><strong>2003-07-28</strong> Bug fix - skip method now takes return values into consideration. Less bytes than necessary
- * may have been skipped, leading to flaws in the retrieved information in some cases. Thanks to Bernard Bernstein for pointing
- * that out. Released as 1.4.</li>
- * <li><strong>2004-02-29</strong> Added support for recognizing progressive JPEG and interlaced PNG and GIF. A new method
- * {@link #isProgressive()} returns whether ImageMetadata has found that the storage type is progressive (or interlaced). Thanks
- * to Joe Germuska for suggesting the feature. Bug fix: BMP physical resolution is now correctly determined. Released as 1.5.</li>
- * <li><strong>2004-11-30</strong> Bug fix: recognizing progressive GIFs (interlaced in GIF terminology) did not work (thanks to
- * Franz Jeitler for pointing this out). Now it should work, but only if the number of images is determined. This is because
- * information on interlacing is stored in a local image header. In theory, different images could be stored interlaced and
- * non-interlaced in one file. However, I think that's unlikely. Right now, the last image in the GIF file that is examined by
- * ImageMetadata is used for the "progressive" status.</li>
- * <li><strong>2005-01-02</strong> Some code clean up (unused methods and variables commented out, missing javadoc comments,
- * etc.). Thanks to George Sexton for a long list. Removed usage of Boolean.toString because it's a Java 1.4+ feature (thanks to
- * Gregor Dupont). Changed delimiter character in compact output from semicolon to tabulator (for better integration with cut(1)
- * and other Unix tools). Added some points to the <a href="http://schmidt.devlib.org/image-info/index.html#knownissues">'Known
- * issues' section of the website</a>. Released as 1.6.</li>
- * <li><strong>2005-07-26</strong> Removed code to identify Flash (SWF) files. Has repeatedly led to problems and support
- * requests, and I don't know the format and don't have the time and interest to fix it myself. I repeatedly included fixes by
- * others which didn't work for some people. I give up on SWF. Please do not contact me about it anymore. Set package of
- * ImageMetadata class to org.devlib.schmidt.imageinfo (a package was repeatedly requested by some users). Released as 1.7.</li>
- * <li><strong>2006-02-23</strong> Removed Flash helper methods which weren't used elsewhere. Updated skip method which tries
- * "read" whenever "skip(Bytes)" returns a result of 0. The old method didn't work with certain input stream types on truncated
- * data streams. Thanks to Martin Leidig for reporting this and sending in code. Released as 1.8.</li>
- * </li>
- * <li><strong>2006-11-13</strong> Removed check that made ImageMetadata report JPEG APPx markers smaller than 14 bytes as files
- * in unknown format. Such JPEGs seem to be generated by Google's Picasa application. First reported with fix by Karl von Randow.
- * Released as 1.9.</li>
- * <li><strong>2008-04-10</strong> Changed comment vector to be <code>Vector&lt;String&gt;</code>, and removed any
- * unnecessary casting. Also removed the unnecessary else statements where the previous block ended in a return. Also renamed to
- * <code>ImageMetadata</code>.
- * </ul>
- * 
- * @author Marco Schmidt
- */
-public class ImageMetadata {
-
-    /**
-     * Return value of {@link #getFormat()} for JPEG streams. ImageMetadata can extract physical resolution and comments from
-     * JPEGs (only from APP0 headers). Only one image can be stored in a file. It is determined whether the JPEG stream is
-     * progressive (see {@link #isProgressive()}).
-     */
-    public static final int FORMAT_JPEG = 0;
-
-    /**
-     * Return value of {@link #getFormat()} for GIF streams. ImageMetadata can extract comments from GIFs and count the number of
-     * images (GIFs with more than one image are animations). It is determined whether the GIF stream is interlaced (see
-     * {@link #isProgressive()}).
-     */
-    public static final int FORMAT_GIF = 1;
-
-    /**
-     * Return value of {@link #getFormat()} for PNG streams. PNG only supports one image per file. Both physical resolution and
-     * comments can be stored with PNG, but ImageMetadata is currently not able to extract those. It is determined whether the PNG
-     * stream is interlaced (see {@link #isProgressive()}).
-     */
-    public static final int FORMAT_PNG = 2;
-
-    /**
-     * Return value of {@link #getFormat()} for BMP streams. BMP only supports one image per file. BMP does not allow for
-     * comments. The physical resolution can be stored.
-     */
-    public static final int FORMAT_BMP = 3;
-
-    /**
-     * Return value of {@link #getFormat()} for PCX streams. PCX does not allow for comments or more than one image per file.
-     * However, the physical resolution can be stored.
-     */
-    public static final int FORMAT_PCX = 4;
-
-    /**
-     * Return value of {@link #getFormat()} for IFF streams.
-     */
-    public static final int FORMAT_IFF = 5;
-
-    /**
-     * Return value of {@link #getFormat()} for RAS streams. Sun Raster allows for one image per file only and is not able to
-     * store physical resolution or comments.
-     */
-    public static final int FORMAT_RAS = 6;
-
-    /** Return value of {@link #getFormat()} for PBM streams. */
-    public static final int FORMAT_PBM = 7;
-
-    /** Return value of {@link #getFormat()} for PGM streams. */
-    public static final int FORMAT_PGM = 8;
-
-    /** Return value of {@link #getFormat()} for PPM streams. */
-    public static final int FORMAT_PPM = 9;
-
-    /** Return value of {@link #getFormat()} for PSD streams. */
-    public static final int FORMAT_PSD = 10;
-
-    /*
-     * public static final int COLOR_TYPE_UNKNOWN = -1; public static final int COLOR_TYPE_TRUECOLOR_RGB = 0; public static final
-     * int COLOR_TYPE_PALETTED = 1; public static final int COLOR_TYPE_GRAYSCALE= 2; public static final int
-     * COLOR_TYPE_BLACK_AND_WHITE = 3;
-     */
-
-    /**
-     * The names of all supported file formats. The FORMAT_xyz int constants can be used as index values for this array.
-     */
-    private static final String[] FORMAT_NAMES = {"JPEG", "GIF", "PNG", "BMP", "PCX", "IFF", "RAS", "PBM", "PGM", "PPM", "PSD"};
-
-    /**
-     * The names of the MIME types for all supported file formats. The FORMAT_xyz int constants can be used as index values for
-     * this array.
-     */
-    private static final String[] MIME_TYPE_STRINGS = {"image/jpeg", "image/gif", "image/png", "image/bmp", "image/pcx",
-        "image/iff", "image/ras", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap", "image/psd"};
-
-    private int width;
-    private int height;
-    private int bitsPerPixel;
-    // private int colorType = COLOR_TYPE_UNKNOWN;
-    private boolean progressive;
-    private int format;
-    private InputStream in;
-    private DataInput din;
-    private boolean collectComments = true;
-    private Vector<String> comments;
-    private boolean determineNumberOfImages;
-    private int numberOfImages;
-    private int physicalHeightDpi;
-    private int physicalWidthDpi;
-
-    private void addComment( String s ) {
-        if (comments == null) {
-            comments = new Vector<String>();
-        }
-        comments.addElement(s);
-    }
-
-    /**
-     * Call this method after you have provided an input stream or file using {@link #setInput(InputStream)} or
-     * {@link #setInput(DataInput)}. If true is returned, the file format was known and information on the file's content can be
-     * retrieved using the various getXyz methods.
-     * 
-     * @return if information could be retrieved from input
-     */
-    public boolean check() {
-        format = -1;
-        width = -1;
-        height = -1;
-        bitsPerPixel = -1;
-        numberOfImages = 1;
-        physicalHeightDpi = -1;
-        physicalWidthDpi = -1;
-        comments = null;
-        try {
-            int b1 = read() & 0xff;
-            int b2 = read() & 0xff;
-            if (b1 == 0x47 && b2 == 0x49) {
-                return checkGif();
-            } else if (b1 == 0x89 && b2 == 0x50) {
-                return checkPng();
-            } else if (b1 == 0xff && b2 == 0xd8) {
-                return checkJpeg();
-            } else if (b1 == 0x42 && b2 == 0x4d) {
-                return checkBmp();
-            } else if (b1 == 0x0a && b2 < 0x06) {
-                return checkPcx();
-            } else if (b1 == 0x46 && b2 == 0x4f) {
-                return checkIff();
-            } else if (b1 == 0x59 && b2 == 0xa6) {
-                return checkRas();
-            } else if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
-                return checkPnm(b2 - '0');
-            } else if (b1 == 0x38 && b2 == 0x42) {
-                return checkPsd();
-            } else {
-                return false;
-            }
-        } catch (IOException ioe) {
-            return false;
-        }
-    }
-
-    private boolean checkBmp() throws IOException {
-        byte[] a = new byte[44];
-        if (read(a) != a.length) {
-            return false;
-        }
-        width = getIntLittleEndian(a, 16);
-        height = getIntLittleEndian(a, 20);
-        if (width < 1 || height < 1) {
-            return false;
-        }
-        bitsPerPixel = getShortLittleEndian(a, 26);
-        if (bitsPerPixel != 1 && bitsPerPixel != 4 && bitsPerPixel != 8 && bitsPerPixel != 16 && bitsPerPixel != 24
-            && bitsPerPixel != 32) {
-            return false;
-        }
-        int x = (int)(getIntLittleEndian(a, 36) * 0.0254);
-        if (x > 0) {
-            setPhysicalWidthDpi(x);
-        }
-        int y = (int)(getIntLittleEndian(a, 40) * 0.0254);
-        if (y > 0) {
-            setPhysicalHeightDpi(y);
-        }
-        format = FORMAT_BMP;
-        return true;
-    }
-
-    private boolean checkGif() throws IOException {
-        final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
-        final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
-        byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
-        if (read(a) != 11) {
-            return false;
-        }
-        if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4)) && (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
-            return false;
-        }
-        format = FORMAT_GIF;
-        width = getShortLittleEndian(a, 4);
-        height = getShortLittleEndian(a, 6);
-        int flags = a[8] & 0xff;
-        bitsPerPixel = ((flags >> 4) & 0x07) + 1;
-        // progressive = (flags & 0x02) != 0;
-        if (!determineNumberOfImages) {
-            return true;
-        }
-        // skip global color palette
-        if ((flags & 0x80) != 0) {
-            int tableSize = (1 << ((flags & 7) + 1)) * 3;
-            skip(tableSize);
-        }
-        numberOfImages = 0;
-        int blockType;
-        do {
-            blockType = read();
-            switch (blockType) {
-                case (0x2c): // image separator
-                {
-                    if (read(a, 0, 9) != 9) {
-                        return false;
-                    }
-                    flags = a[8] & 0xff;
-                    progressive = (flags & 0x40) != 0;
-                    /*
-                     * int locWidth = getShortLittleEndian(a, 4); int locHeight = getShortLittleEndian(a, 6);
-                     * System.out.println("LOCAL: " + locWidth + " x " + locHeight);
-                     */
-                    int localBitsPerPixel = (flags & 0x07) + 1;
-                    if (localBitsPerPixel > bitsPerPixel) {
-                        bitsPerPixel = localBitsPerPixel;
-                    }
-                    if ((flags & 0x80) != 0) {
-                        skip((1 << localBitsPerPixel) * 3);
-                    }
-                    skip(1); // initial code length
-                    int n;
-                    do {
-                        n = read();
-                        if (n > 0) {
-                            skip(n);
-                        } else if (n == -1) {
-                            return false;
-                        }
-                    } while (n > 0);
-                    numberOfImages++;
-                    break;
-                }
-                case (0x21): // extension
-                {
-                    int extensionType = read();
-                    if (collectComments && extensionType == 0xfe) {
-                        StringBuffer sb = new StringBuffer();
-                        int n;
-                        do {
-                            n = read();
-                            if (n == -1) {
-                                return false;
-                            }
-                            if (n > 0) {
-                                for (int i = 0; i < n; i++) {
-                                    int ch = read();
-                                    if (ch == -1) {
-                                        return false;
-                                    }
-                                    sb.append((char)ch);
-                                }
-                            }
-                        } while (n > 0);
-                    } else {
-                        int n;
-                        do {
-                            n = read();
-                            if (n > 0) {
-                                skip(n);
-                            } else if (n == -1) {
-                                return false;
-                            }
-                        } while (n > 0);
-                    }
-                    break;
-                }
-                case (0x3b): // end of file
-                {
-                    break;
-                }
-                default: {
-                    return false;
-                }
-            }
-        } while (blockType != 0x3b);
-        return true;
-    }
-
-    private boolean checkIff() throws IOException {
-        byte[] a = new byte[10];
-        // read remaining 2 bytes of file id, 4 bytes file size
-        // and 4 bytes IFF subformat
-        if (read(a, 0, 10) != 10) {
-            return false;
-        }
-        final byte[] IFF_RM = {0x52, 0x4d};
-        if (!equals(a, 0, IFF_RM, 0, 2)) {
-            return false;
-        }
-        int type = getIntBigEndian(a, 6);
-        if (type != 0x494c424d && // type must be ILBM...
-            type != 0x50424d20) { // ...or PBM
-            return false;
-        }
-        // loop chunks to find BMHD chunk
-        do {
-            if (read(a, 0, 8) != 8) {
-                return false;
-            }
-            int chunkId = getIntBigEndian(a, 0);
-            int size = getIntBigEndian(a, 4);
-            if ((size & 1) == 1) {
-                size++;
-            }
-            if (chunkId == 0x424d4844) { // BMHD chunk
-                if (read(a, 0, 9) != 9) {
-                    return false;
-                }
-                format = FORMAT_IFF;
-                width = getShortBigEndian(a, 0);
-                height = getShortBigEndian(a, 2);
-                bitsPerPixel = a[8] & 0xff;
-                return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel < 33);
-            }
-            skip(size);
-        } while (true);
-    }
-
-    private boolean checkJpeg() throws IOException {
-        byte[] data = new byte[12];
-        while (true) {
-            if (read(data, 0, 4) != 4) {
-                return false;
-            }
-            int marker = getShortBigEndian(data, 0);
-            int size = getShortBigEndian(data, 2);
-            if ((marker & 0xff00) != 0xff00) {
-                return false; // not a valid marker
-            }
-            if (marker == 0xffe0) { // APPx
-                if (size < 14) {
-                    // not an APPx header as we know it, skip
-                    skip(size - 2);
-                    continue;
-                }
-                if (read(data, 0, 12) != 12) {
-                    return false;
-                }
-                final byte[] APP0_ID = {0x4a, 0x46, 0x49, 0x46, 0x00};
-                if (equals(APP0_ID, 0, data, 0, 5)) {
-                    // System.out.println("data 7=" + data[7]);
-                    if (data[7] == 1) {
-                        setPhysicalWidthDpi(getShortBigEndian(data, 8));
-                        setPhysicalHeightDpi(getShortBigEndian(data, 10));
-                    } else if (data[7] == 2) {
-                        int x = getShortBigEndian(data, 8);
-                        int y = getShortBigEndian(data, 10);
-                        setPhysicalWidthDpi((int)(x * 2.54f));
-                        setPhysicalHeightDpi((int)(y * 2.54f));
-                    }
-                }
-                skip(size - 14);
-            } else if (collectComments && size > 2 && marker == 0xfffe) { // comment
-                size -= 2;
-                byte[] chars = new byte[size];
-                if (read(chars, 0, size) != size) {
-                    return false;
-                }
-                String comment = new String(chars, "iso-8859-1");
-                comment = comment.trim();
-                addComment(comment);
-            } else if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 && marker != 0xffc8) {
-                if (read(data, 0, 6) != 6) {
-                    return false;
-                }
-                format = FORMAT_JPEG;
-                bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
-                progressive = marker == 0xffc2 || marker == 0xffc6 || marker == 0xffca || marker == 0xffce;
-                width = getShortBigEndian(data, 3);
-                height = getShortBigEndian(data, 1);
-                return true;
-            } else {
-                skip(size - 2);
-            }
-        }
-    }
-
-    private boolean checkPcx() throws IOException {
-        byte[] a = new byte[64];
-        if (read(a) != a.length) {
-            return false;
-        }
-        if (a[0] != 1) { // encoding, 1=RLE is only valid value
-            return false;
-        }
-        // width / height
-        int x1 = getShortLittleEndian(a, 2);
-        int y1 = getShortLittleEndian(a, 4);
-        int x2 = getShortLittleEndian(a, 6);
-        int y2 = getShortLittleEndian(a, 8);
-        if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
-            return false;
-        }
-        width = x2 - x1 + 1;
-        height = y2 - y1 + 1;
-        // color depth
-        int bits = a[1];
-        int planes = a[63];
-        if (planes == 1 && (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
-            // paletted
-            bitsPerPixel = bits;
-        } else if (planes == 3 && bits == 8) {
-            // RGB truecolor
-            bitsPerPixel = 24;
-        } else {
-            return false;
-        }
-        setPhysicalWidthDpi(getShortLittleEndian(a, 10));
-        setPhysicalHeightDpi(getShortLittleEndian(a, 10));
-        format = FORMAT_PCX;
-        return true;
-    }
-
-    private boolean checkPng() throws IOException {
-        final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
-        byte[] a = new byte[27];
-        if (read(a) != 27) {
-            return false;
-        }
-        if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
-            return false;
-        }
-        format = FORMAT_PNG;
-        width = getIntBigEndian(a, 14);
-        height = getIntBigEndian(a, 18);
-        bitsPerPixel = a[22] & 0xff;
-        int colorType = a[23] & 0xff;
-        if (colorType == 2 || colorType == 6) {
-            bitsPerPixel *= 3;
-        }
-        progressive = (a[26] & 0xff) != 0;
-        return true;
-    }
-
-    private boolean checkPnm( int id ) throws IOException {
-        if (id < 1 || id > 6) {
-            return false;
-        }
-        final int[] PNM_FORMATS = {FORMAT_PBM, FORMAT_PGM, FORMAT_PPM};
-        format = PNM_FORMATS[(id - 1) % 3];
-        boolean hasPixelResolution = false;
-        String s;
-        while (true) {
-            s = readLine();
-            if (s != null) {
-                s = s.trim();
-            }
-            if (s == null || s.length() < 1) {
-                continue;
-            }
-            if (s.charAt(0) == '#') { // comment
-                if (collectComments && s.length() > 1) {
-                    addComment(s.substring(1));
-                }
-                continue;
-            }
-            if (!hasPixelResolution) { // split "343 966" into width=343, height=966
-                int spaceIndex = s.indexOf(' ');
-                if (spaceIndex == -1) {
-                    return false;
-                }
-                String widthString = s.substring(0, spaceIndex);
-                spaceIndex = s.lastIndexOf(' ');
-                if (spaceIndex == -1) {
-                    return false;
-                }
-                String heightString = s.substring(spaceIndex + 1);
-                try {
-                    width = Integer.parseInt(widthString);
-                    height = Integer.parseInt(heightString);
-                } catch (NumberFormatException nfe) {
-                    return false;
-                }
-                if (width < 1 || height < 1) {
-                    return false;
-                }
-                if (format == FORMAT_PBM) {
-                    bitsPerPixel = 1;
-                    return true;
-                }
-                hasPixelResolution = true;
-            } else {
-                int maxSample;
-                try {
-                    maxSample = Integer.parseInt(s);
-                } catch (NumberFormatException nfe) {
-                    return false;
-                }
-                if (maxSample < 0) {
-                    return false;
-                }
-                for (int i = 0; i < 25; i++) {
-                    if (maxSample < (1 << (i + 1))) {
-                        bitsPerPixel = i + 1;
-                        if (format == FORMAT_PPM) {
-                            bitsPerPixel *= 3;
-                        }
-                        return true;
-                    }
-                }
-                return false;
-            }
-        }
-    }
-
-    private boolean checkPsd() throws IOException {
-        byte[] a = new byte[24];
-        if (read(a) != a.length) {
-            return false;
-        }
-        final byte[] PSD_MAGIC = {0x50, 0x53};
-        if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
-            return false;
-        }
-        format = FORMAT_PSD;
-        width = getIntBigEndian(a, 16);
-        height = getIntBigEndian(a, 12);
-        int channels = getShortBigEndian(a, 10);
-        int depth = getShortBigEndian(a, 20);
-        bitsPerPixel = channels * depth;
-        return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 64);
-    }
-
-    private boolean checkRas() throws IOException {
-        byte[] a = new byte[14];
-        if (read(a) != a.length) {
-            return false;
-        }
-        final byte[] RAS_MAGIC = {0x6a, (byte)0x95};
-        if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
-            return false;
-        }
-        format = FORMAT_RAS;
-        width = getIntBigEndian(a, 2);
-        height = getIntBigEndian(a, 6);
-        bitsPerPixel = getIntBigEndian(a, 10);
-        return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 24);
-    }
-
-    /**
-     * Run over String list, return false if and only if at least one of the arguments equals <code>-c</code>.
-     * 
-     * @param args string list to check
-     * @return <code>true</code> none of the supplied parameters is <code>-c</code>
-     */
-    private static boolean determineVerbosity( String[] args ) {
-        if (args != null && args.length > 0) {
-            for (int i = 0; i < args.length; i++) {
-                if ("-c".equals(args[i])) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private static boolean equals( byte[] a1,
-                                   int offs1,
-                                   byte[] a2,
-                                   int offs2,
-                                   int num ) {
-        while (num-- > 0) {
-            if (a1[offs1++] != a2[offs2++]) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * If {@link #check()} was successful, returns the image's number of bits per pixel. Does not include transparency information
-     * like the alpha channel.
-     * 
-     * @return number of bits per image pixel
-     */
-    public int getBitsPerPixel() {
-        return bitsPerPixel;
-    }
-
-    /**
-     * Returns the index'th comment retrieved from the file.
-     * 
-     * @param index int index of comment to return
-     * @return the comment at the supplied index
-     * @throws IllegalArgumentException if index is smaller than 0 or larger than or equal to the number of comments retrieved
-     * @see #getNumberOfComments
-     */
-    public String getComment( int index ) {
-        if (comments == null || index < 0 || index >= comments.size()) {
-            throw new IllegalArgumentException("Not a valid comment index: " + index);
-        }
-        return comments.elementAt(index);
-    }
-
-    /**
-     * If {@link #check()} was successful, returns the image format as one of the FORMAT_xyz constants from this class. Use
-     * {@link #getFormatName()} to get a textual description of the file format.
-     * 
-     * @return file format as a FORMAT_xyz constant
-     */
-    public int getFormat() {
-        return format;
-    }
-
-    /**
-     * If {@link #check()} was successful, returns the image format's name. Use {@link #getFormat()} to get a unique number.
-     * 
-     * @return file format name
-     */
-    public String getFormatName() {
-        if (format >= 0 && format < FORMAT_NAMES.length) {
-            return FORMAT_NAMES[format];
-        }
-        return "?";
-    }
-
-    /**
-     * If {@link #check()} was successful, returns one the image's vertical resolution in pixels.
-     * 
-     * @return image height in pixels
-     */
-    public int getHeight() {
-        return height;
-    }
-
-    private static int getIntBigEndian( byte[] a,
-                                        int offs ) {
-        return (a[offs] & 0xff) << 24 | (a[offs + 1] & 0xff) << 16 | (a[offs + 2] & 0xff) << 8 | a[offs + 3] & 0xff;
-    }
-
-    private static int getIntLittleEndian( byte[] a,
-                                           int offs ) {
-        return (a[offs + 3] & 0xff) << 24 | (a[offs + 2] & 0xff) << 16 | (a[offs + 1] & 0xff) << 8 | a[offs] & 0xff;
-    }
-
-    /**
-     * If {@link #check()} was successful, returns a String with the MIME type of the format.
-     * 
-     * @return MIME type, e.g. <code>image/jpeg</code>
-     */
-    public String getMimeType() {
-        if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
-            if (format == FORMAT_JPEG && progressive) {
-                return "image/pjpeg";
-            }
-            return MIME_TYPE_STRINGS[format];
-        }
-        return null;
-    }
-
-    /**
-     * If {@link #check()} was successful and {@link #setCollectComments(boolean)} was called with <code>true</code> as
-     * argument, returns the number of comments retrieved from the input image stream / file. Any number &gt;= 0 and smaller than
-     * this number of comments is then a valid argument for the {@link #getComment(int)} method.
-     * 
-     * @return number of comments retrieved from input image
-     */
-    public int getNumberOfComments() {
-        if (comments == null) {
-            return 0;
-        }
-        return comments.size();
-    }
-
-    /**
-     * Returns the number of images in the examined file. Assumes that <code>setDetermineImageNumber(true);</code> was called
-     * before a successful call to {@link #check()}. This value can currently be only different from <code>1</code> for GIF
-     * images.
-     * 
-     * @return number of images in file
-     */
-    public int getNumberOfImages() {
-        return numberOfImages;
-    }
-
-    /**
-     * Returns the physical height of this image in dots per inch (dpi). Assumes that {@link #check()} was successful. Returns
-     * <code>-1</code> on failure.
-     * 
-     * @return physical height (in dpi)
-     * @see #getPhysicalWidthDpi()
-     * @see #getPhysicalHeightInch()
-     */
-    public int getPhysicalHeightDpi() {
-        return physicalHeightDpi;
-    }
-
-    /**
-     * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch) or -1 if no value could
-     * be found.
-     * 
-     * @return physical height (in dpi)
-     * @see #getPhysicalHeightDpi()
-     * @see #getPhysicalWidthDpi()
-     * @see #getPhysicalWidthInch()
-     */
-    public float getPhysicalHeightInch() {
-        int h = getHeight();
-        int ph = getPhysicalHeightDpi();
-        if (h > 0 && ph > 0) {
-            return ((float)h) / ((float)ph);
-        }
-        return -1.0f;
-    }
-
-    /**
-     * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch) or -1 if no value could
-     * be found.
-     * 
-     * @return physical width (in dpi)
-     * @see #getPhysicalHeightDpi()
-     * @see #getPhysicalWidthInch()
-     * @see #getPhysicalHeightInch()
-     */
-    public int getPhysicalWidthDpi() {
-        return physicalWidthDpi;
-    }
-
-    /**
-     * Returns the physical width of an image in inches, or <code>-1.0f</code> if width information is not available. Assumes
-     * that {@link #check} has been called successfully.
-     * 
-     * @return physical width in inches or <code>-1.0f</code> on failure
-     * @see #getPhysicalWidthDpi
-     * @see #getPhysicalHeightInch
-     */
-    public float getPhysicalWidthInch() {
-        int w = getWidth();
-        int pw = getPhysicalWidthDpi();
-        if (w > 0 && pw > 0) {
-            return ((float)w) / ((float)pw);
-        }
-        return -1.0f;
-    }
-
-    private static int getShortBigEndian( byte[] a,
-                                          int offs ) {
-        return (a[offs] & 0xff) << 8 | (a[offs + 1] & 0xff);
-    }
-
-    private static int getShortLittleEndian( byte[] a,
-                                             int offs ) {
-        return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
-    }
-
-    /**
-     * If {@link #check()} was successful, returns one the image's horizontal resolution in pixels.
-     * 
-     * @return image width in pixels
-     */
-    public int getWidth() {
-        return width;
-    }
-
-    /**
-     * Returns whether the image is stored in a progressive (also called: interlaced) way.
-     * 
-     * @return true for progressive/interlaced, false otherwise
-     */
-    public boolean isProgressive() {
-        return progressive;
-    }
-
-    /**
-     * To use this class as a command line application, give it either some file names as parameters (information on them will be
-     * printed to standard output, one line per file) or call it with no parameters. It will then check data given to it via
-     * standard input.
-     * 
-     * @param args the program arguments which must be file names
-     */
-    public static void main( String[] args ) {
-        ImageMetadata imageMetadata = new ImageMetadata();
-        imageMetadata.setDetermineImageNumber(true);
-        boolean verbose = determineVerbosity(args);
-        if (args.length == 0) {
-            run(null, System.in, imageMetadata, verbose);
-        } else {
-            int index = 0;
-            while (index < args.length) {
-                InputStream in = null;
-                try {
-                    String name = args[index++];
-                    System.out.print(name + ";");
-                    if (name.startsWith("http://")) {
-                        in = new URL(name).openConnection().getInputStream();
-                    } else {
-                        in = new FileInputStream(name);
-                    }
-                    run(name, in, imageMetadata, verbose);
-                    in.close();
-                } catch (IOException e) {
-                    System.out.println(e);
-                    try {
-                        if (in != null) {
-                            in.close();
-                        }
-                    } catch (IOException ee) {
-                    }
-                }
-            }
-        }
-    }
-
-    private static void print( String sourceName,
-                               ImageMetadata ii,
-                               boolean verbose ) {
-        if (verbose) {
-            printVerbose(sourceName, ii);
-        } else {
-            printCompact(sourceName, ii);
-        }
-    }
-
-    private static void printCompact( String sourceName,
-                                      ImageMetadata imageMetadata ) {
-        final String SEP = "\t";
-        System.out.println(sourceName + SEP + imageMetadata.getFormatName() + SEP + imageMetadata.getMimeType() + SEP
-                           + imageMetadata.getWidth() + SEP + imageMetadata.getHeight() + SEP + imageMetadata.getBitsPerPixel()
-                           + SEP + imageMetadata.getNumberOfImages() + SEP + imageMetadata.getPhysicalWidthDpi() + SEP
-                           + imageMetadata.getPhysicalHeightDpi() + SEP + imageMetadata.getPhysicalWidthInch() + SEP
-                           + imageMetadata.getPhysicalHeightInch() + SEP + imageMetadata.isProgressive());
-    }
-
-    private static void printLine( int indentLevels,
-                                   String text,
-                                   float value,
-                                   float minValidValue ) {
-        if (value < minValidValue) {
-            return;
-        }
-        printLine(indentLevels, text, Float.toString(value));
-    }
-
-    private static void printLine( int indentLevels,
-                                   String text,
-                                   int value,
-                                   int minValidValue ) {
-        if (value >= minValidValue) {
-            printLine(indentLevels, text, Integer.toString(value));
-        }
-    }
-
-    private static void printLine( int indentLevels,
-                                   String text,
-                                   String value ) {
-        if (value == null || value.length() == 0) {
-            return;
-        }
-        while (indentLevels-- > 0) {
-            System.out.print("\t");
-        }
-        if (text != null && text.length() > 0) {
-            System.out.print(text);
-            System.out.print(" ");
-        }
-        System.out.println(value);
-    }
-
-    private static void printVerbose( String sourceName,
-                                      ImageMetadata ii ) {
-        printLine(0, null, sourceName);
-        printLine(1, "File format: ", ii.getFormatName());
-        printLine(1, "MIME type: ", ii.getMimeType());
-        printLine(1, "Width (pixels): ", ii.getWidth(), 1);
-        printLine(1, "Height (pixels): ", ii.getHeight(), 1);
-        printLine(1, "Bits per pixel: ", ii.getBitsPerPixel(), 1);
-        printLine(1, "Progressive: ", ii.isProgressive() ? "yes" : "no");
-        printLine(1, "Number of images: ", ii.getNumberOfImages(), 1);
-        printLine(1, "Physical width (dpi): ", ii.getPhysicalWidthDpi(), 1);
-        printLine(1, "Physical height (dpi): ", ii.getPhysicalHeightDpi(), 1);
-        printLine(1, "Physical width (inches): ", ii.getPhysicalWidthInch(), 1.0f);
-        printLine(1, "Physical height (inches): ", ii.getPhysicalHeightInch(), 1.0f);
-        int numComments = ii.getNumberOfComments();
-        printLine(1, "Number of textual comments: ", numComments, 1);
-        if (numComments > 0) {
-            for (int i = 0; i < numComments; i++) {
-                printLine(2, null, ii.getComment(i));
-            }
-        }
-    }
-
-    private int read() throws IOException {
-        if (in != null) {
-            return in.read();
-        }
-        return din.readByte();
-    }
-
-    private int read( byte[] a ) throws IOException {
-        if (in != null) {
-            return in.read(a);
-        }
-        din.readFully(a);
-        return a.length;
-    }
-
-    private int read( byte[] a,
-                      int offset,
-                      int num ) throws IOException {
-        if (in != null) {
-            return in.read(a, offset, num);
-        }
-        din.readFully(a, offset, num);
-        return num;
-    }
-
-    private String readLine() throws IOException {
-        return readLine(new StringBuffer());
-    }
-
-    private String readLine( StringBuffer sb ) throws IOException {
-        boolean finished;
-        do {
-            int value = read();
-            finished = (value == -1 || value == 10);
-            if (!finished) {
-                sb.append((char)value);
-            }
-        } while (!finished);
-        return sb.toString();
-    }
-
-    private static void run( String sourceName,
-                             InputStream in,
-                             ImageMetadata imageMetadata,
-                             boolean verbose ) {
-        imageMetadata.setInput(in);
-        imageMetadata.setDetermineImageNumber(true);
-        imageMetadata.setCollectComments(verbose);
-        if (imageMetadata.check()) {
-            print(sourceName, imageMetadata, verbose);
-        }
-    }
-
-    /**
-     * Specify whether textual comments are supposed to be extracted from input. Default is <code>false</code>. If enabled,
-     * comments will be added to an internal list.
-     * 
-     * @param newValue if <code>true</code>, this class will read comments
-     * @see #getNumberOfComments
-     * @see #getComment
-     */
-    public void setCollectComments( boolean newValue ) {
-        collectComments = newValue;
-    }
-
-    /**
-     * Specify whether the number of images in a file is to be determined - default is <code>false</code>. This is a special
-     * option because some file formats require running over the entire file to find out the number of images, a rather
-     * time-consuming task. Not all file formats support more than one image. If this method is called with <code>true</code> as
-     * argument, the actual number of images can be queried via {@link #getNumberOfImages()} after a successful call to
-     * {@link #check()}.
-     * 
-     * @param newValue will the number of images be determined?
-     * @see #getNumberOfImages
-     */
-    public void setDetermineImageNumber( boolean newValue ) {
-        determineNumberOfImages = newValue;
-    }
-
-    /**
-     * Set the input stream to the argument stream (or file). Note that {@link java.io.RandomAccessFile} implements
-     * {@link java.io.DataInput}.
-     * 
-     * @param dataInput the input stream to read from
-     */
-    public void setInput( DataInput dataInput ) {
-        din = dataInput;
-        in = null;
-    }
-
-    /**
-     * Set the input stream to the argument stream (or file).
-     * 
-     * @param inputStream the input stream to read from
-     */
-    public void setInput( InputStream inputStream ) {
-        in = inputStream;
-        din = null;
-    }
-
-    private void setPhysicalHeightDpi( int newValue ) {
-        physicalWidthDpi = newValue;
-    }
-
-    private void setPhysicalWidthDpi( int newValue ) {
-        physicalHeightDpi = newValue;
-    }
-
-    private void skip( int num ) throws IOException {
-        while (num > 0) {
-            long result;
-            if (in != null) {
-                result = in.skip(num);
-            } else {
-                result = din.skipBytes(num);
-            }
-            if (result > 0) {
-                num -= result;
-            } else {
-                if (in != null) {
-                    result = in.read();
-                } else {
-                    result = din.readByte();
-                }
-                if (result == -1) {
-                    throw new IOException("Premature end of input.");
-                }
-                num--;
-            }
-        }
-    }
-}

Copied: trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadata.java (from rev 706, trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/images/ImageMetadata.java)
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadata.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadata.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,1142 @@
+/*
+ * ImageInfo.java
+ *
+ * Version 1.9
+ *
+ * A Java class to determine image width, height and color depth for
+ * a number of image file formats.
+ *
+ * Written by Marco Schmidt 
+ *
+ * Contributed to the Public Domain.
+ */
+
+package org.jboss.dna.sequencer.image;
+
+import java.io.DataInput;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Vector;
+
+/**
+ * Get file format, image resolution, number of bits per pixel and optionally number of images, comments and physical resolution
+ * from JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM and PSD files (or input streams).
+ * <p>
+ * Use the class like this:
+ * 
+ * <pre>
+ * ImageMetadata ii = new ImageMetadata();
+ * ii.setInput(in); // in can be InputStream or RandomAccessFile
+ * ii.setDetermineImageNumber(true); // default is false
+ * ii.setCollectComments(true); // default is false
+ * if (!ii.check()) {
+ *     System.err.println(&quot;Not a supported image file format.&quot;);
+ *     return;
+ * }
+ * System.out.println(ii.getFormatName() + &quot;, &quot; + ii.getMimeType() + &quot;, &quot; + ii.getWidth() + &quot; x &quot; + ii.getHeight() + &quot; pixels, &quot;
+ *                    + ii.getBitsPerPixel() + &quot; bits per pixel, &quot; + ii.getNumberOfImages() + &quot; image(s), &quot;
+ *                    + ii.getNumberOfComments() + &quot; comment(s).&quot;);
+ * // there are other properties, check out the API documentation
+ * </pre>
+ * 
+ * You can also use this class as a command line program. Call it with a number of image file names and URLs as parameters:
+ * 
+ * <pre>
+ *   java ImageMetadata *.jpg *.png *.gif http://somesite.tld/image.jpg
+ * </pre>
+ * 
+ * or call it without parameters and pipe data to it:
+ * 
+ * <pre>
+ *   java ImageMetadata &lt; image.jpg  
+ * </pre>
+ * 
+ * <p>
+ * Known limitations:
+ * <ul>
+ * <li>When the determination of the number of images is turned off, GIF bits per pixel are only read from the global header. For
+ * some GIFs, local palettes change this to a typically larger value. To be certain to get the correct color depth, call
+ * setDetermineImageNumber(true) before calling check(). The complete scan over the GIF file will take additional time.</li>
+ * <li>Transparency information is not included in the bits per pixel count. Actually, it was my decision not to include those
+ * bits, so it's a feature! ;-)</li>
+ * </ul>
+ * <p>
+ * Requirements:
+ * <ul>
+ * <li>Java 1.1 or higher</li>
+ * </ul>
+ * <p>
+ * The latest version can be found at <a href="http://schmidt.devlib.org/image-info/">http://schmidt.devlib.org/image-info/</a>.
+ * <p>
+ * Written by Marco Schmidt.
+ * <p>
+ * This class is contributed to the Public Domain. Use it at your own risk.
+ * <p>
+ * <a name="history">History</a>:
+ * <ul>
+ * <li><strong>2001-08-24</strong> Initial version.</li>
+ * <li><strong>2001-10-13</strong> Added support for the file formats BMP and PCX.</li>
+ * <li><strong>2001-10-16</strong> Fixed bug in read(int[], int, int) that returned
+ * <li><strong>2002-01-22</strong> Added support for file formats Amiga IFF and Sun Raster (RAS).</li>
+ * <li><strong>2002-01-24</strong> Added support for file formats Portable Bitmap / Graymap / Pixmap (PBM, PGM, PPM) and Adobe
+ * Photoshop (PSD). Added new method getMimeType() to return the MIME type associated with a particular file format.</li>
+ * <li><strong>2002-03-15</strong> Added support to recognize number of images in file. Only works with GIF. Use
+ * {@link #setDetermineImageNumber} with <code>true</code> as argument to identify animated GIFs ({@link #getNumberOfImages()}
+ * will return a value larger than <code>1</code>).</li>
+ * <li><strong>2002-04-10</strong> Fixed a bug in the feature 'determine number of images in animated GIF' introduced with
+ * version 1.1. Thanks to Marcelo P. Lima for sending in the bug report. Released as 1.1.1.</li>
+ * <li><strong>2002-04-18</strong> Added {@link #setCollectComments(boolean)}. That new method lets the user specify whether
+ * textual comments are to be stored in an internal list when encountered in an input image file / stream. Added two methods to
+ * return the physical width and height of the image in dpi: {@link #getPhysicalWidthDpi()} and {@link #getPhysicalHeightDpi()}.
+ * If the physical resolution could not be retrieved, these methods return <code>-1</code>. </li>
+ * <li><strong>2002-04-23</strong> Added support for the new properties physical resolution and comments for some formats.
+ * Released as 1.2.</li>
+ * <li><strong>2002-06-17</strong> Added support for SWF, sent in by Michael Aird. Changed checkJpeg() so that other APP markers
+ * than APP0 will not lead to a failure anymore. Released as 1.3.</li>
+ * <li><strong>2003-07-28</strong> Bug fix - skip method now takes return values into consideration. Less bytes than necessary
+ * may have been skipped, leading to flaws in the retrieved information in some cases. Thanks to Bernard Bernstein for pointing
+ * that out. Released as 1.4.</li>
+ * <li><strong>2004-02-29</strong> Added support for recognizing progressive JPEG and interlaced PNG and GIF. A new method
+ * {@link #isProgressive()} returns whether ImageMetadata has found that the storage type is progressive (or interlaced). Thanks
+ * to Joe Germuska for suggesting the feature. Bug fix: BMP physical resolution is now correctly determined. Released as 1.5.</li>
+ * <li><strong>2004-11-30</strong> Bug fix: recognizing progressive GIFs (interlaced in GIF terminology) did not work (thanks to
+ * Franz Jeitler for pointing this out). Now it should work, but only if the number of images is determined. This is because
+ * information on interlacing is stored in a local image header. In theory, different images could be stored interlaced and
+ * non-interlaced in one file. However, I think that's unlikely. Right now, the last image in the GIF file that is examined by
+ * ImageMetadata is used for the "progressive" status.</li>
+ * <li><strong>2005-01-02</strong> Some code clean up (unused methods and variables commented out, missing javadoc comments,
+ * etc.). Thanks to George Sexton for a long list. Removed usage of Boolean.toString because it's a Java 1.4+ feature (thanks to
+ * Gregor Dupont). Changed delimiter character in compact output from semicolon to tabulator (for better integration with cut(1)
+ * and other Unix tools). Added some points to the <a href="http://schmidt.devlib.org/image-info/index.html#knownissues">'Known
+ * issues' section of the website</a>. Released as 1.6.</li>
+ * <li><strong>2005-07-26</strong> Removed code to identify Flash (SWF) files. Has repeatedly led to problems and support
+ * requests, and I don't know the format and don't have the time and interest to fix it myself. I repeatedly included fixes by
+ * others which didn't work for some people. I give up on SWF. Please do not contact me about it anymore. Set package of
+ * ImageMetadata class to org.devlib.schmidt.imageinfo (a package was repeatedly requested by some users). Released as 1.7.</li>
+ * <li><strong>2006-02-23</strong> Removed Flash helper methods which weren't used elsewhere. Updated skip method which tries
+ * "read" whenever "skip(Bytes)" returns a result of 0. The old method didn't work with certain input stream types on truncated
+ * data streams. Thanks to Martin Leidig for reporting this and sending in code. Released as 1.8.</li>
+ * </li>
+ * <li><strong>2006-11-13</strong> Removed check that made ImageMetadata report JPEG APPx markers smaller than 14 bytes as files
+ * in unknown format. Such JPEGs seem to be generated by Google's Picasa application. First reported with fix by Karl von Randow.
+ * Released as 1.9.</li>
+ * <li><strong>2008-04-10</strong> Changed comment vector to be <code>Vector&lt;String&gt;</code>, and removed any
+ * unnecessary casting. Also removed the unnecessary else statements where the previous block ended in a return. Also renamed to
+ * <code>ImageMetadata</code>.
+ * </ul>
+ * 
+ * @author Marco Schmidt
+ */
+public class ImageMetadata {
+
+    /**
+     * Return value of {@link #getFormat()} for JPEG streams. ImageMetadata can extract physical resolution and comments from
+     * JPEGs (only from APP0 headers). Only one image can be stored in a file. It is determined whether the JPEG stream is
+     * progressive (see {@link #isProgressive()}).
+     */
+    public static final int FORMAT_JPEG = 0;
+
+    /**
+     * Return value of {@link #getFormat()} for GIF streams. ImageMetadata can extract comments from GIFs and count the number of
+     * images (GIFs with more than one image are animations). It is determined whether the GIF stream is interlaced (see
+     * {@link #isProgressive()}).
+     */
+    public static final int FORMAT_GIF = 1;
+
+    /**
+     * Return value of {@link #getFormat()} for PNG streams. PNG only supports one image per file. Both physical resolution and
+     * comments can be stored with PNG, but ImageMetadata is currently not able to extract those. It is determined whether the PNG
+     * stream is interlaced (see {@link #isProgressive()}).
+     */
+    public static final int FORMAT_PNG = 2;
+
+    /**
+     * Return value of {@link #getFormat()} for BMP streams. BMP only supports one image per file. BMP does not allow for
+     * comments. The physical resolution can be stored.
+     */
+    public static final int FORMAT_BMP = 3;
+
+    /**
+     * Return value of {@link #getFormat()} for PCX streams. PCX does not allow for comments or more than one image per file.
+     * However, the physical resolution can be stored.
+     */
+    public static final int FORMAT_PCX = 4;
+
+    /**
+     * Return value of {@link #getFormat()} for IFF streams.
+     */
+    public static final int FORMAT_IFF = 5;
+
+    /**
+     * Return value of {@link #getFormat()} for RAS streams. Sun Raster allows for one image per file only and is not able to
+     * store physical resolution or comments.
+     */
+    public static final int FORMAT_RAS = 6;
+
+    /** Return value of {@link #getFormat()} for PBM streams. */
+    public static final int FORMAT_PBM = 7;
+
+    /** Return value of {@link #getFormat()} for PGM streams. */
+    public static final int FORMAT_PGM = 8;
+
+    /** Return value of {@link #getFormat()} for PPM streams. */
+    public static final int FORMAT_PPM = 9;
+
+    /** Return value of {@link #getFormat()} for PSD streams. */
+    public static final int FORMAT_PSD = 10;
+
+    /*
+     * public static final int COLOR_TYPE_UNKNOWN = -1; public static final int COLOR_TYPE_TRUECOLOR_RGB = 0; public static final
+     * int COLOR_TYPE_PALETTED = 1; public static final int COLOR_TYPE_GRAYSCALE= 2; public static final int
+     * COLOR_TYPE_BLACK_AND_WHITE = 3;
+     */
+
+    /**
+     * The names of all supported file formats. The FORMAT_xyz int constants can be used as index values for this array.
+     */
+    private static final String[] FORMAT_NAMES = {"JPEG", "GIF", "PNG", "BMP", "PCX", "IFF", "RAS", "PBM", "PGM", "PPM", "PSD"};
+
+    /**
+     * The names of the MIME types for all supported file formats. The FORMAT_xyz int constants can be used as index values for
+     * this array.
+     */
+    private static final String[] MIME_TYPE_STRINGS = {"image/jpeg", "image/gif", "image/png", "image/bmp", "image/pcx",
+        "image/iff", "image/ras", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap", "image/psd"};
+
+    private int width;
+    private int height;
+    private int bitsPerPixel;
+    // private int colorType = COLOR_TYPE_UNKNOWN;
+    private boolean progressive;
+    private int format;
+    private InputStream in;
+    private DataInput din;
+    private boolean collectComments = true;
+    private Vector<String> comments;
+    private boolean determineNumberOfImages;
+    private int numberOfImages;
+    private int physicalHeightDpi;
+    private int physicalWidthDpi;
+
+    private void addComment( String s ) {
+        if (comments == null) {
+            comments = new Vector<String>();
+        }
+        comments.addElement(s);
+    }
+
+    /**
+     * Call this method after you have provided an input stream or file using {@link #setInput(InputStream)} or
+     * {@link #setInput(DataInput)}. If true is returned, the file format was known and information on the file's content can be
+     * retrieved using the various getXyz methods.
+     * 
+     * @return if information could be retrieved from input
+     */
+    public boolean check() {
+        format = -1;
+        width = -1;
+        height = -1;
+        bitsPerPixel = -1;
+        numberOfImages = 1;
+        physicalHeightDpi = -1;
+        physicalWidthDpi = -1;
+        comments = null;
+        try {
+            int b1 = read() & 0xff;
+            int b2 = read() & 0xff;
+            if (b1 == 0x47 && b2 == 0x49) {
+                return checkGif();
+            } else if (b1 == 0x89 && b2 == 0x50) {
+                return checkPng();
+            } else if (b1 == 0xff && b2 == 0xd8) {
+                return checkJpeg();
+            } else if (b1 == 0x42 && b2 == 0x4d) {
+                return checkBmp();
+            } else if (b1 == 0x0a && b2 < 0x06) {
+                return checkPcx();
+            } else if (b1 == 0x46 && b2 == 0x4f) {
+                return checkIff();
+            } else if (b1 == 0x59 && b2 == 0xa6) {
+                return checkRas();
+            } else if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
+                return checkPnm(b2 - '0');
+            } else if (b1 == 0x38 && b2 == 0x42) {
+                return checkPsd();
+            } else {
+                return false;
+            }
+        } catch (IOException ioe) {
+            return false;
+        }
+    }
+
+    private boolean checkBmp() throws IOException {
+        byte[] a = new byte[44];
+        if (read(a) != a.length) {
+            return false;
+        }
+        width = getIntLittleEndian(a, 16);
+        height = getIntLittleEndian(a, 20);
+        if (width < 1 || height < 1) {
+            return false;
+        }
+        bitsPerPixel = getShortLittleEndian(a, 26);
+        if (bitsPerPixel != 1 && bitsPerPixel != 4 && bitsPerPixel != 8 && bitsPerPixel != 16 && bitsPerPixel != 24
+            && bitsPerPixel != 32) {
+            return false;
+        }
+        int x = (int)(getIntLittleEndian(a, 36) * 0.0254);
+        if (x > 0) {
+            setPhysicalWidthDpi(x);
+        }
+        int y = (int)(getIntLittleEndian(a, 40) * 0.0254);
+        if (y > 0) {
+            setPhysicalHeightDpi(y);
+        }
+        format = FORMAT_BMP;
+        return true;
+    }
+
+    private boolean checkGif() throws IOException {
+        final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
+        final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
+        byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
+        if (read(a) != 11) {
+            return false;
+        }
+        if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4)) && (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
+            return false;
+        }
+        format = FORMAT_GIF;
+        width = getShortLittleEndian(a, 4);
+        height = getShortLittleEndian(a, 6);
+        int flags = a[8] & 0xff;
+        bitsPerPixel = ((flags >> 4) & 0x07) + 1;
+        // progressive = (flags & 0x02) != 0;
+        if (!determineNumberOfImages) {
+            return true;
+        }
+        // skip global color palette
+        if ((flags & 0x80) != 0) {
+            int tableSize = (1 << ((flags & 7) + 1)) * 3;
+            skip(tableSize);
+        }
+        numberOfImages = 0;
+        int blockType;
+        do {
+            blockType = read();
+            switch (blockType) {
+                case (0x2c): // image separator
+                {
+                    if (read(a, 0, 9) != 9) {
+                        return false;
+                    }
+                    flags = a[8] & 0xff;
+                    progressive = (flags & 0x40) != 0;
+                    /*
+                     * int locWidth = getShortLittleEndian(a, 4); int locHeight = getShortLittleEndian(a, 6);
+                     * System.out.println("LOCAL: " + locWidth + " x " + locHeight);
+                     */
+                    int localBitsPerPixel = (flags & 0x07) + 1;
+                    if (localBitsPerPixel > bitsPerPixel) {
+                        bitsPerPixel = localBitsPerPixel;
+                    }
+                    if ((flags & 0x80) != 0) {
+                        skip((1 << localBitsPerPixel) * 3);
+                    }
+                    skip(1); // initial code length
+                    int n;
+                    do {
+                        n = read();
+                        if (n > 0) {
+                            skip(n);
+                        } else if (n == -1) {
+                            return false;
+                        }
+                    } while (n > 0);
+                    numberOfImages++;
+                    break;
+                }
+                case (0x21): // extension
+                {
+                    int extensionType = read();
+                    if (collectComments && extensionType == 0xfe) {
+                        StringBuffer sb = new StringBuffer();
+                        int n;
+                        do {
+                            n = read();
+                            if (n == -1) {
+                                return false;
+                            }
+                            if (n > 0) {
+                                for (int i = 0; i < n; i++) {
+                                    int ch = read();
+                                    if (ch == -1) {
+                                        return false;
+                                    }
+                                    sb.append((char)ch);
+                                }
+                            }
+                        } while (n > 0);
+                    } else {
+                        int n;
+                        do {
+                            n = read();
+                            if (n > 0) {
+                                skip(n);
+                            } else if (n == -1) {
+                                return false;
+                            }
+                        } while (n > 0);
+                    }
+                    break;
+                }
+                case (0x3b): // end of file
+                {
+                    break;
+                }
+                default: {
+                    return false;
+                }
+            }
+        } while (blockType != 0x3b);
+        return true;
+    }
+
+    private boolean checkIff() throws IOException {
+        byte[] a = new byte[10];
+        // read remaining 2 bytes of file id, 4 bytes file size
+        // and 4 bytes IFF subformat
+        if (read(a, 0, 10) != 10) {
+            return false;
+        }
+        final byte[] IFF_RM = {0x52, 0x4d};
+        if (!equals(a, 0, IFF_RM, 0, 2)) {
+            return false;
+        }
+        int type = getIntBigEndian(a, 6);
+        if (type != 0x494c424d && // type must be ILBM...
+            type != 0x50424d20) { // ...or PBM
+            return false;
+        }
+        // loop chunks to find BMHD chunk
+        do {
+            if (read(a, 0, 8) != 8) {
+                return false;
+            }
+            int chunkId = getIntBigEndian(a, 0);
+            int size = getIntBigEndian(a, 4);
+            if ((size & 1) == 1) {
+                size++;
+            }
+            if (chunkId == 0x424d4844) { // BMHD chunk
+                if (read(a, 0, 9) != 9) {
+                    return false;
+                }
+                format = FORMAT_IFF;
+                width = getShortBigEndian(a, 0);
+                height = getShortBigEndian(a, 2);
+                bitsPerPixel = a[8] & 0xff;
+                return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel < 33);
+            }
+            skip(size);
+        } while (true);
+    }
+
+    private boolean checkJpeg() throws IOException {
+        byte[] data = new byte[12];
+        while (true) {
+            if (read(data, 0, 4) != 4) {
+                return false;
+            }
+            int marker = getShortBigEndian(data, 0);
+            int size = getShortBigEndian(data, 2);
+            if ((marker & 0xff00) != 0xff00) {
+                return false; // not a valid marker
+            }
+            if (marker == 0xffe0) { // APPx
+                if (size < 14) {
+                    // not an APPx header as we know it, skip
+                    skip(size - 2);
+                    continue;
+                }
+                if (read(data, 0, 12) != 12) {
+                    return false;
+                }
+                final byte[] APP0_ID = {0x4a, 0x46, 0x49, 0x46, 0x00};
+                if (equals(APP0_ID, 0, data, 0, 5)) {
+                    // System.out.println("data 7=" + data[7]);
+                    if (data[7] == 1) {
+                        setPhysicalWidthDpi(getShortBigEndian(data, 8));
+                        setPhysicalHeightDpi(getShortBigEndian(data, 10));
+                    } else if (data[7] == 2) {
+                        int x = getShortBigEndian(data, 8);
+                        int y = getShortBigEndian(data, 10);
+                        setPhysicalWidthDpi((int)(x * 2.54f));
+                        setPhysicalHeightDpi((int)(y * 2.54f));
+                    }
+                }
+                skip(size - 14);
+            } else if (collectComments && size > 2 && marker == 0xfffe) { // comment
+                size -= 2;
+                byte[] chars = new byte[size];
+                if (read(chars, 0, size) != size) {
+                    return false;
+                }
+                String comment = new String(chars, "iso-8859-1");
+                comment = comment.trim();
+                addComment(comment);
+            } else if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 && marker != 0xffc8) {
+                if (read(data, 0, 6) != 6) {
+                    return false;
+                }
+                format = FORMAT_JPEG;
+                bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
+                progressive = marker == 0xffc2 || marker == 0xffc6 || marker == 0xffca || marker == 0xffce;
+                width = getShortBigEndian(data, 3);
+                height = getShortBigEndian(data, 1);
+                return true;
+            } else {
+                skip(size - 2);
+            }
+        }
+    }
+
+    private boolean checkPcx() throws IOException {
+        byte[] a = new byte[64];
+        if (read(a) != a.length) {
+            return false;
+        }
+        if (a[0] != 1) { // encoding, 1=RLE is only valid value
+            return false;
+        }
+        // width / height
+        int x1 = getShortLittleEndian(a, 2);
+        int y1 = getShortLittleEndian(a, 4);
+        int x2 = getShortLittleEndian(a, 6);
+        int y2 = getShortLittleEndian(a, 8);
+        if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
+            return false;
+        }
+        width = x2 - x1 + 1;
+        height = y2 - y1 + 1;
+        // color depth
+        int bits = a[1];
+        int planes = a[63];
+        if (planes == 1 && (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
+            // paletted
+            bitsPerPixel = bits;
+        } else if (planes == 3 && bits == 8) {
+            // RGB truecolor
+            bitsPerPixel = 24;
+        } else {
+            return false;
+        }
+        setPhysicalWidthDpi(getShortLittleEndian(a, 10));
+        setPhysicalHeightDpi(getShortLittleEndian(a, 10));
+        format = FORMAT_PCX;
+        return true;
+    }
+
+    private boolean checkPng() throws IOException {
+        final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
+        byte[] a = new byte[27];
+        if (read(a) != 27) {
+            return false;
+        }
+        if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
+            return false;
+        }
+        format = FORMAT_PNG;
+        width = getIntBigEndian(a, 14);
+        height = getIntBigEndian(a, 18);
+        bitsPerPixel = a[22] & 0xff;
+        int colorType = a[23] & 0xff;
+        if (colorType == 2 || colorType == 6) {
+            bitsPerPixel *= 3;
+        }
+        progressive = (a[26] & 0xff) != 0;
+        return true;
+    }
+
+    private boolean checkPnm( int id ) throws IOException {
+        if (id < 1 || id > 6) {
+            return false;
+        }
+        final int[] PNM_FORMATS = {FORMAT_PBM, FORMAT_PGM, FORMAT_PPM};
+        format = PNM_FORMATS[(id - 1) % 3];
+        boolean hasPixelResolution = false;
+        String s;
+        while (true) {
+            s = readLine();
+            if (s != null) {
+                s = s.trim();
+            }
+            if (s == null || s.length() < 1) {
+                continue;
+            }
+            if (s.charAt(0) == '#') { // comment
+                if (collectComments && s.length() > 1) {
+                    addComment(s.substring(1));
+                }
+                continue;
+            }
+            if (!hasPixelResolution) { // split "343 966" into width=343, height=966
+                int spaceIndex = s.indexOf(' ');
+                if (spaceIndex == -1) {
+                    return false;
+                }
+                String widthString = s.substring(0, spaceIndex);
+                spaceIndex = s.lastIndexOf(' ');
+                if (spaceIndex == -1) {
+                    return false;
+                }
+                String heightString = s.substring(spaceIndex + 1);
+                try {
+                    width = Integer.parseInt(widthString);
+                    height = Integer.parseInt(heightString);
+                } catch (NumberFormatException nfe) {
+                    return false;
+                }
+                if (width < 1 || height < 1) {
+                    return false;
+                }
+                if (format == FORMAT_PBM) {
+                    bitsPerPixel = 1;
+                    return true;
+                }
+                hasPixelResolution = true;
+            } else {
+                int maxSample;
+                try {
+                    maxSample = Integer.parseInt(s);
+                } catch (NumberFormatException nfe) {
+                    return false;
+                }
+                if (maxSample < 0) {
+                    return false;
+                }
+                for (int i = 0; i < 25; i++) {
+                    if (maxSample < (1 << (i + 1))) {
+                        bitsPerPixel = i + 1;
+                        if (format == FORMAT_PPM) {
+                            bitsPerPixel *= 3;
+                        }
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+    }
+
+    private boolean checkPsd() throws IOException {
+        byte[] a = new byte[24];
+        if (read(a) != a.length) {
+            return false;
+        }
+        final byte[] PSD_MAGIC = {0x50, 0x53};
+        if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
+            return false;
+        }
+        format = FORMAT_PSD;
+        width = getIntBigEndian(a, 16);
+        height = getIntBigEndian(a, 12);
+        int channels = getShortBigEndian(a, 10);
+        int depth = getShortBigEndian(a, 20);
+        bitsPerPixel = channels * depth;
+        return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 64);
+    }
+
+    private boolean checkRas() throws IOException {
+        byte[] a = new byte[14];
+        if (read(a) != a.length) {
+            return false;
+        }
+        final byte[] RAS_MAGIC = {0x6a, (byte)0x95};
+        if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
+            return false;
+        }
+        format = FORMAT_RAS;
+        width = getIntBigEndian(a, 2);
+        height = getIntBigEndian(a, 6);
+        bitsPerPixel = getIntBigEndian(a, 10);
+        return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 24);
+    }
+
+    /**
+     * Run over String list, return false if and only if at least one of the arguments equals <code>-c</code>.
+     * 
+     * @param args string list to check
+     * @return <code>true</code> none of the supplied parameters is <code>-c</code>
+     */
+    private static boolean determineVerbosity( String[] args ) {
+        if (args != null && args.length > 0) {
+            for (int i = 0; i < args.length; i++) {
+                if ("-c".equals(args[i])) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private static boolean equals( byte[] a1,
+                                   int offs1,
+                                   byte[] a2,
+                                   int offs2,
+                                   int num ) {
+        while (num-- > 0) {
+            if (a1[offs1++] != a2[offs2++]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * If {@link #check()} was successful, returns the image's number of bits per pixel. Does not include transparency information
+     * like the alpha channel.
+     * 
+     * @return number of bits per image pixel
+     */
+    public int getBitsPerPixel() {
+        return bitsPerPixel;
+    }
+
+    /**
+     * Returns the index'th comment retrieved from the file.
+     * 
+     * @param index int index of comment to return
+     * @return the comment at the supplied index
+     * @throws IllegalArgumentException if index is smaller than 0 or larger than or equal to the number of comments retrieved
+     * @see #getNumberOfComments
+     */
+    public String getComment( int index ) {
+        if (comments == null || index < 0 || index >= comments.size()) {
+            throw new IllegalArgumentException("Not a valid comment index: " + index);
+        }
+        return comments.elementAt(index);
+    }
+
+    /**
+     * If {@link #check()} was successful, returns the image format as one of the FORMAT_xyz constants from this class. Use
+     * {@link #getFormatName()} to get a textual description of the file format.
+     * 
+     * @return file format as a FORMAT_xyz constant
+     */
+    public int getFormat() {
+        return format;
+    }
+
+    /**
+     * If {@link #check()} was successful, returns the image format's name. Use {@link #getFormat()} to get a unique number.
+     * 
+     * @return file format name
+     */
+    public String getFormatName() {
+        if (format >= 0 && format < FORMAT_NAMES.length) {
+            return FORMAT_NAMES[format];
+        }
+        return "?";
+    }
+
+    /**
+     * If {@link #check()} was successful, returns one the image's vertical resolution in pixels.
+     * 
+     * @return image height in pixels
+     */
+    public int getHeight() {
+        return height;
+    }
+
+    private static int getIntBigEndian( byte[] a,
+                                        int offs ) {
+        return (a[offs] & 0xff) << 24 | (a[offs + 1] & 0xff) << 16 | (a[offs + 2] & 0xff) << 8 | a[offs + 3] & 0xff;
+    }
+
+    private static int getIntLittleEndian( byte[] a,
+                                           int offs ) {
+        return (a[offs + 3] & 0xff) << 24 | (a[offs + 2] & 0xff) << 16 | (a[offs + 1] & 0xff) << 8 | a[offs] & 0xff;
+    }
+
+    /**
+     * If {@link #check()} was successful, returns a String with the MIME type of the format.
+     * 
+     * @return MIME type, e.g. <code>image/jpeg</code>
+     */
+    public String getMimeType() {
+        if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
+            if (format == FORMAT_JPEG && progressive) {
+                return "image/pjpeg";
+            }
+            return MIME_TYPE_STRINGS[format];
+        }
+        return null;
+    }
+
+    /**
+     * If {@link #check()} was successful and {@link #setCollectComments(boolean)} was called with <code>true</code> as
+     * argument, returns the number of comments retrieved from the input image stream / file. Any number &gt;= 0 and smaller than
+     * this number of comments is then a valid argument for the {@link #getComment(int)} method.
+     * 
+     * @return number of comments retrieved from input image
+     */
+    public int getNumberOfComments() {
+        if (comments == null) {
+            return 0;
+        }
+        return comments.size();
+    }
+
+    /**
+     * Returns the number of images in the examined file. Assumes that <code>setDetermineImageNumber(true);</code> was called
+     * before a successful call to {@link #check()}. This value can currently be only different from <code>1</code> for GIF
+     * images.
+     * 
+     * @return number of images in file
+     */
+    public int getNumberOfImages() {
+        return numberOfImages;
+    }
+
+    /**
+     * Returns the physical height of this image in dots per inch (dpi). Assumes that {@link #check()} was successful. Returns
+     * <code>-1</code> on failure.
+     * 
+     * @return physical height (in dpi)
+     * @see #getPhysicalWidthDpi()
+     * @see #getPhysicalHeightInch()
+     */
+    public int getPhysicalHeightDpi() {
+        return physicalHeightDpi;
+    }
+
+    /**
+     * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch) or -1 if no value could
+     * be found.
+     * 
+     * @return physical height (in dpi)
+     * @see #getPhysicalHeightDpi()
+     * @see #getPhysicalWidthDpi()
+     * @see #getPhysicalWidthInch()
+     */
+    public float getPhysicalHeightInch() {
+        int h = getHeight();
+        int ph = getPhysicalHeightDpi();
+        if (h > 0 && ph > 0) {
+            return ((float)h) / ((float)ph);
+        }
+        return -1.0f;
+    }
+
+    /**
+     * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch) or -1 if no value could
+     * be found.
+     * 
+     * @return physical width (in dpi)
+     * @see #getPhysicalHeightDpi()
+     * @see #getPhysicalWidthInch()
+     * @see #getPhysicalHeightInch()
+     */
+    public int getPhysicalWidthDpi() {
+        return physicalWidthDpi;
+    }
+
+    /**
+     * Returns the physical width of an image in inches, or <code>-1.0f</code> if width information is not available. Assumes
+     * that {@link #check} has been called successfully.
+     * 
+     * @return physical width in inches or <code>-1.0f</code> on failure
+     * @see #getPhysicalWidthDpi
+     * @see #getPhysicalHeightInch
+     */
+    public float getPhysicalWidthInch() {
+        int w = getWidth();
+        int pw = getPhysicalWidthDpi();
+        if (w > 0 && pw > 0) {
+            return ((float)w) / ((float)pw);
+        }
+        return -1.0f;
+    }
+
+    private static int getShortBigEndian( byte[] a,
+                                          int offs ) {
+        return (a[offs] & 0xff) << 8 | (a[offs + 1] & 0xff);
+    }
+
+    private static int getShortLittleEndian( byte[] a,
+                                             int offs ) {
+        return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
+    }
+
+    /**
+     * If {@link #check()} was successful, returns one the image's horizontal resolution in pixels.
+     * 
+     * @return image width in pixels
+     */
+    public int getWidth() {
+        return width;
+    }
+
+    /**
+     * Returns whether the image is stored in a progressive (also called: interlaced) way.
+     * 
+     * @return true for progressive/interlaced, false otherwise
+     */
+    public boolean isProgressive() {
+        return progressive;
+    }
+
+    /**
+     * To use this class as a command line application, give it either some file names as parameters (information on them will be
+     * printed to standard output, one line per file) or call it with no parameters. It will then check data given to it via
+     * standard input.
+     * 
+     * @param args the program arguments which must be file names
+     */
+    public static void main( String[] args ) {
+        ImageMetadata imageMetadata = new ImageMetadata();
+        imageMetadata.setDetermineImageNumber(true);
+        boolean verbose = determineVerbosity(args);
+        if (args.length == 0) {
+            run(null, System.in, imageMetadata, verbose);
+        } else {
+            int index = 0;
+            while (index < args.length) {
+                InputStream in = null;
+                try {
+                    String name = args[index++];
+                    System.out.print(name + ";");
+                    if (name.startsWith("http://")) {
+                        in = new URL(name).openConnection().getInputStream();
+                    } else {
+                        in = new FileInputStream(name);
+                    }
+                    run(name, in, imageMetadata, verbose);
+                    in.close();
+                } catch (IOException e) {
+                    System.out.println(e);
+                    try {
+                        if (in != null) {
+                            in.close();
+                        }
+                    } catch (IOException ee) {
+                    }
+                }
+            }
+        }
+    }
+
+    private static void print( String sourceName,
+                               ImageMetadata ii,
+                               boolean verbose ) {
+        if (verbose) {
+            printVerbose(sourceName, ii);
+        } else {
+            printCompact(sourceName, ii);
+        }
+    }
+
+    private static void printCompact( String sourceName,
+                                      ImageMetadata imageMetadata ) {
+        final String SEP = "\t";
+        System.out.println(sourceName + SEP + imageMetadata.getFormatName() + SEP + imageMetadata.getMimeType() + SEP
+                           + imageMetadata.getWidth() + SEP + imageMetadata.getHeight() + SEP + imageMetadata.getBitsPerPixel()
+                           + SEP + imageMetadata.getNumberOfImages() + SEP + imageMetadata.getPhysicalWidthDpi() + SEP
+                           + imageMetadata.getPhysicalHeightDpi() + SEP + imageMetadata.getPhysicalWidthInch() + SEP
+                           + imageMetadata.getPhysicalHeightInch() + SEP + imageMetadata.isProgressive());
+    }
+
+    private static void printLine( int indentLevels,
+                                   String text,
+                                   float value,
+                                   float minValidValue ) {
+        if (value < minValidValue) {
+            return;
+        }
+        printLine(indentLevels, text, Float.toString(value));
+    }
+
+    private static void printLine( int indentLevels,
+                                   String text,
+                                   int value,
+                                   int minValidValue ) {
+        if (value >= minValidValue) {
+            printLine(indentLevels, text, Integer.toString(value));
+        }
+    }
+
+    private static void printLine( int indentLevels,
+                                   String text,
+                                   String value ) {
+        if (value == null || value.length() == 0) {
+            return;
+        }
+        while (indentLevels-- > 0) {
+            System.out.print("\t");
+        }
+        if (text != null && text.length() > 0) {
+            System.out.print(text);
+            System.out.print(" ");
+        }
+        System.out.println(value);
+    }
+
+    private static void printVerbose( String sourceName,
+                                      ImageMetadata ii ) {
+        printLine(0, null, sourceName);
+        printLine(1, "File format: ", ii.getFormatName());
+        printLine(1, "MIME type: ", ii.getMimeType());
+        printLine(1, "Width (pixels): ", ii.getWidth(), 1);
+        printLine(1, "Height (pixels): ", ii.getHeight(), 1);
+        printLine(1, "Bits per pixel: ", ii.getBitsPerPixel(), 1);
+        printLine(1, "Progressive: ", ii.isProgressive() ? "yes" : "no");
+        printLine(1, "Number of images: ", ii.getNumberOfImages(), 1);
+        printLine(1, "Physical width (dpi): ", ii.getPhysicalWidthDpi(), 1);
+        printLine(1, "Physical height (dpi): ", ii.getPhysicalHeightDpi(), 1);
+        printLine(1, "Physical width (inches): ", ii.getPhysicalWidthInch(), 1.0f);
+        printLine(1, "Physical height (inches): ", ii.getPhysicalHeightInch(), 1.0f);
+        int numComments = ii.getNumberOfComments();
+        printLine(1, "Number of textual comments: ", numComments, 1);
+        if (numComments > 0) {
+            for (int i = 0; i < numComments; i++) {
+                printLine(2, null, ii.getComment(i));
+            }
+        }
+    }
+
+    private int read() throws IOException {
+        if (in != null) {
+            return in.read();
+        }
+        return din.readByte();
+    }
+
+    private int read( byte[] a ) throws IOException {
+        if (in != null) {
+            return in.read(a);
+        }
+        din.readFully(a);
+        return a.length;
+    }
+
+    private int read( byte[] a,
+                      int offset,
+                      int num ) throws IOException {
+        if (in != null) {
+            return in.read(a, offset, num);
+        }
+        din.readFully(a, offset, num);
+        return num;
+    }
+
+    private String readLine() throws IOException {
+        return readLine(new StringBuffer());
+    }
+
+    private String readLine( StringBuffer sb ) throws IOException {
+        boolean finished;
+        do {
+            int value = read();
+            finished = (value == -1 || value == 10);
+            if (!finished) {
+                sb.append((char)value);
+            }
+        } while (!finished);
+        return sb.toString();
+    }
+
+    private static void run( String sourceName,
+                             InputStream in,
+                             ImageMetadata imageMetadata,
+                             boolean verbose ) {
+        imageMetadata.setInput(in);
+        imageMetadata.setDetermineImageNumber(true);
+        imageMetadata.setCollectComments(verbose);
+        if (imageMetadata.check()) {
+            print(sourceName, imageMetadata, verbose);
+        }
+    }
+
+    /**
+     * Specify whether textual comments are supposed to be extracted from input. Default is <code>false</code>. If enabled,
+     * comments will be added to an internal list.
+     * 
+     * @param newValue if <code>true</code>, this class will read comments
+     * @see #getNumberOfComments
+     * @see #getComment
+     */
+    public void setCollectComments( boolean newValue ) {
+        collectComments = newValue;
+    }
+
+    /**
+     * Specify whether the number of images in a file is to be determined - default is <code>false</code>. This is a special
+     * option because some file formats require running over the entire file to find out the number of images, a rather
+     * time-consuming task. Not all file formats support more than one image. If this method is called with <code>true</code> as
+     * argument, the actual number of images can be queried via {@link #getNumberOfImages()} after a successful call to
+     * {@link #check()}.
+     * 
+     * @param newValue will the number of images be determined?
+     * @see #getNumberOfImages
+     */
+    public void setDetermineImageNumber( boolean newValue ) {
+        determineNumberOfImages = newValue;
+    }
+
+    /**
+     * Set the input stream to the argument stream (or file). Note that {@link java.io.RandomAccessFile} implements
+     * {@link java.io.DataInput}.
+     * 
+     * @param dataInput the input stream to read from
+     */
+    public void setInput( DataInput dataInput ) {
+        din = dataInput;
+        in = null;
+    }
+
+    /**
+     * Set the input stream to the argument stream (or file).
+     * 
+     * @param inputStream the input stream to read from
+     */
+    public void setInput( InputStream inputStream ) {
+        in = inputStream;
+        din = null;
+    }
+
+    private void setPhysicalHeightDpi( int newValue ) {
+        physicalWidthDpi = newValue;
+    }
+
+    private void setPhysicalWidthDpi( int newValue ) {
+        physicalHeightDpi = newValue;
+    }
+
+    private void skip( int num ) throws IOException {
+        while (num > 0) {
+            long result;
+            if (in != null) {
+                result = in.skip(num);
+            } else {
+                result = din.skipBytes(num);
+            }
+            if (result > 0) {
+                num -= result;
+            } else {
+                if (in != null) {
+                    result = in.read();
+                } else {
+                    result = din.readByte();
+                }
+                if (result == -1) {
+                    throw new IOException("Premature end of input.");
+                }
+                num--;
+            }
+        }
+    }
+}

Deleted: trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadataSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/images/ImageMetadataSequencer.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadataSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,128 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.sequencer.images;
-
-import java.io.InputStream;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
-
-/**
- * A sequencer that processes the binary content of an image file, extracts the metadata for the image, and then writes that image
- * metadata to the repository.
- * <p>
- * This sequencer produces data that corresponds to the following structure:
- * <ul>
- * <li><strong>image:metadata</strong> node of type <code>image:metadata</code>
- * <ul>
- * <li><strong>jcr:mimeType</strong> - optional string property for the mime type of the image</li>
- * <li><strong>jcr:encoding</strong> - optional string property for the encoding of the image</li>
- * <li><strong>image:formatName</strong> - string property for the name of the format</li>
- * <li><strong>image:width</strong> - optional integer property for the image's width in pixels</li>
- * <li><strong>image:height</strong> - optional integer property for the image's height in pixles</li>
- * <li><strong>image:bitsPerPixel</strong> - optional integer property for the number of bits per pixel</li>
- * <li><strong>image:progressive</strong> - optional boolean property specifying whether the image is stored in a progressive
- * (i.e., interlaced) form</li>
- * <li><strong>image:numberOfImages</strong> - optional integer property for the number of images stored in the file; defaults to
- * 1</li>
- * <li><strong>image:physicalWidthDpi</strong> - optional integer property for the physical width of the image in dots per inch</li>
- * <li><strong>image:physicalHeightDpi</strong> - optional integer property for the physical height of the image in dots per inch</li>
- * <li><strong>image:physicalWidthInches</strong> - optional double property for the physical width of the image in inches</li>
- * <li><strong>image:physicalHeightInches</strong> - optional double property for the physical height of the image in inches</li>
- * </ul>
- * </li>
- * </ul>
- * </p>
- * <p>
- * This structure could be extended in the future to add EXIF and IPTC metadata as child nodes. For example, EXIF metadata is
- * structured as tags in directories, where the directories form something like namespaces, and which are used by different camera
- * vendors to store custom metadata. This structure could be mapped with each directory (e.g. "EXIF" or "Nikon Makernote" or
- * "IPTC") as the name of a child node, with the EXIF tags values stored as either properties or child nodes.
- * </p>
- * 
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class ImageMetadataSequencer implements StreamSequencer {
-
-    public static final String METADATA_NODE = "image:metadata";
-    public static final String IMAGE_PRIMARY_TYPE = "jcr:primaryType";
-    public static final String IMAGE_MIXINS = "jcr:mixinTypes";
-    public static final String IMAGE_MIME_TYPE = "jcr:mimeType";
-    public static final String IMAGE_ENCODING = "jcr:encoding";
-    public static final String IMAGE_FORMAT_NAME = "image:formatName";
-    public static final String IMAGE_WIDTH = "image:width";
-    public static final String IMAGE_HEIGHT = "image:height";
-    public static final String IMAGE_BITS_PER_PIXEL = "image:bitsPerPixel";
-    public static final String IMAGE_PROGRESSIVE = "image:progressive";
-    public static final String IMAGE_NUMBER_OF_IMAGES = "image:numberOfImages";
-    public static final String IMAGE_PHYSICAL_WIDTH_DPI = "image:physicalWidthDpi";
-    public static final String IMAGE_PHYSICAL_HEIGHT_DPI = "image:physicalHeightDpi";
-    public static final String IMAGE_PHYSICAL_WIDTH_INCHES = "image:physicalWidthInches";
-    public static final String IMAGE_PHYSICAL_HEIGHT_INCHES = "image:physicalHeightInches";
-
-    /**
-     * {@inheritDoc}
-     * 
-     * @see StreamSequencer#sequence(InputStream, SequencerOutput, SequencerContext)
-     */
-    public void sequence( InputStream stream,
-                          SequencerOutput output,
-                          SequencerContext context ) {
-
-        ImageMetadata metadata = new ImageMetadata();
-        metadata.setInput(stream);
-        metadata.setDetermineImageNumber(true);
-        metadata.setCollectComments(true);
-
-        // Process the image stream and extract the metadata ...
-        if (!metadata.check()) {
-            metadata = null;
-        }
-
-        // Generate the output graph if we found useful metadata ...
-        if (metadata != null) {
-            NameFactory nameFactory = context.getValueFactories().getNameFactory();
-            PathFactory pathFactory = context.getValueFactories().getPathFactory();
-            Path metadataNode = pathFactory.create(METADATA_NODE);
-
-            // Place the image metadata into the output map ...
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_PRIMARY_TYPE), "image:metadata");
-            // output.psetProperty(metadataNode, nameFactory.create(IMAGE_MIXINS), "");
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_MIME_TYPE), metadata.getMimeType());
-            // output.setProperty(metadataNode, nameFactory.create(IMAGE_ENCODING), "");
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_FORMAT_NAME), metadata.getFormatName());
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_WIDTH), metadata.getWidth());
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_HEIGHT), metadata.getHeight());
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_BITS_PER_PIXEL), metadata.getBitsPerPixel());
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_PROGRESSIVE), metadata.isProgressive());
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_NUMBER_OF_IMAGES), metadata.getNumberOfImages());
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_PHYSICAL_WIDTH_DPI), metadata.getPhysicalWidthDpi());
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_PHYSICAL_HEIGHT_DPI), metadata.getPhysicalHeightDpi());
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_PHYSICAL_WIDTH_INCHES), metadata.getPhysicalWidthInch());
-            output.setProperty(metadataNode, nameFactory.create(IMAGE_PHYSICAL_HEIGHT_INCHES), metadata.getPhysicalHeightInch());
-        }
-    }
-}

Copied: trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadataSequencer.java (from rev 706, trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/images/ImageMetadataSequencer.java)
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadataSequencer.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageMetadataSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,128 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.image;
+
+import java.io.InputStream;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
+import org.jboss.dna.graph.sequencer.StreamSequencer;
+
+/**
+ * A sequencer that processes the binary content of an image file, extracts the metadata for the image, and then writes that image
+ * metadata to the repository.
+ * <p>
+ * This sequencer produces data that corresponds to the following structure:
+ * <ul>
+ * <li><strong>image:metadata</strong> node of type <code>image:metadata</code>
+ * <ul>
+ * <li><strong>jcr:mimeType</strong> - optional string property for the mime type of the image</li>
+ * <li><strong>jcr:encoding</strong> - optional string property for the encoding of the image</li>
+ * <li><strong>image:formatName</strong> - string property for the name of the format</li>
+ * <li><strong>image:width</strong> - optional integer property for the image's width in pixels</li>
+ * <li><strong>image:height</strong> - optional integer property for the image's height in pixles</li>
+ * <li><strong>image:bitsPerPixel</strong> - optional integer property for the number of bits per pixel</li>
+ * <li><strong>image:progressive</strong> - optional boolean property specifying whether the image is stored in a progressive
+ * (i.e., interlaced) form</li>
+ * <li><strong>image:numberOfImages</strong> - optional integer property for the number of images stored in the file; defaults to
+ * 1</li>
+ * <li><strong>image:physicalWidthDpi</strong> - optional integer property for the physical width of the image in dots per inch</li>
+ * <li><strong>image:physicalHeightDpi</strong> - optional integer property for the physical height of the image in dots per inch</li>
+ * <li><strong>image:physicalWidthInches</strong> - optional double property for the physical width of the image in inches</li>
+ * <li><strong>image:physicalHeightInches</strong> - optional double property for the physical height of the image in inches</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </p>
+ * <p>
+ * This structure could be extended in the future to add EXIF and IPTC metadata as child nodes. For example, EXIF metadata is
+ * structured as tags in directories, where the directories form something like namespaces, and which are used by different camera
+ * vendors to store custom metadata. This structure could be mapped with each directory (e.g. "EXIF" or "Nikon Makernote" or
+ * "IPTC") as the name of a child node, with the EXIF tags values stored as either properties or child nodes.
+ * </p>
+ * 
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class ImageMetadataSequencer implements StreamSequencer {
+
+    public static final String METADATA_NODE = "image:metadata";
+    public static final String IMAGE_PRIMARY_TYPE = "jcr:primaryType";
+    public static final String IMAGE_MIXINS = "jcr:mixinTypes";
+    public static final String IMAGE_MIME_TYPE = "jcr:mimeType";
+    public static final String IMAGE_ENCODING = "jcr:encoding";
+    public static final String IMAGE_FORMAT_NAME = "image:formatName";
+    public static final String IMAGE_WIDTH = "image:width";
+    public static final String IMAGE_HEIGHT = "image:height";
+    public static final String IMAGE_BITS_PER_PIXEL = "image:bitsPerPixel";
+    public static final String IMAGE_PROGRESSIVE = "image:progressive";
+    public static final String IMAGE_NUMBER_OF_IMAGES = "image:numberOfImages";
+    public static final String IMAGE_PHYSICAL_WIDTH_DPI = "image:physicalWidthDpi";
+    public static final String IMAGE_PHYSICAL_HEIGHT_DPI = "image:physicalHeightDpi";
+    public static final String IMAGE_PHYSICAL_WIDTH_INCHES = "image:physicalWidthInches";
+    public static final String IMAGE_PHYSICAL_HEIGHT_INCHES = "image:physicalHeightInches";
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see StreamSequencer#sequence(InputStream, SequencerOutput, SequencerContext)
+     */
+    public void sequence( InputStream stream,
+                          SequencerOutput output,
+                          SequencerContext context ) {
+
+        ImageMetadata metadata = new ImageMetadata();
+        metadata.setInput(stream);
+        metadata.setDetermineImageNumber(true);
+        metadata.setCollectComments(true);
+
+        // Process the image stream and extract the metadata ...
+        if (!metadata.check()) {
+            metadata = null;
+        }
+
+        // Generate the output graph if we found useful metadata ...
+        if (metadata != null) {
+            NameFactory nameFactory = context.getValueFactories().getNameFactory();
+            PathFactory pathFactory = context.getValueFactories().getPathFactory();
+            Path metadataNode = pathFactory.create(METADATA_NODE);
+
+            // Place the image metadata into the output map ...
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_PRIMARY_TYPE), "image:metadata");
+            // output.psetProperty(metadataNode, nameFactory.create(IMAGE_MIXINS), "");
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_MIME_TYPE), metadata.getMimeType());
+            // output.setProperty(metadataNode, nameFactory.create(IMAGE_ENCODING), "");
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_FORMAT_NAME), metadata.getFormatName());
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_WIDTH), metadata.getWidth());
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_HEIGHT), metadata.getHeight());
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_BITS_PER_PIXEL), metadata.getBitsPerPixel());
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_PROGRESSIVE), metadata.isProgressive());
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_NUMBER_OF_IMAGES), metadata.getNumberOfImages());
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_PHYSICAL_WIDTH_DPI), metadata.getPhysicalWidthDpi());
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_PHYSICAL_HEIGHT_DPI), metadata.getPhysicalHeightDpi());
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_PHYSICAL_WIDTH_INCHES), metadata.getPhysicalWidthInch());
+            output.setProperty(metadataNode, nameFactory.create(IMAGE_PHYSICAL_HEIGHT_INCHES), metadata.getPhysicalHeightInch());
+        }
+    }
+}

Deleted: trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageSequencerI18n.java
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/images/ImageSequencerI18n.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageSequencerI18n.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,54 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.sequencer.images;
-
-import java.util.Locale;
-import java.util.Set;
-import org.jboss.dna.common.i18n.I18n;
-
-/**
- * @author Randall Hauch
- */
-public final class ImageSequencerI18n {
-
-    public static I18n sequencerTaskName;
-
-    static {
-        try {
-            I18n.initialize(ImageSequencerI18n.class);
-        } catch (final Exception err) {
-            System.err.println(err);
-        }
-    }
-
-    public static Set<Locale> getLocalizationProblemLocales() {
-        return I18n.getLocalizationProblemLocales(ImageSequencerI18n.class);
-    }
-
-    public static Set<String> getLocalizationProblems() {
-        return I18n.getLocalizationProblems(ImageSequencerI18n.class);
-    }
-
-    public static Set<String> getLocalizationProblems( Locale locale ) {
-        return I18n.getLocalizationProblems(ImageSequencerI18n.class, locale);
-    }
-}

Copied: trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageSequencerI18n.java (from rev 706, trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/images/ImageSequencerI18n.java)
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageSequencerI18n.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-images/src/main/java/org/jboss/dna/sequencer/image/ImageSequencerI18n.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.image;
+
+import java.util.Locale;
+import java.util.Set;
+import org.jboss.dna.common.i18n.I18n;
+
+/**
+ * @author Randall Hauch
+ */
+public final class ImageSequencerI18n {
+
+    public static I18n sequencerTaskName;
+
+    static {
+        try {
+            I18n.initialize(ImageSequencerI18n.class);
+        } catch (final Exception err) {
+            System.err.println(err);
+        }
+    }
+
+    public static Set<Locale> getLocalizationProblemLocales() {
+        return I18n.getLocalizationProblemLocales(ImageSequencerI18n.class);
+    }
+
+    public static Set<String> getLocalizationProblems() {
+        return I18n.getLocalizationProblems(ImageSequencerI18n.class);
+    }
+
+    public static Set<String> getLocalizationProblems( Locale locale ) {
+        return I18n.getLocalizationProblems(ImageSequencerI18n.class, locale);
+    }
+}

Copied: trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image (from rev 705, trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/images)

Deleted: trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/ImageSequencerI18n.properties
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/images/ImageSequencerI18n.properties	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/ImageSequencerI18n.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,22 +0,0 @@
-#
-# JBoss, Home of Professional Open Source.
-# Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
-# as indicated by the @author tags. See the copyright.txt file in the
-# distribution for a full listing of individual contributors.
-#
-# This is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2.1 of
-# the License, or (at your option) any later version.
-#
-# This software is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this software; if not, write to the Free
-# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-#
-sequencerTaskName = Processing image contents

Copied: trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/ImageSequencerI18n.properties (from rev 706, trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/images/ImageSequencerI18n.properties)
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/ImageSequencerI18n.properties	                        (rev 0)
+++ trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/ImageSequencerI18n.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,22 @@
+#
+# JBoss, Home of Professional Open Source.
+# Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+# as indicated by the @author tags. See the copyright.txt file in the
+# distribution for a full listing of individual contributors.
+#
+# This is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this software; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+#
+sequencerTaskName = Processing image contents

Deleted: trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/images.cnd
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/images/images.cnd	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/images.cnd	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,61 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
- 
-//------------------------------------------------------------------------------
-// N A M E S P A C E S
-//------------------------------------------------------------------------------
-<jcr='http://www.jcp.org/jcr/1.0'>
-<nt='http://www.jcp.org/jcr/nt/1.0'>
-<mix='http://www.jcp.org/jcr/mix/1.0'>
-<image='http://jboss.org/dna/images/1.0'>
-
-// ----------------------------------------------------------
-// JCR Pre-defined Mixin Types that are not loaded by default
-// ----------------------------------------------------------
-
-[mix:mimeType] mixin 
-  - jcr:mimeType (string)  
-  - jcr:encoding (string)
-
-
-//------------------------------------------------------------------------------
-// N O D E T Y P E S
-//------------------------------------------------------------------------------
-
-/**
- * Mixin that defines the metadata for an image
- */
-[image:metadata] > nt:unstructured, mix:mimeType
-  - image:formatName (string) mandatory
-    < 'JPEG', 'GIF', 'PNG', 'BMP', 'PCX', 'IFF', 'RAS', 'PBM', 'PGM', 'PPM', 'PSD'
-  - image:width (long)
-  - image:height (long)
-  - image:bitsPerPixel (long)
-  - image:progressive (boolean)
-  - image:numberOfImages (long)
-  - image:physicalWidthDpi (long)
-  - image:physicalHeightDpi (long)
-  - image:physicalWidthInches (long)
-  - image:physicalHeightInches (long)
-
-
- 
\ No newline at end of file

Copied: trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/images.cnd (from rev 706, trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/images/images.cnd)
===================================================================
--- trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/images.cnd	                        (rev 0)
+++ trunk/extensions/dna-sequencer-images/src/main/resources/org/jboss/dna/sequencer/image/images.cnd	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,61 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+ 
+//------------------------------------------------------------------------------
+// N A M E S P A C E S
+//------------------------------------------------------------------------------
+<jcr='http://www.jcp.org/jcr/1.0'>
+<nt='http://www.jcp.org/jcr/nt/1.0'>
+<mix='http://www.jcp.org/jcr/mix/1.0'>
+<image='http://jboss.org/dna/images/1.0'>
+
+// ----------------------------------------------------------
+// JCR Pre-defined Mixin Types that are not loaded by default
+// ----------------------------------------------------------
+
+[mix:mimeType] mixin 
+  - jcr:mimeType (string)  
+  - jcr:encoding (string)
+
+
+//------------------------------------------------------------------------------
+// N O D E T Y P E S
+//------------------------------------------------------------------------------
+
+/**
+ * Mixin that defines the metadata for an image
+ */
+[image:metadata] > nt:unstructured, mix:mimeType
+  - image:formatName (string) mandatory
+    < 'JPEG', 'GIF', 'PNG', 'BMP', 'PCX', 'IFF', 'RAS', 'PBM', 'PGM', 'PPM', 'PSD'
+  - image:width (long)
+  - image:height (long)
+  - image:bitsPerPixel (long)
+  - image:progressive (boolean)
+  - image:numberOfImages (long)
+  - image:physicalWidthDpi (long)
+  - image:physicalHeightDpi (long)
+  - image:physicalWidthInches (long)
+  - image:physicalHeightInches (long)
+
+
+ 
\ No newline at end of file

Copied: trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image (from rev 705, trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/images)

Deleted: trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataSequencerTest.java
===================================================================
--- trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/images/ImageMetadataSequencerTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataSequencerTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,150 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.sequencer.images;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.number.IsCloseTo.closeTo;
-import static org.junit.Assert.assertThat;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import org.jboss.dna.graph.sequencers.MockSequencerContext;
-import org.jboss.dna.graph.sequencers.MockSequencerOutput;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class ImageMetadataSequencerTest {
-
-    private ImageMetadataSequencer sequencer;
-    private InputStream content;
-    private MockSequencerOutput output;
-    private URL cautionGif;
-    private URL cautionJpg;
-    private URL cautionPict;
-    private URL cautionPng;
-    private SequencerContext context;
-
-    @Before
-    public void beforeEach() {
-        sequencer = new ImageMetadataSequencer();
-        context = new MockSequencerContext();
-        context.getNamespaceRegistry().register("image", "http://jboss.org/dna/images/1.0");
-        output = new MockSequencerOutput(context);
-        cautionGif = this.getClass().getClassLoader().getResource("caution.gif");
-        cautionJpg = this.getClass().getClassLoader().getResource("caution.jpg");
-        cautionPict = this.getClass().getClassLoader().getResource("caution.pict");
-        cautionPng = this.getClass().getClassLoader().getResource("caution.png");
-    }
-
-    @After
-    public void afterEach() throws Exception {
-        if (content != null) {
-            try {
-                content.close();
-            } finally {
-                content = null;
-            }
-        }
-    }
-
-    @Test
-    public void shouldGenerateMetadataForJpegImageFiles() throws IOException {
-        URL url = this.cautionJpg;
-        assertThat(url, is(notNullValue()));
-        content = url.openStream();
-        assertThat(content, is(notNullValue()));
-        sequencer.sequence(content, output, context);
-        assertThat(output.getPropertyValues("image:metadata", "jcr:primaryType"), is(new Object[] {"image:metadata"}));
-        assertThat(output.getPropertyValues("image:metadata", "jcr:mimeType"), is(new Object[] {"image/jpeg"}));
-        assertThat(output.getPropertyValues("image:metadata", "image:formatName"), is(new Object[] {"JPEG"}));
-        assertThat(output.getPropertyValues("image:metadata", "image:width"), is(new Object[] {48}));
-        assertThat(output.getPropertyValues("image:metadata", "image:height"), is(new Object[] {48}));
-        assertThat(output.getPropertyValues("image:metadata", "image:bitsPerPixel"), is(new Object[] {24}));
-        assertThat(output.getPropertyValues("image:metadata", "image:progressive"), is(new Object[] {false}));
-        assertThat(output.getPropertyValues("image:metadata", "image:numberOfImages"), is(new Object[] {1}));
-        assertThat(output.getPropertyValues("image:metadata", "image:physicalWidthDpi"), is(new Object[] {72}));
-        assertThat(output.getPropertyValues("image:metadata", "image:physicalHeightDpi"), is(new Object[] {72}));
-        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalWidthInches")[0])).doubleValue(),
-                   is(closeTo(0.666667d, 0.0001d)));
-        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalHeightInches")[0])).doubleValue(),
-                   is(closeTo(0.666667d, 0.0001d)));
-    }
-
-    @Test
-    public void shouldGenerateMetadataForPngImageFiles() throws IOException {
-        URL url = this.cautionPng;
-        assertThat(url, is(notNullValue()));
-        content = url.openStream();
-        assertThat(content, is(notNullValue()));
-        sequencer.sequence(content, output, context);
-        assertThat(output.getPropertyValues("image:metadata", "jcr:primaryType"), is(new Object[] {"image:metadata"}));
-        assertThat(output.getPropertyValues("image:metadata", "jcr:mimeType"), is(new Object[] {"image/png"}));
-        assertThat(output.getPropertyValues("image:metadata", "image:formatName"), is(new Object[] {"PNG"}));
-        assertThat(output.getPropertyValues("image:metadata", "image:width"), is(new Object[] {48}));
-        assertThat(output.getPropertyValues("image:metadata", "image:height"), is(new Object[] {48}));
-        assertThat(output.getPropertyValues("image:metadata", "image:bitsPerPixel"), is(new Object[] {24}));
-        assertThat(output.getPropertyValues("image:metadata", "image:progressive"), is(new Object[] {false}));
-        assertThat(output.getPropertyValues("image:metadata", "image:numberOfImages"), is(new Object[] {1}));
-        assertThat(output.getPropertyValues("image:metadata", "image:physicalWidthDpi"), is(new Object[] {-1}));
-        assertThat(output.getPropertyValues("image:metadata", "image:physicalHeightDpi"), is(new Object[] {-1}));
-        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalWidthInches")[0])), is(-1f));
-        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalHeightInches")[0])), is(-1f));
-    }
-
-    @Test
-    public void shouldGenerateMetadataForGifImageFiles() throws IOException {
-        URL url = this.cautionGif;
-        assertThat(url, is(notNullValue()));
-        content = url.openStream();
-        assertThat(content, is(notNullValue()));
-        sequencer.sequence(content, output, context);
-        assertThat(output.getPropertyValues("image:metadata", "jcr:mimeType"), is(new Object[] {"image/gif"}));
-        assertThat(output.getPropertyValues("image:metadata", "image:formatName"), is(new Object[] {"GIF"}));
-        assertThat(output.getPropertyValues("image:metadata", "image:width"), is(new Object[] {48}));
-        assertThat(output.getPropertyValues("image:metadata", "image:height"), is(new Object[] {48}));
-        assertThat(output.getPropertyValues("image:metadata", "image:bitsPerPixel"), is(new Object[] {8}));
-        assertThat(output.getPropertyValues("image:metadata", "image:progressive"), is(new Object[] {false}));
-        assertThat(output.getPropertyValues("image:metadata", "image:numberOfImages"), is(new Object[] {1}));
-        assertThat(output.getPropertyValues("image:metadata", "image:physicalWidthDpi"), is(new Object[] {-1}));
-        assertThat(output.getPropertyValues("image:metadata", "image:physicalHeightDpi"), is(new Object[] {-1}));
-        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalWidthInches")[0])), is(-1f));
-        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalHeightInches")[0])), is(-1f));
-    }
-
-    @Test
-    public void shouldGenerateNoMetadataforPictImageFiles() throws IOException {
-        URL url = this.cautionPict;
-        assertThat(url, is(notNullValue()));
-        content = url.openStream();
-        assertThat(content, is(notNullValue()));
-        sequencer.sequence(content, output, context);
-        assertThat(output.hasProperties(), is(false));
-
-    }
-}

Copied: trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataSequencerTest.java (from rev 706, trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/images/ImageMetadataSequencerTest.java)
===================================================================
--- trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataSequencerTest.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataSequencerTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,151 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.image;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.number.IsCloseTo.closeTo;
+import static org.junit.Assert.assertThat;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import org.jboss.dna.graph.sequencer.MockSequencerContext;
+import org.jboss.dna.graph.sequencer.MockSequencerOutput;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.sequencer.image.ImageMetadataSequencer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class ImageMetadataSequencerTest {
+
+    private ImageMetadataSequencer sequencer;
+    private InputStream content;
+    private MockSequencerOutput output;
+    private URL cautionGif;
+    private URL cautionJpg;
+    private URL cautionPict;
+    private URL cautionPng;
+    private SequencerContext context;
+
+    @Before
+    public void beforeEach() {
+        sequencer = new ImageMetadataSequencer();
+        context = new MockSequencerContext();
+        context.getNamespaceRegistry().register("image", "http://jboss.org/dna/images/1.0");
+        output = new MockSequencerOutput(context);
+        cautionGif = this.getClass().getClassLoader().getResource("caution.gif");
+        cautionJpg = this.getClass().getClassLoader().getResource("caution.jpg");
+        cautionPict = this.getClass().getClassLoader().getResource("caution.pict");
+        cautionPng = this.getClass().getClassLoader().getResource("caution.png");
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        if (content != null) {
+            try {
+                content.close();
+            } finally {
+                content = null;
+            }
+        }
+    }
+
+    @Test
+    public void shouldGenerateMetadataForJpegImageFiles() throws IOException {
+        URL url = this.cautionJpg;
+        assertThat(url, is(notNullValue()));
+        content = url.openStream();
+        assertThat(content, is(notNullValue()));
+        sequencer.sequence(content, output, context);
+        assertThat(output.getPropertyValues("image:metadata", "jcr:primaryType"), is(new Object[] {"image:metadata"}));
+        assertThat(output.getPropertyValues("image:metadata", "jcr:mimeType"), is(new Object[] {"image/jpeg"}));
+        assertThat(output.getPropertyValues("image:metadata", "image:formatName"), is(new Object[] {"JPEG"}));
+        assertThat(output.getPropertyValues("image:metadata", "image:width"), is(new Object[] {48}));
+        assertThat(output.getPropertyValues("image:metadata", "image:height"), is(new Object[] {48}));
+        assertThat(output.getPropertyValues("image:metadata", "image:bitsPerPixel"), is(new Object[] {24}));
+        assertThat(output.getPropertyValues("image:metadata", "image:progressive"), is(new Object[] {false}));
+        assertThat(output.getPropertyValues("image:metadata", "image:numberOfImages"), is(new Object[] {1}));
+        assertThat(output.getPropertyValues("image:metadata", "image:physicalWidthDpi"), is(new Object[] {72}));
+        assertThat(output.getPropertyValues("image:metadata", "image:physicalHeightDpi"), is(new Object[] {72}));
+        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalWidthInches")[0])).doubleValue(),
+                   is(closeTo(0.666667d, 0.0001d)));
+        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalHeightInches")[0])).doubleValue(),
+                   is(closeTo(0.666667d, 0.0001d)));
+    }
+
+    @Test
+    public void shouldGenerateMetadataForPngImageFiles() throws IOException {
+        URL url = this.cautionPng;
+        assertThat(url, is(notNullValue()));
+        content = url.openStream();
+        assertThat(content, is(notNullValue()));
+        sequencer.sequence(content, output, context);
+        assertThat(output.getPropertyValues("image:metadata", "jcr:primaryType"), is(new Object[] {"image:metadata"}));
+        assertThat(output.getPropertyValues("image:metadata", "jcr:mimeType"), is(new Object[] {"image/png"}));
+        assertThat(output.getPropertyValues("image:metadata", "image:formatName"), is(new Object[] {"PNG"}));
+        assertThat(output.getPropertyValues("image:metadata", "image:width"), is(new Object[] {48}));
+        assertThat(output.getPropertyValues("image:metadata", "image:height"), is(new Object[] {48}));
+        assertThat(output.getPropertyValues("image:metadata", "image:bitsPerPixel"), is(new Object[] {24}));
+        assertThat(output.getPropertyValues("image:metadata", "image:progressive"), is(new Object[] {false}));
+        assertThat(output.getPropertyValues("image:metadata", "image:numberOfImages"), is(new Object[] {1}));
+        assertThat(output.getPropertyValues("image:metadata", "image:physicalWidthDpi"), is(new Object[] {-1}));
+        assertThat(output.getPropertyValues("image:metadata", "image:physicalHeightDpi"), is(new Object[] {-1}));
+        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalWidthInches")[0])), is(-1f));
+        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalHeightInches")[0])), is(-1f));
+    }
+
+    @Test
+    public void shouldGenerateMetadataForGifImageFiles() throws IOException {
+        URL url = this.cautionGif;
+        assertThat(url, is(notNullValue()));
+        content = url.openStream();
+        assertThat(content, is(notNullValue()));
+        sequencer.sequence(content, output, context);
+        assertThat(output.getPropertyValues("image:metadata", "jcr:mimeType"), is(new Object[] {"image/gif"}));
+        assertThat(output.getPropertyValues("image:metadata", "image:formatName"), is(new Object[] {"GIF"}));
+        assertThat(output.getPropertyValues("image:metadata", "image:width"), is(new Object[] {48}));
+        assertThat(output.getPropertyValues("image:metadata", "image:height"), is(new Object[] {48}));
+        assertThat(output.getPropertyValues("image:metadata", "image:bitsPerPixel"), is(new Object[] {8}));
+        assertThat(output.getPropertyValues("image:metadata", "image:progressive"), is(new Object[] {false}));
+        assertThat(output.getPropertyValues("image:metadata", "image:numberOfImages"), is(new Object[] {1}));
+        assertThat(output.getPropertyValues("image:metadata", "image:physicalWidthDpi"), is(new Object[] {-1}));
+        assertThat(output.getPropertyValues("image:metadata", "image:physicalHeightDpi"), is(new Object[] {-1}));
+        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalWidthInches")[0])), is(-1f));
+        assertThat(((Float)(output.getPropertyValues("image:metadata", "image:physicalHeightInches")[0])), is(-1f));
+    }
+
+    @Test
+    public void shouldGenerateNoMetadataforPictImageFiles() throws IOException {
+        URL url = this.cautionPict;
+        assertThat(url, is(notNullValue()));
+        content = url.openStream();
+        assertThat(content, is(notNullValue()));
+        sequencer.sequence(content, output, context);
+        assertThat(output.hasProperties(), is(false));
+
+    }
+}

Deleted: trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataTest.java
===================================================================
--- trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/images/ImageMetadataTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,159 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors. 
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.sequencer.images;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.number.IsCloseTo.closeTo;
-import static org.junit.Assert.assertThat;
-import java.io.InputStream;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class ImageMetadataTest {
-
-    private ImageMetadata image;
-    private InputStream imageStream;
-
-    @Before
-    public void beforeEach() {
-        this.image = new ImageMetadata();
-    }
-
-    @After
-    public void afterEach() throws Exception {
-        if (imageStream != null) {
-            try {
-                imageStream.close();
-            } finally {
-                imageStream = null;
-            }
-        }
-    }
-
-    protected InputStream getTestImage( String resourcePath ) {
-        return this.getClass().getResourceAsStream("/" + resourcePath);
-    }
-
-    @Test
-    public void shouldBeAbleToCreateWithDefaultConstructor() {
-        assertThat(new ImageMetadata(), is(notNullValue()));
-    }
-
-    @Test
-    public void shouldBeAbleToLoadPngImage() {
-        // Get an input stream to a test file ...
-        InputStream stream = getTestImage("caution.png");
-        image.setInput(stream);
-        image.setDetermineImageNumber(true);
-        image.setCollectComments(true);
-
-        // Process the image ...
-        assertThat(image.check(), is(true));
-
-        assertThat(image.getFormatName(), is("PNG"));
-        assertThat(image.getMimeType(), is("image/png"));
-        assertThat(image.getWidth(), is(48));
-        assertThat(image.getHeight(), is(48));
-        assertThat(image.getBitsPerPixel(), is(24));
-        assertThat(image.isProgressive(), is(false));
-        assertThat(image.getNumberOfImages(), is(1));
-        assertThat(image.getPhysicalWidthDpi(), is(-1));
-        assertThat(image.getPhysicalHeightDpi(), is(-1));
-        assertThat(image.getPhysicalWidthInch(), is(-1.0f));
-        assertThat(image.getPhysicalHeightInch(), is(-1.0f));
-
-        assertThat(image.getNumberOfComments(), is(0));
-        // assertThat(image.getComment(0), is(""));
-    }
-
-    @Test
-    public void shouldBeAbleToLoadGifImage() {
-        // Get an input stream to a test file ...
-        InputStream stream = getTestImage("caution.gif");
-        image.setInput(stream);
-        image.setDetermineImageNumber(true);
-        image.setCollectComments(true);
-
-        // Process the image ...
-        assertThat(image.check(), is(true));
-
-        assertThat(image.getFormatName(), is("GIF"));
-        assertThat(image.getMimeType(), is("image/gif"));
-        assertThat(image.getWidth(), is(48));
-        assertThat(image.getHeight(), is(48));
-        assertThat(image.getBitsPerPixel(), is(8));
-        assertThat(image.isProgressive(), is(false));
-        assertThat(image.getNumberOfImages(), is(1));
-        assertThat(image.getPhysicalWidthDpi(), is(-1));
-        assertThat(image.getPhysicalHeightDpi(), is(-1));
-        assertThat(image.getPhysicalWidthInch(), is(-1.0f));
-        assertThat(image.getPhysicalHeightInch(), is(-1.0f));
-
-        assertThat(image.getNumberOfComments(), is(0));
-        // assertThat(image.getComment(0), is(""));
-    }
-
-    @Test
-    public void shouldBeAbleToLoadJpegImage() {
-        // Get an input stream to a test file ...
-        InputStream stream = getTestImage("caution.jpg");
-        image.setInput(stream);
-        image.setDetermineImageNumber(true);
-        image.setCollectComments(true);
-
-        // Process the image ...
-        assertThat(image.check(), is(true));
-
-        assertThat(image.getFormatName(), is("JPEG"));
-        assertThat(image.getMimeType(), is("image/jpeg"));
-        assertThat(image.getWidth(), is(48));
-        assertThat(image.getHeight(), is(48));
-        assertThat(image.getBitsPerPixel(), is(24));
-        assertThat(image.isProgressive(), is(false));
-        assertThat(image.getNumberOfImages(), is(1));
-        assertThat(image.getPhysicalWidthDpi(), is(72));
-        assertThat(image.getPhysicalHeightDpi(), is(72));
-        assertThat((double)image.getPhysicalWidthInch(), is(closeTo(0.66666666d, 0.00001d)));
-        assertThat((double)image.getPhysicalHeightInch(), is(closeTo(0.66666666d, 0.00001d)));
-
-        assertThat(image.getNumberOfComments(), is(0));
-        // assertThat(image.getComment(0), is(""));
-    }
-
-    @Test
-    public void shouldNotBeAbleToLoadPictImage() {
-        // Get an input stream to a test file ...
-        InputStream stream = getTestImage("caution.pict");
-        image.setInput(stream);
-        image.setDetermineImageNumber(true);
-        image.setCollectComments(true);
-
-        // Process the image ...
-        assertThat(image.check(), is(false));
-    }
-
-}

Copied: trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataTest.java (from rev 706, trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/images/ImageMetadataTest.java)
===================================================================
--- trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataTest.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageMetadataTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,160 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.image;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.number.IsCloseTo.closeTo;
+import static org.junit.Assert.assertThat;
+import java.io.InputStream;
+import org.jboss.dna.sequencer.image.ImageMetadata;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ImageMetadataTest {
+
+    private ImageMetadata image;
+    private InputStream imageStream;
+
+    @Before
+    public void beforeEach() {
+        this.image = new ImageMetadata();
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        if (imageStream != null) {
+            try {
+                imageStream.close();
+            } finally {
+                imageStream = null;
+            }
+        }
+    }
+
+    protected InputStream getTestImage( String resourcePath ) {
+        return this.getClass().getResourceAsStream("/" + resourcePath);
+    }
+
+    @Test
+    public void shouldBeAbleToCreateWithDefaultConstructor() {
+        assertThat(new ImageMetadata(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldBeAbleToLoadPngImage() {
+        // Get an input stream to a test file ...
+        InputStream stream = getTestImage("caution.png");
+        image.setInput(stream);
+        image.setDetermineImageNumber(true);
+        image.setCollectComments(true);
+
+        // Process the image ...
+        assertThat(image.check(), is(true));
+
+        assertThat(image.getFormatName(), is("PNG"));
+        assertThat(image.getMimeType(), is("image/png"));
+        assertThat(image.getWidth(), is(48));
+        assertThat(image.getHeight(), is(48));
+        assertThat(image.getBitsPerPixel(), is(24));
+        assertThat(image.isProgressive(), is(false));
+        assertThat(image.getNumberOfImages(), is(1));
+        assertThat(image.getPhysicalWidthDpi(), is(-1));
+        assertThat(image.getPhysicalHeightDpi(), is(-1));
+        assertThat(image.getPhysicalWidthInch(), is(-1.0f));
+        assertThat(image.getPhysicalHeightInch(), is(-1.0f));
+
+        assertThat(image.getNumberOfComments(), is(0));
+        // assertThat(image.getComment(0), is(""));
+    }
+
+    @Test
+    public void shouldBeAbleToLoadGifImage() {
+        // Get an input stream to a test file ...
+        InputStream stream = getTestImage("caution.gif");
+        image.setInput(stream);
+        image.setDetermineImageNumber(true);
+        image.setCollectComments(true);
+
+        // Process the image ...
+        assertThat(image.check(), is(true));
+
+        assertThat(image.getFormatName(), is("GIF"));
+        assertThat(image.getMimeType(), is("image/gif"));
+        assertThat(image.getWidth(), is(48));
+        assertThat(image.getHeight(), is(48));
+        assertThat(image.getBitsPerPixel(), is(8));
+        assertThat(image.isProgressive(), is(false));
+        assertThat(image.getNumberOfImages(), is(1));
+        assertThat(image.getPhysicalWidthDpi(), is(-1));
+        assertThat(image.getPhysicalHeightDpi(), is(-1));
+        assertThat(image.getPhysicalWidthInch(), is(-1.0f));
+        assertThat(image.getPhysicalHeightInch(), is(-1.0f));
+
+        assertThat(image.getNumberOfComments(), is(0));
+        // assertThat(image.getComment(0), is(""));
+    }
+
+    @Test
+    public void shouldBeAbleToLoadJpegImage() {
+        // Get an input stream to a test file ...
+        InputStream stream = getTestImage("caution.jpg");
+        image.setInput(stream);
+        image.setDetermineImageNumber(true);
+        image.setCollectComments(true);
+
+        // Process the image ...
+        assertThat(image.check(), is(true));
+
+        assertThat(image.getFormatName(), is("JPEG"));
+        assertThat(image.getMimeType(), is("image/jpeg"));
+        assertThat(image.getWidth(), is(48));
+        assertThat(image.getHeight(), is(48));
+        assertThat(image.getBitsPerPixel(), is(24));
+        assertThat(image.isProgressive(), is(false));
+        assertThat(image.getNumberOfImages(), is(1));
+        assertThat(image.getPhysicalWidthDpi(), is(72));
+        assertThat(image.getPhysicalHeightDpi(), is(72));
+        assertThat((double)image.getPhysicalWidthInch(), is(closeTo(0.66666666d, 0.00001d)));
+        assertThat((double)image.getPhysicalHeightInch(), is(closeTo(0.66666666d, 0.00001d)));
+
+        assertThat(image.getNumberOfComments(), is(0));
+        // assertThat(image.getComment(0), is(""));
+    }
+
+    @Test
+    public void shouldNotBeAbleToLoadPictImage() {
+        // Get an input stream to a test file ...
+        InputStream stream = getTestImage("caution.pict");
+        image.setInput(stream);
+        image.setDetermineImageNumber(true);
+        image.setCollectComments(true);
+
+        // Process the image ...
+        assertThat(image.check(), is(false));
+    }
+
+}

Deleted: trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageSequencerI18nTest.java
===================================================================
--- trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/images/ImageSequencerI18nTest.java	2009-01-15 02:10:17 UTC (rev 705)
+++ trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageSequencerI18nTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -1,13 +0,0 @@
-package org.jboss.dna.sequencer.images;
-
-import org.jboss.dna.common.AbstractI18nTest;
-
-/**
- * @author John Verhaeg
- */
-public class ImageSequencerI18nTest extends AbstractI18nTest {
-
-    public ImageSequencerI18nTest() {
-        super(ImageSequencerI18n.class);
-    }
-}

Copied: trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageSequencerI18nTest.java (from rev 706, trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/images/ImageSequencerI18nTest.java)
===================================================================
--- trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageSequencerI18nTest.java	                        (rev 0)
+++ trunk/extensions/dna-sequencer-images/src/test/java/org/jboss/dna/sequencer/image/ImageSequencerI18nTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -0,0 +1,14 @@
+package org.jboss.dna.sequencer.image;
+
+import org.jboss.dna.common.AbstractI18nTest;
+import org.jboss.dna.sequencer.image.ImageSequencerI18n;
+
+/**
+ * @author John Verhaeg
+ */
+public class ImageSequencerI18nTest extends AbstractI18nTest {
+
+    public ImageSequencerI18nTest() {
+        super(ImageSequencerI18n.class);
+    }
+}

Modified: trunk/extensions/dna-sequencer-images/src/test/resources/log4j.properties
===================================================================
--- trunk/extensions/dna-sequencer-images/src/test/resources/log4j.properties	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-images/src/test/resources/log4j.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -10,3 +10,6 @@
 # Set up the default logging to be INFO level, then override specific units
 log4j.logger.org.jboss.dna=INFO
 
+# Jackrabbit logging
+log4j.logger.org.apache.jackrabbit=WARN, stdout
+

Modified: trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/ArrayTypeFieldMetadataSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/ArrayTypeFieldMetadataSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/ArrayTypeFieldMetadataSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -22,10 +22,10 @@
 package org.jboss.dna.sequencer.java;
 
 import java.util.List;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
 import org.jboss.dna.sequencer.java.metadata.ArrayTypeFieldMetadata;
 import org.jboss.dna.sequencer.java.metadata.ModifierMetadata;
 import org.jboss.dna.sequencer.java.metadata.Variable;

Modified: trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -25,12 +25,12 @@
 import java.io.InputStream;
 import java.util.List;
 import org.apache.commons.lang.StringUtils;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
+import org.jboss.dna.graph.sequencer.StreamSequencer;
 import org.jboss.dna.sequencer.java.metadata.AnnotationMetadata;
 import org.jboss.dna.sequencer.java.metadata.ArrayTypeFieldMetadata;
 import org.jboss.dna.sequencer.java.metadata.ClassMetadata;
@@ -173,8 +173,8 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.sequencers.StreamSequencer#sequence(java.io.InputStream,
-     *      org.jboss.dna.graph.sequencers.SequencerOutput, org.jboss.dna.graph.sequencers.SequencerContext)
+     * @see org.jboss.dna.graph.sequencer.StreamSequencer#sequence(java.io.InputStream,
+     *      org.jboss.dna.graph.sequencer.SequencerOutput, org.jboss.dna.graph.sequencer.SequencerContext)
      */
     public void sequence( InputStream stream,
                           SequencerOutput output,

Modified: trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/MethodMetadataSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/MethodMetadataSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/MethodMetadataSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.sequencer.java;
 
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
 import org.jboss.dna.sequencer.java.metadata.MethodMetadata;
 
 /**

Modified: trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/ParameterizedTypeFieldMetadataSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/ParameterizedTypeFieldMetadataSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/ParameterizedTypeFieldMetadataSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,10 +21,10 @@
  */
 package org.jboss.dna.sequencer.java;
 
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
 import org.jboss.dna.sequencer.java.metadata.ModifierMetadata;
 import org.jboss.dna.sequencer.java.metadata.ParameterizedTypeFieldMetadata;
 

Modified: trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/SimpleTypeMetadataSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/SimpleTypeMetadataSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/SimpleTypeMetadataSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,10 +21,10 @@
  */
 package org.jboss.dna.sequencer.java;
 
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
 import org.jboss.dna.sequencer.java.metadata.SimpleTypeFieldMetadata;
 import org.jboss.dna.sequencer.java.metadata.Variable;
 

Modified: trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/VariableSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/VariableSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/VariableSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,9 +21,9 @@
  */
 package org.jboss.dna.sequencer.java;
 
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
 import org.jboss.dna.sequencer.java.metadata.Variable;
 
 /**

Modified: trunk/extensions/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataSequencerTest.java
===================================================================
--- trunk/extensions/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataSequencerTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataSequencerTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -29,9 +29,9 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import org.jboss.dna.graph.sequencers.MockSequencerContext;
-import org.jboss.dna.graph.sequencers.MockSequencerOutput;
-import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.jboss.dna.graph.sequencer.MockSequencerContext;
+import org.jboss.dna.graph.sequencer.MockSequencerOutput;
+import org.jboss.dna.graph.sequencer.SequencerContext;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/extensions/dna-sequencer-java/src/test/resources/log4j.properties
===================================================================
--- trunk/extensions/dna-sequencer-java/src/test/resources/log4j.properties	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-java/src/test/resources/log4j.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -10,3 +10,5 @@
 # Set up the default logging to be INFO level, then override specific units
 log4j.logger.org.jboss.dna=INFO
 
+# Jackrabbit logging
+log4j.logger.org.apache.jackrabbit=WARN, stdout

Modified: trunk/extensions/dna-sequencer-mp3/src/main/java/org/jboss/dna/sequencer/mp3/Mp3MetadataSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-mp3/src/main/java/org/jboss/dna/sequencer/mp3/Mp3MetadataSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-mp3/src/main/java/org/jboss/dna/sequencer/mp3/Mp3MetadataSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -22,9 +22,9 @@
 package org.jboss.dna.sequencer.mp3;
 
 import java.io.InputStream;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
+import org.jboss.dna.graph.sequencer.StreamSequencer;
 
 /**
  * A sequencer that processes the binary content of an MP3 audio file, extracts the metadata for the file, and then writes that

Modified: trunk/extensions/dna-sequencer-mp3/src/test/resources/log4j.properties
===================================================================
--- trunk/extensions/dna-sequencer-mp3/src/test/resources/log4j.properties	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-mp3/src/test/resources/log4j.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -10,3 +10,5 @@
 # Set up the default logging to be INFO level, then override specific units
 log4j.logger.org.jboss.dna=INFO
 
+# Jackrabbit logging
+log4j.logger.org.apache.jackrabbit=WARN, stdout

Modified: trunk/extensions/dna-sequencer-msoffice/src/main/java/org/jboss/dna/sequencer/msoffice/MSOfficeMetadataSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-msoffice/src/main/java/org/jboss/dna/sequencer/msoffice/MSOfficeMetadataSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-msoffice/src/main/java/org/jboss/dna/sequencer/msoffice/MSOfficeMetadataSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,9 +24,9 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
+import org.jboss.dna.graph.sequencer.StreamSequencer;
 import org.jboss.dna.sequencer.msoffice.excel.ExcelMetadata;
 import org.jboss.dna.sequencer.msoffice.excel.ExcelMetadataReader;
 import org.jboss.dna.sequencer.msoffice.powerpoint.PowerPointMetadataReader;

Modified: trunk/extensions/dna-sequencer-msoffice/src/test/resources/log4j.properties
===================================================================
--- trunk/extensions/dna-sequencer-msoffice/src/test/resources/log4j.properties	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-msoffice/src/test/resources/log4j.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -10,3 +10,6 @@
 # Set up the default logging to be INFO level, then override specific units
 log4j.logger.org.jboss.dna=INFO
 
+# Jackrabbit logging
+log4j.logger.org.apache.jackrabbit=WARN, stdout
+

Modified: trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaDtdLexicon.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaDtdLexicon.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaDtdLexicon.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.sequencer.xml;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
 
 /**
  * @author Randall Hauch

Modified: trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaXmlLexicon.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaXmlLexicon.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/DnaXmlLexicon.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -21,8 +21,8 @@
  */
 package org.jboss.dna.sequencer.xml;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
 
 /**
  * @author Randall Hauch

Modified: trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,10 +24,10 @@
 import java.io.InputStream;
 import org.jboss.dna.common.text.TextDecoder;
 import org.jboss.dna.graph.JcrNtLexicon;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
+import org.jboss.dna.graph.sequencer.StreamSequencer;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXNotRecognizedException;
 import org.xml.sax.SAXNotSupportedException;
@@ -82,7 +82,7 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.sequencers.StreamSequencer#sequence(InputStream, SequencerOutput, SequencerContext)
+     * @see org.jboss.dna.graph.sequencer.StreamSequencer#sequence(InputStream, SequencerOutput, SequencerContext)
      */
     public void sequence( InputStream stream,
                           SequencerOutput output,

Modified: trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerHandler.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerHandler.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerHandler.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -33,16 +33,16 @@
 import org.jboss.dna.common.util.StringUtil;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.JcrLexicon;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.jboss.dna.graph.properties.basic.LocalNamespaceRegistry;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.LocalNamespaceRegistry;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXParseException;
 import org.xml.sax.ext.DefaultHandler2;

Modified: trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencerTest.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencerTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencerTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,10 +28,10 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.sequencers.MockSequencerContext;
-import org.jboss.dna.graph.sequencers.MockSequencerOutput;
-import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.sequencer.MockSequencerContext;
+import org.jboss.dna.graph.sequencer.MockSequencerOutput;
+import org.jboss.dna.graph.sequencer.SequencerContext;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerHandlerTest.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerHandlerTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerHandlerTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -31,19 +31,19 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.Map;
-import org.jboss.dna.common.stats.Stopwatch;
+import org.jboss.dna.common.statistic.Stopwatch;
 import org.jboss.dna.common.text.Jsr283Encoder;
 import org.jboss.dna.common.text.TextDecoder;
 import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.JcrNtLexicon;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.PathFactory;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.sequencers.MockSequencerContext;
-import org.jboss.dna.graph.sequencers.MockSequencerOutput;
-import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.sequencer.MockSequencerContext;
+import org.jboss.dna.graph.sequencer.MockSequencerOutput;
+import org.jboss.dna.graph.sequencer.SequencerContext;
 import org.junit.Before;
 import org.junit.Test;
 import org.xml.sax.InputSource;

Modified: trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -28,10 +28,10 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.sequencers.MockSequencerContext;
-import org.jboss.dna.graph.sequencers.MockSequencerOutput;
-import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.sequencer.MockSequencerContext;
+import org.jboss.dna.graph.sequencer.MockSequencerOutput;
+import org.jboss.dna.graph.sequencer.SequencerContext;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;

Modified: trunk/extensions/dna-sequencer-xml/src/test/resources/log4j.properties
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/log4j.properties	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/log4j.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -10,3 +10,5 @@
 # Set up the default logging to be INFO level, then override specific units
 log4j.logger.org.jboss.dna=INFO
 
+# Jackrabbit logging
+log4j.logger.org.apache.jackrabbit=WARN, stdout

Modified: trunk/extensions/dna-sequencer-xml/src/test/resources/master.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/master.xml	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/master.xml	2009-01-15 18:32:57 UTC (rev 707)
@@ -1492,7 +1492,7 @@
       <para>Create a Maven 2 project for your sequencer;</para>
     </listitem>
     <listitem>
-      <para>Implement the <code>org.jboss.dna.graph.sequencers.StreamSequencer</code> interface with your own implementation, and create unit tests to verify
+      <para>Implement the <code>org.jboss.dna.graph.sequencer.StreamSequencer</code> interface with your own implementation, and create unit tests to verify
       the functionality and expected behavior;</para>
     </listitem>
     <listitem>
@@ -1631,7 +1631,7 @@
   <sect1 id="custom_sequencer_implementation">
     <title>Implementing the StreamSequencer interface</title>
     <para>After creating the project and setting up the dependencies, the next step is to create a Java class that implements
-    the <code>org.jboss.dna.graph.sequencers.StreamSequencer</code> interface.  This interface is very straightforward
+    the <code>org.jboss.dna.graph.sequencer.StreamSequencer</code> interface.  This interface is very straightforward
     and involves a single method:
     <programlisting>
 public interface StreamSequencer {

Modified: trunk/extensions/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java
===================================================================
--- trunk/extensions/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -26,9 +26,9 @@
 import java.io.InputStream;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
-import org.jboss.dna.graph.sequencers.SequencerContext;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
-import org.jboss.dna.graph.sequencers.StreamSequencer;
+import org.jboss.dna.graph.sequencer.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
+import org.jboss.dna.graph.sequencer.StreamSequencer;
 
 /**
  * @author Michael Trezzi
@@ -39,8 +39,8 @@
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.sequencers.StreamSequencer#sequence(java.io.InputStream,
-     *      org.jboss.dna.graph.sequencers.SequencerOutput, org.jboss.dna.graph.sequencers.SequencerContext)
+     * @see org.jboss.dna.graph.sequencer.StreamSequencer#sequence(java.io.InputStream,
+     *      org.jboss.dna.graph.sequencer.SequencerOutput, org.jboss.dna.graph.sequencer.SequencerContext)
      */
     public void sequence( InputStream stream,
                           SequencerOutput output,

Modified: trunk/extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/SequencingOutputTestClass.java
===================================================================
--- trunk/extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/SequencingOutputTestClass.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/SequencingOutputTestClass.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -24,11 +24,11 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.sequencers.SequencerOutput;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.sequencer.SequencerOutput;
 import org.junit.Ignore;
 
 /**

Modified: trunk/extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java
===================================================================
--- trunk/extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java	2009-01-15 18:32:57 UTC (rev 707)
@@ -26,7 +26,7 @@
 import static org.junit.Assert.assertThat;
 import static org.mockito.Mockito.mock;
 import java.io.InputStream;
-import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.jboss.dna.graph.sequencer.SequencerContext;
 import org.junit.After;
 import org.junit.Test;
 

Modified: trunk/extensions/dna-sequencer-zip/src/test/resources/log4j.properties
===================================================================
--- trunk/extensions/dna-sequencer-zip/src/test/resources/log4j.properties	2009-01-15 16:09:50 UTC (rev 706)
+++ trunk/extensions/dna-sequencer-zip/src/test/resources/log4j.properties	2009-01-15 18:32:57 UTC (rev 707)
@@ -10,3 +10,6 @@
 # Set up the default logging to be INFO level, then override specific units
 log4j.logger.org.jboss.dna=INFO
 
+# Jackrabbit logging
+log4j.logger.org.apache.jackrabbit=WARN, stdout
+




More information about the dna-commits mailing list