[dna-commits] DNA SVN: r175 - in branches/federation/dna-spi/src: main/java/org/jboss/dna/spi/cache and 10 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Thu May 15 16:21:26 EDT 2008


Author: rhauch
Date: 2008-05-15 16:21:25 -0400 (Thu, 15 May 2008)
New Revision: 175

Added:
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/cache/
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/cache/CachePolicy.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/cache/Cacheable.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositoryConnection.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositoryConnectionFactory.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySource.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceEnvironment.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceException.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceListener.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetChildrenCommand.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetCommand.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetNodeCommand.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetPropertiesCommand.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/RepositoryCommand.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Binary.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/InvalidPathException.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Name.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/NameFactory.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathNotFoundException.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Property.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyType.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValue.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValueFactory.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValues.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueFormatException.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicName.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicNameFactory.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPathFactory.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPathSegment.java
   branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/InMemoryBinary.java
   branches/federation/dna-spi/src/main/resources/org/
   branches/federation/dna-spi/src/main/resources/org/jboss/
   branches/federation/dna-spi/src/main/resources/org/jboss/dna/
   branches/federation/dna-spi/src/main/resources/org/jboss/dna/spi/
   branches/federation/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties
   branches/federation/dna-spi/src/test/java/org/jboss/dna/spi/SpiI18nTest.java
Log:
Added preliminary SPI interfaces, including start of connector and graph.

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,52 @@
+/*
+ * 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.spi;
+
+import org.jboss.dna.common.i18n.I18n;
+
+/**
+ * @author Randall Hauch
+ */
+public final class SpiI18n {
+
+    static {
+        try {
+            I18n.initialize(SpiI18n.class);
+        } catch (final Exception err) {
+            System.err.println(err);
+        }
+    }
+
+    public static I18n unableToDiscoverPropertyType;
+    public static I18n errorReadingPropertyValueBytes;
+    public static I18n valueJavaTypeNotCompatibleWithPropertyType;
+
+    public static I18n errorConvertingBinaryValueToString;
+
+    public static I18n pathAncestorDegreeIsInvalid;
+    public static I18n pathIsAlreadyAbsolute;
+    public static I18n pathIsNotAbsolute;
+    public static I18n pathIsNotRelative;
+    public static I18n pathCannotBeNormalized;
+
+    public static I18n invalidQualifiedNameString;
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/cache/CachePolicy.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/cache/CachePolicy.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/cache/CachePolicy.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,47 @@
+/*
+ * 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.spi.cache;
+
+import java.io.Serializable;
+import net.jcip.annotations.Immutable;
+
+/**
+ * The specification of how node data is to be cached. The time values provided are relative, allowing the same cache policy
+ * instance to be shared among multiple {@link Cacheable} objects.
+ * @author Randall Hauch
+ */
+ at Immutable
+public interface CachePolicy extends Serializable {
+
+    /**
+     * Get the system time in milliseconds before which the node data remains valid.
+     * @return the number of milliseconds that the cached data should be used before consulting the original source.
+     */
+    public long getTimeToCache();
+
+    /**
+     * Get the relative time after which the cached data should expire and no longer be used.
+     * @return the number of milliseconds until the cached data expires
+     */
+    public long getTimeToExpire();
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/cache/Cacheable.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/cache/Cacheable.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/cache/Cacheable.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,55 @@
+/*
+ * 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.spi.cache;
+
+import java.io.Serializable;
+
+/**
+ * Interface defining an object that can be cached according to a {@link CachePolicy}.
+ * @author Randall Hauch
+ */
+public interface Cacheable extends Serializable {
+
+    /**
+     * Get the time that this node data was originally loaded.
+     * @return the system time (in milliseconds) that the node data was loaded
+     */
+    long getTimeLoaded();
+
+    /**
+     * Get the caching policy to be used for this object.
+     * <p>
+     * Note that the values of the policy are relative to the {@link #getTimeLoaded() time the node was loaded}, so the same
+     * instance can be used for many nodes.
+     * </p>
+     * @return cachePolicy the caching policy, which may not be null
+     */
+    public CachePolicy getCachePolicy();
+
+    /**
+     * Set the caching policy for this object.
+     * @param cachePolicy the caching policy to use for this object
+     * @throws IllegalArgumentException if the cachePolicy is null
+     */
+    public void setCachePolicy( CachePolicy cachePolicy );
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositoryConnection.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositoryConnection.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositoryConnection.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,76 @@
+/*
+ * 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.spi.connector;
+
+import java.util.concurrent.TimeUnit;
+import javax.transaction.xa.XAResource;
+import org.jboss.dna.spi.connector.commands.RepositoryCommand;
+
+/**
+ * A connection to a repository source.
+ * <p>
+ * These connections need not support concurrent operations by multiple threads, since the federation engine never uses them this
+ * way.
+ * </p>
+ * @author Randall Hauch
+ */
+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;
+
+    void setListener( RepositorySourceListener listener );
+
+    /**
+     * Execute the supplied commands against this repository source.
+     * @param env the environment in which the commands are being executed; never null
+     * @param commands the commands to be executed; never null
+     * @throws RepositorySourceException if there is a problem loading the node data
+     */
+    void execute( RepositorySourceEnvironment env, RepositoryCommand... commands ) throws RepositorySourceException;
+
+    /**
+     * Close this connection to signal that it is no longer needed and that any accumulated resources are to be released.
+     * @throws InterruptedException if the thread has been interrupted while the close was in progress
+     */
+    void close() throws InterruptedException;
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositoryConnectionFactory.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositoryConnectionFactory.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositoryConnectionFactory.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,37 @@
+/*
+ * 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.spi.connector;
+
+/**
+ * @author Randall Hauch
+ */
+public interface RepositoryConnectionFactory {
+
+    /**
+     * Get a connection from this factory.
+     * @return a connection
+     * @throws RepositorySourceException if there is a problem obtaining a connection
+     * @throws InterruptedException if the thread is interrupted while attempting to get a connection
+     * @throws IllegalStateException if the factory is not in a state to create or return connections
+     */
+    RepositoryConnection getConnection() throws RepositorySourceException, InterruptedException;
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySource.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySource.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySource.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,74 @@
+/*
+ * 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.spi.connector;
+
+import java.io.Serializable;
+import javax.naming.Referenceable;
+import org.jboss.dna.spi.cache.CachePolicy;
+
+/**
+ * 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>
+ * 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>
+ * @author Randall Hauch
+ */
+public interface RepositorySource extends RepositoryConnectionFactory, Referenceable, Serializable {
+
+    /**
+     * Get the name for this repository source.
+     * @return the name; never null or empty
+     */
+    String getName();
+
+    /**
+     * 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 default cache policy for this source. If none is provided, a global cache policy will be used.
+     * @return the default cache policy
+     */
+    CachePolicy getDefaultCachePolicy();
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceEnvironment.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceEnvironment.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceEnvironment.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,53 @@
+/*
+ * 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.spi.connector;
+
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.NameFactory;
+import org.jboss.dna.spi.graph.PropertyValue;
+import org.jboss.dna.spi.graph.PropertyValueFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public interface RepositorySourceEnvironment {
+
+    /**
+     * Get the factory that should be used to create {@link PropertyValue property values}.
+     * @return the property value factory; never null
+     */
+    PropertyValueFactory getPropertyValueFactory();
+
+    /**
+     * Get the factory that should be used to create {@link Name names}.
+     * @return the name factory; never null
+     */
+    NameFactory getNameFactory();
+
+    /**
+     * Get the {@link RepositorySource} instance that this environment represents. This instance will be the same instance that
+     * created the {@link RepositoryConnection} for which this environment was created and is being used.
+     * @return the repository source; never null
+     */
+    RepositorySource getRepositorySource();
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceException.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceException.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceException.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,73 @@
+/*
+ * 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.spi.connector;
+
+/**
+ * @author Randall Hauch
+ */
+public class RepositorySourceException extends RuntimeException {
+
+    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;
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceListener.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceListener.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/RepositorySourceListener.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,30 @@
+/*
+ * 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.spi.connector;
+
+/**
+ * @author Randall Hauch
+ */
+public interface RepositorySourceListener {
+
+    void notify( String sourceName, Object... events );
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetChildrenCommand.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetChildrenCommand.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetChildrenCommand.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,75 @@
+/*
+ * 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.spi.connector.commands;
+
+import java.util.Iterator;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+
+/**
+ * A command to get the children of a single node.
+ * @author Randall Hauch
+ */
+public interface GetChildrenCommand extends GetCommand {
+
+    /**
+     * Get the path of the node for which the children are to be obtained.
+     * @return the node's path
+     */
+    Path getPath();
+
+    /**
+     * Set the children of this node using an iterator of names. Any existing child references already set on this command will be
+     * replaced by those supplied to this method.
+     * <p>
+     * The indexes of the same-name siblings will be determined by the order in which they appear in the iterator.
+     * </p>
+     * <p>
+     * The caller may supply a custom iterator implementation, which will be called on this same connection within the same
+     * transaction when the node data is processed and consumed.
+     * </p>
+     * @param namesOfChildren the iterator over the names of children; may be null if there are no children
+     */
+    void setChildren( Iterator<Name> namesOfChildren );
+
+    /**
+     * Set the children of this node using the array of names. Any existing child references already set on this command will be
+     * replaced by those supplied to this method.
+     * <p>
+     * The indexes of the same-name siblings will be determined by the order in which they appear in the iterator.
+     * </p>
+     * @param namesOfChildren the names of children; may be null if there are no children
+     */
+    void setChildren( Name... namesOfChildren );
+
+    /**
+     * Set the child of this node using the supplied name. Any existing child references already set on this command will be
+     * replaced by those supplied to this method.
+     * @param nameOfChild
+     */
+    void setChild( Name nameOfChild );
+
+    /**
+     * Set that this node has no children. Any existing child references already set on this command will be removed.
+     */
+    void setNoChildren();
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetCommand.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetCommand.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetCommand.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,45 @@
+/*
+ * 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.spi.connector.commands;
+
+import org.jboss.dna.spi.cache.CachePolicy;
+
+/**
+ * Base interface for any repository command that retrieves information.
+ * @author Randall Hauch
+ */
+public interface GetCommand extends RepositoryCommand {
+
+    /**
+     * Get the caching policy to be used for this command's results. Note that the values of the policy are relative to the time
+     * the information was obtained, so the same instance can be used repeatedly.
+     * </p>
+     * @return cachePolicy the caching policy, which may not be null if no caching policy is defined
+     */
+    public CachePolicy getCachePolicy();
+
+    /**
+     * Set the caching policy for this command's results.
+     * @param cachePolicy the caching policy to use for this command's results
+     */
+    public void setCachePolicy( CachePolicy cachePolicy );
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetNodeCommand.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetNodeCommand.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetNodeCommand.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,30 @@
+/*
+ * 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.spi.connector.commands;
+
+/**
+ * A command to get the properties and children for a single node.
+ * @author Randall Hauch
+ */
+public interface GetNodeCommand extends GetChildrenCommand, GetPropertiesCommand {
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetPropertiesCommand.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetPropertiesCommand.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/GetPropertiesCommand.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,48 @@
+/*
+ * 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.spi.connector.commands;
+
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PropertyValue;
+
+/**
+ * A command to get the properties for a single node.
+ * @author Randall Hauch
+ */
+public interface GetPropertiesCommand extends GetCommand {
+
+    /**
+     * Get the path of the node for which the properties are to be obtained.
+     * @return the node's path
+     */
+    Path getPath();
+
+    /**
+     * Set the values for the named property. Any existing property values, if previously set, will be overwritten. If there are
+     * no property vlaues or if all of the property values are null, the property will be removed.
+     * @param propertyName the name of the property
+     * @param values the property values
+     */
+    void setProperty( Name propertyName, PropertyValue... values );
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/RepositoryCommand.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/RepositoryCommand.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/connector/commands/RepositoryCommand.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,36 @@
+/*
+ * 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.spi.connector.commands;
+
+/**
+ * The base interface for all repository commands
+ * @author Randall Hauch
+ */
+public interface RepositoryCommand {
+
+    /**
+     * Return whether this command has been cancelled.
+     * @return true if this command has been cancelled, or false otherwise.
+     */
+    boolean isCancelled();
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Binary.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Binary.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Binary.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,63 @@
+/*
+ * 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.spi.graph;
+
+import java.io.Externalizable;
+import java.io.InputStream;
+import net.jcip.annotations.ThreadSafe;
+
+/**
+ * Value holder for binary data.
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public interface Binary extends Comparable<Binary>, Externalizable {
+
+    /**
+     * Get the length of this binary data.
+     * @return the number of bytes in this binary data
+     */
+    public long getSize();
+
+    /**
+     * Get the contents of this data as a stream.
+     * @return the stream to this data's contents
+     */
+    public InputStream getStream();
+
+    /**
+     * Get the contents of this data as a byte array.
+     * @return the data as an array
+     */
+    public byte[] getBytes();
+
+    /**
+     * Acquire any resources for this data. This method must be called before any other method on this object.
+     */
+    public void acquire();
+
+    /**
+     * Release any acquired resources. This method must be called after a client is finished with this value.
+     */
+    public void release();
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/InvalidPathException.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/InvalidPathException.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/InvalidPathException.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,60 @@
+/*
+ * 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.spi.graph;
+
+/**
+ * @author Randall Hauch
+ */
+public class InvalidPathException extends RuntimeException {
+
+    /**
+     * 
+     */
+    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);
+
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Name.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Name.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Name.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,62 @@
+/*
+ * 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.spi.graph;
+
+import java.io.Serializable;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+
+/**
+ * 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 );
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/NameFactory.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/NameFactory.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/NameFactory.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,73 @@
+/*
+ * 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.spi.graph;
+
+import org.jboss.dna.common.text.TextEncoder;
+
+/**
+ * A factory for creating {@link Name names}.
+ * @author Randall Hauch
+ */
+public interface NameFactory {
+
+    /**
+     * Create a name from the qualified name, which must be of the same form as returned by {@link Name#getString()}.
+     * <p>
+     * This method is equivalent to calling {@link #create(String, TextEncoder)} with a null encoder.
+     * </p>
+     * @param qualifiedName
+     * @return the new name.
+     * @throws IllegalArgumentException if the qualified name is null or invalid
+     */
+    Name create( String qualifiedName );
+
+    /**
+     * Create a name from the qualified name, which must be of the same form as returned by {@link Name#getString()}.
+     * @param qualifiedName
+     * @param encoder the encoder that should be used to decode the qualified name
+     * @return the new name
+     * @throws IllegalArgumentException if the qualified name is null or invalid
+     */
+    Name create( String qualifiedName, TextEncoder encoder );
+
+    /**
+     * Create a name from the given namespace URI and local name.
+     * <p>
+     * This method is equivalent to calling {@link #create(String, String, TextEncoder)} 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 null
+     */
+    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 encoder the encoder that should be used to decode the qualified name
+     * @return the new name
+     * @throws IllegalArgumentException if the local name is null
+     */
+    Name create( String namespaceUri, String localName, TextEncoder encoder );
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,361 @@
+/*
+ * 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.spi.graph;
+
+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.TextEncoder;
+import org.jboss.dna.common.text.UrlEncoder;
+
+/**
+ * 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 #getAncestor() 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
+ */
+ 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 and decodes according to JSR-283.
+     */
+    public static final TextEncoder JSR283_ENCODER = new Jsr283Encoder();
+
+    /**
+     * The text encoder that encodes and decodes 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 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 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 = 0;
+
+    /**
+     * 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 0} 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 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 );
+    }
+
+    /**
+     * 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
+     * @return true if the paths are equivalent, or false otherwise
+     */
+    public boolean isSame( 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
+     * @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
+     * @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.
+     * @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 path if it is already the root
+     */
+    public Path getAncestor();
+
+    /**
+     * 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 PathNotFoundException 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 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 substring.
+     * @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 );
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,112 @@
+/*
+ * 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.spi.graph;
+
+/**
+ * A factory for creating {@link Path paths}.
+ * @author Randall Hauch
+ */
+public interface PathFactory {
+
+    /**
+     * 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 create( 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 create( Path.Segment... segments );
+
+    /**
+     * 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 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 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 );
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathNotFoundException.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathNotFoundException.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathNotFoundException.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,60 @@
+/*
+ * 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.spi.graph;
+
+/**
+ * @author Randall Hauch
+ */
+public class PathNotFoundException extends RuntimeException {
+
+    /**
+     * 
+     */
+    public PathNotFoundException() {
+    }
+
+    /**
+     * @param message
+     */
+    public PathNotFoundException( String message ) {
+        super(message);
+
+    }
+
+    /**
+     * @param cause
+     */
+    public PathNotFoundException( Throwable cause ) {
+        super(cause);
+
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public PathNotFoundException( String message, Throwable cause ) {
+        super(message, cause);
+
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Property.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Property.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/Property.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,37 @@
+/*
+ * 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.spi.graph;
+
+import java.util.Iterator;
+
+/**
+ * @author Randall Hauch
+ */
+public interface Property extends Iterable<PropertyValue> {
+
+    Name getName();
+
+    boolean isMultiple();
+
+    Iterator<PropertyValue> getValues();
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyType.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyType.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyType.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,89 @@
+/*
+ * 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.spi.graph;
+
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.spi.SpiI18n;
+import com.sun.tools.javac.tree.Tree.Binary;
+
+/**
+ * @author Randall Hauch
+ */
+ at Immutable
+public enum PropertyType {
+
+    STRING("String", PropertyValues.STRING_COMPARATOR, String.class),
+    BINARY("Binary", PropertyValues.BINARY_COMPARATOR, Binary.class),
+    LONG("Long", PropertyValues.LONG_COMPARATOR, Long.class),
+    DOUBLE("Double", PropertyValues.DOUBLE_COMPARATOR, Double.class),
+    DECIMAL("Decimal", PropertyValues.DECIMAL_COMPARATOR, BigDecimal.class),
+    DATE("Date", PropertyValues.DATE_COMPARATOR, Date.class),
+    BOOLEAN("Boolean", PropertyValues.BOOLEAN_COMPARATOR, Boolean.class),
+    NAME("Name", PropertyValues.NAME_COMPARATOR, Name.class),
+    PATH("Path", PropertyValues.PATH_COMPARATOR, Path.class),
+    REFERENCE("Reference", PropertyValues.REFERENCE_COMPARATOR, UUID.class),
+    URI("URI", PropertyValues.URI_COMPARATOR, URI.class),
+    UNDEFINED("undefined", PropertyValues.UNDEFINED_COMPARATOR, Comparable.class);
+
+    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 isInstance( Object value ) {
+        return this.valueClass.isInstance(value);
+    }
+
+    public static PropertyType discoverType( Object value ) {
+        if (value == null) {
+            throw new ValueFormatException(SpiI18n.unableToDiscoverPropertyType.text(value));
+        }
+        for (PropertyType type : PropertyType.values()) {
+            if (type.isInstance(value)) return type;
+        }
+        throw new ValueFormatException(SpiI18n.unableToDiscoverPropertyType.text(StringUtil.readableString(value)));
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValue.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValue.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValue.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,42 @@
+/*
+ * 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.spi.graph;
+
+import java.io.Serializable;
+
+/**
+ * @author Randall Hauch
+ */
+public interface PropertyValue extends Comparable<PropertyValue>, Cloneable, Serializable {
+
+    /**
+     * Determine whether the property value is null.
+     * @return true if the property value is null, or false otherwise
+     */
+    boolean isNull();
+
+    String getValueAsString();
+
+    PropertyType getPropertyType();
+
+    boolean isEquivalentTo( PropertyValue value );
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValueFactory.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValueFactory.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValueFactory.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,68 @@
+/*
+ * 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.spi.graph;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+import net.jcip.annotations.ThreadSafe;
+
+/**
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public interface PropertyValueFactory {
+
+    PropertyValue create( String value ) throws ValueFormatException;
+
+    PropertyValue create( int value ) throws ValueFormatException;
+
+    PropertyValue create( long value ) throws ValueFormatException;
+
+    PropertyValue create( boolean value ) throws ValueFormatException;
+
+    PropertyValue create( float value ) throws ValueFormatException;
+
+    PropertyValue create( double value ) throws ValueFormatException;
+
+    PropertyValue create( Calendar value ) throws ValueFormatException;
+
+    PropertyValue create( Date value ) throws ValueFormatException;
+
+    PropertyValue create( Name value ) throws ValueFormatException;
+
+    PropertyValue create( Path value ) throws ValueFormatException;
+
+    PropertyValue create( UUID value ) throws ValueFormatException;
+
+    PropertyValue create( URI value ) throws ValueFormatException;
+
+    PropertyValue create( byte[] value ) throws ValueFormatException;
+
+    PropertyValue create( InputStream value, int approximateLength ) throws ValueFormatException;
+
+    PropertyValue create( Reader reader, int approximateLength ) throws ValueFormatException;
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValues.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValues.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/PropertyValues.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,402 @@
+/*
+ * 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.spi.graph;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+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.common.util.DateUtil;
+import org.jboss.dna.spi.SpiI18n;
+
+/**
+ * @author Randall Hauch
+ */
+public class PropertyValues {
+
+    /**
+     * A comparator of string values.
+     */
+    public static final Comparator<String> STRING_COMPARATOR = new Comparator<String>() {
+
+        public int compare( String o1, String o2 ) {
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of integer values.
+     */
+    public static final Comparator<Integer> INTEGER_COMPARATOR = new Comparator<Integer>() {
+
+        public int compare( Integer o1, Integer o2 ) {
+            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 ) {
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of float values.
+     */
+    public static final Comparator<Float> FLOAT_COMPARATOR = new Comparator<Float>() {
+
+        public int compare( Float o1, Float o2 ) {
+            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 ) {
+            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 ) {
+            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;
+                    // 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 ValueFormatException(SpiI18n.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 ValueFormatException(SpiI18n.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 ) {
+            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 ) {
+            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 ) {
+            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 ) {
+            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 ) {
+            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 ) {
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of reference values.
+     */
+    public static final Comparator<UUID> REFERENCE_COMPARATOR = new Comparator<UUID>() {
+
+        public int compare( UUID o1, UUID o2 ) {
+            return o1.compareTo(o2);
+        }
+    };
+    /**
+     * A comparator of other values.
+     */
+    public static final Comparator<Object> UNDEFINED_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 == type2) return type1.getComparator().compare(o1, o2);
+            // The types are different but the classes are the same ...
+            if (type1.getDeclaringClass().isAssignableFrom(type2.getDeclaringClass())) {
+                return type1.getComparator().compare(o1, o2);
+            }
+            if (type2.getDeclaringClass().isAssignableFrom(type1.getDeclaringClass())) {
+                return type2.getComparator().compare(o1, o2);
+            }
+            // The types are different and must be converted ...
+            String value1 = PropertyValues.getString(o1);
+            String value2 = PropertyValues.getString(o2);
+            return value1.compareTo(value2);
+        }
+    };
+
+    /**
+     * Get the string representation of the supplied value. This method may perform an conversion that may lose information.
+     * @param value the value to be interpreted as a string
+     * @return the string representation
+     */
+    public static String getString( Object value ) {
+        if (value == null) return null;
+        if (value instanceof String) return (String)value;
+        if (value instanceof Boolean) return getString(((Boolean)value).booleanValue());
+        if (value instanceof Double) return getString(((Double)value).doubleValue());
+        if (value instanceof Long) return getString(((Long)value).longValue());
+        if (value instanceof Date) return getString((Date)value);
+        if (value instanceof Binary) return getString((Binary)value);
+        if (value instanceof Calendar) return getString((Calendar)value);
+        if (value instanceof BigDecimal) return getString((BigDecimal)value);
+        if (value instanceof Name) return getString((Name)value);
+        if (value instanceof Path) return getString((Path)value);
+        if (value instanceof URI) return getString((URI)value);
+        if (value instanceof UUID) return getString((UUID)value);
+        return value.toString();
+    }
+
+    /**
+     * Get the string representation of the supplied boolean value. This method is implemented by calling
+     * {@link Boolean#toString(boolean) Boolean.toString(boolean)}.
+     * @param value the boolean value
+     * @return the string representation
+     */
+    public static String getString( boolean value ) {
+        return Boolean.toString(value);
+    }
+
+    /**
+     * Get the string representation of the supplied double value. This method is implemented by calling
+     * {@link Double#toString(double) Double.toString(double)}.
+     * @param value the double value
+     * @return the string representation
+     */
+    public static String getString( double value ) {
+        return Double.toString(value);
+    }
+
+    /**
+     * Get the string representation of the supplied long value. This method is implemented by calling
+     * {@link Long#toString(long) Long.toString(long)}.
+     * @param value the long value
+     * @return the string representation
+     */
+    public static String getString( long value ) {
+        return Long.toString(value);
+    }
+
+    /**
+     * Get the string representation of the supplied binary value. This method attempts to interpret the binary value as a UTF-8
+     * encoded string.
+     * @param value the binary value
+     * @return the string representation
+     */
+    public static String getString( Binary value ) {
+        if (value == null) return null;
+        try {
+            value.acquire();
+            byte[] bytes = value.getBytes();
+            try {
+                return new String(bytes, "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                throw new ValueFormatException(SpiI18n.errorConvertingBinaryValueToString.text());
+            }
+        } finally {
+            value.release();
+        }
+    }
+
+    /**
+     * Get the ISO 8601:2004 string representation of the supplied date value.
+     * @param value the date value
+     * @return the string representation
+     */
+    public static String getString( Date value ) {
+        if (value == null) return null;
+        return DateUtil.getDateAsStandardString(value);
+    }
+
+    /**
+     * Get the ISO 8601:2004 string representation of the supplied calendar value.
+     * @param value the calendar value
+     * @return the string representation
+     */
+    public static String getString( Calendar value ) {
+        if (value == null) return null;
+        return getString(value.getTime());
+    }
+
+    /**
+     * Get the string representation of the supplied decimal value.
+     * @param value the decimal value
+     * @return the string representation
+     */
+    public static String getString( BigDecimal value ) {
+        if (value == null) return null;
+        return value.toString();
+    }
+
+    /**
+     * Get the string representation of the supplied name. This method calls {@link Name#getString() Name.getString()}.
+     * @param value the name value
+     * @return the string representation
+     */
+    public static String getString( Name value ) {
+        if (value == null) return null;
+        return value.getString();
+    }
+
+    /**
+     * Get the string representation of the supplied path. This method calls {@link Path#getString() Path.getString()}.
+     * @param value the path value
+     * @return the string representation
+     */
+    public static String getString( Path value ) {
+        if (value == null) return null;
+        return value.getString();
+    }
+
+    /**
+     * Get the string representation of the supplied URI. This method calls {@link URI#toASCIIString() URI.toASCIIString()}.
+     * @param value the URI value
+     * @return the string representation
+     */
+    public static String getString( URI value ) {
+        if (value == null) return null;
+        return value.toASCIIString();
+    }
+
+    /**
+     * Get the string representation of the supplied UUID.
+     * @param value the UUID value
+     * @return the string representation
+     */
+    public static String getString( UUID value ) {
+        if (value == null) return null;
+        return value.toString();
+    }
+
+    /**
+     * Get the string representation of the supplied string value. This method simply returns the supplied value.
+     * @param value the date value
+     * @return the string representation
+     */
+    public static String getString( String value ) {
+        return value;
+    }
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueFormatException.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueFormatException.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueFormatException.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,60 @@
+/*
+ * 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.spi.graph;
+
+/**
+ * @author Randall Hauch
+ */
+public class ValueFormatException extends RuntimeException {
+
+    /**
+     * 
+     */
+    public ValueFormatException() {
+    }
+
+    /**
+     * @param message
+     */
+    public ValueFormatException( String message ) {
+        super(message);
+
+    }
+
+    /**
+     * @param cause
+     */
+    public ValueFormatException( Throwable cause ) {
+        super(cause);
+
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public ValueFormatException( String message, Throwable cause ) {
+        super(message, cause);
+
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicName.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicName.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicName.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,117 @@
+/*
+ * 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.spi.graph.impl;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+
+/**
+ * A basic implementation of {@link Name}.
+ * @author Randall Hauch
+ */
+ at Immutable
+public class BasicName implements Name {
+
+    private final String namespaceUri;
+    private final String localName;
+    private final int hc;
+
+    public BasicName( String namespaceUri, String localName ) {
+        this.namespaceUri = namespaceUri != null ? namespaceUri.trim() : "";
+        this.localName = localName != null ? localName.trim() : "";
+        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 (encoder == null) encoder = Path.DEFAULT_ENCODER;
+        return "{" + encoder.encode(this.namespaceUri) + "}" + encoder.encode(this.localName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( Name that ) {
+        if (that == this) return 0;
+        int diff = this.getNamespaceUri().compareTo(that.getNamespaceUri());
+        if (diff != 0) return diff;
+        diff = this.getLocalName().compareTo(that.getLocalName());
+        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.getNamespaceUri().equals(that.getNamespaceUri())) return false;
+            return this.getLocalName().equals(that.getLocalName());
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return "{" + this.namespaceUri + "}" + this.localName;
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicNameFactory.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicNameFactory.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicNameFactory.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,83 @@
+/*
+ * 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.spi.graph.impl;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.SpiI18n;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.NameFactory;
+import org.jboss.dna.spi.graph.Path;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicNameFactory implements NameFactory {
+
+    // Non-escaped pattern: (\{([^}]*)\})?(.*)
+    protected static final String QUALFIED_NAME_PATTERN_STRING = "(\\{([^}]*)\\})?(.*)";
+    protected static final Pattern QUALIFIED_NAME_PATTERN = Pattern.compile(QUALFIED_NAME_PATTERN_STRING);
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( String qualifiedName ) {
+        return create(qualifiedName, Path.DEFAULT_ENCODER);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( String qualifiedName, TextEncoder encoder ) {
+        ArgCheck.isNotNull(qualifiedName, "qualifiedName");
+        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
+        String decodedQualifiedName = encoder.decode(qualifiedName.trim());
+        Matcher matcher = QUALIFIED_NAME_PATTERN.matcher(decodedQualifiedName);
+        if (!matcher.matches()) {
+            throw new IllegalArgumentException(SpiI18n.invalidQualifiedNameString.text(qualifiedName));
+        }
+        String namespaceUri = matcher.group(2);
+        String localName = matcher.group(3);
+        return new BasicName(namespaceUri, localName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( String namespaceUri, String localName ) {
+        return create(namespaceUri, localName, Path.DEFAULT_ENCODER);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Name create( String namespaceUri, String localName, TextEncoder encoder ) {
+        ArgCheck.isNotNull(localName, "localName");
+        if (encoder == null) encoder = Path.DEFAULT_ENCODER;
+        namespaceUri = namespaceUri != null ? encoder.decode(namespaceUri.trim()) : null;
+        localName = encoder.decode(localName.trim());
+        return new BasicName(namespaceUri, localName);
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,441 @@
+/*
+ * 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.spi.graph.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.CommonI18n;
+import org.jboss.dna.common.text.Inflector;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.SpiI18n;
+import org.jboss.dna.spi.graph.InvalidPathException;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathNotFoundException;
+
+/**
+ * A basic implementation of {@link Path}.
+ * @author Randall Hauch
+ */
+ at Immutable
+public class BasicPath implements Path {
+
+    public static final Path ROOT = new BasicPath(null, true);
+
+    protected static final Path SELF_PATH = new BasicPath(Collections.singletonList(BasicPathSegment.SELF_SEGMENT), false);
+
+    private static final List<Segment> EMPTY_SEGMENTS = Collections.emptyList();
+
+    private final List<Segment> segments;
+    private final boolean absolute;
+    private final boolean normalized;
+    private transient String path;
+
+    /**
+     * @param segments the segments
+     * @param absolute true if this path is absolute, or false otherwise
+     */
+    public BasicPath( List<Segment> segments, boolean absolute ) {
+        this.segments = segments != null && segments.size() > 0 ? Collections.unmodifiableList(segments) : EMPTY_SEGMENTS;
+        this.absolute = absolute;
+        this.normalized = isNormalized(segments);
+    }
+
+    protected boolean isNormalized( List<Segment> segments ) {
+        for (Segment segment : segments) {
+            if (segment.isSelfReference() || segment.isParentReference()) return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path getAncestor() {
+        if (this.isRoot()) return this;
+        if (this.segments.size() == 1) return ROOT;
+        return subpath(0, this.segments.size() - 1);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path getAncestor( int degree ) {
+        ArgCheck.isNonNegative(degree, "degree");
+        if (this.isRoot()) return this;
+        int endIndex = this.segments.size() - degree;
+        if (endIndex < 0) {
+            String msg = SpiI18n.pathAncestorDegreeIsInvalid.text(this.getString(), Inflector.getInstance().ordinalize(degree));
+            throw new PathNotFoundException(msg);
+        }
+        return subpath(0, endIndex);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path getCanonicalPath() {
+        if (!this.isAbsolute()) {
+            String msg = SpiI18n.pathIsNotAbsolute.text(this);
+            throw new InvalidPathException(msg);
+        }
+        if (this.isNormalized()) return this;
+        return this.getNormalizedPath();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path getCommonAncestor( Path that ) {
+        if (that == null) return null;
+        Path normalizedPath = this.getNormalizedPath();
+        int lastIndex = normalizedPath.size();
+        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 ROOT;
+        return normalizedPath.subpath(0, lastIndex);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path.Segment getLastSegment() {
+        if (this.isRoot()) return null;
+        return this.segments.get(size() - 1);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path getNormalizedPath() {
+        if (this.isNormalized()) return this; // ROOT is normalized already
+        LinkedList<Segment> newSegments = new LinkedList<Segment>();
+        for (Segment segment : segments) {
+            if (segment.isSelfReference()) continue;
+            if (segment.isParentReference()) {
+                if (newSegments.size() <= 0) {
+                    if (this.isAbsolute()) {
+                        throw new InvalidPathException(CommonI18n.pathCannotBeNormalized.text(this));
+                    }
+                }
+                if (newSegments.size() > 0 && !newSegments.getLast().isParentReference()) {
+                    newSegments.removeLast();
+                    continue;
+                }
+            }
+            newSegments.add(segment);
+        }
+        if (newSegments.isEmpty()) {
+            if (this.isAbsolute()) return ROOT;
+            // Otherwise relative and it had contained nothing but self references ...
+            return SELF_PATH;
+        }
+        return new BasicPath(newSegments, this.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Segment getSegment( int index ) {
+        return this.segments.get(index);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Segment[] getSegmentsArray() {
+        return this.segments.toArray(new Path.Segment[this.segments.size()]);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public List<Segment> getSegmentsList() {
+        return this.segments;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString() {
+        return getString(DEFAULT_ENCODER);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString( TextEncoder encoder ) {
+        if (encoder == null) encoder = DEFAULT_ENCODER;
+        if (encoder == DEFAULT_ENCODER && this.path != null) return this.path;
+
+        // 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.segments) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(DELIMITER);
+            }
+            assert segment != null;
+            sb.append(segment.getString(encoder));
+        }
+        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
+        if (encoder == DEFAULT_ENCODER && this.path == null) this.path = result;
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasSameAncestor( Path that ) {
+        if (that == null) return false;
+        if (that.size() != this.size()) return false;
+        if (this.size() == 1) return false;
+        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 isAbsolute() {
+        return this.absolute;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAncestorOf( Path decendant ) {
+        if (decendant == null) return false;
+        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}
+     */
+    public boolean isDecendantOf( Path ancestor ) {
+        if (ancestor == null) return false;
+        return ancestor.isAncestorOf(this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isNormalized() {
+        return this.normalized;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isRoot() {
+        return this == ROOT || this.segments.isEmpty();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isSame( Path other ) {
+        return this.compareTo(other) == 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<Segment> iterator() {
+        return this.segments.iterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path relativeTo( Path startingPath ) {
+        ArgCheck.isNotNull(startingPath, "to");
+        if (!this.isAbsolute()) {
+            String msg = SpiI18n.pathIsNotAbsolute.text(this);
+            throw new InvalidPathException(msg);
+        }
+        if (!startingPath.isAbsolute()) {
+            String msg = SpiI18n.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(BasicPathSegment.PARENT_SEGMENT);
+        }
+        // Add the segments of this path from the common ancestor ...
+        for (int i = lengthOfCommonAncestor; i < this.size(); ++i) {
+            relativeSegments.add(this.segments.get(i));
+        }
+        if (relativeSegments.isEmpty()) {
+            relativeSegments.add(BasicPathSegment.SELF_SEGMENT);
+        }
+        return new BasicPath(relativeSegments, false);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path resolve( Path relativePath ) {
+        ArgCheck.isNotNull(relativePath, "relative path");
+        if (!this.isAbsolute()) {
+            String msg = SpiI18n.pathIsAlreadyAbsolute.text(this.path);
+            throw new InvalidPathException(msg);
+        }
+        if (relativePath.isAbsolute()) {
+            String msg = SpiI18n.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.getAncestor();
+        }
+        List<Segment> segments = new ArrayList<Segment>(this.size() + relativePath.size());
+        segments.addAll(this.segments);
+        segments.addAll(relativePath.getSegmentsList());
+        return new BasicPath(segments, true).getNormalizedPath();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path resolveAgainst( Path absolutePath ) {
+        ArgCheck.isNotNull(absolutePath, "absolute path");
+        return absolutePath.resolve(this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int size() {
+        return this.segments.size();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path subpath( int beginIndex, int endIndex ) {
+        if (beginIndex == 0 && endIndex == 0) return ROOT;
+        // This reuses the same list, so it's pretty efficient ...
+        return new BasicPath(this.segments.subList(beginIndex, endIndex), this.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return this.segments.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof Path) {
+            Path that = (Path)obj;
+            return this.segments.equals(that.getSegmentsList());
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( Path that ) {
+        if (that == null) return 1;
+        if (this == that) return 0;
+        Iterator<Segment> thisIter = this.segments.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);
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPathFactory.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPathFactory.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPathFactory.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,167 @@
+/*
+ * 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.spi.graph.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.Path.Segment;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicPathFactory implements PathFactory {
+
+    /**
+     * 
+     */
+    public BasicPathFactory() {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Name... segmentNames ) {
+        if (segmentNames == null || segmentNames.length == 0) return BasicPath.ROOT;
+        List<Segment> segments = new ArrayList<Segment>(segmentNames.length);
+        for (Name segmentName : segmentNames) {
+            if (segmentName == null) {
+                ArgCheck.containsNoNulls(segmentNames, "segment names");
+            }
+            segments.add(new BasicPathSegment(segmentName));
+        }
+        return new BasicPath(segments, true);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Segment... segments ) {
+        if (segments == null || segments.length == 0) return BasicPath.ROOT;
+        List<Segment> segmentsList = new ArrayList<Segment>(segments.length);
+        for (Segment segment : segments) {
+            if (segment == null) {
+                ArgCheck.containsNoNulls(segments, "segments");
+            }
+            segmentsList.add(segment);
+        }
+        return new BasicPath(segmentsList, true);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path createRelativePath( Name... segmentNames ) {
+        if (segmentNames == null || segmentNames.length == 0) return BasicPath.ROOT;
+        List<Segment> segments = new ArrayList<Segment>(segmentNames.length);
+        for (Name segmentName : segmentNames) {
+            if (segmentName == null) {
+                ArgCheck.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.ROOT;
+        List<Segment> segmentsList = new ArrayList<Segment>(segments.length);
+        for (Segment segment : segments) {
+            if (segment == null) {
+                ArgCheck.containsNoNulls(segments, "segments");
+            }
+            segmentsList.add(segment);
+        }
+        return new BasicPath(segmentsList, false);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Path parentPath, Name segmentName, int index ) {
+        ArgCheck.isNotNull(parentPath, "parent path");
+        ArgCheck.isNotNull(segmentName, "segment name");
+        List<Segment> segments = new ArrayList<Segment>(parentPath.size() + 1);
+        segments.addAll(parentPath.getSegmentsList());
+        segments.add(new BasicPathSegment(segmentName, index));
+        return new BasicPath(segments, parentPath.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Path parentPath, Name... segmentNames ) {
+        ArgCheck.isNotNull(parentPath, "parent path");
+        if (segmentNames == null || segmentNames.length == 0) return parentPath;
+
+        List<Segment> segments = new ArrayList<Segment>(parentPath.size() + 1);
+        segments.addAll(parentPath.getSegmentsList());
+        for (Name segmentName : segmentNames) {
+            if (segmentName == null) {
+                ArgCheck.containsNoNulls(segmentNames, "segment names");
+            }
+            segments.add(new BasicPathSegment(segmentName));
+        }
+        return new BasicPath(segments, parentPath.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Path create( Path parentPath, Segment... segments ) {
+        ArgCheck.isNotNull(parentPath, "parent path");
+        if (segments == null || segments.length == 0) return BasicPath.ROOT;
+
+        List<Segment> segmentsList = new ArrayList<Segment>(parentPath.size() + 1);
+        segmentsList.addAll(parentPath.getSegmentsList());
+        for (Segment segment : segments) {
+            if (segment == null) {
+                ArgCheck.containsNoNulls(segments, "segments");
+            }
+            segmentsList.add(segment);
+        }
+        return new BasicPath(segmentsList, parentPath.isAbsolute());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Segment createSegment( Name segmentName ) {
+        ArgCheck.isNotNull(segmentName, "segment name");
+        return new BasicPathSegment(segmentName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Segment createSegment( Name segmentName, int index ) {
+        ArgCheck.isNotNull(segmentName, "segment name");
+        return new BasicPathSegment(segmentName, index);
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPathSegment.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPathSegment.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPathSegment.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,160 @@
+/*
+ * 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.spi.graph.impl;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+
+/**
+ * A basic implementation of {@link Path.Segment}.
+ * @author Randall Hauch
+ */
+ at Immutable
+public class BasicPathSegment implements Path.Segment {
+
+    public static final Path.Segment SELF_SEGMENT = new BasicPathSegment(new BasicName("", Path.SELF));
+    public static final Path.Segment PARENT_SEGMENT = new BasicPathSegment(new BasicName("", Path.PARENT));
+
+    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 ) {
+        ArgCheck.isNotNull(name, "name");
+        ArgCheck.isNonNegative(index, "index");
+        this.name = name;
+        this.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.hasIndex() == false && this.name.getNamespaceUri().length() == 0 && this.name.getLocalName().equals(Path.PARENT);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isSelfReference() {
+        return this.hasIndex() == false && 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 this.getIndex() != 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 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;
+    }
+
+}

Added: branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/InMemoryBinary.java
===================================================================
--- branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/InMemoryBinary.java	                        (rev 0)
+++ branches/federation/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/InMemoryBinary.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,107 @@
+/*
+ * 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.spi.graph.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.graph.Binary;
+import org.jboss.dna.spi.graph.PropertyValues;
+
+/**
+ * An implementation of {@link Binary} that keeps the binary data in-memory.
+ * @author Randall Hauch
+ */
+ at Immutable
+public class InMemoryBinary implements Binary {
+
+    private byte[] bytes;
+
+    public InMemoryBinary( byte[] bytes ) {
+        ArgCheck.isNotNull(bytes, "bytes");
+        this.bytes = bytes;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getSize() {
+        return this.bytes.length;
+    }
+
+    /**
+     * {@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
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo( Binary o ) {
+        return PropertyValues.BINARY_COMPARATOR.compare(this, o);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void readExternal( ObjectInput in ) throws IOException {
+        int length = in.readInt();
+        this.bytes = new byte[length];
+        in.read(this.bytes);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void writeExternal( ObjectOutput out ) throws IOException {
+        out.write(this.bytes.length);
+        out.write(this.bytes);
+    }
+
+}

Added: branches/federation/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties
===================================================================
--- branches/federation/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties	                        (rev 0)
+++ branches/federation/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,13 @@
+unableToDiscoverPropertyType = Unable to discover property type for {0}
+errorReadingPropertyValueBytes = Error reading bytes
+valueJavaTypeNotCompatibleWithPropertyType = Value is instance of Java type "{0}" and is not compatible with the "{1}" property type
+
+errorConvertingBinaryValueToString = Error while interpretting binary value as a UTF-8 string
+
+pathAncestorDegreeIsInvalid = Unable to obtain the {1} ancestor for {0}
+pathIsAlreadyAbsolute = The path {0} is already an absolute path
+pathIsNotAbsolute = The path {0} is not an absolute path
+pathIsNotRelative = The path {0} is not a relative path
+pathCannotBeNormalized = The path {0} is invalid and cannot be normalized
+
+invalidQualifiedNameString = Unable to parse qualified name from "{0}"
\ No newline at end of file

Added: branches/federation/dna-spi/src/test/java/org/jboss/dna/spi/SpiI18nTest.java
===================================================================
--- branches/federation/dna-spi/src/test/java/org/jboss/dna/spi/SpiI18nTest.java	                        (rev 0)
+++ branches/federation/dna-spi/src/test/java/org/jboss/dna/spi/SpiI18nTest.java	2008-05-15 20:21:25 UTC (rev 175)
@@ -0,0 +1,16 @@
+/*
+ *
+ */
+package org.jboss.dna.spi;
+
+import org.jboss.dna.common.AbstractI18nTest;
+
+/**
+ * @author Randall Hauch
+ */
+public class SpiI18nTest extends AbstractI18nTest {
+
+    public SpiI18nTest() {
+        super(SpiI18n.class);
+    }
+}




More information about the dna-commits mailing list