DNA SVN: r239 - in trunk: dna-common/src/test/java/org/jboss/dna/common/util and 9 other directories.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-06-05 20:37:18 -0400 (Thu, 05 Jun 2008)
New Revision: 239
Added:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/xml/
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/xml/XmlSequencer.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/xml/
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/xml/XmlSequencerTest.java
trunk/dna-repository/src/test/resources/CurrencyFormatterExample.mxml
trunk/dna-repository/src/test/resources/Descriptor.1.0.xsd
trunk/dna-repository/src/test/resources/master.xml
trunk/dna-repository/src/test/resources/plugin.xml
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/util/StringUtil.java
trunk/dna-common/src/test/java/org/jboss/dna/common/util/StringUtilTest.java
trunk/dna-repository/pom.xml
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties
trunk/dna-spi/src/test/java/org/jboss/dna/spi/sequencers/MockSequencerOutput.java
Log:
DNA-72: Create XML sequencer and associated tests in dna-repository project, and added a utility method used by the sequencer to StringUtil, normalize(String), that removes leading and trailing whitespace and reduces consecutive internal whitespace characters to a single space.
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/util/StringUtil.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/util/StringUtil.java 2008-06-05 23:50:49 UTC (rev 238)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/util/StringUtil.java 2008-06-06 00:37:18 UTC (rev 239)
@@ -46,6 +46,7 @@
public class StringUtil {
public static final String[] EMPTY_STRING_ARRAY = new String[0];
+ private static final Pattern NORMALIZE_PATTERN = Pattern.compile("\\s+");
private static final Pattern PARAMETER_COUNT_PATTERN = Pattern.compile("\\{(\\d+)\\}");
/**
@@ -623,18 +624,31 @@
/**
* Get the stack trace of the supplied exception.
*
- * @param t the exception for which the stack trace is to be returned
+ * @param throwable the exception for which the stack trace is to be returned
* @return the stack trace, or null if the supplied exception is null
*/
- public static String getStackTrace( Throwable t ) {
- if (t == null) return null;
+ public static String getStackTrace( Throwable throwable ) {
+ if (throwable == null) return null;
final ByteArrayOutputStream bas = new ByteArrayOutputStream();
final PrintWriter pw = new PrintWriter(bas);
- t.printStackTrace(pw);
+ throwable.printStackTrace(pw);
pw.close();
return bas.toString();
}
+ /**
+ * Removes leading and trailing whitespace from the supplied text, and reduces other consecutive whitespace characters to a
+ * single space. Whitespace includes line-feeds.
+ *
+ * @param text the text to be normalized
+ * @return the normalized text
+ */
+ public static String normalize( String text ) {
+ ArgCheck.isNotNull(text, "text");
+ // This could be much more efficient.
+ return NORMALIZE_PATTERN.matcher(text).replaceAll(" ").trim();
+ }
+
private StringUtil() {
// Prevent construction
}
Modified: trunk/dna-common/src/test/java/org/jboss/dna/common/util/StringUtilTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/util/StringUtilTest.java 2008-06-05 23:50:49 UTC (rev 238)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/util/StringUtilTest.java 2008-06-06 00:37:18 UTC (rev 239)
@@ -415,6 +415,26 @@
assertThat(StringUtil.readableString(list3), is("[ [ \"a1\", \"a2\" ], [ \"b1\", \"b2\" ] ]"));
}
+ @Test( expected = IllegalArgumentException.class )
+ public void normalizeShouldFailIfTextNull() {
+ StringUtil.normalize(null);
+ }
+
+ @Test
+ public void normalizeShouldRemoveLeadingTrailingWhitespace() {
+ assertThat(StringUtil.normalize(" \t\n test this \t"), is("test this"));
+ }
+
+ @Test
+ public void normalizeShouldReduceInternalWhitespace() {
+ assertThat(StringUtil.normalize("test \t\n\r this"), is("test this"));
+ }
+
+ @Test
+ public void normalizeShouldReturnEqualStringIfNothingToNormalize() {
+ assertThat(StringUtil.normalize("test this"), is("test this"));
+ }
+
protected class InputStreamWrapper extends InputStream {
private boolean closed = false;
Modified: trunk/dna-repository/pom.xml
===================================================================
--- trunk/dna-repository/pom.xml 2008-06-05 23:50:49 UTC (rev 238)
+++ trunk/dna-repository/pom.xml 2008-06-06 00:37:18 UTC (rev 239)
@@ -35,6 +35,13 @@
<groupId>org.jboss.dna</groupId>
<artifactId>dna-spi</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-spi</artifactId>
+ <version>${dna-version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<!--
Rules
-->
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java 2008-06-05 23:50:49 UTC (rev 238)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java 2008-06-06 00:37:18 UTC (rev 239)
@@ -27,6 +27,7 @@
/**
* @author Randall Hauch
+ * @author John Verhaeg
*/
public final class RepositoryI18n {
@@ -102,6 +103,11 @@
public static I18n invalidRepositoryNodePath;
+ // XML Sequencer
+ public static I18n errorSequencingXmlDocument;
+ public static I18n sequencingXmlDocument;
+ public static I18n canceledSequencingXmlDocument;
+
static {
try {
I18n.initialize(RepositoryI18n.class);
Added: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/xml/XmlSequencer.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/xml/XmlSequencer.java (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/xml/XmlSequencer.java 2008-06-06 00:37:18 UTC (rev 239)
@@ -0,0 +1,681 @@
+/*
+ *
+ */
+package org.jboss.dna.repository.sequencers.xml;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.jboss.dna.common.monitor.ProgressMonitor;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.repository.RepositoryI18n;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.NameFactory;
+import org.jboss.dna.spi.graph.NamespaceRegistry;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.sequencers.SequencerOutput;
+import org.jboss.dna.spi.sequencers.StreamSequencer;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.DefaultHandler2;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * @author John Verhaeg
+ */
+public class XmlSequencer implements StreamSequencer {
+
+ static final Logger LOGGER = Logger.getLogger(XmlSequencer.class);
+
+ static final String CDATA = "dnaxml:cData";
+ static final String CDATA_CONTENT = "dnaxml:cDataContent";
+ static final String COMMENT = "dnaxml:comment";
+ static final String COMMENT_CONTENT = "dnaxml:commentContent";
+ static final String DOCUMENT = "dnaxml:document";
+ static final String DTD_NAME = "dnadtd:name";
+ static final String DTD_PUBLIC_ID = "dnadtd:publicId";
+ static final String DTD_SYSTEM_ID = "dnadtd:systemId";
+ static final String DTD_VALUE = "dnadtd:value";
+ static final String ELEMENT_CONTENT = "dnaxml:elementContent";
+ static final String ENTITY = "dnadtd:entity";
+ static final String PI = "dnaxml:processingInstruction";
+ static final String PI_CONTENT = "dnaxml:processingInstructionContent";
+ static final String TARGET = "dnaxml:target";
+
+ private static final String DECL_HANDLER_FEATURE = "http://xml.org/sax/properties/declaration-handler";
+ private static final String ENTITY_RESOLVER_2_FEATURE = "http://xml.org/sax/features/use-entity-resolver2";
+ private static final String LEXICAL_HANDLER_FEATURE = "http://xml.org/sax/properties/lexical-handler";
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.jboss.dna.spi.sequencers.StreamSequencer#sequence(java.io.InputStream,
+ * org.jboss.dna.spi.sequencers.SequencerOutput, org.jboss.dna.common.monitor.ProgressMonitor)
+ */
+ public void sequence( InputStream stream,
+ SequencerOutput output,
+ ProgressMonitor monitor ) {
+ monitor.beginTask(100.0, RepositoryI18n.sequencingXmlDocument);
+ XMLReader reader;
+ try {
+ reader = XMLReaderFactory.createXMLReader();
+ Handler handler = new Handler(output, monitor);
+ reader.setContentHandler(handler);
+ reader.setErrorHandler(handler);
+ // Ensure handler acting as entity resolver 2
+ reader.setProperty(DECL_HANDLER_FEATURE, handler);
+ // Ensure handler acting as lexical handler
+ reader.setProperty(LEXICAL_HANDLER_FEATURE, handler);
+ // Ensure handler acting as entity resolver 2
+ try {
+ if (!reader.getFeature(ENTITY_RESOLVER_2_FEATURE)) {
+ reader.setFeature(ENTITY_RESOLVER_2_FEATURE, true);
+ }
+ } catch (SAXNotRecognizedException meansFeatureNotSupported) {
+ }
+ // Prevent loading of external DTDs
+ reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ // Parse XML document
+ reader.parse(new InputSource(stream));
+ } catch (Exception err) {
+ LOGGER.error(err, RepositoryI18n.errorSequencingXmlDocument);
+ } finally {
+ monitor.done();
+ }
+ }
+
+ private class Handler extends DefaultHandler2 {
+
+ private ProgressMonitor monitor;
+ private SequencerOutput output;
+ private double progress;
+
+ private Path path; // The DNA path of the node representing the current XML element
+
+ // Cached instances of the name factory and commonly referenced names
+ private NameFactory nameFactory;
+ private Name commentContentName;
+ private Name commentName;
+ private Name elementContentName;
+ private Name primaryTypeName;
+ private Name targetName;
+
+ // Recursive map used to track the number of occurrences of names for elements under a particular path
+ private Map<Name, List<IndexedName>> nameToIndexedNamesMap = new HashMap<Name, List<IndexedName>>();
+
+ // The stack of recursive maps being processed, with the head entry being the map for the current path
+ private LinkedList<Map<Name, List<IndexedName>>> nameToIndexedNamesMapStack = new LinkedList<Map<Name, List<IndexedName>>>();
+
+ // The stack of XML namespace in scope, with the head entry being namespace of the closest ancestor element declaring a
+ // namespace.
+ private LinkedList<String> nsStack = new LinkedList<String>();
+
+ // Builder used to concatenate concurrent lines of CDATA into a single value.
+ private StringBuilder cDataBuilder;
+
+ // Builder used to concatenate concurrent lines of element content and entity evaluations into a single value.
+ private StringBuilder contentBuilder;
+
+ // The entity being processed
+ private String entity;
+
+ Handler( SequencerOutput output,
+ ProgressMonitor monitor ) {
+ this.output = output;
+ this.monitor = monitor;
+ // Initialize path to a an empty path relative to the SequencerOutput's target path.
+ path = output.getFactories().getPathFactory().createRelativePath();
+ // Cache name factory since it is frequently used
+ nameFactory = output.getFactories().getNameFactory();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#attributeDecl(java.lang.String, java.lang.String, java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ @Override
+ public void attributeDecl( String name,
+ String name2,
+ String type,
+ String mode,
+ String value ) throws SAXException {
+ stopIfCancelled();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
+ */
+ @Override
+ public void characters( char[] ch,
+ int start,
+ int length ) throws SAXException {
+ stopIfCancelled();
+ String content = String.valueOf(ch, start, length);
+ // Check if data should be appended to previously parsed CDATA
+ if (cDataBuilder == null) {
+ // If content is for an entity, replace with entity reference
+ if (entity != null) {
+ content = '&' + entity + ';';
+ }
+ // Check if first line of content
+ if (contentBuilder == null) {
+ contentBuilder = new StringBuilder(content);
+ } else {
+ // Append additional lines or entity evaluations to previous content, separated by a space
+ if (entity == null) {
+ contentBuilder.append(' ');
+ }
+ contentBuilder.append(content);
+ // Text within builder will be output when another element or CDATA is encountered
+ }
+ } else {
+ cDataBuilder.append(ch, start, length);
+ // Text within builder will be output at the end of CDATA
+ }
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#comment(char[], int, int)
+ */
+ @Override
+ public void comment( char[] ch,
+ int start,
+ int length ) throws SAXException {
+ stopIfCancelled();
+ // Output separate nodes for each comment since multiple are allowed
+ startElement(getCommentName());
+ output.setProperty(path, getPrimaryTypeName(), getCommentName());
+ output.setProperty(path, getCommentContentName(), String.valueOf(ch, start, length));
+ endElement();
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#elementDecl(java.lang.String, java.lang.String)
+ */
+ @Override
+ public void elementDecl( String name,
+ String model ) throws SAXException {
+ stopIfCancelled();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#endCDATA()
+ */
+ @Override
+ public void endCDATA() throws SAXException {
+ stopIfCancelled();
+ // Output CDATA built in characters() method
+ output.setProperty(path, nameFactory.create(CDATA_CONTENT), cDataBuilder.toString());
+ endElement();
+ // Null-out builder to free memory
+ cDataBuilder = null;
+ updateProgress();
+ }
+
+ private void endContent() {
+ if (contentBuilder != null) {
+ // Normalize content
+ String content = StringUtil.normalize(contentBuilder.toString());
+ // Null-out builder to setup for subsequent content.
+ // Must be done before call to startElement below to prevent infinite loop.
+ contentBuilder = null;
+ // Skip if nothing in content but whitespace
+ if (content.length() > 0) {
+ // Create separate node for each content entry since entries can be interspersed amongst child elements
+ startElement(getElementContentName());
+ output.setProperty(path, getPrimaryTypeName(), getElementContentName());
+ output.setProperty(path, getElementContentName(), content);
+ endElement();
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#endDocument()
+ */
+ @Override
+ public void endDocument() throws SAXException {
+ stopIfCancelled();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#endDTD()
+ */
+ @Override
+ public void endDTD() throws SAXException {
+ stopIfCancelled();
+ }
+
+ private void endElement() {
+ // Recover parent's path, namespace, and indexedName map, clearing the ended element's map to free memory
+ path = path.getAncestor();
+ nameToIndexedNamesMap.clear();
+ nameToIndexedNamesMap = nameToIndexedNamesMapStack.removeFirst();
+ nsStack.removeFirst();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public void endElement( String uri,
+ String localName,
+ String name ) throws SAXException {
+ stopIfCancelled();
+ // Check if content still needs to be output
+ endContent();
+ endElement();
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#endEntity(java.lang.String)
+ */
+ @Override
+ public void endEntity( String name ) throws SAXException {
+ stopIfCancelled();
+ entity = null;
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
+ */
+ @Override
+ public void error( SAXParseException error ) throws SAXException {
+ LOGGER.error(error, RepositoryI18n.errorSequencingXmlDocument);
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#externalEntityDecl(java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public void externalEntityDecl( String name,
+ String publicId,
+ String systemId ) throws SAXException {
+ stopIfCancelled();
+ // Add "synthetic" entity container to path to help prevent name collisions with XML elements
+ Name entityName = nameFactory.create(ENTITY);
+ startElement(entityName);
+ output.setProperty(path, getPrimaryTypeName(), entityName);
+ output.setProperty(path, nameFactory.create(DTD_NAME), name);
+ output.setProperty(path, nameFactory.create(DTD_PUBLIC_ID), publicId);
+ output.setProperty(path, nameFactory.create(DTD_SYSTEM_ID), systemId);
+ endElement();
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException)
+ */
+ @Override
+ public void fatalError( SAXParseException error ) throws SAXException {
+ LOGGER.error(error, RepositoryI18n.errorSequencingXmlDocument);
+ }
+
+ private Name getCommentContentName() {
+ if (commentContentName == null) {
+ commentContentName = nameFactory.create(COMMENT_CONTENT);
+ }
+ return commentContentName;
+ }
+
+ private Name getCommentName() {
+ if (commentName == null) {
+ commentName = nameFactory.create(COMMENT);
+ }
+ return commentName;
+ }
+
+ private Name getElementContentName() {
+ if (elementContentName == null) {
+ elementContentName = nameFactory.create(ELEMENT_CONTENT);
+ }
+ return elementContentName;
+ }
+
+ private Name getPrimaryTypeName() {
+ if (primaryTypeName == null) {
+ primaryTypeName = nameFactory.create(NameFactory.JCR_PRIMARY_TYPE);
+ }
+ return primaryTypeName;
+ }
+
+ private Name getTargetName() {
+ if (targetName == null) {
+ targetName = nameFactory.create(TARGET);
+ }
+ return targetName;
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#ignorableWhitespace(char[], int, int)
+ */
+ @Override
+ public void ignorableWhitespace( char[] ch,
+ int start,
+ int length ) throws SAXException {
+ stopIfCancelled();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#internalEntityDecl(java.lang.String, java.lang.String)
+ */
+ @Override
+ public void internalEntityDecl( String name,
+ String value ) throws SAXException {
+ stopIfCancelled();
+ // Add "synthetic" entity container to path to help prevent name collisions with XML elements
+ Name entityName = nameFactory.create(ENTITY);
+ startElement(entityName);
+ output.setProperty(path, getPrimaryTypeName(), entityName);
+ output.setProperty(path, nameFactory.create(DTD_NAME), name);
+ output.setProperty(path, nameFactory.create(DTD_VALUE), value);
+ endElement();
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#notationDecl(java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public void notationDecl( String name,
+ String publicId,
+ String systemId ) throws SAXException {
+ stopIfCancelled();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#processingInstruction(java.lang.String, java.lang.String)
+ */
+ @Override
+ public void processingInstruction( String target,
+ String data ) throws SAXException {
+ stopIfCancelled();
+ // Output separate nodes for each instruction since multiple are allowed
+ Name name = nameFactory.create(PI);
+ startElement(name);
+ output.setProperty(path, getPrimaryTypeName(), name);
+ output.setProperty(path, getTargetName(), target);
+ output.setProperty(path, nameFactory.create(PI_CONTENT), data);
+ endElement();
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#skippedEntity(java.lang.String)
+ */
+ @Override
+ public void skippedEntity( String name ) throws SAXException {
+ stopIfCancelled();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#startCDATA()
+ */
+ @Override
+ public void startCDATA() throws SAXException {
+ stopIfCancelled();
+ // Output separate nodes for each CDATA since multiple are allowed
+ startElement(nameFactory.create(CDATA));
+ // Prepare builder for concatenating consecutive lines of CDATA
+ cDataBuilder = new StringBuilder();
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#startDocument()
+ */
+ @Override
+ public void startDocument() throws SAXException {
+ stopIfCancelled();
+ output.setProperty(path, getPrimaryTypeName(), nameFactory.create(DOCUMENT));
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#startDTD(java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public void startDTD( String name,
+ String publicId,
+ String systemId ) throws SAXException {
+ stopIfCancelled();
+ output.setProperty(path, nameFactory.create(DTD_NAME), name);
+ output.setProperty(path, nameFactory.create(DTD_PUBLIC_ID), publicId);
+ output.setProperty(path, nameFactory.create(DTD_SYSTEM_ID), systemId);
+ updateProgress();
+ }
+
+ private void startElement( Name name ) {
+ // Check if content still needs to be output
+ endContent();
+ // Add name to list of indexed names for this element to ensure we use the correct index (which is the size of the
+ // list)
+ List<IndexedName> indexedNames = nameToIndexedNamesMap.get(name);
+ if (indexedNames == null) {
+ indexedNames = new ArrayList<IndexedName>();
+ nameToIndexedNamesMap.put(name, indexedNames);
+ }
+ IndexedName indexedName = new IndexedName();
+ indexedNames.add(indexedName);
+ // Add element name and the appropriate index to the path.
+ // Per the JCR spec, the index must be relative to same-name sibling nodes
+ path = output.getFactories().getPathFactory().create(path, name, indexedNames.size());
+ // Add the indexed name map to the stack and set the current map to the new element's map
+ nameToIndexedNamesMapStack.addFirst(nameToIndexedNamesMap);
+ nameToIndexedNamesMap = indexedName.nameToIndexedNamesMap;
+ // Set the current namespace to whatever is declared by this element, or if not declared, to its nearest ancestor that
+ // does declare a namespace.
+ String ns = name.getNamespaceUri();
+ if (ns.length() == 0) {
+ nsStack.addFirst(nsStack.isEmpty() ? "" : nsStack.getFirst());
+ } else {
+ nsStack.addFirst(ns);
+ }
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String,
+ * org.xml.sax.Attributes)
+ */
+ @Override
+ public void startElement( String uri,
+ String localName,
+ String name,
+ Attributes attributes ) throws SAXException {
+ stopIfCancelled();
+ startElement(nameFactory.create(name));
+ output.setProperty(path, getPrimaryTypeName(), nameFactory.create(uri, localName));
+ // Output this element's attributes using the attribute's namespace, if supplied, or the current namespace in scope.
+ String inheritedNs = nsStack.getFirst();
+ for (int ndx = 0, len = attributes.getLength(); ndx < len; ++ndx) {
+ String ns = attributes.getURI(ndx);
+ output.setProperty(path,
+ nameFactory.create(ns.length() == 0 ? inheritedNs : ns, attributes.getLocalName(ndx)),
+ attributes.getValue(ndx));
+ }
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#startEntity(java.lang.String)
+ */
+ @Override
+ public void startEntity( String name ) throws SAXException {
+ stopIfCancelled();
+ entity = name;
+ updateProgress();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#startPrefixMapping(java.lang.String, java.lang.String)
+ */
+ @Override
+ public void startPrefixMapping( String prefix,
+ String uri ) throws SAXException {
+ stopIfCancelled();
+ // Register any unregistered namespaces
+ NamespaceRegistry registry = output.getNamespaceRegistry();
+ if (!registry.isRegisteredNamespaceUri(uri)) {
+ registry.register(prefix, uri);
+ }
+ updateProgress();
+ }
+
+ private void stopIfCancelled() throws SAXException {
+ if (monitor.isCancelled()) {
+ throw new SAXException(RepositoryI18n.canceledSequencingXmlDocument.text());
+ }
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String,
+ * java.lang.String)
+ */
+ @Override
+ public void unparsedEntityDecl( String name,
+ String publicId,
+ String systemId,
+ String notationName ) throws SAXException {
+ stopIfCancelled();
+ }
+
+ private void updateProgress() {
+ if (progress == 100.0) {
+ progress = 1;
+ } else {
+ progress++;
+ }
+ monitor.worked(progress);
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException)
+ */
+ @Override
+ public void warning( SAXParseException error ) throws SAXException {
+ LOGGER.warn(error, RepositoryI18n.errorSequencingXmlDocument);
+ }
+ }
+
+ private class IndexedName {
+
+ Map<Name, List<IndexedName>> nameToIndexedNamesMap = new HashMap<Name, List<IndexedName>>();
+
+ IndexedName() {
+ }
+ }
+}
Property changes on: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/xml/XmlSequencer.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties
===================================================================
--- trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties 2008-06-05 23:50:49 UTC (rev 238)
+++ trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties 2008-06-06 00:37:18 UTC (rev 239)
@@ -90,3 +90,7 @@
errorUnregisteringWorkspaceListenerWhileShuttingDownObservationService = Error unregistering workspace listener while shutting down observation service
invalidRepositoryNodePath = The repository node path "{0}" is not valid: {1}
+
+errorSequencingXmlDocument = An error occurred while sequencing XML:
+sequencingXmlDocument = Sequencing XML
+canceledSequencingXmlDocument = Canceled sequencing XML
\ No newline at end of file
Added: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/xml/XmlSequencerTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/xml/XmlSequencerTest.java (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/xml/XmlSequencerTest.java 2008-06-06 00:37:18 UTC (rev 239)
@@ -0,0 +1,213 @@
+/*
+ * 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.repository.sequencers.xml;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import org.jboss.dna.common.monitor.ProgressMonitor;
+import org.jboss.dna.common.monitor.SimpleProgressMonitor;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.NameFactory;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.sequencers.MockSequencerOutput;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author John Verhaeg
+ */
+public class XmlSequencerTest {
+
+ private XmlSequencer sequencer;
+ private InputStream stream;
+ private MockSequencerOutput output;
+ private ProgressMonitor monitor;
+ private URL xml1;
+ private URL xml2;
+ private URL xml3;
+ private URL xml4;
+ private URL xsd;
+
+ @Before
+ public void beforeEach() throws Exception {
+ sequencer = new XmlSequencer();
+ output = new MockSequencerOutput() {
+
+ @Override
+ public void setProperty( Path nodePath,
+ Name propertyName,
+ Object... values ) {
+ super.setProperty(nodePath, propertyName, values);
+ // System.out.println(nodePath + "." + propertyName + " = " + Arrays.asList(values));
+ }
+ };
+ monitor = new SimpleProgressMonitor("Test activity");
+ xml1 = this.getClass().getClassLoader().getResource("jackrabbitInMemoryTestRepositoryConfig.xml");
+ assertThat(xml1, is(notNullValue()));
+ xml2 = this.getClass().getClassLoader().getResource("master.xml");
+ assertThat(xml2, is(notNullValue()));
+ xml3 = this.getClass().getClassLoader().getResource("CurrencyFormatterExample.mxml");
+ assertThat(xml3, is(notNullValue()));
+ xml4 = this.getClass().getClassLoader().getResource("plugin.xml");
+ assertThat(xml4, is(notNullValue()));
+ xsd = this.getClass().getClassLoader().getResource("Descriptor.1.0.xsd");
+ assertThat(xsd, is(notNullValue()));
+ }
+
+ @After
+ public void afterEach() throws Exception {
+ if (stream != null) {
+ try {
+ stream.close();
+ } finally {
+ stream = null;
+ }
+ }
+ }
+
+ @Test
+ public void shouldSequenceXml() throws IOException {
+ verifyDocument(xml1);
+ verifyName(XmlSequencer.COMMENT + "[1]", NameFactory.JCR_PRIMARY_TYPE, XmlSequencer.COMMENT);
+ String text = verify(XmlSequencer.COMMENT + "[1]", XmlSequencer.COMMENT_CONTENT, String.class);
+ assertThat(text.startsWith("\n Licensed to the Apache Software Foundation (ASF)"), is(true));
+ assertThat(text.endsWith(" limitations under the License.\n"), is(true));
+ verifyString("", XmlSequencer.DTD_NAME, "Repository");
+ verifyString("", XmlSequencer.DTD_PUBLIC_ID, "-//The Apache Software Foundation//DTD Jackrabbit 1.2//EN");
+ verifyString("", XmlSequencer.DTD_SYSTEM_ID, "http://jackrabbit.apache.org/dtd/repository-1.2.dtd");
+ verifyName(XmlSequencer.COMMENT + "[2]", NameFactory.JCR_PRIMARY_TYPE, XmlSequencer.COMMENT);
+ verifyString(XmlSequencer.COMMENT + "[2]", XmlSequencer.COMMENT_CONTENT, " Example Repository Configuration File ");
+ verifyName("Repository[1]", NameFactory.JCR_PRIMARY_TYPE, "Repository");
+ verifyName("Repository[1]/" + XmlSequencer.COMMENT + "[1]", NameFactory.JCR_PRIMARY_TYPE, XmlSequencer.COMMENT);
+ }
+
+ @Test
+ public void shouldHandleNamespaces() throws IOException {
+ verifyDocument(xml2);
+ verifyName("book[1]/bookinfo[1]/xi:include[1]", NameFactory.JCR_PRIMARY_TYPE, "xi:include");
+ verifyString("book[1]/bookinfo[1]/xi:include[1]", "xi:href", "Author_Group.xml");
+ verifyName("book[1]/bookinfo[1]/xi:include[2]", NameFactory.JCR_PRIMARY_TYPE, "xi:include");
+ verifyString("book[1]/bookinfo[1]/xi:include[2]", "xi:href", "Legal_Notice.xml");
+ }
+
+ @Test
+ public void shouldSequenceEntityDeclarations() throws IOException {
+ verifyDocument(xml2);
+ verifyName(XmlSequencer.ENTITY + "[1]", NameFactory.JCR_PRIMARY_TYPE, XmlSequencer.ENTITY);
+ verifyString(XmlSequencer.ENTITY + "[1]", XmlSequencer.DTD_NAME, "%RH-ENTITIES");
+ verifyString(XmlSequencer.ENTITY + "[1]", XmlSequencer.DTD_SYSTEM_ID, "Common_Config/rh-entities.ent");
+ verifyName(XmlSequencer.ENTITY + "[2]", NameFactory.JCR_PRIMARY_TYPE, XmlSequencer.ENTITY);
+ verifyString(XmlSequencer.ENTITY + "[2]", XmlSequencer.DTD_NAME, "versionNumber");
+ verifyString(XmlSequencer.ENTITY + "[2]", XmlSequencer.DTD_VALUE, "0.1");
+ verifyName(XmlSequencer.ENTITY + "[3]", NameFactory.JCR_PRIMARY_TYPE, XmlSequencer.ENTITY);
+ verifyString(XmlSequencer.ENTITY + "[3]", XmlSequencer.DTD_NAME, "copyrightYear");
+ verifyString(XmlSequencer.ENTITY + "[3]", XmlSequencer.DTD_VALUE, "2008");
+ }
+
+ @Test
+ public void shouldSequenceElementContent() throws IOException {
+ verifyDocument(xml2);
+ verifyString("book[1]/chapter[4]/sect1[1]/para[8]/" + XmlSequencer.ELEMENT_CONTENT + "[1]",
+ XmlSequencer.ELEMENT_CONTENT,
+ "The path expression is more complicated."
+ + " Sequencer path expressions are used by the sequencing service to determine whether a particular changed node should be sequenced."
+ + " The expressions consist of two parts: a selection criteria and an output expression."
+ + " Here's a simple example:");
+ verifyString("book[1]/chapter[4]/sect1[1]/para[8]/programlisting[1]/" + XmlSequencer.ELEMENT_CONTENT + "[1]",
+ XmlSequencer.ELEMENT_CONTENT,
+ "/a/b/c@title => /d/e/f");
+ }
+
+ @Test
+ public void shouldSequenceCData() throws IOException {
+ verifyDocument(xml3);
+ verifyString("mx:Application[1]/mx:Script[1]/" + XmlSequencer.CDATA + "[1]",
+ XmlSequencer.CDATA_CONTENT,
+ "\n\n" + " import mx.events.ValidationResultEvent;\t\t\t\n"
+ + " private var vResult:ValidationResultEvent;\n" + "\t\t\t\n"
+ + " // Event handler to validate and format input.\n"
+ + " private function Format():void {\n" + " \n"
+ + " vResult = numVal.validate();\n\n"
+ + " if (vResult.type==ValidationResultEvent.VALID) {\n"
+ + " var temp:Number=Number(priceUS.text); \n"
+ + " formattedUSPrice.text= usdFormatter.format(temp);\n" + " }\n"
+ + " \n" + " else {\n"
+ + " formattedUSPrice.text=\"\";\n" + " }\n" + " }\n"
+ + " ");
+ }
+
+ @Test
+ public void shouldSequenceProcessingInstructions() throws IOException {
+ verifyDocument(xml4);
+ verifyName(XmlSequencer.PI + "[1]", NameFactory.JCR_PRIMARY_TYPE, XmlSequencer.PI);
+ verifyString(XmlSequencer.PI + "[1]", XmlSequencer.TARGET, "eclipse");
+ verifyString(XmlSequencer.PI + "[1]", XmlSequencer.PI_CONTENT, "version=\"3.0\"");
+ }
+
+ @Test
+ public void shouldSequenceXsds() throws IOException {
+ verifyDocument(xsd);
+ verifyName("xs:schema[1]", NameFactory.JCR_PRIMARY_TYPE, "xs:schema");
+ verifyString("xs:schema[1]", "xs:targetNamespace", "http://ns.adobe.com/air/application/1.0");
+ verifyString("xs:schema[1]", "xs:elementFormDefault", "qualified");
+ verifyName("xs:schema[1]/xs:element[1]", NameFactory.JCR_PRIMARY_TYPE, "xs:element");
+ verifyString("xs:schema[1]/xs:element[1]", "xs:name", "application");
+ }
+
+ private <T> T verify( String nodePath,
+ String property,
+ Class<T> expectedClass ) {
+ Object[] values = output.getPropertyValues(nodePath.length() == 0 ? "." : "./" + nodePath, property);
+ assertThat(values, notNullValue());
+ assertThat(values.length, is(1));
+ Object value = values[0];
+ assertThat(value, instanceOf(expectedClass));
+ return expectedClass.cast(value);
+ }
+
+ private void verifyDocument( URL url ) throws IOException {
+ stream = url.openStream();
+ assertThat(stream, is(notNullValue()));
+ sequencer.sequence(stream, output, monitor);
+ verifyName("", NameFactory.JCR_PRIMARY_TYPE, XmlSequencer.DOCUMENT);
+ }
+
+ private void verifyName( String nodePath,
+ String property,
+ String expectedName ) {
+ Name name = verify(nodePath, property, Name.class);
+ assertThat(name, is(output.getFactories().getNameFactory().create(expectedName)));
+ }
+
+ private void verifyString( String nodePath,
+ String property,
+ String expectedString ) {
+ String string = verify(nodePath, property, String.class);
+ assertThat(string, is(expectedString));
+ }
+}
Property changes on: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/xml/XmlSequencerTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-repository/src/test/resources/CurrencyFormatterExample.mxml
===================================================================
--- trunk/dna-repository/src/test/resources/CurrencyFormatterExample.mxml (rev 0)
+++ trunk/dna-repository/src/test/resources/CurrencyFormatterExample.mxml 2008-06-06 00:37:18 UTC (rev 239)
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Simple example to demonstrate the CurrencyFormatter. -->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
+
+ <mx:Script>
+ <![CDATA[
+
+ import mx.events.ValidationResultEvent;
+ private var vResult:ValidationResultEvent;
+
+ // Event handler to validate and format input.
+ private function Format():void {
+
+ vResult = numVal.validate();
+
+ if (vResult.type==ValidationResultEvent.VALID) {
+ var temp:Number=Number(priceUS.text);
+ formattedUSPrice.text= usdFormatter.format(temp);
+ }
+
+ else {
+ formattedUSPrice.text="";
+ }
+ }
+ ]]>
+ </mx:Script>
+
+ <mx:CurrencyFormatter id="usdFormatter" precision="2"
+ currencySymbol="$" decimalSeparatorFrom="."
+ decimalSeparatorTo="." useNegativeSign="true"
+ useThousandsSeparator="true" alignSymbol="left"/>
+
+ <mx:NumberValidator id="numVal" source="{priceUS}" property="text"
+ allowNegative="true" domain="real"/>
+
+ <mx:Panel title="CurrencyFormatter Example" width="75%" height="75%"
+ paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
+
+ <mx:Form>
+ <mx:FormItem label="Enter U.S. dollar amount:">
+ <mx:TextInput id="priceUS" text="" width="50%"/>
+ </mx:FormItem>
+
+ <mx:FormItem label="Formatted amount: ">
+ <mx:TextInput id="formattedUSPrice" text="" width="50%" editable="false"/>
+ </mx:FormItem>
+
+ <mx:FormItem>
+ <mx:Button label="Validate and Format" click="Format();"/>
+ </mx:FormItem>
+ </mx:Form>
+
+ </mx:Panel>
+</mx:Application>
Added: trunk/dna-repository/src/test/resources/Descriptor.1.0.xsd
===================================================================
--- trunk/dna-repository/src/test/resources/Descriptor.1.0.xsd (rev 0)
+++ trunk/dna-repository/src/test/resources/Descriptor.1.0.xsd 2008-06-06 00:37:18 UTC (rev 239)
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<xs:schema
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://ns.adobe.com/air/application/1.0"
+ xmlns="http://ns.adobe.com/air/application/1.0"
+ elementFormDefault="qualified"
+>
+ <xs:element name="application">
+ <xs:complexType>
+ <xs:all>
+ <!-- About this application -->
+ <xs:element name="id">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Za-z0-9\-\.]{1,212}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="name" type="xs:string" minOccurs="0"/>
+ <xs:element name="version" type="xs:string"/>
+ <xs:element name="filename">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <!-- name cannot begin with a ' ' (space), have any of these characters: *"/:<>?\|, and end with a . (dot) or ' ' (space) -->
+ <xs:pattern value='[^\*"/:><\?\\\|\. ]|[^\*"/:><\?\\\| ][^\*"/:><\?\\\|]*[^\*"/:><\?\\\|\. ]'/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0"/>
+ <xs:element name="copyright" type="xs:string" minOccurs="0"/>
+ <xs:element name="icon" type="IconType" minOccurs="0"/>
+
+ <!-- How to start this application -->
+ <xs:element name="initialWindow">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="content" type="xs:anyURI" minOccurs="1" />
+ <xs:element name="title" type="xs:string" minOccurs="0" />
+
+ <xs:element name="systemChrome" minOccurs="0" >
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="standard"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="transparent" type="xs:boolean" minOccurs="0" />
+ <xs:element name="visible" type="xs:boolean" minOccurs="0" />
+
+ <xs:element name="minimizable" type="xs:boolean" minOccurs="0" />
+ <xs:element name="maximizable" type="xs:boolean" minOccurs="0" />
+ <xs:element name="resizable" type="xs:boolean" minOccurs="0" />
+
+ <xs:element name="x" type="xs:int" minOccurs="0" />
+ <xs:element name="y" type="xs:int" minOccurs="0" />
+ <xs:element name="width" type="xs:unsignedInt" minOccurs="0" />
+ <xs:element name="height" type="xs:unsignedInt" minOccurs="0" />
+ <xs:element name="minSize" type="BoundsSizeType" minOccurs="0" />
+ <xs:element name="maxSize" type="BoundsSizeType" minOccurs="0" />
+ </xs:all>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- About installing this application -->
+ <xs:element name="installFolder" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <!-- installFolder cannot begin with a / (forward-slash) or a ' ' (space), have any of these characters: *":<>?\|, and end with a . (dot) or ' ' (space) -->
+ <xs:pattern value='[^\*"/:><\?\\\|\. ]|[^\*"/:><\?\\\| ][^\*":><\?\\\|]*[^\*":><\?\\\|\. ]'/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="programMenuFolder" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <!-- programMenuFolder cannot begin with a / (forward-slash) or a ' ' (space), have any of these characters: *":<>?\|, and end with a . (dot) or ' ' (space) -->
+ <xs:pattern value='[^\*"/:><\?\\\|\. ]|[^\*"/:><\?\\\| ][^\*":><\?\\\|]*[^\*":><\?\\\|\. ]'/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+
+ <!-- Features this application can opt in to -->
+ <xs:element name="customUpdateUI" type="xs:boolean" minOccurs="0"/>
+ <xs:element name="allowBrowserInvocation" type="xs:boolean" minOccurs="0"/>
+ <xs:element name="fileTypes" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="fileType" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="name" type="xs:string"/>
+ <xs:element name="extension" type="xs:string"/>
+ <xs:element name="description" type="xs:string" minOccurs="0"/>
+ <xs:element name="contentType" type="xs:string" minOccurs="0"/>
+ <xs:element name="icon" type="IconType" minOccurs="0"/>
+ </xs:all>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:all>
+
+ <!-- About the runtime version required -->
+ <xs:attribute name="minimumPatchLevel" type="xs:unsignedInt"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Type definitions -->
+ <xs:complexType name="IconType">
+ <xs:all>
+ <xs:element name="image16x16" type="xs:anyURI" minOccurs="0"/>
+ <xs:element name="image32x32" type="xs:anyURI" minOccurs="0"/>
+ <xs:element name="image48x48" type="xs:anyURI" minOccurs="0"/>
+ <xs:element name="image128x128" type="xs:anyURI" minOccurs="0"/>
+ </xs:all>
+ </xs:complexType>
+ <xs:simpleType name="UnsignedIntListType">
+ <xs:list itemType="xs:unsignedInt"/>
+ </xs:simpleType>
+ <xs:simpleType name="BoundsSizeType">
+ <xs:restriction base="UnsignedIntListType">
+ <xs:length value="2"/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
Added: trunk/dna-repository/src/test/resources/master.xml
===================================================================
--- trunk/dna-repository/src/test/resources/master.xml (rev 0)
+++ trunk/dna-repository/src/test/resources/master.xml 2008-06-06 00:37:18 UTC (rev 239)
@@ -0,0 +1,1890 @@
+<!--
+ ~ JBoss, Home of Professional Open Source.
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!ENTITY % RH-ENTITIES SYSTEM "Common_Config/rh-entities.ent">
+<!ENTITY versionNumber "0.1">
+<!ENTITY copyrightYear "2008">
+<!ENTITY copyrightHolder "Red Hat Middleware, LLC.">]>
+<book>
+ <bookinfo>
+ <title>JBoss DNA</title>
+ <subtitle>Getting Started Guide</subtitle>
+ <releaseinfo>&versionNumber;
+ </releaseinfo>
+ <productnumber>&versionNumber;
+ </productnumber>
+ <issuenum>1</issuenum>
+ <mediaobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/dna-logo.png" align="center" />
+ </imageobject>
+ <imageobject role="pdf">
+ <imagedata fileref="images/dna-logo.png" scale="75" align="center" />
+ </imageobject>
+ <imageobject role="html">
+ <imagedata fileref="images/dna-logo.png" depth="3cm" />
+ </imageobject>
+ <imageobject role="xhtml">
+ <imagedata fileref="images/dna-logo.png" depth="3cm" />
+ </imageobject>
+ <imageobject role="xhtml_single">
+ <imagedata fileref="images/dna-logo.png" depth="3cm" />
+ </imageobject>
+ </mediaobject>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Legal_Notice.xml" />
+ </bookinfo>
+ <preface id="preface" revision="1">
+ <title>What this book covers</title>
+ <para>The goal of this book is to help you learn about JBoss DNA and how you can use it in your own applications to get the
+ most out of your JCR repositories.</para>
+ <para>The first part of the book starts out with an introduction to content repositories and an overview of the JCR API,
+ both of which are important aspects of JBoss DNA. This is followed by an overview of the JBoss DNA project, its
+ architecture, and a basic roadmap for what's coming next.</para>
+ <para>The next part of the book covers how to download and build the examples, how to use JBoss DNA with existing
+ repositories, and how to build and use custom sequencers.</para>
+ <para>
+ If you have any questions or comments, please feel free to contact JBoss DNA's
+ <ulink url="mailto:dna-users@jboss.org">user mailing list</ulink>
+ or use the
+ <ulink url="http://www.jboss.com/index.html?module=bb&op=viewforum&f=272">user forums</ulink>
+ . If you'd like to get involved on the project, join the
+ <ulink url="http://www.jboss.org/dna/lists.html">mailing lists</ulink>
+ ,
+ <ulink url="http://www.jboss.org/dna/subversion.html">download the code</ulink>
+ and get it building, and visit our
+ <ulink url="http://jira.jboss.org/jira/browse/DNA">JIRA issue management system</ulink>
+ . If there's something in particular you're interested in, talk with the community - there may be others interested in the
+ same thing.
+ </para>
+ </preface>
+ <chapter id="introduction">
+ <title>Introduction</title>
+ <para>There are a lot of choices for how applications can store information persistently so that it can be accessed at a
+ later time and by other processes. The challenge developers face is how to use an approach that most closely matches the
+ needs of their application. This choice becomes more important as developers choose to focus their efforts on
+ application-specific logic, delegating much of the responsibilities for persistence to libraries and frameworks.</para>
+ <para>
+ Perhaps one of the easiest techniques is to simply store information in
+ <emphasis>files</emphasis>
+ . The Java language makes working with files relatively easy, but Java really doesn't provide many bells and whistles. So
+ using files is an easy choice when the information is either not complicated (for example property files), or when users may
+ need to read or change the information outside of the application (for example log files or configuration files). But using
+ files to persist information becomes more difficult as the information becomes more complex, as the volume of it increases,
+ or if it needs to be accessed by multiple processes. For these situations, other techniques often offer better choices.
+ </para>
+ <para>
+ Another technique built into the Java language is
+ <emphasis>Java serialization</emphasis>
+ , which is capable of persisting the state of an object graph so that it can be read back in at a later time. However, Java
+ serialization can quickly become tricky if the classes are changed, and so it's beneficial usually when the information is
+ persisted for a very short period of time. For example, serialization is sometimes used to send an object graph from one
+ process to another.
+ </para>
+ <para>
+ One of the more popular persistence technologies is the
+ <emphasis>relational database</emphasis>
+ . Relational database management systems have been around for decades and are very capable. The Java Database Connectivity
+ (JDBC) API provides a standard interface for connecting to and interacting with relational databases. However, it is a
+ low-level API that requires a lot of code to use correctly, and it still doesn't abstract away the DBMS-specific SQL
+ grammar. Also, working with relational data in an object-oriented language can feel somewhat unnatural, so many developers
+ map this data to classes that fit much more cleanly into their application. The problem is that manually creating this
+ mapping layer requires a lot of repetitive and non-trivial JDBC code.
+ </para>
+ <para>
+ <emphasis>Object-relational mapping</emphasis>
+ libraries automate the creation of this mapping layer and result in far less code that is much more maintainable with
+ performance that is often as good as (if not better than) handwritten JDBC code. The new
+ <ulink url="http://java.sun.com/developer/technicalArticles/J2EE/jpa/">Java Persistence API (JPA)</ulink>
+ provide a standard mechanism for defining the mappings (through annotations) and working with these entity objects. Several
+ commercial and open-source libraries implement JPA, and some even offer additional capabilities and features that go beyond
+ JPA. For example,
+ <ulink url="http://www.hibernate.org">Hibernate</ulink>
+ is one of the most feature-rich JPA implementations and offers object caching, statement caching, extra association
+ mappings, and other features that help to improve performance and usefulness.
+ </para>
+ <para>
+ While relational databases and JPA are solutions that work for many applications, they become more limited in cases when the
+ information structure is highly flexible, is not known
+ <emphasis>a priori</emphasis>
+ , or is subject to frequent change and customization. In these situations,
+ <emphasis>content repositories</emphasis>
+ may offer a better choice for persistence. Content repositories are almost a hybrid between relational databases and file
+ systems, and typically provide other capabilities as well, including versioning, indexing, search, access control,
+ transactions, and observation. Because of this, content repositories are used by content management systems (CMS), document
+ management systems (DMS), and other applications that manage electronic files (e.g., documents, images, multi-media, web
+ content, etc.) and metadata associated with them (e.g., author, date, status, security information, etc.). The
+ <ulink url="http://www.jcp.org/en/jsr/detail?id=170">Content Repository for Java technology API</ulink>
+ provides a standard Java API for working with content repositories. Abbreviated "JCR", this API was developed as part of the
+ Java Community Process under
+ <ulink url="http://www.jcp.org/en/jsr/detail?id=170">JSR-170</ulink>
+ and is being revised under
+ <ulink url="http://www.jcp.org/en/jsr/detail?id=283">JSR-283</ulink>
+ .
+ </para>
+ <para>
+ The
+ <emphasis>JBoss DNA project</emphasis>
+ is building the tools and services that surround content repositories. Nearly all of these capabilities are to be hidden
+ below the JCR API and involve automated processing of the information in the repository. Thus, JBoss DNA can add value to
+ existing repository implementations. For example, JCR repositories offer the ability to upload files into the repository and
+ have the file content indexed for search purposes. JBoss DNA also defines a library for "sequencing" content - to extract
+ meaningful information from that content and store it in the repository, where it can then be searched, accessed, and
+ analyzed using the JCR API.
+ </para>
+ <para> JBoss DNA is building other features as well. One goal of JBoss DNA is to create federated repositories that
+ dynamically merge the information from multiple databases, services, applications, and other JCR repositories. Another is to
+ create customized views based upon the type of data and the role of the user that is accessing the data. And yet another is
+ to create a REST-ful API to allow the JCR content to be accessed easily by other applications written in other languages.
+ </para>
+ <para>
+ The
+ <link linkend="jboss_dna">next chapter</link>
+ in this book goes into more detail about JBoss DNA and its architecture, the different components, what's available now, and
+ what's coming in future releases.
+ <link linkend="downloading_and_running">Chapter 3</link>
+ then provides instructions for downloading and running the sequencer examples for the current release.
+ <link linkend="using_dna">Chapter 4</link>
+ walks through how to use JBoss DNA in your applications, while
+ <link linkend="custom_sequencers">Chapter 5</link>
+ goes over how to create custom sequencers. Finally,
+ <link linkend="future_directions">Chapter 6</link>
+ wraps things up with a discussion about the future of JBoss DNA.
+ </para>
+ </chapter>
+ <chapter id="jboss_dna">
+ <title>Understanding JBoss DNA</title>
+ <sect1 id="jboss_dna_overview">
+ <title>Overview</title>
+ <para>JBoss DNA is a repository and set of tools that make it easy to capture, version, analyze, and understand the
+ fundamental building blocks of information. As models, service and process definitions, schemas, source code, and other
+ artifacts are added to the repository, JBoss DNA "sequences" the makeup of these components and extracts their structure
+ and interdependencies. The JBoss DNA web application allows end users to access, visualize, and edit this information in
+ the terminology and structure they are familiar with. Such domain-specific solutions can be easily created with little or
+ no programming.</para>
+ <para> JBoss DNA supports the Java Content Repository (JCR) standard and is able to provide a single integrated view of
+ multiple repositories, external databases, services, and applications, ensuring that JBoss DNA has access to the latest
+ and most reliable master data. For instance, DNA could provide in a single view valuable insight into the business
+ processes and process-level services impacted by a change to in an intermediary web server operation defined via WSDL.
+ Similarly, a user could quickly view and navigate the dependencies between the data source models and transformation
+ information stored within a content repository, the code base stored within a version control system, and the database
+ schemas used by an application.</para>
+ </sect1>
+ <sect1 id="architecture">
+ <title>Architecture</title>
+ <para>The architecture for JBoss DNA consists of several major components that will be built on top of standard APIs,
+ including JCR, JDBC, JNDI and HTTP. The goal is to allow these components to be assembled as needed and add value on top
+ of other DNA components or third-party systems that support these standard APIs.</para>
+ <mediaobject>
+ <imageobject role="fo">
+ <imagedata align="center" fileref="images/dna-architecture.png" />
+ </imageobject>
+ <imageobject role="html">
+ <imagedata align="center" fileref="images/dna-architecture.png" />
+ </imageobject>
+ </mediaobject>
+ <para>
+ As shown in the diagram above, the major components are (starting at the top):
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Eclipse Plugins</emphasis>
+ enable Eclipse users to access the contents of a JBoss DNA repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA JDBC Driver</emphasis>
+ provides a driver implementation, allowing JDBC-aware applications to connect to and use a JBoss DNA repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Remote JCR</emphasis>
+ is a client-side component for accessing remote JCR repositories.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Web Application</emphasis>
+ is used by end users and domain experts to visualize, search, edit, change and tag the repository content. The web
+ application uses views to define how different types of information are to be presented and edited in
+ domain-specific ways. The goal is that this web application is easily customized and branded for inclusion into
+ other solutions and application systems. The DNA Web Application operates upon any JCR-compliant repository,
+ although it does rely upon the DNA analysis and templating services.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Publishing Server</emphasis>
+ allows content to be downloaded, uploaded, and edited using the Atom Publishing Protocol. With the DNA Publishing
+ Server, the content of the repository can easily be created, read, edited, and deleted using the standard HTTP
+ operations of POST, GET, PUT, and DELETE (respectively). More and more tools are being created that support working
+ with Atom Publishing servers. The DNA Publishing Server operates upon any JCR-compliant repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA WebDAV Server</emphasis>
+ allows clients such as Microsoft Windows and Apple OS X to connect to, read, and edit the content in the repository
+ using the WebDAV standard. Since WebDAV is an extension of HTTP, web browsers are able to read (but not modify) the
+ content served by a WebDAV compliant server. The DNA WebDAV Server operates upon any JCR-compliant repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Sequencers</emphasis>
+ are pluggable components that make it possible for content to be uploaded to the repository and automatically
+ processed to extract meaningful structure and place that structure in the repository. Once this information is in
+ the repository, it can be viewed, edited, analyzed, searched, and related to other content. DNA defines a Java
+ interface that sequencers must implement. DNA sequencers operate upon any JCR-compliant repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Analyses</emphasis>
+ are pluggable components that analyze content and the relationships between content to generate reports or to answer
+ queries. DNA will include some standard analyzers, like dependency analysis and similarity analysis, that are
+ commonly needed by many different solutions. DNA analyzers operate upon any JCR-compliant repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Views</emphasis>
+ are definitions of how types of information are to be presented in a user interface to allow for creation, reading,
+ editing, and deletion of information. DNA view definitions consist of data stored in a JCR repository, and as such
+ views can be easily added, changed or removed entirely by using the DNA Web Application, requiring no programming.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Federation</emphasis>
+ is an implementation of the JCR API that builds the content within the repository by accessing and integrating
+ information from multiple sources. DNA Federation allows the integration of external systems, like other JCR
+ repositories, databases, applications, and services.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Connectors</emphasis>
+ are used to communicate with these external sources of information. In the federation engine, each source is able to
+ contribute node structure and node properties to any part of the federated graph, although typically many connectors
+ will contribute most of their information to isolated subgraphs. The result is that integration from a wide range of
+ systems can be integrated and accessed through the DNA Web Application, DNA Publishing Server, and DNA WebDAV
+ Server. Connectors also may optionally participate in distributed transactions by exposing an XAResource.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Maven</emphasis>
+ is a classloader library compatible with Maven 2 project dependencies. This allows the creation of Java ClassLoader
+ instances using Maven 2 style paths, and all dependencies are transitively managed and included.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Continue reading the rest of this chapter for more detail about the
+ <link linkend="sequencers">sequencing framework</link>
+ available in this release, or the
+ <link linkend="federation">federation engine</link>
+ and
+ <link linkend="federation_connectors">connectors</link>
+ that will be the focus of the next release. Or, skip to the
+ <link linkend="downloading_and_running">examples</link>
+ to see how to start using JBoss DNA &versionNumber;
+ today.
+ </para>
+ </sect1>
+ <sect1 id="sequencers">
+ <title>Sequencing content</title>
+ <para> The current JBoss DNA release contains a sequencing framework that is designed to sequence data (typically files)
+ stored in a JCR repository to automatically extract meaningful and useful information. This additional information is then
+ saved back into the repository, where it can be accessed and used.</para>
+ <para> In other words, you can just upload various kinds of files into a JCR repository, and DNA automatically processes
+ those files to extract meaningful structured information. For example, load DDL files into the repository, and let
+ sequencers extract the structure and metadata for the database schema. Load Hibernate configuration files into the
+ repository, and let sequencers extract the schema and mapping information. Load Java source into the repository, and let
+ sequencers extract the class structure, JavaDoc, and annotations. Load a PNG, JPEG, or other image into the repository,
+ and let sequencers extract the metadata from the image and save it in the repository. The same with XSDs, WSDL, WS
+ policies, UML, MetaMatrix models, etc.</para>
+ <para>
+ JBoss DNA sequencers sit on top of existing JCR repositories (including federated repositories) - they basically extract
+ more useful information from what's already stored in the repository. And they use the existing JCR versioning system. Each
+ sequencer typically processes a single kind of file format or a single kind of content. </para>
+ <para>The following sequencers are included in JBoss DNA:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="strong">Image sequencer</emphasis>
+ - A sequencer that processes the binary content of an image file, extracts the metadata for the image, and then
+ writes that image metadata to the repository. It gets the file format, image resolution, number of bits per pixel
+ (and optionally number of images), comments and physical resolution from JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM,
+ PGM, PPM, and PSD files. (This sequencer may be improved in the future to also extract EXIF metadata from JPEG
+ files; see
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
+ .)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">MP3 sequencer</emphasis>
+ - A sequencer that processes the contents of an MP3 audio file, extracts the metadata for the file, and then
+ writes that image metadata to the repository. It gets the title, author, album, year, and comment.
+ (This sequencer may be improved in the future to also extract other ID3 metadata from other audio file formats; see
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-66">DNA-26</ulink>
+ .)
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ As the community develops additional sequencers, they will also be included in JBoss DNA. Some of those that have been
+ identified as being useful include:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="strong">XML Schema Document (XSD) Sequencer</emphasis>
+ - Process XSD files and extract the various elements, attributes, complex types, simple types, groups, and other
+ information. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-32">DNA-32</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">Web Service Definition Language (WSDL) Sequencer</emphasis>
+ - Process WSDL files and extract the services, bindings, ports, operations, parameters, and other information. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-33">DNA-33</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">Hibernate File Sequencer</emphasis>
+ - Process Hibernate configuration (cfg.xml) and mapping (hbm.xml) files to extract the configuration and mapping
+ information. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-61">DNA-61</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">XML Metadata Interchange (XMI) Sequencer</emphasis>
+ - Process XMI documents that contain UML models or models using another metamodel, extracting the model structure
+ into the repository. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-31">DNA-31</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">ZIP Archive Sequencer</emphasis>
+ - Process ZIP archive files to extract (explode) the contents into the repository. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-63">DNA-63</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">Java Archive (JAR) Sequencer</emphasis>
+ - Process JAR files to extract (explode) the contents into the classes and file resources. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-64">DNA-64</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">Java Class File Sequencer</emphasis>
+ - Process Java class files (bytecode) to extract the class structure (including annotations) into the repository.
+ (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-62">DNA-62</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">Java Source File Sequencer</emphasis>
+ - Process Java source files to extract the class structure (including annotations) into the repository. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-51">DNA-51</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">PDF Sequencer</emphasis>
+ - Process PDF files to extract the document metadata, including table of contents. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-50">DNA-50</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">Maven 2 POM Sequencer</emphasis>
+ - Process Maven 2 Project Object Model (POM) files to extract the project information, dependencies, plugins, and
+ other content. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-24">DNA-24</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">Data Definition Language (DDL) Sequencer</emphasis>
+ - Process various dialects of DDL, including that from Oracle, SQL Server, MySQL, PostgreSQL, and others. May need
+ to be split up into a different sequencer for each dialect. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">MP3 and MP4 Sequencer</emphasis>
+ - Process MP3 and MP4 audio files to extract the name of the song, artist, album, track number, and other metadata.
+ (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-30">DNA-30</ulink>
+ )
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ The
+ <link linkend="using_dna">examples</link>
+ in this book go into more detail about how sequencers are managed and used, and
+ <link linkend="custom_sequencers">Chapter 5</link>
+ goes into detail about how to write custom sequencers.
+ </para>
+ </sect1>
+ <sect1 id="federation">
+ <title>Federating content</title>
+ <para>There is a lot of information stored in many of different places: databases, repositories, SCM systems,
+ registries, file systems, services, etc. The purpose of the federation engine is to allow applications to use the JCR API
+ to access that information as if it were all stored in a single JCR repository, but to really leave the information where
+ it is.</para>
+ <para>Why not just move the information into a JCR repository? Most likely there are existing applications that rely upon
+ that information being where it is. If we were to move it, then all those applications would break. Or they'd have to be
+ changed to use JCR. If the information is being used, the most practical thing is to leave it where it is.</para>
+ <para>
+ Then why not just copy the information into a JCR repository? Actually, there are times when it's perfectly reasonable to
+ make a copy of the data. Perhaps the system managing the existing information cannot handle the additional load of more
+ clients. Or, perhaps the information doesn't change, or it does change and we want snapshots that don't change. But more
+ likely, the data
+ <emphasis>does</emphasis>
+ change. So if applications are to use the most current information and we make copies of the data, we have to keep the
+ copies synchronized with the master. That's generally a lot of work.
+ </para>
+ <para>The JBoss DNA federation engine lets us leave the information where it is, yet lets client applications use the JCR
+ API to access all the information without caring where the information really exists. If the underlying information
+ changes, client applications using JCR observation will be notified of the changes. If a JBoss DNA federated repository is
+ configured to allow updates, client applications can change the information in the repository and JBoss DNA will propagate
+ those changes down to the original source.</para>
+ <sect2 id="federation_connectors">
+ <title>Connecting to information sources</title>
+ <para>
+ The JBoss DNA federation engine will use connectors to interact with different information sources to get at the content
+ in those systems. Some ideas for connectors include:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="strong">JCR Repository Connector</emphasis>
+ - Connect to and interact with other JCR repositories.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">File System Connector</emphasis>
+ - Expose the files and directories on a file system through JCR.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">Maven 2 Repository Connector</emphasis>
+ - Access and expose the contents of a Maven 2 repository (either on the local file system or via HTTP) through
+ JCR.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">JDBC Metadata Connector</emphasis>
+ - Connect to relational databases via JDBC and expose their schema as content in a repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">UDDI Connector</emphasis>
+ - Interact with UDDI registries to integrate their content into a repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">SVN Connector</emphasis>
+ - Interact with Subversion software configuration management (SCM) repositories to expose the managed resources
+ through JCR. Consider using the
+ <ulink url="http://svnkit.com/">SVNkit</ulink>
+ (dual license) library for an API into Subversion.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">CVS Connector</emphasis>
+ - Interact with CVS software configuration management (SCM) repositories to expose the managed resources through
+ JCR.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">JDBC Storage Connector</emphasis>
+ - Store and access information in a relational database. Also useful for persisting information in the federated
+ repository not stored elsewhere.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">Distributed Database Connector</emphasis>
+ - Store and access information in a
+ <ulink url="http://www.hypertable.org/">Hypertable</ulink>
+ or
+ <ulink url="http://hadoop.apache.org/hbase/">HBase</ulink>
+ distributed databases. Also useful for persisting information in the federated repository not stored elsewhere.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ If the connectors allow the information they contribute to be updated, they must provide an
+ <code>XAResource</code>
+ implementation that can be used with a Java Transaction Service. Connectors that provide read-only access need not
+ provide an implementation.
+ </para>
+ <para>
+ Also, connectors talk to
+ <emphasis>sources</emphasis>
+ of information, and it's quite likely that the same connector is used to talk to different sources. Each source contains
+ the configuration details (e.g., connection information, location, properties, options, etc.) for working with that
+ particular source, as well as a reference to the connector that should be used to establish connections to the source.
+ And of course, sources can be added or removed without having to stop and restart the federated repository.
+ </para>
+ </sect2>
+ <sect2 id="federation_graph">
+ <title>Building the unified graph</title>
+ <para> The federation engine works by effectively building up a single graph by querying each source and merging or
+ unifying the responses. This information is cached, which improves performance, reduces the number of (potentially
+ expensive) remote calls, reduces the load on the sources, and helps mitigate problems with source availability. As
+ clients interact with the repository, this cache is consulted first. When the requested portion of the graph (or
+ "subgraph") is contained completely in the cache, it is retuned immediately. However, if any part of the requested
+ subgraph is not in the cache, each source is consulted for their contributions to that subgraph, and any results are
+ cached.</para>
+ <para> This basic flow makes it possible for the federated repository to build up a local cache of the integrated graph
+ (or at least the portions that are used by clients). In fact, the federated repository caches information in a manner
+ that is similar to that of the Domain Name System (DNS). As sources are consulted for their contributions, the source
+ also specifies whether it is the authoritative source for this information (some sources that are themselves federated
+ may not be the information's authority), whether the information may be modified, the time-to-live (TTL) value (the time
+ after which the cached information should be refreshed), and the expiration time (the time after which the cached
+ information is no longer valid). In effect, the source has complete control over how the information it contributes is
+ cached and used.</para>
+ <para>
+ The federated repository also needs to incorporate
+ <emphasis>negative caching</emphasis>
+ , which is storage of the knowledge that something does not exist. Sources can be configured to contribute information
+ only below certain paths (e.g.,
+ <code>/A/B/C</code>
+ ), and the federation engine can take advantage of this by never consulting that source for contributions to information
+ on other paths. However, below that path, any negative responses must also be cached (with appropriate TTL and expiry
+ parameters) to prevent the exclusion of that source (in case the source has information to contribute at a later time)
+ or the frequent checking with the source.
+ </para>
+ </sect2>
+ <sect2 id="federation_queries">
+ <title>Searching and querying</title>
+ <para> The JBoss DNA federated repository will also support queries against the integrated and unified graph. In some
+ situations the query can be determined to apply to a single source, but in most situations the query must be planned
+ (and possibly rewritten) such that it can be pushed down to all the appropriate sources. Also, the cached results must
+ be consulted prior to returning the query results, as the results from one source might have contributions from another
+ source.</para>
+ <note>
+ <para> It is hoped that the MetaMatrix query engine can be used for this purpose after it is open-sourced. This engine
+ implements sophisticated query planning and optimization techniques for working efficiently with multiple sources.
+ </para>
+ </note>
+ <para>Searching the whole federated repository is also important. This allows users to simply supply a handful of
+ search terms, and to get results that are ranked based upon how close each result is to the search terms. (Searching is
+ very different from querying, which involves specifying the exact semantics of what is to be searched and how the
+ information is to be compared.) JBoss DNA will incorporate a search engine (e.g., likely to be Lucene) and will populate
+ the engine's indexes using the federated content and the cached information. Notifications of changing information will
+ be reflected in the indexes, but some sources may want to explicitly allow or disallow periodic crawling of their
+ content.</para>
+ </sect2>
+ <sect2 id="federation_updates">
+ <title>Updating content</title>
+ <para>
+ The JBoss DNA federated repositories also make it possible for client applications to make changes to the unified graph
+ within the context of distributed transactions. According to the JCR API, client applications use the Java Transaction
+ API (JTA) to control the boundaries of their transactions. Meanwhile, the federated repository uses a
+ <ulink url="http://www.jboss.org/jbosstm/">distributed transaction service</ulink>
+ to coordinate the XA resources provided by the connectors.
+ </para>
+ <para> It is quite possible that clients add properties to nodes in the unified graph, and that this information cannot be
+ handled by the same underlying source that contributed to the node. In this case, the federated repository can be
+ configured with a fallback source that will be used used to store this "extra" information.</para>
+ <para>
+ It is a goal that non-XA sources (i.e., sources that use connectors without XA resources) can participate in distributed
+ transactions through the use of
+ <emphasis>compensating transactions</emphasis>
+ . Because the JBoss DNA federation engine implements the JCR observation system, it is capable of recording all of the
+ changes made to the distributed graph (and those changes sent to each updatable source). Therefore, if a non-XA source
+ is involved in a distributed transaction that must be rolled back, any changes made to non-XA sources can be undone. (Of
+ course, this does not make the underlying source transactional: non-transactional sources still may expose the interim
+ changes to other clients.)
+ </para>
+ </sect2>
+ <sect2 id="federation_events">
+ <title>Observing changes</title>
+ <para> The JCR API supports observing a repository to receive notifications of additions, changes and deletions of nodes
+ and properties. The JBoss DNA federated repository will support this API through two primary means.</para>
+ <para> When the changes are made through the federated repository, the JBoss DNA federation engine is well aware of the
+ set of changes that have been (or are being) made to the unified graph. These events are directly propagated to
+ listeners.</para>
+ <para> Sources have the ability to publish events, making it possible for the JBoss DNA federation engine and clients that
+ have registered listeners to be notified of changes in the information managed by that source. These events are first
+ processed by the federation engine and possibly altered based upon contributions from other sources. (The federation
+ engine also uses these events to update or purge information in the cache, which may add to the event set.) The
+ resulting (and possibly altered) event set is then sent to all client listeners.</para>
+ </sect2>
+ </sect1>
+ </chapter>
+ <!-- ====================================================================================================
+ Chapter
+ ==================================================================================================== -->
+ <chapter id="downloading_and_running">
+ <title>Running the example application</title>
+ <para>
+ This chapter provides instructions for downloading and running a sample application that demonstrates how JBoss DNA works
+ with a JCR repository to automatically sequence changing content to extract useful information. So read on to get the simple
+ application running, and then in the
+ <link linkend="using_dna">next chapter</link>
+ we'll dive into the source code for the example and show how to use JBoss DNA in your own applications.
+ </para>
+ <para>JBoss DNA uses Maven 2 for its build system, as is this example. Using Maven 2 has several advantages, including
+ the ability to manage dependencies. If a library is needed, Maven automatically finds and downloads that library, plus
+ everything that library needs. This means that it's very easy to build the examples - or even create a maven project that
+ depends on the JBoss DNA JARs.</para>
+ <note>
+ <para>
+ To use Maven with JBoss DNA, you'll need to have
+ <ulink url="http://java.sun.com/javase/downloads/index_jdk5.jsp">JDK 5 or 6</ulink>
+ and Maven 2.0.7 (or higher).
+ </para>
+ <para>
+ Maven can be downloaded from
+ <ulink url="http://maven.apache.org/">http://maven.apache.org/</ulink>
+ , and is installed by unzipping the
+ <code>maven-2.0.7-bin.zip</code>
+ file to a convenient location on your local disk. Simply add
+ <code>$MAVEN_HOME/bin</code>
+ to your path and add the following profile to your
+ <code>~/.m2/settings.xml</code>
+ file:
+ <programlisting role="XML" language="xml"><settings>
+ <profiles>
+ <profile>
+ <id>jboss.repository</id>
+ <activation>
+ <property>
+ <name>!jboss.repository.off</name>
+ </property>
+ </activation>
+ <repositories>
+ <repository>
+ <id>snapshots.jboss.org</id>
+ <url>http://snapshots.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>repository.jboss.org</id>
+ <url>http://repository.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>repository.jboss.org</id>
+ <url>http://repository.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+ <pluginRepository>
+ <id>snapshots.jboss.org</id>
+ <url>http://snapshots.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+ </profile>
+ </profiles>
+</settings></programlisting>
+ This profile informs Maven of the two JBoss repositories (snapshots and releases) that contain
+ all of the JARs for JBoss DNA and all dependent libraries.</para>
+ </note>
+ <sect1 id="downloading">
+ <title>Downloading and compiling</title>
+ <para>The next step is to <ulink url="http://www.jboss.org/file-access/default/members/dna/downloads/0.1/jboss-...">download</ulink>
+ the example for this Getting Started guide, and extract the contents to a convenient location on your local disk.
+ You'll find the example contains the following files, which are organized according to the standard Maven directory structure:
+ <programlisting>
+examples/pom.xml
+ sequencers/pom.xml
+ /src/main/assembly
+ /config
+ /java
+ /resources
+ /test/java
+ /resources
+ </programlisting>
+ </para>
+ <para>There are essentially two Maven projects: a <code>sequencers</code> project and a parent project. All of the source
+ for the example is located in the <code>sequencers</code> subdirectory. And you may have noticed that none
+ of the JBoss DNA libraries are there. This is where Maven comes in. The two <code>pom.xml</code> files tell
+ Maven everything it needs to know about what libraries are required and how to build the example.</para>
+ <para>In a terminal, go to the <code>examples</code> directory and run <emphasis role="strong"><code>mvn install</code></emphasis>.
+ This command downloads all of the JARs necessary to compile and build the example, including the JBoss DNA libraries,
+ the libraries they depend on, and any missing Maven components. (These are downloaded from the JBoss repositories
+ only once and saved on your machine. This means that the next time you run Maven, all the libraries will
+ already be available locally, and the build will run much faster.) The command then continues by compiling the example's source
+ code (and unit tests) and running the unit tests. The build is successful if you see the following:
+ <programlisting language="bash">$ mvn install
+...
+[INFO] ------------------------------------------------------------------------
+[INFO] Reactor Summary:
+[INFO] ------------------------------------------------------------------------
+[INFO] Getting Started examples .............................. SUCCESS [2.106s]
+[INFO] Sequencer Examples .................................... SUCCESS [9.768s]
+[INFO] ------------------------------------------------------------------------
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESSFUL
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 12 seconds
+[INFO] Finished at: Wed May 07 12:00:06 CDT 2008
+[INFO] Final Memory: 14M/28M
+[INFO] ------------------------------------------------------------------------
+$ </programlisting>
+ If there are errors, check whether you have the correct version of Maven installed and that you've correctly updated
+ your Maven settings as described above.</para>
+ <para>If you've successfully built the examples, there will be a <code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code>
+ directory that contains the following:
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="strong"><code>run.sh</code></emphasis> is the *nix shell script that will run the example.</para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>log4j.properties</code>
+ </emphasis>
+ is the Log4J configuration file.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>jackrabbitConfig.xml</code>
+ </emphasis>
+ is the Jackrabbit configuration file, which is set up to use a transient in-memory repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>jackrabbitNodeTypes.cnd</code>
+ </emphasis>
+ defines the additional JCR node types used by this example.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>sample1.mp3</code>
+ </emphasis>
+ is a sample MP3 audio file you'll use later to upload into the repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>caution.gif</code>
+ </emphasis>, <emphasis role="strong">
+ <code>caution.png</code>
+ </emphasis>, and <emphasis role="strong">
+ <code>caution.jpg</code>
+ </emphasis>
+ are images that you'll use later and upload into the repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>lib</code>
+ </emphasis>
+ subdirectory contains the JARs for all of the JBoss DNA artifacts as well as those for other libraries required
+ by JBoss DNA and the example.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <note>
+ <para>JBoss DNA 0.1 and the examples are currently tested with <ulink url="http://jackrabbit.apache.org/">Apache Jackrabbit</ulink> version 1.3.3.
+ This version is stable and used by a number of other projects and applications. However, you should be able to use a newer
+ version of Jackrabbit, as long as that version uses the same JCR API. For example, version 1.4.2 was released on March 26, 2008 and
+ should be compatible.
+ </para>
+ <para>Just remember, if the version of Jackrabbit you want to use for these examples is not in the Maven repository,
+ you'll have to either add it or add it locally. For more information, see the <ulink url="http://maven.apache.org/">Maven documentation</ulink>.
+ </para>
+ </note>
+ </para>
+ </sect1>
+ <sect1 id="running">
+ <title>Running the example</title>
+ <para>This example consists of a client application that sets up an in-memory JCR repository and that allows a user to
+ upload files into that repository. The client also sets up the DNA services with two sequencers so that if any of the
+ uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will automatically extract the image's metadata (e.g., image
+ format, physical size, pixel density, etc.) and store that in the repository. Alternatively, if the uploaded file
+ is an MP3 audio file, DNA will extract some of the ID3 metadata (e.g., the author, title, album, year and comment)
+ and store that in the repository.</para>
+ <para>
+ To run the client application, go to the
+ <code>examples/sequencers/target/dna-example-sequencers-basic.dir/
+ </code>
+ directory and type
+ <code>./run.sh</code>
+ . You should see the command-line client and its menus in your terminal:
+ <figure id="xample-sequencer-cli-client">
+ <title>Example Client</title>
+ <graphic align="center" scale="100" fileref="images/example-sequencer-cli-client.png" />
+ </figure>
+ From this menu, you can upload a file into the repository, search for media in the repository, print sequencing statistics,
+ or quit the application.
+ </para>
+ <para>
+ The first step is to upload one of the example images. If you type 'u' and press return, you'll be prompted to supply the
+ path to the file you want to upload. Since the application is running from within the
+ <code>examples/sequencers/target/dna-example-sequencers-basic.dir/
+ </code>
+ directory, you can specify any of the files in that directory without specifying the path:
+ <figure id="example-sequencer-upload">
+ <title>Uploading an image using the Example Client</title>
+ <graphic align="center" scale="100" fileref="images/example-sequencer-upload.png" />
+ </figure>
+ You can specify any fully-qualified or relative path. The application will notify you if it cannot find the file you
+ specified. The example client configures JBoss DNA to sequence and MP3 audio files and image files with one of
+ the following extensions (technically, nodes that have names ending in the following):
+ <code>jpg</code>
+ ,
+ <code>jpeg</code>
+ ,
+ <code>gif</code>
+ ,
+ <code>bmp</code>
+ ,
+ <code>pcx</code>
+ ,
+ <code>png</code>
+ ,
+ <code>iff</code>
+ ,
+ <code>ras</code>
+ ,
+ <code>pbm</code>
+ ,
+ <code>pgm</code>
+ ,
+ <code>ppm</code>
+ , and
+ <code>psd</code>
+ . Files with other extensions in the repository path will be ignored. For your convenience, the example provides several
+ files that will be sequenced (
+ <code>caution.png</code>
+ ,
+ <code>caution.jpg</code>
+ ,
+ <code>caution.gif</code>
+ , and
+ <code>sample1.mp3</code>
+ ) and one image that will not be sequenced (
+ <code>caution.pict</code>
+ ). Feel free to try other files.
+ </para>
+ <para>
+ After you have specified the file you want to upload, the example application asks you where in the repository you'd like to
+ place the file. (If you want to use the suggested location, just press
+ <code>return</code>
+ .) The client application uses the JCR API to upload the file to that location in the repository, creating any nodes (of
+ type
+ <code>nt:folder</code>
+ ) for any directories that don't exist, and creating a node (of type
+ <code>nt:file</code>
+ ) for the file. And, per the JCR specification, the application creates a
+ <code>jcr:content</code>
+ node (of type
+ <code>nt:resource</code>
+ ) under the file node. The file contents are placed on this
+ <code>jcr:content</code>
+ node in the
+ <code>jcr:data</code>
+ property. For example, if you specify
+ <code>/a/b/caution.png</code>
+ , the following structure will be created in the repository:<programlisting>
+ /a (nt:folder)
+ /b (nt:folder)
+ /caution.png (nt:file)
+ /jcr:content (nt:resource)
+ @jcr:data = {contents of the file}
+ @jcr:mimeType = {mime type of the file}
+ @jcr:lastModified = {now}
+ </programlisting>
+ Other kinds of files are treated in a similar way.
+ </para>
+ <para>
+ When the client uploads the file using the JCR API, DNA gets notified of the changes, consults the sequencers to see whether
+ any of them are interested in the new or updated content, and if so runs those sequencers. The image sequencer processes image
+ files for metadata, and any metadata found is stored under the
+ <code>/images</code>
+ branch of the repository. The MP3 sequencer processes MP3 audio files for metadata, and any metadata found is stored under the
+ <code>/mp3s</code>
+ branch of the repository. All of this happens asynchronously, so any DNA activity doesn't impede or slow down the client
+ activities.
+ </para>
+ <para>
+ So, after the file is uploaded, you can search the repository for the image metadata using the "s" menu option:
+ <figure id="example-sequencer-search">
+ <title>Searching for media using the Example Client</title>
+ <graphic align="center" scale="100" fileref="images/example-sequencer-search.png" />
+ </figure>
+ Here are the search results after the <code>sample1.mp3</code> audio file has been uploaded (to the <code>/a/b/sample1.mp3</code> location):
+ <figure id="example-sequencer-search-with-mp3">
+ <title>Searching for media using the Example Client</title>
+ <graphic align="center" scale="100" fileref="images/example-sequencer-search-with-mp3.png" />
+ </figure>
+ You can also display the sequencing statistics using the "d" menu option:
+ <figure id="example-sequencer-statistics">
+ <title>Sequencing statistics using the Example Client</title>
+ <graphic align="center" scale="100" fileref="images/example-sequencer-statistics.png" />
+ </figure>
+ These stats show how many nodes were sequenced, and how many nodes were skipped because they didn't apply to the sequencer's
+ criteria.
+ </para>
+ <note>
+ <para>
+ There will probably be more nodes skipped than sequenced, since there are more
+ <code>nt:folder</code>
+ and
+ <code>nt:resource</code>
+ nodes than there are
+ <code>nt:file</code>
+ nodes with acceptable names.
+ </para>
+ </note>
+ <para>You can repeat this process with other files. Any file that isn't an image or MP3 files (as recognized by the sequencing configurations
+ that we'll describe later) will not be sequenced.</para>
+ </sect1>
+ <sect1 id="downloading_and_running_review">
+ <title>Summarizing what we just did</title>
+ <para>In this chapter you downloaded and installed the example application and used it to upload files into a
+ JCR repository. JBoss DNA automatically sequenced the image and/or MP3 files you uploaded, extracted the metadata from the
+ files, and stored that metadata inside the repository. The application allowed you to see this metadata
+ and the sequencing statistics.</para>
+ <para>This application was very simplistic. In fact, running through the example probably only took you a minute or two.
+ So while this application won't win any awards, it does show the basics of what JBoss DNA can do.</para>
+ <para>In the <link linkend="using_dna">next chapter</link> we'll venture into the code to get an understanding
+ of how JBoss DNA actually works and how you can use it in your own applications.</para>
+ </sect1>
+ </chapter>
+
+ <!-- ====================================================================================================
+ Chapter
+ ==================================================================================================== -->
+<chapter id="using_dna">
+ <title>Using JBoss DNA</title>
+ <para>As we've mentioned before, JBoss DNA is able to work with existing JCR repositories. Your client applications
+ make changes to the information in those repositories, and JBoss DNA automatically uses its sequencers to extract
+ additional information from the uploaded files.</para>
+ <note>
+ <para>Configuring JBoss DNA sequencers is a bit more manual than is ideal. As you'll see, JBoss DNA uses dependency
+ injection to allow a great deal of flexibility in how it can be configured and customized. However, the next release will
+ provide a much easier mechanism for configuring not only the sequencer service but also the upcoming federation engine and
+ JCR implementation.</para>
+ </note>
+ <sect1 id="sequencing_service">
+ <title>Configuring the Sequencing Service</title>
+ <para>
+ The JBoss DNA <emphasis>sequencing service</emphasis> is the component that manages the <emphasis>sequencers</emphasis>
+ , reacting to changes in JCR repositories and then running the appropriate sequencers.
+ This involves processing the changes on a node, determining which (if any) sequencers should be run on that node,
+ and for each sequencer constructing the execution environment, calling the sequencer, and saving the information
+ generated by the sequencer.</para>
+ <para>To set up the sequencing service, an instance is created, and dependent components are injected into
+ the object. This includes among other things:
+ <itemizedlist>
+ <listitem>
+ <para>An <emphasis>execution context</emphasis> that defines the context in which the service runs, including
+ a factory for JCR sessions given names of the repository and workspace. This factory must be configured,
+ and is how JBoss DNA knows about your JCR repositories and how to connect to them. More on this a bit later.</para>
+ </listitem>
+ <listitem>
+ <para>An optional <emphasis>factory for class loaders</emphasis> used to load sequencers. If no factory is supplied,
+ the service uses the current thread's context class loader (or if that is null, the class loader that loaded the
+ sequencing service class).</para>
+ </listitem>
+ <listitem>
+ <para>An <code>java.util.concurrent.ExecutorService</code> used to execute the sequencing activites. If none
+ is supplied, a new single-threaded executor is created by calling <code>Executors.newSingleThreadExecutor()</code>.
+ (This can easily be changed by subclassing and overriding the <code>SequencerService.createDefaultExecutorService()</code> method.)</para>
+ </listitem>
+ <listitem>
+ <para>Filters for sequencers and events. By default, all sequencers are considered for "node added", "property added"
+ and "property changed" events.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>As mentioned above, the <code>ExecutionContext</code> provides access to a <code>SessionFactory</code> that is used
+ by JBoss DNA to establish sessions to your JCR repositories. Two implementations are available:
+ <itemizedlist>
+ <listitem>
+ <para>The <code>JndiSessionFactory</code> looks up JCR <code>Repository</code> instances in JNDI using
+ names that are supplied when creating sessions. This implementation also has methods to set the
+ JCR <code>Credentials</code> for a given workspace name.</para>
+ </listitem>
+ <listitem>
+ <para>The <code>SimpleSessionFactory</code> has methods to register the JCR <code>Repository</code> instances
+ with names, as well as methods to set the JCR <code>Credentials</code> for a given workspace name.</para>
+ </listitem>
+ </itemizedlist>
+ You can use the <code>SimpleExecutionContext</code> implementation of <code>ExecutionContext</code> and supply
+ a <code>SessionFactory</code> instance, or you can provide your own implementation.
+ </para>
+ <para>Here's an example of how to instantiate and configure the SequencingService:
+ <programlisting>
+SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
+sessionFactory.registerRepository("Main Repository", this.repository);
+Credentials credentials = new SimpleCredentials("jsmith", "secret".toCharArray());
+sessionFactory.registerCredentials("Main Repository/Workspace1", credentials);
+ExecutionContext executionContext = new SimpleExecutionContext(sessionFactory);
+
+// Create the sequencing service, passing in the execution context ...
+SequencingService sequencingService = new SequencingService();
+sequencingService.setExecutionContext(executionContext);</programlisting>
+ </para>
+ <para>After the sequencing service is created and configured, it must be started. The SequencingService
+ has an <emphasis>administration object</emphasis> (that is an instance of <code>ServiceAdministrator</code>)
+ with <code>start()</code>, <code>pause()</code>, and <code>shutdown()</code> methods. The latter method will
+ close the queue for sequencing, but will allow sequencing operations already running to complete normally.
+ To wait until all sequencing operations have completed, simply call the <code>awaitTermination</code> method
+ and pass it the maximum amount of time you want to wait.</para>
+ <para>
+ <programlisting>
+sequencingService.getAdministrator().start();</programlisting>
+ </para>
+ <para>The sequencing service must also be configured with the sequencers that it will use. This is done using the
+ <code>addSequencer(SequencerConfig)</code> method and passing a <code>SequencerConfig</code> instance that
+ you create. Here's an example:
+ <programlisting>
+String name = "Image Sequencer";
+String desc = "Sequences image files to extract the characteristics of the image";
+String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
+String[] classpath = null; // Use the current classpath
+String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png))[*]/jcr:content[@jcr:data] => /images/$1"};
+SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
+sequencingService.addSequencer(imageSequencerConfig);
+
+name = "Mp3 Sequencer";
+desc = "Sequences mp3 files to extract the id3 tags of the audio file";
+classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
+String[] mp3PathExpressions = {"//(*.mp3)[*]/jcr:content[@jcr:data] => /mp3s/$1"};
+SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname, classpath, mp3PathExpressions);
+sequencingService.addSequencer(mp3SequencerConfig);</programlisting>
+ This is pretty self-explanatory, except for the <code>classpath</code> and <code>pathExpression</code> parameters.
+ The classpath parameter defines the classpath that is passed to the class loader factory mentioned above.
+ Our sequencer is on the classpath, so we can simply use <code>null</code> here.
+ </para>
+ <para>The path expression is more complicated. Sequencer path expressions are used by the sequencing service to
+ determine whether a particular changed node should be sequenced. The expressions consist of two parts: a selection
+ criteria and an output expression. Here's a simple example:
+ <programlisting>
+/a/b/c@title => /d/e/f</programlisting>
+ Here, the <code>/a/b/c@title</code> is the selection criteria that applies when the <code>/a/b/c</code> node has a <code>title</code> property
+ that is added or changed. When the selection criteria matches a change event, the sequencer will be run
+ and any generated output will be inserted into the repository described by the output expression. In this example,
+ the generated output would be placed at the <code>/d/e/f</code> node.
+ </para>
+ <note>
+ <para>Sequencer path expressions can be fairly complex and may use wildcards, specificy same-name sibling indexes,
+ provide optional and choice elements, and may capture parts of the selection criteria for use in the output expression.
+ The path expression used in the image sequencer configuration example above shows a more complex example:
+ <programlisting>
+//(*.(jpg|jpeg|gif|bmp|pcx|png))[*]/jcr:content[@jcr:data] => /images/$1</programlisting>
+ This uses "//" to select any node at any level in the repository whose name ends with "." and one of the extensions (e.g., ".jpg", ".jpeg", etc.)
+ and that has a child node named "jcr:content" that has a "jcr:data" property. It also selects the file name
+ as the first capture group (the first set of parentheses) for use in the output expression.
+ In this example, any sequencer output is placed on a node with that same file name under the "/images" node.
+ </para>
+ <para></para>
+ <para>Other things are possible, too. For example, the name of the repository/workspace (as used by the <code>SessionFactory</code>)
+ may be specified at the beginning of the select criteria and/or the output expression. This means it's possible to place
+ the sequencer output in a different repository than the node being sequenced.</para>
+ <para>For more detail about sequencer path expressions, see the <code>org.jboss.dna.repository.sequencer.SequencerPathExpression</code>
+ class and the corresponding <code>org.jboss.dna.repository.sequencer.SequencerPathExpressionTest</code> test case.</para>
+ </note>
+ <para>After the service is started, it is ready to start reacting to changes in the repository. But it first
+ must be wired to the repositories using a listener. This is accomplished using the <code>ObservationService</code>
+ described in the <link linkend="observation_service">next section</link>.</para>
+ </sect1>
+ <sect1 id="observation_service">
+ <title>Configuring the Observation Service</title>
+ <para>The JBoss DNA <code>ObservationService</code> is responsible for listening to one or more JCR repositories
+ and multiplexing the events to its listeners. Unlike JCR events, this framework embeds in the events the
+ name of the repository and workspace that can be passed to a <code>SessionFactory</code> to obtain a session
+ to the repository in which the change occurred. This simple design makes it very easy for JBoss DNA to
+ concurrently work with multiple JCR repositories.</para>
+ <para>Configuring an observation service is pretty easy, especially if you reuse the same <code>SessionFactory</code>
+ supplied to the sequencing service. Here's an example:
+ <programlisting>
+this.observationService = new ObservationService(sessionFactory);
+this.observationService.getAdministrator().start();</programlisting>
+ </para>
+ <note>
+ <para>Both <code>ObservationService</code> and <code>SequencingService</code> implement
+ <code>AdministeredService</code>, which has a <code>ServiceAdministrator</code> used to start, pause, and shutdown the
+ service. In other words, the lifecycle of the services are managed in the same way.</para>
+ </note>
+ <para>
+ After the observation service is started, listeners can be added. The <code>SequencingService</code> implements the required
+ interface, and so it may be registered directly:
+ <programlisting>
+observationService.addListener(sequencingService);</programlisting>
+ </para>
+ <para>Finally, the observation service must be wired to monitor one of your JCR repositories. This is done with
+ one of the <code>monitor(...)</code> methods:
+ <programlisting>
+int eventTypes = Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED;
+observationService.monitor("Main Repository/Workspace1", eventTypes);</programlisting>
+ </para>
+ <para>At this point, the observation service is listening to a JCR repository and forwarding the appropriate events
+ to the sequencing service, which will asynchronously process the changes and sequence the information added to or changed in the repository.
+ </para>
+ </sect1>
+ <sect1 id="shutting_down">
+ <title>Shutting down JBoss DNA services</title>
+ <para>The JBoss DNA services are utilizing resources and threads that must be released before your application is ready to shut down.
+ The safe way to do this is to simply obtain the <code>ServiceAdministrator</code> for each service (via the <code>getServiceAdministrator()</code> method)
+ and call <code>shutdown()</code>. As previously mentioned, the shutdown method will simply prevent new work from being processed
+ and will not wait for existing work to be completed. If you want to wait until the service completes all its work, you must wait
+ until the service terminates. Here's an example that shows how this is done:
+ <programlisting>
+// Shut down the service and wait until it's all shut down ...
+sequencingService.getAdministrator().shutdown();
+sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+
+// Shut down the observation service ...
+observationService.getAdministrator().shutdown();
+observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);</programlisting>
+ </para>
+ <para>At this point, we've covered how to configure and use the JBoss DNA services in your application.
+ The next chapter goes back to the <link linkend="downloading_and_running">sample application</link> to show how all these pieces fit together.</para>
+ </sect1>
+ <sect1 id="example_application_review">
+ <title>Reviewing the example application</title>
+ <para>Recall that the example application consists of a client application that sets up an in-memory JCR repository and
+ that allows a user to upload files into that repository. The client also sets up the DNA services with an image sequencer so
+ that if any of the uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will automatically extract the image's
+ metadata (e.g., image format, physical size, pixel density, etc.) and store that in the repository. Or, if the client uploads
+ MP3 audio files, the title, author, album, year, and comment are extracted from the audio file and stored in the repository.</para>
+ <para>
+ The example is comprised of 3 classes and 1 interface, located in the
+ <code>src/main/java</code>
+ directory:
+ <programlisting>
+ org/jboss/example/dna/sequencers/ConsoleInput.java
+ /MediaInfo.java
+ /SequencingClient.java
+ /UserInterface.java</programlisting>
+ </para>
+ <para>
+ <code>SequencingClient</code>
+ is the class that contains the main application.
+ <code>MediaInfo</code>
+ is a simple Java object that encapsulates metadata about a media file (as generated by the sequencer), and used by the client to
+ pass information to the
+ <code>UserInterface</code>
+ , which is an interface with methods that will be called at runtime to request data from the user.
+ <code>ConsoleInput</code>
+ is an implementation of this that creates a text user interface, allowing the user to operate the client from the command-line.
+ We can easily create a graphical implementation of
+ <code>UserInterface</code>
+ at a later date. We can also create a mock implementation for testing purposes that simulates a user entering data. This
+ allows us to check the behavior of the client automatically using conventional JUnit test cases, as demonstrated by the
+ code in the
+ <code>src/test/java</code>
+ directory:
+ <programlisting>
+ org/jboss/example/dna/sequencers/SequencingClientTest.java
+ /MockUserInterface.java</programlisting>
+ </para>
+ <para>
+ If we look at the
+ <code>SequencingClient</code>
+ code, there are a handful of methods that encapsulate the various activities.
+ </para>
+ <note>
+ <para>To keep the code shown in this book as readable as possible, some of the comments and error handling
+ have been removed.</para>
+ </note>
+ <para>
+ The
+ <code>startRepository()</code>
+ method starts up an in-memory Jackrabbit JCR repository. The bulk of this method is simply gathering and passing the
+ information required by Jackrabbit. Because Jackrabbit's
+ <code>TransientRepository</code>
+ implementation shuts down after the last session is closed, the application maintains a session to ensure that the
+ repository remains open throughout the application's lifetime. And finally, the node type needed by the image sequencer is
+ registered with Jackrabbit.
+ </para>
+ <programlisting>
+public void startRepository() throws Exception {
+ if (this.repository == null) {
+ try {
+
+ // Load the Jackrabbit configuration ...
+ File configFile = new File(this.jackrabbitConfigPath);
+ String pathToConfig = configFile.getAbsolutePath();
+
+ // Find the directory where the Jackrabbit repository data will be stored ...
+ File workingDirectory = new File(this.workingDirectory);
+ String workingDirectoryPath = workingDirectory.getAbsolutePath();
+
+ // Get the Jackrabbit custom node definition (CND) file ...
+ URL cndFile = Thread.currentThread().getContextClassLoader().getResource("jackrabbitNodeTypes.cnd");
+
+ // Create the Jackrabbit repository instance and establish a session to keep the repository alive ...
+ this.repository = new TransientRepository(pathToConfig, workingDirectoryPath);
+ if (this.username != null) {
+ Credentials credentials = new SimpleCredentials(this.username, this.password);
+ this.keepAliveSession = this.repository.login(credentials, this.workspaceName);
+ } else {
+ this.keepAliveSession = this.repository.login();
+ }
+
+ try {
+ // Register the node types (only valid the first time) ...
+ JackrabbitNodeTypeManager mgr = (JackrabbitNodeTypeManager)this.keepAliveSession.getWorkspace().getNodeTypeManager();
+ mgr.registerNodeTypes(cndFile.openStream(), JackrabbitNodeTypeManager.TEXT_X_JCR_CND);
+ } catch (RepositoryException e) {
+ if (!e.getMessage().contains("already exists")) throw e;
+ }
+
+ } catch (Exception e) {
+ this.repository = null;
+ this.keepAliveSession = null;
+ throw e;
+ }
+ }
+}</programlisting>
+ <para>As you can see, this method really has nothing to do with JBoss DNA, other than setting up a JCR repository that JBoss
+ DNA will use.</para>
+ <para>
+ The
+ <code>shutdownRepository()</code>
+ method shuts down the Jackrabbit transient repository by closing the "keep-alive session". Again, this method really does
+ nothing specifically with JBoss DNA, but is needed to manage the JCR repository that JBoss DNA uses.
+ <programlisting>
+public void shutdownRepository() throws Exception {
+ if (this.repository != null) {
+ try {
+ this.keepAliveSession.logout();
+ } finally {
+ this.repository = null;
+ this.keepAliveSession = null;
+ }
+ }
+}</programlisting>
+ </para>
+ <para>
+ The
+ <code>startDnaServices()</code>
+ method first starts the JCR repository (if it was not already started), and proceeds to create and configure the
+ <code>SequencingService</code>
+ as described
+ <link linkend="sequencing_service">earlier</link>
+ . This involes setting up the
+ <code>SessionFactory</code>
+ and
+ <code>ExecutionContext</code>
+ , creating the
+ <code>SequencingService</code>
+ instance, and configuring the image sequencer. The method then continues by setting up the
+ <code>ObservationService</code>
+ as described
+ <link linkend="observation_service">earlier</link>
+ and starting the service.
+ <programlisting>
+public void startDnaServices() throws Exception {
+ if (this.repository == null) this.startRepository();
+ if (this.sequencingService == null) {
+
+ SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
+ sessionFactory.registerRepository(this.repositoryName, this.repository);
+ if (this.username != null) {
+ Credentials credentials = new SimpleCredentials(this.username, this.password);
+ sessionFactory.registerCredentials(this.repositoryName + "/" + this.workspaceName, credentials);
+ }
+ this.executionContext = new SimpleExecutionContext(sessionFactory);
+
+ // Create the sequencing service, passing in the execution context ...
+ this.sequencingService = new SequencingService();
+ this.sequencingService.setExecutionContext(executionContext);
+
+ // Configure the sequencers.
+ String name = "Image Sequencer";
+ String desc = "Sequences image files to extract the characteristics of the image";
+ String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
+ String[] classpath = null; // Use the current classpath
+ String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data] => /images/$1"};
+ SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
+ this.sequencingService.addSequencer(imageSequencerConfig);
+
+ // Set up the MP3 sequencer ...
+ name = "Mp3 Sequencer";
+ desc = "Sequences mp3 files to extract the id3 tags of the audio file";
+ classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
+ String[] mp3PathExpressions = {"//(*.mp3)[*]/jcr:content[@jcr:data] => /mp3s/$1"};
+ SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname, classpath, mp3PathExpressions);
+ this.sequencingService.addSequencer(mp3SequencerConfig);
+
+ // Use the DNA observation service to listen to the JCR repository (or multiple ones), and
+ // then register the sequencing service as a listener to this observation service...
+ this.observationService = new ObservationService(this.executionContext.getSessionFactory());
+ this.observationService.getAdministrator().start();
+ this.observationService.addListener(this.sequencingService);
+ this.observationService.monitor(this.repositoryName + "/" + this.workspaceName, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED);
+ }
+ // Start up the sequencing service ...
+ this.sequencingService.getAdministrator().start();
+}</programlisting>
+ </para>
+ <para>
+ The
+ <code>shutdownDnaServices()</code>
+ method is pretty straightforward: it just calls shutdown on each of the services and waits until they terminate.
+ <programlisting>
+public void shutdownDnaServices() throws Exception {
+ if (this.sequencingService == null) return;
+
+ // Shut down the service and wait until it's all shut down ...
+ this.sequencingService.getAdministrator().shutdown();
+ this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+
+ // Shut down the observation service ...
+ this.observationService.getAdministrator().shutdown();
+ this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+}</programlisting>
+ </para>
+ <para>None of the other methods really do anything with JBoss DNA <emphasis>per se</emphasis>. Instead, they merely work with the repository
+ using the JCR API.</para>
+ <para>
+ The <code>main</code> method of the <code>SequencingClient</code> class creates a <code>SequencingClient</code> instance,
+ and passes a new <code>ConsoleInput</code> instance:
+ <programlisting>
+public static void main( String[] args ) throws Exception {
+ SequencingClient client = new SequencingClient();
+ client.setRepositoryInformation("repo", "default", "jsmith", "secret".toCharArray());
+ client.setUserInterface(new ConsoleInput(client));
+}</programlisting>
+ </para>
+ <para>If we look at the
+ <code>ConsoleInput</code>
+ constructor, it starts the repository, the DNA services, and a thread for the user interface. At this point, the constructor
+ returns, but the main application continues under the user interface thread. When the user requests to quit,
+ the user interface thread also shuts down the DNA services and JCR repository.
+ <programlisting>
+public ConsoleInput( SequencerClient client ) {
+ try {
+ client.startRepository();
+ client.startDnaServices();
+
+ System.out.println(getMenu());
+ Thread eventThread = new Thread(new Runnable() {
+ private boolean quit = false;
+ public void run() {
+ try {
+ while (!quit) {
+ // Display the prompt and process the requested operation ...
+ }
+ } finally {
+ try {
+ // Terminate ...
+ client.shutdownDnaServices();
+ client.shutdownRepository();
+ } catch (Exception err) {
+ System.out.println("Error shutting down sequencing service and repository: " + err.getLocalizedMessage());
+ err.printStackTrace(System.err);
+ }
+ }
+ }
+ });
+ eventThread.start();
+ } catch (Exception err) {
+ System.out.println("Error: " + err.getLocalizedMessage());
+ err.printStackTrace(System.err);
+ }
+}</programlisting>
+ </para>
+ <para>At this point, we've reviewed all of the interesting code in the example application. However, feel free
+ to play with the application, trying different things.
+ </para>
+ </sect1>
+ <sect1 id="using_dna_review">
+ <title>Summarizing what we just did</title>
+ <para>In this chapter we covered the different JBoss DNA components and how they can be used in your application.
+ Specifically, we described how the <code>SequencingService</code> and <code>ObservationService</code> can
+ be configured and used. And we ended the chapter by reviewing the example application, which not only uses
+ JBoss DNA, but also the repository via the JCR API.
+ </para>
+ </sect1>
+</chapter>
+
+<!-- ====================================================================================================
+ Chapter
+ ==================================================================================================== -->
+<chapter id="custom_sequencers">
+ <title>Creating custom sequencers</title>
+ <para>The current release of JBoss DNA comes with two sequencers: one that extracts metadata from a variety of image file formats,
+ and another that extracts some of the ID3 metadata from MP3 audio files. However, it's very easy to create your own
+ sequencers and to then configure JBoss DNA to use them in your own application.
+ </para>
+ <para>
+ Creating a custom sequencer involves the following steps:
+ <itemizedlist>
+ <listitem>
+ <para>Create a Maven 2 project for your sequencer;</para>
+ </listitem>
+ <listitem>
+ <para>Implement the <code>org.jboss.dna.spi.sequencers.StreamSequencer</code> interface with your own implementation, and create unit tests to verify
+ the functionality and expected behavior;</para>
+ </listitem>
+ <listitem>
+ <para>Add the sequencer configuration to the JBoss DNA <code>SequencingService</code> in your application
+ as described in the <link linkend="using_dna">previous chapter</link>; and</para>
+ </listitem>
+ <listitem>
+ <para>Deploy the JAR file with your implementation (as well as any dependencies), and make them available to JBoss DNA
+ in your application.</para>
+ </listitem>
+ </itemizedlist>
+ It's that simple.
+ </para>
+ <sect1 id="custom_sequencer_project">
+ <title>Creating the Maven 2 project</title>
+ <para>The first step is to create the Maven 2 project that you can use to compile your code and build the JARs.
+ Maven 2 automates a lot of the work, and since you're already <link linkend="downloading_and_running">set up to use Maven</link>,
+ using Maven for your project will save you a lot of time and effort. Of course, you don't have to use Maven 2, but then you'll
+ have to get the required libraries and manage the compiling and building process yourself.</para>
+ <note>
+ <para>JBoss DNA may provide in the future a Maven archetype for creating sequencer projects. If you'd find this useful
+ and would like to help create it, please <link linkend="preface">join the community</link>.</para>
+ </note>
+ <note>
+ <para>The <code>dna-sequencer-images</code> project is a small, self-contained sequencer implementation that
+ has only the minimal dependencies. Starting with this project's source and modifying it to suit your needs may be the easiest way to get started.
+ See the subversion repository: <ulink url="http://anonsvn.jboss.org/repos/dna/trunk/sequencers/dna-sequencer-images/">http://anonsvn.jboss.org/repos/dna/trunk/sequencers/dna-sequencer-images/</ulink>
+ </para>
+ </note>
+ <para>You can create your Maven project any way you'd like. For examples, see the <ulink url="http://maven.apache.org/guides/getting-started/index.html#How_do_I_make_m...">Maven 2 documentation</ulink>.
+ Once you've done that, just add the dependencies in your project's <code>pom.xml</code> dependencies section:
+ <programlisting>
+<dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-common</artifactId>
+ <version>0.1</version>
+</dependency>
+<dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-spi</artifactId>
+ <version>0.1</version>
+</dependency>
+<dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+</dependency>
+</programlisting>
+ These are minimum dependencies required for compiling a sequencer. Of course, you'll have to add
+ other dependencies that your sequencer needs.</para>
+ <para>As for testing, you probably will want to add more dependencies, such as those listed here:
+<programlisting>
+<dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+</dependency>
+<dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <version>1.1</version>
+ <scope>test</scope>
+</dependency>
+<!-- Logging with Log4J -->
+<dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.4.3</version>
+ <scope>test</scope>
+</dependency>
+<dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ <scope>test</scope>
+</dependency>
+</programlisting>
+ Testing JBoss DNA sequencers does not require a JCR repository or the JBoss DNA services. (For more detail,
+ see the <link linkend="testing_custom_sequencers">testing section</link>.) However, if you want to do
+ integration testing with a JCR repository and the JBoss DNA services, you'll need additional dependencies for these libraries.
+<programlisting>
+<dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-repository</artifactId>
+ <version>0.1</version>
+ <scope>test</scope>
+</dependency>
+<!-- Java Content Repository API -->
+<dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <version>1.0.1</version>
+ <scope>test</scope>
+</dependency>
+<!-- Apache Jackrabbit (JCR Implementation) -->
+<dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-api</artifactId>
+ <version>1.3.3</version>
+ <scope>test</scope>
+ <!-- Exclude these since they are included in JDK 1.5 -->
+ <exclusions>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ </exclusion>
+ </exclusions>
+</dependency>
+<dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-core</artifactId>
+ <version>1.3.3</version>
+ <scope>test</scope>
+ <!-- Exclude these since they are included in JDK 1.5 -->
+ <exclusions>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ </exclusion>
+ </exclusions>
+</dependency>
+</programlisting>
+ </para>
+ <para>At this point, your project should be set up correctly, and you're ready to move on to
+ <link linkend="custom_sequencer_implementation">writing the Java implementation</link> for your sequencer.
+ </para>
+ </sect1>
+ <sect1 id="custom_sequencer_implementation">
+ <title>Implementing the StreamSequencer interface</title>
+ <para>After creating the project and setting up the dependencies, the next step is to create a Java class that implements
+ the <code>org.jboss.dna.spi.sequencers.StreamSequencer</code> interface. This interface is very straightforward
+ and involves a single method:
+ <programlisting>
+public interface StreamSequencer {
+
+ /**
+ * Sequence the data found in the supplied stream, placing the output
+ * information into the supplied map.
+ *
+ * @param stream the stream with the data to be sequenced; never null
+ * @param output the output from the sequencing operation; never null
+ * @param progressMonitor the progress monitor that should be kept
+ * updated with the sequencer's progress and that should be
+ * frequently consulted as to whether this operation has been cancelled.
+ */
+ void sequence( InputStream stream, SequencerOutput output,
+ ProgressMonitor progressMonitor );</programlisting>
+ </para>
+ <para>The job of a stream sequencer is to process the data in the supplied stream, and place into the <code>SequencerOutput</code>
+ any information that is to go into the JCR repository. JBoss DNA figures out when your sequencer should be called
+ (of course, using the sequencing configuration you'll add in a bit), and then makes sure the generated information
+ is saved in the correct place in the repository.
+ </para>
+ <para>The <code>SequencerOutput</code> class is fairly easy to use. There are basically two methods you need to call.
+ One method sets the property values, while the other sets references to other nodes in the repository. Use these
+ methods to describe the properties of the nodes you want to create, using relative paths for the nodes and
+ valid JCR property names for properties and references. JBoss DNA will ensure that nodes are created or updated
+ whenever they're needed.
+ <programlisting>
+public interface SequencerOutput {
+
+ /**
+ * Set the supplied property on the supplied node. The allowable
+ * values are any of the following:
+ * - primitives (which will be autoboxed)
+ * - String instances
+ * - String arrays
+ * - byte arrays
+ * - InputStream instances
+ * - Calendar instances
+ *
+ * @param nodePath the path to the node containing the property;
+ * may not be null
+ * @param property the name of the property to be set
+ * @param values the value(s) for the property; may be empty if
+ * any existing property is to be removed
+ */
+ void setProperty( String nodePath, String property,
+ Object... values );
+
+ /**
+ * Set the supplied reference on the supplied node.
+ *
+ * @param nodePath the path to the node containing the property;
+ * may not be null
+ * @param property the name of the property to be set
+ * @param paths the paths to the referenced property, which may be
+ * absolute paths or relative to the sequencer output node;
+ * may be empty if any existing property is to be removed
+ */
+ void setReference( String nodePath, String property,
+ String... paths );
+}</programlisting>
+ </para>
+ <para>JBoss DNA will create nodes of type <code>nt:unstructured</code> unless you specify the value for the
+ <code>jcr:primaryType</code> property. You can also specify the values for the <code>jcr:mixinTypes</code> property
+ if you want to add mixins to any node.
+ </para>
+ <para>For a complete example of a sequencer, let's look at the <code>org.jboss.dna.sequencers.image.ImageMetadataSequencer</code> implementation:
+ <programlisting>
+public class ImageMetadataSequencer implements StreamSequencer {
+
+ public static final String METADATA_NODE = "image:metadata";
+ public static final String IMAGE_PRIMARY_TYPE = "jcr:primaryType";
+ public static final String IMAGE_MIXINS = "jcr:mixinTypes";
+ public static final String IMAGE_MIME_TYPE = "jcr:mimeType";
+ public static final String IMAGE_ENCODING = "jcr:encoding";
+ public static final String IMAGE_FORMAT_NAME = "image:formatName";
+ public static final String IMAGE_WIDTH = "image:width";
+ public static final String IMAGE_HEIGHT = "image:height";
+ public static final String IMAGE_BITS_PER_PIXEL = "image:bitsPerPixel";
+ public static final String IMAGE_PROGRESSIVE = "image:progressive";
+ public static final String IMAGE_NUMBER_OF_IMAGES = "image:numberOfImages";
+ public static final String IMAGE_PHYSICAL_WIDTH_DPI = "image:physicalWidthDpi";
+ public static final String IMAGE_PHYSICAL_HEIGHT_DPI = "image:physicalHeightDpi";
+ public static final String IMAGE_PHYSICAL_WIDTH_INCHES = "image:physicalWidthInches";
+ public static final String IMAGE_PHYSICAL_HEIGHT_INCHES = "image:physicalHeightInches";
+
+ /**
+ * {@inheritDoc}
+ */
+ public void sequence( InputStream stream, SequencerOutput output,
+ ProgressMonitor progressMonitor ) {
+ progressMonitor.beginTask(10, ImageSequencerI18n.sequencerTaskName);
+
+ ImageMetadata metadata = new ImageMetadata();
+ metadata.setInput(stream);
+ metadata.setDetermineImageNumber(true);
+ metadata.setCollectComments(true);
+
+ // Process the image stream and extract the metadata ...
+ if (!metadata.check()) {
+ metadata = null;
+ }
+ progressMonitor.worked(5);
+ if (progressMonitor.isCancelled()) return;
+
+ // Generate the output graph if we found useful metadata ...
+ if (metadata != null) {
+ // Place the image metadata into the output map ...
+ output.setProperty(METADATA_NODE, IMAGE_PRIMARY_TYPE, "image:metadata");
+ // output.psetProperty(METADATA_NODE, IMAGE_MIXINS, "");
+ output.setProperty(METADATA_NODE, IMAGE_MIME_TYPE, metadata.getMimeType());
+ // output.setProperty(METADATA_NODE, IMAGE_ENCODING, "");
+ output.setProperty(METADATA_NODE, IMAGE_FORMAT_NAME, metadata.getFormatName());
+ output.setProperty(METADATA_NODE, IMAGE_WIDTH, metadata.getWidth());
+ output.setProperty(METADATA_NODE, IMAGE_HEIGHT, metadata.getHeight());
+ output.setProperty(METADATA_NODE, IMAGE_BITS_PER_PIXEL, metadata.getBitsPerPixel());
+ output.setProperty(METADATA_NODE, IMAGE_PROGRESSIVE, metadata.isProgressive());
+ output.setProperty(METADATA_NODE, IMAGE_NUMBER_OF_IMAGES, metadata.getNumberOfImages());
+ output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_WIDTH_DPI, metadata.getPhysicalWidthDpi());
+ output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_HEIGHT_DPI, metadata.getPhysicalHeightDpi());
+ output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_WIDTH_INCHES, metadata.getPhysicalWidthInch());
+ output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_HEIGHT_INCHES, metadata.getPhysicalHeightInch());
+ }
+
+ progressMonitor.done();
+ }
+}</programlisting>
+ </para>
+ <para>
+ Notice how the image metadata is extracted and the output graph is generated. A single node is created with the name <code>image:metadata</code>
+ and with the <code>image:metadata</code> node type. No mixins are defined for the node, but several properties are set on the node
+ using the values obtained from the image metadata. After this method returns, the constructed graph will be saved to the repository
+ in all of the places defined by its configuration. (This is why only relative paths are used in the sequencer.)
+ </para>
+ <para>Also note how the progress monitor is used. Reporting progress through the supplied <code>ProgressMonitor</code> is very easy, and it ensures that JBoss DNA
+ can accurately monitor and report the status of sequencing activities to the users. At the beginning of the operation, call
+ <code>beginTask(...)</code> with a meaningful message describing
+ the operation and a total for the amount of work that will be done by this sequencer. Then perform the sequencing work,
+ periodically reporting work by specifying the incremental amount of work with the <code>worked(double)</code> method, or
+ by creating a subtask with the <code>createSubtask(double)</code> method and reporting work against that subtask
+ monitor.
+ </para>
+ <para>Your method should periodically use the ProgressMonitor's <code>isCancelled()</code> method to check whether the operation has been
+ cancelled.. If this method returns true, the implementation should abort all work as
+ soon as possible and close any resources that were acquired or opened.
+ </para>
+ <para>
+ Finally, when your sequencing operation is completed, it should call <code>done()</code> on the progress monitor.
+ </para>
+ </sect1>
+ <sect1 id="testing_custom_sequencers">
+ <title>Testing custom sequencers</title>
+ <para>The sequencing framework was designed to make testing sequencers much easier. In particular, the
+ <code>StreamSequencer</code> interface does not make use of the JCR API. So instead of requiring a fully-configured
+ JCR repository and JBoss DNA system, unit tests for a sequencer can focus on testing that the content is
+ processed correctly and the desired output graph is generated.</para>
+ <note>
+ <para>For a complete example of a sequencer unit test, see the <code>ImageMetadataSequencerTest</code> unit test
+ in the <code>org.jboss.dna.sequencer.images</code> package of the <code>dna-sequencers-image</code> project.
+ </para>
+ </note>
+ <para>The following code fragment shows one way of testing a sequencer, using JUnit 4.4 assertions and
+ some of the classes made available by JBoss DNA. Of course,
+ this example code does not do any error handling and does not make all the assertions a real test would.
+ <programlisting>
+Sequencer sequencer = new ImageMetadataSequencer();
+MockSequencerOutput output = new MockSequencerOutput();
+ProgressMonitor progress = new SimpleProgressMonitor("Test activity");
+InputStream stream = null;
+try {
+ stream = this.getClass().getClassLoader().getResource("caution.gif").openStream();
+ sequencer.sequence(stream,output,progress); // writes to 'output'
+ assertThat(output.getPropertyValues("image:metadata", "jcr:primaryType"),
+ is(new Object[] {"image:metadata"}));
+ assertThat(output.getPropertyValues("image:metadata", "jcr:mimeType"),
+ is(new Object[] {"image/gif"}));
+ // ... make more assertions here
+ assertThat(output.hasReferences(), is(false));
+} finally {
+ stream.close();
+}</programlisting>
+ </para>
+ <para>It's also useful to test that a sequencer produces no output for something it should not understand:
+ <programlisting>
+Sequencer sequencer = new ImageMetadataSequencer();
+MockSequencerOutput output = new MockSequencerOutput();
+ProgressMonitor progress = new SimpleProgressMonitor("Test activity");
+InputStream stream = null;
+try {
+ stream = this.getClass().getClassLoader().getResource("caution.pict").openStream();
+ sequencer.sequence(stream,output,progress); // writes to 'output'
+ assertThat(output.hasProperties(), is(false));
+ assertThat(output.hasReferences(), is(false));
+} finally {
+ stream.close();
+}</programlisting>
+ </para>
+ <para>These are just two simple tests that show ways of testing a sequencer. Some tests may get quite involved,
+ especially if a lot of output data is produced.
+ </para>
+ <para>It may also be useful to create some integration tests
+ that <link linkend="using_dna">configure JBoss DNA</link> to use a custom sequencer, and to then upload
+ content using the JCR API, verifying that the custom sequencer did run. However, remember that JBoss DNA
+ runs sequencers asynchronously in the background, and you must sychronize your tests to ensure that the
+ sequencers have a chance to run before checking the results. (One way of doing this (although, granted, not always reliable) is to wait for a second
+ after uploading your content, shutdown the <code>SequencingService</code> and await its termination,
+ and then check that the sequencer output has been saved to the JCR repository. For an example of this technique,
+ see the <code>SequencingClientTest</code> unit test in the example application.)
+ </para>
+ </sect1>
+ <sect1 id="deploying_custom_sequencers">
+ <title>Deploying custom sequencers</title>
+ <para>The first step of deploying a sequencer consists of adding/changing the sequencer configuration (e.g., <code>SequencerConfig</code>)
+ in the <code>SequencingService</code>. This was covered in the <link linkend="sequencing_service">previous chapter</link>.
+ </para>
+ <para>
+ The second step is to make the sequencer implementation available to JBoss DNA. At this time, the JAR containing
+ your new sequencer, as well as any JARs that your sequencer depends on, should be placed on your application classpath.</para>
+ <note>
+ <para>A future goal of JBoss DNA is to allow sequencers, connectors, and other extensions to be easily deployed into
+ a runtime repository. This process will not only be much simpler, but it will also provide JBoss DNA
+ with the information necessary to update configurations and create the appropriate class loaders for each extension.
+ Having separate class loaders for each extension helps prevent the pollution of the common classpath,
+ facilitates an isolated runtime environment to eliminate any dependency conflicts, and may potentially
+ enable hot redeployment of newer extension versions.
+ </para>
+ </note>
+ </sect1>
+</chapter>
+
+<!-- ====================================================================================================
+ Chapter
+ ==================================================================================================== -->
+<chapter id="future_directions">
+ <title>Looking to the future</title>
+ <para>What's next for JBoss DNA? Well, the sequencing system is just the beginning. With this release, the sequencing system
+ is stable enough so that more <link linkend="sequencers">sequencers</link> can be developed and used within your own applications.
+ If you're interested in getting involved with the JBoss DNA project, consider picking up one of the sequencers on our
+ <ulink url="http://jira.jboss.org/jira/browse/DNA?report=com.atlassian.jira.plugin.sy...">roadmap</ulink>.
+ Or, check out <ulink url="http://jira.jboss.org/jira/secure/IssueNavigator.jspa?reset=true&mode...">JIRA</ulink>
+ for the list of sequencers we've thought of. If you think of one that's not there, please add it to JIRA!
+ </para>
+ <para>
+ The next release will focus on creating the <link linkend="federation">federation engine</link> and connectors
+ for several popular and ubiquitous systems. The 0.2 release will likely only federate information in a read-only manner,
+ but updates will soon follow. Also, during the early part of the next release, the JBoss DNA project will switch to use JDK 6.
+ Java 5 is being end-of-lifed, so we want to move to a supported JDK. However, a number of JBoss projects and products continue to
+ require Java 5, so our next release will most likely use JDK 6 with Java 5 compatibility.</para>
+ <para>
+ Other components on our roadmap include a web user interface, a REST-ful server, and a view system that allows domain-specific
+ views of information in the repository. These components are farther out on our roadmap, and at this time have not been
+ targeted to a particular release. If any of these are of interest to you, please <link linkend="preface">get involved</link> in the community.
+ </para>
+</chapter>
+</book>
\ No newline at end of file
Property changes on: trunk/dna-repository/src/test/resources/master.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-repository/src/test/resources/plugin.xml
===================================================================
--- trunk/dna-repository/src/test/resources/plugin.xml (rev 0)
+++ trunk/dna-repository/src/test/resources/plugin.xml 2008-06-06 00:37:18 UTC (rev 239)
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<!-- (c) 2007 Varsity Gateway LLC. All rights reserved. -->
+<plugin
+ id="com.metamatrix.metamodels.transformation"
+ name="%pluginName"
+ version="5.5.1"
+ provider-name="%providerName"
+ class="com.metamatrix.metamodels.transformation.TransformationPlugin">
+
+ <runtime>
+ <library name="metamodelsTransformation.jar">
+ <export name="*"/>
+ </library>
+ </runtime>
+ <requires>
+ <import plugin="org.eclipse.emf.mapping" export="true"/>
+ <import plugin="org.eclipse.emf.ecore" export="true"/>
+ <import plugin="org.eclipse.emf.edit" export="true"/>
+ <import plugin="org.eclipse.emf.ecore.edit" export="true"/>
+ <import plugin="org.eclipse.core.runtime" export="true"/>
+ <import plugin="com.metamatrix.core" export="true"/>
+ <import plugin="com.metamatrix.metamodels.core" export="true"/>
+ </requires>
+
+
+<!--
+ Each extension below represents a single metamodel. Each metmodel is
+ registered using under the specified <uri> value which must be the same
+ eNS_URI value defined in the EPackage class for that metamodel.
+ -->
+ <extension
+ id="transformation"
+ name="%metamodelName"
+ point="com.metamatrix.modeler.core.metamodel">
+ <uri>
+ http://www.metamatrix.com/metamodels/Transformation
+ </uri>
+ <alternateUri>
+ mtkplugin:///com.metamatrix.metamodels.Transformation
+ </alternateUri>
+ <packageClass
+ name="com.metamatrix.metamodels.transformation.TransformationPackage">
+ </packageClass>
+ <adapterClass
+ name="com.metamatrix.metamodels.transformation.provider.TransformationItemProviderAdapterFactory">
+ </adapterClass>
+ <properties
+ createAsPhysical="false"
+ requiresProxies="false"
+ participatoryOnly="true"
+ createAsVirtual="false"
+ supportsDiagrams="false"
+ supportsExtension="true">
+ </properties>
+ </extension>
+ <extension
+ point="org.eclipse.emf.ecore.generated_package">
+ <package
+ uri="http://www.metamatrix.com/metamodels/Transformation"
+ class="com.metamatrix.metamodels.transformation.TransformationPackage">
+ </package>
+ </extension>
+
+ <extension
+ id="mapping"
+ name="%mappingMetamodelName"
+ point="com.metamatrix.modeler.core.metamodel">
+ <uri>
+ http://www.eclipse.org/emf/2002/Mapping
+ </uri>
+ <alternateUri>
+ mtkplugin:///www.eclipse.org/emf/2002/Mapping
+ </alternateUri>
+ <packageClass
+ name="org.eclipse.emf.mapping.MappingPackage">
+ </packageClass>
+ <adapterClass
+ name="org.eclipse.emf.mapping.provider.MappingItemProviderAdapterFactory">
+ </adapterClass>
+ <properties
+ createAsPhysical="false"
+ requiresProxies="false"
+ participatoryOnly="true"
+ createAsVirtual="false"
+ supportsDiagrams="false"
+ supportsExtension="false">
+ </properties>
+ </extension>
+
+</plugin>
Property changes on: trunk/dna-repository/src/test/resources/plugin.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/sequencers/MockSequencerOutput.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/sequencers/MockSequencerOutput.java 2008-06-05 23:50:49 UTC (rev 238)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/sequencers/MockSequencerOutput.java 2008-06-06 00:37:18 UTC (rev 239)
@@ -34,6 +34,7 @@
/**
* @author Randall Hauch
+ * @author John Verhaeg
*/
@NotThreadSafe
public class MockSequencerOutput implements SequencerOutput {
@@ -46,10 +47,12 @@
public MockSequencerOutput() {
this.properties = new HashMap<Path, Object[]>();
NamespaceRegistry registry = new BasicNamespaceRegistry();
- registry.register("dna", "http://www.jboss.org/dna/1.0");
registry.register("jcr", "http://www.jcp.org/jcr/1.0");
registry.register("mix", "http://www.jcp.org/jcr/mix/1.0");
registry.register("nt", "http://www.jcp.org/jcr/nt/1.0");
+ registry.register("dna", "http://www.jboss.org/dna/1.0");
+ registry.register("dnadtd", "http://www.jboss.org/dna/1.0/dtd");
+ registry.register("dnaxml", "http://www.jboss.org/dna/1.0/xml");
factories = new StandardValueFactories(registry);
}
@@ -64,7 +67,7 @@
* <p>
* {@inheritDoc}
* </p>
- *
+ *
* @see org.jboss.dna.spi.sequencers.SequencerOutput#getNamespaceRegistry()
*/
public NamespaceRegistry getNamespaceRegistry() {
17 years, 6 months
DNA SVN: r238 - in trunk: dna-integration-tests and 3 other directories.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-06-05 19:50:49 -0400 (Thu, 05 Jun 2008)
New Revision: 238
Modified:
trunk/dna-common/.classpath
trunk/dna-integration-tests/.classpath
trunk/dna-maven-classloader/.classpath
trunk/dna-repository/.classpath
trunk/docs/examples/gettingstarted/sequencers/.classpath
Log:
DNA-112: Setup each project to allow for different output folders, with the folder for src/main/java and src/main/resources set to target/classes, and with the folder for src/test/java and src/test/resources set to target/test-classes.
Modified: trunk/dna-common/.classpath
===================================================================
--- trunk/dna-common/.classpath 2008-06-04 11:52:30 UTC (rev 237)
+++ trunk/dna-common/.classpath 2008-06-05 23:50:49 UTC (rev 238)
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
- <classpathentry kind="src" path="src/test/java"/>
- <classpathentry excluding="**" kind="src" output="src/main/resources" path="src/main/resources"/>
- <classpathentry excluding="**" kind="src" output="src/test/resources" path="src/test/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry excluding="**" kind="src" path="src/main/resources"/>
+ <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
Modified: trunk/dna-integration-tests/.classpath
===================================================================
--- trunk/dna-integration-tests/.classpath 2008-06-04 11:52:30 UTC (rev 237)
+++ trunk/dna-integration-tests/.classpath 2008-06-05 23:50:49 UTC (rev 238)
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
- <classpathentry kind="src" path="src/test/java"/>
- <classpathentry excluding="**" kind="src" output="src/main/resources" path="src/main/resources"/>
- <classpathentry excluding="**" kind="src" output="src/test/resources" path="src/test/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry excluding="**" kind="src" path="src/main/resources"/>
+ <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
Modified: trunk/dna-maven-classloader/.classpath
===================================================================
--- trunk/dna-maven-classloader/.classpath 2008-06-04 11:52:30 UTC (rev 237)
+++ trunk/dna-maven-classloader/.classpath 2008-06-05 23:50:49 UTC (rev 238)
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
- <classpathentry kind="src" path="src/test/java"/>
- <classpathentry excluding="**" kind="src" output="src/main/resources" path="src/main/resources"/>
- <classpathentry excluding="**" kind="src" output="src/test/resources" path="src/test/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry excluding="**" kind="src" path="src/main/resources"/>
+ <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
Modified: trunk/dna-repository/.classpath
===================================================================
--- trunk/dna-repository/.classpath 2008-06-04 11:52:30 UTC (rev 237)
+++ trunk/dna-repository/.classpath 2008-06-05 23:50:49 UTC (rev 238)
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
- <classpathentry kind="src" path="src/test/java"/>
- <classpathentry excluding="**" kind="src" output="src/main/resources" path="src/main/resources"/>
- <classpathentry excluding="**" kind="src" output="src/test/resources" path="src/test/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry excluding="**" kind="src" path="src/main/resources"/>
+ <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
Modified: trunk/docs/examples/gettingstarted/sequencers/.classpath
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/.classpath 2008-06-04 11:52:30 UTC (rev 237)
+++ trunk/docs/examples/gettingstarted/sequencers/.classpath 2008-06-05 23:50:49 UTC (rev 238)
@@ -2,8 +2,8 @@
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" path="src/main/resources"/>
- <classpathentry kind="src" path="src/test/java"/>
- <classpathentry kind="src" path="src/test/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
17 years, 6 months
DNA SVN: r237 - branches/maeste.
by dna-commits@lists.jboss.org
Author: maeste
Date: 2008-06-04 07:52:30 -0400 (Wed, 04 Jun 2008)
New Revision: 237
Modified:
branches/maeste/
Log:
Initialized merge tracking via "svnmerge" with revisions "1-235" from
https://svn.jboss.org/repos/dna/trunk
Property changes on: branches/maeste
___________________________________________________________________
Name: svnmerge-integrated
+ /trunk:1-235
17 years, 6 months
DNA SVN: r236 - branches.
by dna-commits@lists.jboss.org
Author: maeste
Date: 2008-06-04 07:49:18 -0400 (Wed, 04 Jun 2008)
New Revision: 236
Added:
branches/maeste/
Log:
[DNA-78] creating personal branch to work on esb message sequencer
Copied: branches/maeste (from rev 235, trunk)
17 years, 6 months
DNA SVN: r235 - in trunk: dna-maven-classloader/src/main/java/org/jboss/dna/maven and 4 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-06-03 13:32:57 -0400 (Tue, 03 Jun 2008)
New Revision: 235
Added:
trunk/dna-common/src/main/java/org/jboss/dna/common/text/TextDecoder.java
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/text/Jsr283Encoder.java
trunk/dna-common/src/main/java/org/jboss/dna/common/text/NoOpEncoder.java
trunk/dna-common/src/main/java/org/jboss/dna/common/text/TextEncoder.java
trunk/dna-common/src/main/java/org/jboss/dna/common/text/UrlEncoder.java
trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/MavenUrl.java
trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/spi/JcrMavenUrlProvider.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/NameFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueComparators.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/AbstractValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BooleanValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DecimalValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DoubleValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/InMemoryBinaryValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/LongValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/NameValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/ObjectValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/StandardValueFactories.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/StringValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/UriValueFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/UuidReferenceValueFactory.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/AbstractValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathSegmentTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BooleanValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DecimalValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DoubleValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/InMemoryBinaryValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/LongValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/NameValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/PathValueFactoryTest.java
Log:
DNA-82: Break TextEncoder interface into two interfaces: one for encoding and one for decoding
http://jira.jboss.org/jira/browse/DNA-82
Broke into separate interfaces, and changed all uses. Some places did require references to both a TextEncoder and TextDecoder, but most only required a single reference. It also made some of the uses of a decoder more clear (than calling it a "decoder" but having the type be TextEncoder, as it was previously.)
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/text/Jsr283Encoder.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/text/Jsr283Encoder.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/text/Jsr283Encoder.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -57,9 +57,10 @@
* </tr>
* </table>
* </p>
+ *
* @author Randall Hauch
*/
-public class Jsr283Encoder implements TextEncoder {
+public class Jsr283Encoder implements TextEncoder, TextDecoder {
/**
* {@inheritDoc}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/text/NoOpEncoder.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/text/NoOpEncoder.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/text/NoOpEncoder.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -24,9 +24,10 @@
/**
* An encoder implementation that does nothing. This is useful when a {@link TextEncoder encoder} is optional but the code is
* easier to write when there is always an encoder.
+ *
* @author Randall Hauch
*/
-public class NoOpEncoder implements TextEncoder {
+public class NoOpEncoder implements TextEncoder, TextDecoder {
private static final NoOpEncoder INSTANCE = new NoOpEncoder();
Added: trunk/dna-common/src/main/java/org/jboss/dna/common/text/TextDecoder.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/text/TextDecoder.java (rev 0)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/text/TextDecoder.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -0,0 +1,41 @@
+/*
+ * 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.common.text;
+
+/**
+ * Interface for components that can decode text. This is the counterpart to {@link TextEncoder}.
+ *
+ * @author Randall Hauch
+ * @see TextEncoder
+ */
+public interface TextDecoder {
+
+ /**
+ * Return the decoded version of an encoded string
+ *
+ * @param encodedText the encoded text
+ * @return the unecoded form of the text, or null if the supplied node name is also null
+ * @see TextEncoder#encode(String)
+ */
+ public String decode( String encodedText );
+
+}
Property changes on: trunk/dna-common/src/main/java/org/jboss/dna/common/text/TextDecoder.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/text/TextEncoder.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/text/TextEncoder.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/text/TextEncoder.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -22,25 +22,20 @@
package org.jboss.dna.common.text;
/**
- * Interface for components that can encode and unencode text.
+ * Interface for components that can encode text. This is the counterpart to {@link TextDecoder}.
+ *
* @author Randall Hauch
+ * @see TextDecoder
*/
public interface TextEncoder {
/**
* Returns the encoded version of a string.
+ *
* @param text the text with characters that are to be encoded.
* @return the text with the characters encoded as required, or null if the supplied text is null
- * @see #decode(String)
+ * @see TextDecoder#decode(String)
*/
public String encode( String text );
- /**
- * Return the decoded version of an encoded string
- * @param encodedText the encoded text
- * @return the unecoded form of the text, or null if the supplied node name is also null
- * @see #encode(String)
- */
- public String decode( String encodedText );
-
}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/text/UrlEncoder.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/text/UrlEncoder.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/text/UrlEncoder.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,9 +29,10 @@
* An encoder 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>. Note that this class does not encode a complete URL ({@link java.net.URLEncoder}
* and {@link java.net.URLDecoder} should be used for such purposes).
+ *
* @author Randall Hauch
*/
-public class UrlEncoder implements TextEncoder {
+public class UrlEncoder implements TextEncoder, TextDecoder {
/**
* Data characters that are allowed in a URI but do not have a reserved purpose are called unreserved. These include upper and
Modified: trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/MavenUrl.java
===================================================================
--- trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/MavenUrl.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/MavenUrl.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -26,11 +26,13 @@
import java.net.URLStreamHandler;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.text.UrlEncoder;
/**
* Wrapper for a URL that uses a format for referencing JCR nodes and content.
+ *
* @author Randall Hauch
*/
public class MavenUrl {
@@ -46,6 +48,7 @@
/**
* Get the host name
+ *
* @return the host name
*/
public String getHostname() {
@@ -62,6 +65,7 @@
/**
* Get the port. This method returns {@link #NO_PORT} if the port has not been specified.
+ *
* @return the port
*/
public int getPort() {
@@ -90,6 +94,7 @@
/**
* Set the name of the workspace.
+ *
* @param workspaceName the name of the workspace
*/
public void setWorkspaceName( String workspaceName ) {
@@ -123,6 +128,7 @@
/**
* Get a URL that corresponds to the information in this object.
+ *
* @param handler the URL stream handler that will be used to handle obtaining an input stream or an output stream on the
* resulting URL
* @param encoder an encoder that will be used to escape any characters that are not allowed in URLs; {@link UrlEncoder} will
@@ -196,11 +202,13 @@
* <li><b>path/to/node</b> is the path of the node or property that is to be referenced</li>
* </ul>
* </p>
+ *
* @param url the URL to be parsed
* @param decoder the text encoder that should be used to decode the URL; may be null if no decoding should be done
* @return the object representing the JCR information contained in the URL
+ * @see #parse(URL, TextDecoder)
*/
- public static MavenUrl parse( String url, TextEncoder decoder ) {
+ public static MavenUrl parse( String url, TextDecoder decoder ) {
if (decoder == null) decoder = new UrlEncoder();
// This regular expression has the following groups:
// 1) //hostname:port
@@ -231,12 +239,13 @@
/**
* Parse the supplied URL and determine if the URL fits the JCR URL format. If it does, return a {@link MavenUrl} instance;
* otherwise return null. If the URL is malformed or otherwise invalid, this method also returns null.
+ *
* @param url the URL to be parsed
* @param decoder the text encoder that should be used to decode the URL; may be null if no decoding should be done
* @return the object representing the JCR information contained in the URL
- * @see #parse(String,TextEncoder)
+ * @see #parse(String,TextDecoder)
*/
- public static MavenUrl parse( URL url, TextEncoder decoder ) {
+ public static MavenUrl parse( URL url, TextDecoder decoder ) {
if (url == null) return null;
return parse(url.toExternalForm(), decoder);
}
Modified: trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/spi/JcrMavenUrlProvider.java
===================================================================
--- trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/spi/JcrMavenUrlProvider.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/spi/JcrMavenUrlProvider.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -52,6 +52,7 @@
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.version.VersionException;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.text.UrlEncoder;
import org.jboss.dna.common.util.Logger;
@@ -96,7 +97,8 @@
public static final String CONTENT_PROPERTY_NAME = "jcr:data";
private final URLStreamHandler urlStreamHandler = new JcrUrlStreamHandler();
- private final TextEncoder urlEncoder = new UrlEncoder().setSlashEncoded(false);
+ private final TextEncoder urlEncoder;
+ private final TextDecoder urlDecoder;
private Repository repository;
private String workspaceName;
private Credentials credentials;
@@ -104,6 +106,15 @@
private final Logger logger = Logger.getLogger(JcrMavenUrlProvider.class);
/**
+ *
+ */
+ public JcrMavenUrlProvider() {
+ UrlEncoder encoder = new UrlEncoder().setSlashEncoded(false);
+ this.urlEncoder = encoder;
+ this.urlDecoder = encoder;
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -163,6 +174,7 @@
/**
* Get the JCR repository used by this provider
+ *
* @return the repository instance
*/
public Repository getRepository() {
@@ -267,6 +279,7 @@
/**
* Get the JRC path to the node in this repository and it's workspace that represents the artifact with the given type in the
* supplied Maven project.
+ *
* @param mavenId the ID of the Maven project; may not be null
* @param artifactType the type of artifact; may be null
* @param signatureType the type of signature; may be null if the signature file is not desired
@@ -302,6 +315,10 @@
return this.urlEncoder;
}
+ protected TextDecoder getUrlDecoder() {
+ return this.urlDecoder;
+ }
+
protected Session createSession() throws LoginException, NoSuchWorkspaceException, RepositoryException {
if (this.workspaceName != null) {
if (this.credentials != null) {
@@ -319,6 +336,7 @@
* Obtain an input stream to the existing content at the location given by the supplied {@link MavenUrl}. The Maven URL
* should have a path that points to the node where the content is stored in the
* {@link #getContentProperty() content property}.
+ *
* @param mavenUrl the Maven URL to the content; may not be null
* @return the input stream to the content, or null if there is no existing content
* @throws IOException
@@ -354,6 +372,7 @@
* Obtain an output stream to the existing content at the location given by the supplied {@link MavenUrl}. The Maven URL
* should have a path that points to the property or to the node where the content is stored in the
* {@link #getContentProperty() content property}.
+ *
* @param mavenUrl the Maven URL to the content; may not be null
* @return the input stream to the content, or null if there is no existing content
* @throws IOException
@@ -513,6 +532,7 @@
/**
* This {@link URLStreamHandler} specialization understands {@link URL URLs} that point to content in the JCR repository used
* by this Maven repository.
+ *
* @author Randall Hauch
*/
protected class JcrUrlStreamHandler extends URLStreamHandler {
@@ -535,6 +555,7 @@
* Each JcrUrlConnection is used to make a single request to read or write the <code>jcr:content</code> property value on
* the {@link javax.jcr.Node node} that corresponds to the given URL. The node must already exist.
* </p>
+ *
* @author Randall Hauch
*/
protected class MavenUrlConnection extends URLConnection {
@@ -548,7 +569,7 @@
*/
protected MavenUrlConnection( URL url ) {
super(url);
- this.mavenUrl = MavenUrl.parse(url, JcrMavenUrlProvider.this.getUrlEncoder());
+ this.mavenUrl = MavenUrl.parse(url, JcrMavenUrlProvider.this.getUrlDecoder());
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/NameFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/NameFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/NameFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -21,48 +21,45 @@
*/
package org.jboss.dna.spi.graph;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
/**
* A factory for creating {@link Name names}.
- *
+ *
* @author Randall Hauch
*/
public interface NameFactory extends ValueFactory<Name> {
- String JCR_PRIMARY_TYPE = "jcr:primaryType";
+ String JCR_PRIMARY_TYPE = "jcr:primaryType";
- /**
- * 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 <code>null</code> or empty
- */
- Name create( String namespaceUri,
- String localName );
+ /**
+ * Create a name from the given namespace URI and local name.
+ * <p>
+ * This method is equivalent to calling {@link #create(String, String, TextDecoder)} with a null encoder.
+ * </p>
+ *
+ * @param namespaceUri the namespace URI
+ * @param localName the local name
+ * @return the new name
+ * @throws IllegalArgumentException if the local name is <code>null</code> or empty
+ */
+ Name create( String namespaceUri, String localName );
- /**
- * Create a name from the given namespace URI and local name.
- *
- * @param namespaceUri the namespace URI
- * @param localName the local name
- * @param encoder the encoder that should be used to decode the qualified name
- * @return the new name
- * @throws IllegalArgumentException if the local name is <code>null</code> or empty
- */
- Name create( String namespaceUri,
- String localName,
- TextEncoder encoder );
+ /**
+ * Create a name from the given namespace URI and local name.
+ *
+ * @param namespaceUri the namespace URI
+ * @param localName the local name
+ * @param decoder the decoder that should be used to decode the qualified name
+ * @return the new name
+ * @throws IllegalArgumentException if the local name is <code>null</code> or empty
+ */
+ Name create( String namespaceUri, String localName, TextDecoder decoder );
- /**
- * Get the namespace registry.
- *
- * @return the namespace registry; never <code>null</code>
- */
- NamespaceRegistry getNamespaceRegistry();
+ /**
+ * Get the namespace registry.
+ *
+ * @return the namespace registry; never <code>null</code>
+ */
+ NamespaceRegistry getNamespaceRegistry();
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -27,6 +27,7 @@
import net.jcip.annotations.Immutable;
import org.jboss.dna.common.text.Jsr283Encoder;
import org.jboss.dna.common.text.NoOpEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.text.UrlEncoder;
import org.jboss.dna.spi.graph.impl.BasicName;
@@ -73,409 +74,425 @@
@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 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 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 text encoder that encodes text according to the rules of <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
+ */
+ public static final TextEncoder URL_ENCODER = new UrlEncoder().setSlashEncoded(true);
- /**
- * The 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 text decoder that does nothing.
+ */
+ public static final TextDecoder NO_OP_DECODER = new NoOpEncoder();
- /**
- * The delimiter character used to separate segments within a path.
- */
- public static final char DELIMITER = '/';
+ /**
+ * The text decoder that decodes according to JSR-283.
+ */
+ public static final TextDecoder JSR283_DECODER = new Jsr283Encoder();
- /**
- * String form of the delimiter used to separate segments within a path.
- */
- public static final String DELIMITER_STR = new String(new char[] {DELIMITER});
+ /**
+ * The text decoder that decodes text according to the rules of <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
+ */
+ public static final TextDecoder URL_DECODER = new UrlEncoder().setSlashEncoded(true);
- /**
- * String representation of the segment that references a parent.
- */
- public static final String PARENT = "..";
+ /**
+ * 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;
- /**
- * String representation of the segment that references the same segment.
- */
- public static final String SELF = ".";
+ /**
+ * The default text decoder to be used when none is otherwise specified. This is currently the
+ * {@link #JSR283_ENCODER JSR-283 encoder}.
+ */
+ public static final TextDecoder DEFAULT_DECODER = JSR283_DECODER;
- /**
- * The index that will be returned for a {@link Segment} that {@link Segment#hasIndex() has no index}.
- */
- public static final int NO_INDEX = -1;
+ /**
+ * The delimiter character used to separate segments within a path.
+ */
+ public static final char DELIMITER = '/';
- /**
- * Representation of the segments that occur within a path.
- *
- * @author Randall Hauch
- */
- @Immutable
- public static interface Segment extends Cloneable, Comparable<Segment>, Serializable {
+ /**
+ * String form of the delimiter used to separate segments within a path.
+ */
+ public static final String DELIMITER_STR = new String(new char[] {DELIMITER});
- /**
- * Get the name component of this segment.
- *
- * @return the segment's name
- */
- public Name getName();
+ /**
+ * String representation of the segment that references a parent.
+ */
+ public static final String PARENT = "..";
- /**
- * 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();
+ /**
+ * String representation of the segment that references the same segment.
+ */
+ public static final String SELF = ".";
- /**
- * Return whether this segment has an index.
- *
- * @return true if this segment has an index, or false otherwise.
- */
- public boolean hasIndex();
+ /**
+ * The index that will be returned for a {@link Segment} that {@link Segment#hasIndex() has no index}.
+ */
+ public static final int NO_INDEX = -1;
- /**
- * Return whether this segment is a self-reference.
- *
- * @return true if the segment is a self-reference, or false otherwise.
- */
- public boolean isSelfReference();
+ /**
+ * Representation of the segments that occur within a path.
+ *
+ * @author Randall Hauch
+ */
+ @Immutable
+ public static interface Segment extends Cloneable, Comparable<Segment>, Serializable {
- /**
- * 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 name component of this segment.
+ *
+ * @return the segment's name
+ */
+ public Name getName();
- /**
- * 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 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();
- /**
- * 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 whether this segment has an index.
+ *
+ * @return true if this segment has an index, or false otherwise.
+ */
+ public boolean hasIndex();
- /**
- * Get the string form of the segment, using the supplied namespace registry to convert the name's namespace URI to a
- * prefix. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
- *
- * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
- * {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
- * @return the encoded string
- * @throws IllegalArgumentException if the namespace registry is null
- * @see #getString(NamespaceRegistry,TextEncoder)
- */
- public String getString( NamespaceRegistry namespaceRegistry );
+ /**
+ * Return whether this segment is a self-reference.
+ *
+ * @return true if the segment is a self-reference, or false otherwise.
+ */
+ public boolean isSelfReference();
- /**
- * Get the encoded string form of the segment, using the supplied namespace registry to convert the name's namespace URI
- * to a prefix and the supplied encoder to encode characters in each of the path segments.
- *
- * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
- * {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
- * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
- * @return the encoded string
- * @throws IllegalArgumentException if the namespace registry is null
- * @see #getString(NamespaceRegistry)
- */
- public String getString( NamespaceRegistry namespaceRegistry,
- TextEncoder encoder );
- }
+ /**
+ * 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();
- /**
- * Singleton instance of the name referencing a self, provided as a convenience.
- */
- public static final Name SELF_NAME = new BasicName(null, SELF);
+ /**
+ * 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();
- /**
- * Singleton instance of the name referencing a parent, provided as a convenience.
- */
- public static final Name PARENT_NAME = new BasicName(null, PARENT);
+ /**
+ * 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 );
- /**
- * Singleton instance of the path segment referencing a parent, provided as a convenience.
- */
- public static final Path.Segment SELF_SEGMENT = new BasicPathSegment(SELF_NAME);
+ /**
+ * Get the string form of the segment, using the supplied namespace registry to convert the name's namespace URI to a
+ * prefix. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
+ *
+ * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+ * {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
+ * @return the encoded string
+ * @throws IllegalArgumentException if the namespace registry is null
+ * @see #getString(NamespaceRegistry,TextEncoder)
+ */
+ public String getString( NamespaceRegistry namespaceRegistry );
- /**
- * Singleton instance of the path segment referencing a parent, provided as a convenience.
- */
- public static final Path.Segment PARENT_SEGMENT = new BasicPathSegment(PARENT_NAME);
+ /**
+ * Get the encoded string form of the segment, using the supplied namespace registry to convert the name's namespace URI
+ * to a prefix and the supplied encoder to encode characters in each of the path segments.
+ *
+ * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+ * {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
+ * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
+ * @return the encoded string
+ * @throws IllegalArgumentException if the namespace registry is null
+ * @see #getString(NamespaceRegistry)
+ */
+ public String getString( NamespaceRegistry namespaceRegistry, TextEncoder encoder );
+ }
- /**
- * Return the number of segments in this path.
- *
- * @return the number of path segments
- */
- public int size();
+ /**
+ * Singleton instance of the name referencing a self, provided as a convenience.
+ */
+ public static final Name SELF_NAME = new BasicName(null, SELF);
- /**
- * Return whether this path represents the root path.
- *
- * @return true if this path is the root path, or false otherwise
- */
- public boolean isRoot();
+ /**
+ * Singleton instance of the name referencing a parent, provided as a convenience.
+ */
+ public static final Name PARENT_NAME = new BasicName(null, PARENT);
- /**
- * 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 );
+ /**
+ * Singleton instance of the path segment referencing a parent, provided as a convenience.
+ */
+ public static final Path.Segment SELF_SEGMENT = new BasicPathSegment(SELF_NAME);
- /**
- * 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 );
+ /**
+ * Singleton instance of the path segment referencing a parent, provided as a convenience.
+ */
+ public static final Path.Segment PARENT_SEGMENT = new BasicPathSegment(PARENT_NAME);
- /**
- * 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 the number of segments in this path.
+ *
+ * @return the number of path segments
+ */
+ public int size();
- /**
- * 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 represents the root path.
+ *
+ * @return true if this path is the root path, or false otherwise
+ */
+ public boolean isRoot();
- /**
- * 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();
+ /**
+ * 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 );
- /**
- * 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();
+ /**
+ * 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 );
- /**
- * 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();
+ /**
+ * 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 );
- /**
- * 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 );
+ /**
+ * 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();
- /**
- * 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 );
+ /**
+ * 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 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 );
+ /**
+ * 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();
- /**
- * 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();
+ /**
+ * 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();
- /**
- * 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 );
+ /**
+ * 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 );
- /**
- * 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 );
+ /**
+ * 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 );
- /**
- * 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 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 );
- /**
- * Get the last segment in this path.
- *
- * @return the last segment, or null if the path is empty
- */
- public Segment getLastSegment();
+ /**
+ * 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();
- /**
- * 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 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 );
- /**
- * Return a new path consisting of the segments starting at <code>beginIndex</code> index (inclusive). This is equivalent to
- * calling <code>path.subpath(beginIndex,path.size()-1)</code>.
- *
- * @param beginIndex the beginning index, inclusive.
- * @return the specified subpath
- * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative or larger than the length of this
- * <code>Path</code> object
- */
- public Path subpath( int beginIndex );
+ /**
+ * 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 );
- /**
- * Return a new path consisting of the segments between the <code>beginIndex</code> index (inclusive) and the
- * <code>endIndex</code> index (exclusive).
- *
- * @param beginIndex the beginning index, inclusive.
- * @param endIndex the ending index, exclusive.
- * @return the specified subpath
- * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative, or <code>endIndex</code> is larger
- * than the length of this <code>Path</code> object, or <code>beginIndex</code> is larger than
- * <code>endIndex</code>.
- */
- public Path subpath( int beginIndex,
- int endIndex );
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- public Iterator<Segment> iterator();
+ /**
+ * Get the last segment in this path.
+ *
+ * @return the last segment, or null if the path is empty
+ */
+ public Segment getLastSegment();
- /**
- * 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 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 );
- /**
- * Get an unmodifiable list of the path segments.
- *
- * @return the unmodifiable list of path segments; never null
- */
- public List<Segment> getSegmentsList();
+ /**
+ * Return a new path consisting of the segments starting at <code>beginIndex</code> index (inclusive). This is equivalent to
+ * calling <code>path.subpath(beginIndex,path.size()-1)</code>.
+ *
+ * @param beginIndex the beginning index, inclusive.
+ * @return the specified subpath
+ * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative or larger than the length of this
+ * <code>Path</code> object
+ */
+ public Path subpath( int beginIndex );
- /**
- * 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();
+ /**
+ * Return a new path consisting of the segments between the <code>beginIndex</code> index (inclusive) and the
+ * <code>endIndex</code> index (exclusive).
+ *
+ * @param beginIndex the beginning index, inclusive.
+ * @param endIndex the ending index, exclusive.
+ * @return the specified subpath
+ * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative, or <code>endIndex</code> is larger
+ * than the length of this <code>Path</code> object, or <code>beginIndex</code> is larger than <code>endIndex</code>.
+ */
+ public Path subpath( int beginIndex, int endIndex );
- /**
- * 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 );
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator<Segment> iterator();
- /**
- * Get the string form of the path, using the supplied namespace registry to convert the names' namespace URIs to prefixes.
- * The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
- *
- * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
- * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
- * @return the encoded string
- * @throws IllegalArgumentException if the namespace registry is null
- * @see #getString(NamespaceRegistry,TextEncoder)
- */
- public String getString( NamespaceRegistry namespaceRegistry );
+ /**
+ * 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 the encoded string form of the path, using the supplied namespace registry to convert the names' namespace URIs to
- * prefixes and the supplied encoder to encode characters in each of the path segments.
- *
- * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
- * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
- * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
- * @return the encoded string
- * @throws IllegalArgumentException if the namespace registry is null
- * @see #getString(NamespaceRegistry)
- */
- public String getString( NamespaceRegistry namespaceRegistry,
- TextEncoder encoder );
+ /**
+ * Get an unmodifiable list of the path segments.
+ *
+ * @return the unmodifiable list of path segments; never null
+ */
+ public List<Segment> getSegmentsList();
+ /**
+ * Get the string form of the path. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the
+ * path segments.
+ *
+ * @return the encoded string
+ * @see #getString(TextEncoder)
+ */
+ public String getString();
+
+ /**
+ * Get the encoded string form of the path, using the supplied encoder to encode characters in each of the path segments.
+ *
+ * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
+ * @return the encoded string
+ * @see #getString()
+ */
+ public String getString( TextEncoder encoder );
+
+ /**
+ * Get the string form of the path, using the supplied namespace registry to convert the names' namespace URIs to prefixes.
+ * The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
+ *
+ * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+ * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
+ * @return the encoded string
+ * @throws IllegalArgumentException if the namespace registry is null
+ * @see #getString(NamespaceRegistry,TextEncoder)
+ */
+ public String getString( NamespaceRegistry namespaceRegistry );
+
+ /**
+ * Get the encoded string form of the path, using the supplied namespace registry to convert the names' namespace URIs to
+ * prefixes and the supplied encoder to encode characters in each of the path segments.
+ *
+ * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+ * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
+ * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
+ * @return the encoded string
+ * @throws IllegalArgumentException if the namespace registry is null
+ * @see #getString(NamespaceRegistry)
+ */
+ public String getString( NamespaceRegistry namespaceRegistry, TextEncoder encoder );
+
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -21,7 +21,7 @@
*/
package org.jboss.dna.spi.graph;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
/**
* A factory for creating {@link Path paths}. This interface extends the {@link ValueFactory} generic interface and adds specific
@@ -32,148 +32,141 @@
*/
public interface PathFactory extends ValueFactory<Path> {
- /**
- * Create an absolute root path. Subsequent calls will always return the same instance.
- *
- * @return the new path
- */
- Path create();
+ /**
+ * Create an absolute root path. Subsequent calls will always return the same instance.
+ *
+ * @return the new path
+ */
+ Path create();
- /**
- * 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 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 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 an empty relative path (i.e., equivalent to {@link #createRelativePath(Path.Segment...) createRelativePath}({@link Path#SELF_SEGMENT})).
- * Subsequent calls will always return the same instance.
- *
- * @return the new path
- */
- Path createRelativePath();
+ /**
+ * Create an empty relative path (i.e., equivalent to {@link #createRelativePath(Path.Segment...) createRelativePath}({@link Path#SELF_SEGMENT})).
+ * Subsequent calls will always return the same instance.
+ *
+ * @return the new path
+ */
+ Path createRelativePath();
- /**
- * Create a relative path with the supplied segment names, in order. If no segments are provided, the result will be the root
- * path.
- *
- * @param segmentNames the names of the segments
- * @return the new path
- * @throws IllegalArgumentException if at least one segment name is provided and if any of the supplied segment names are null
- */
- Path createRelativePath( Name... segmentNames );
+ /**
+ * Create a relative path with the supplied segment names, in order. If no segments are provided, the result will be the root
+ * path.
+ *
+ * @param segmentNames the names of the segments
+ * @return the new path
+ * @throws IllegalArgumentException if at least one segment name is provided and if any of the supplied segment names are null
+ */
+ Path createRelativePath( Name... segmentNames );
- /**
- * Create a relative path with the supplied segments, in order. If no segments are provided, the result will be the root path.
- *
- * @param segments the segments
- * @return the new path
- * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
- */
- Path createRelativePath( Path.Segment... segments );
+ /**
+ * Create a relative path with the supplied segments, in order. If no segments are provided, the result will be the root path.
+ *
+ * @param segments the segments
+ * @return the new path
+ * @throws IllegalArgumentException if at least one segment is provided and if any of the supplied segments are null
+ */
+ Path createRelativePath( 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.
+ *
+ * @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 segmentNames the names of the segments that are to be appended, in order, to the parent path
+ * @return the new path
+ * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
+ * any of the supplied segment names are null
+ */
+ Path create( Path parentPath, Name... segmentNames );
- /**
- * Create a path by appending the supplied names to the parent path. If no names are appended, the parent path is returned.
- *
- * @param parentPath the path that is to provide the basis for the new path
- * @param segments the segments that are to be appended, in order, to the parent path
- * @return the new path
- * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
- * any of the supplied segment names are null
- */
- Path create( Path parentPath,
- Path.Segment... segments );
+ /**
+ * Create a path by appending the supplied names to the parent path. If no names are appended, the parent path is returned.
+ *
+ * @param parentPath the path that is to provide the basis for the new path
+ * @param segments the segments that are to be appended, in order, to the parent path
+ * @return the new path
+ * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
+ * any of the supplied segment names are null
+ */
+ Path create( Path parentPath, 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 <code>null</code> or the value could not be created
- * from the supplied string
- */
- Path.Segment createSegment( String segmentName );
+ /**
+ * 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 <code>null</code> or the value could not be created
+ * from the supplied string
+ */
+ Path.Segment createSegment( String segmentName );
- /**
- * Create a path segment given the supplied segment name. The resulting segment will have no index.
- *
- * @param segmentName the name of the segment
- * @param encoder the encoder that should be used to decode the qualified name
- * @return the segment
- * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created
- * from the supplied string
- */
- Path.Segment createSegment( String segmentName,
- TextEncoder encoder );
+ /**
+ * Create a path segment given the supplied segment name. The resulting segment will have no index.
+ *
+ * @param segmentName the name of the segment
+ * @param decoder the decoder that should be used to decode the qualified name
+ * @return the segment
+ * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created
+ * from the supplied string
+ */
+ Path.Segment createSegment( String segmentName, TextDecoder decoder );
- /**
- * Create a path segment given the supplied segment name and index.
- *
- * @param segmentName the name of the new segment
- * @param index the index of the new segment
- * @return the segment
- * @throws IllegalArgumentException if the segment name reference is <code>null</code> or if the index is invalid
- */
- Path.Segment createSegment( String segmentName,
- int index );
+ /**
+ * Create a path segment given the supplied segment name and index.
+ *
+ * @param segmentName the name of the new segment
+ * @param index the index of the new segment
+ * @return the segment
+ * @throws IllegalArgumentException if the segment name reference is <code>null</code> or if the index is invalid
+ */
+ Path.Segment createSegment( String segmentName, int index );
- /**
- * Create a path segment given the supplied segment name. The resulting segment will have no index.
- *
- * @param segmentName the name of the segment
- * @return the segment
- * @throws IllegalArgumentException if the segment name reference is null
- */
- Path.Segment createSegment( Name segmentName );
+ /**
+ * Create a path segment given the supplied segment name. 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 );
+ /**
+ * 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 );
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueComparators.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueComparators.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueComparators.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -284,7 +284,7 @@
protected static final ValueFactory<String> getStringValueFactory() {
// No locking is required, because it doesn't matter if we create several instances during initialization ...
if (STRING_VALUE_FACTORY == null) {
- STRING_VALUE_FACTORY = new StringValueFactory(Path.NO_OP_ENCODER);
+ STRING_VALUE_FACTORY = new StringValueFactory(Path.NO_OP_DECODER, Path.NO_OP_ENCODER);
}
return STRING_VALUE_FACTORY;
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/ValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -28,45 +28,52 @@
import java.net.URI;
import java.util.Calendar;
import java.util.Date;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.text.TextEncoder;
/**
* A factory for {@link Property} values. Some of the methods may throw a {@link ValueFormatException} if the parameter supplied
* to the <code>create(...)</code> method cannot be converted to the {@link #getPropertyType() factory's type}.
+ *
* @author Randall Hauch
* @param <T> the type of value to create
*/
public interface ValueFactory<T> {
+ static final TextDecoder DEFAULT_DECODER = Path.NO_OP_DECODER;
static final TextEncoder DEFAULT_ENCODER = Path.NO_OP_ENCODER;
/**
* Get the {@link PropertyType type} of values created by this factory.
+ *
* @return the value type; never null
*/
PropertyType getPropertyType();
/**
* Create a value from a string, using no decoding.
+ *
* @param value the string from which the value is to be created
* @return the value, or null if the supplied string is null
* @throws ValueFormatException if the value could not be created from the supplied string
- * @see #create(String, TextEncoder)
+ * @see #create(String, TextDecoder)
*/
T create( String value ) throws ValueFormatException;
/**
* Create a value from a string, using the supplied decoder.
+ *
* @param value the string from which the value is to be created
- * @param decoder the decoder that should be used; if null, the {@link #DEFAULT_ENCODER default decoder} is used
+ * @param decoder the decoder that should be used; if null, the {@link #DEFAULT_DECODER default decoder} is used
* @return the value, or null if the supplied string is null
* @throws ValueFormatException if the value could not be created from the supplied string
* @see #create(String)
*/
- T create( String value, TextEncoder decoder ) throws ValueFormatException;
+ T create( String value, TextDecoder decoder ) throws ValueFormatException;
/**
* Create a value from an integer.
+ *
* @param value the integer from which the value is to be created
* @return the value; never null
* @throws ValueFormatException if the value could not be created from the supplied integer
@@ -75,6 +82,7 @@
/**
* Create a long from a string.
+ *
* @param value the string from which the long is to be created
* @return the value; never null
* @throws ValueFormatException if the value could not be created from the supplied long
@@ -83,6 +91,7 @@
/**
* Create a boolean from a string.
+ *
* @param value the boolean from which the value is to be created
* @return the value; never null
* @throws ValueFormatException if the value could not be created from the supplied boolean
@@ -91,6 +100,7 @@
/**
* Create a value from a float.
+ *
* @param value the float from which the value is to be created
* @return the value; never null
* @throws ValueFormatException if the value could not be created from the supplied float
@@ -99,6 +109,7 @@
/**
* Create a value from a double.
+ *
* @param value the double from which the value is to be created
* @return the value; never null
* @throws ValueFormatException if the value could not be created from the supplied double
@@ -107,6 +118,7 @@
/**
* Create a value from a decimal.
+ *
* @param value the decimal from which the value is to be created
* @return the value, or null if the supplied decimal is null
* @throws ValueFormatException if the value could not be created from the supplied decimal
@@ -115,6 +127,7 @@
/**
* Create a value from a Calendar instance.
+ *
* @param value the Calendar instance from which the value is to be created
* @return the value, or null if the supplied Calendar is null
* @throws ValueFormatException if the value could not be created from the supplied Calendar object
@@ -123,6 +136,7 @@
/**
* Create a value from a date.
+ *
* @param value the date from which the value is to be created
* @return the value, or null if the supplied date is null
* @throws ValueFormatException if the value could not be created from the supplied date
@@ -131,6 +145,7 @@
/**
* Create a value from a name.
+ *
* @param value the name from which the value is to be created
* @return the value, or null if the supplied name is null
* @throws ValueFormatException if the value could not be created from the supplied name
@@ -139,6 +154,7 @@
/**
* Create a value from a path.
+ *
* @param value the path from which the value is to be created
* @return the value, or null if the supplied path is null
* @throws ValueFormatException if the value could not be created from the supplied path
@@ -147,6 +163,7 @@
/**
* Create a value from a reference.
+ *
* @param value the reference from which the value is to be created
* @return the value, or null if the supplied reference is null
* @throws ValueFormatException if the value could not be created from the supplied reference
@@ -155,6 +172,7 @@
/**
* Create a value from a URI.
+ *
* @param value the URI from which the value is to be created
* @return the value, or null if the supplied URI is null
* @throws ValueFormatException if the value could not be created from the supplied URI
@@ -163,6 +181,7 @@
/**
* Create a value from the binary content given by the supplied array.
+ *
* @param value the content to be used to create the value
* @return the value, or null if the supplied stream is null
* @throws ValueFormatException if the value could not be created from the supplied byte array
@@ -171,6 +190,7 @@
/**
* Create a value from the binary content given by the supplied stream.
+ *
* @param stream the stream containing the content to be used to create the value
* @param approximateLength the approximate length of the content (in bytes)
* @return the value, or null if the supplied stream is null
@@ -181,6 +201,7 @@
/**
* Create a value from a the binary content given by the supplied reader.
+ *
* @param reader the reader containing the content to be used to create the value
* @param approximateLength the approximate length of the content (in bytes)
* @return the value, or null if the supplied string is null
@@ -192,7 +213,8 @@
/**
* Create a value from the specified information by determining which other <code>create</code> method applies and
* delegating to that method. Note that this method only will call <code>create</code> methods that take a single parameter;
- * so this excludes {@link #create(InputStream, int)}, {@link #create(Reader, int)} and {@link #create(String, TextEncoder)}.
+ * so this excludes {@link #create(InputStream, int)}, {@link #create(Reader, int)} and {@link #create(String, TextDecoder)}.
+ *
* @param value the value
* @return the new value, or null if the supplied parameter is null
* @throws ValueFormatException if the value could not be created from the supplied stream
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/AbstractValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/AbstractValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/AbstractValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,7 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -40,20 +40,21 @@
/**
* Abstract {@link ValueFactory}.
+ *
* @author Randall Hauch
* @param <T> the property type
*/
@Immutable
public abstract class AbstractValueFactory<T> implements ValueFactory<T> {
- private final TextEncoder encoder;
+ private final TextDecoder decoder;
private final PropertyType propertyType;
private final ValueFactory<String> stringValueFactory;
- protected AbstractValueFactory( PropertyType type, TextEncoder encoder, ValueFactory<String> stringValueFactory ) {
+ protected AbstractValueFactory( PropertyType type, TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
ArgCheck.isNotNull(type, "type");
this.propertyType = type;
- this.encoder = encoder != null ? encoder : DEFAULT_ENCODER;
+ this.decoder = decoder != null ? decoder : DEFAULT_DECODER;
this.stringValueFactory = stringValueFactory;
}
@@ -65,20 +66,22 @@
}
/**
- * Get the text encoder/decoder.
- * @return encoder/decoder
+ * Get the text decoder.
+ *
+ * @return the decoder
*/
- public TextEncoder getEncoder() {
- return this.encoder;
+ public TextDecoder getDecoder() {
+ return this.decoder;
}
/**
- * Utility method to obtain either the supplied encoder (if not null) or this factory's {@link #getEncoder() encoder}.
- * @param encoder the encoder, which may be null if this factory's {@link #getEncoder() is to be used}
- * @return the encoder; never null
+ * Utility method to obtain either the supplied decoder (if not null) or this factory's {@link #getDecoder() decoder}.
+ *
+ * @param decoder the decoder, which may be null if this factory's {@link #getDecoder() is to be used}
+ * @return the decoder; never null
*/
- protected TextEncoder getEncoder( TextEncoder encoder ) {
- return encoder != null ? encoder : this.getEncoder();
+ protected TextDecoder getDecoder( TextDecoder decoder ) {
+ return decoder != null ? decoder : this.getDecoder();
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BooleanValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BooleanValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BooleanValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,7 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -40,13 +40,14 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#BOOLEAN} values.
+ *
* @author Randall Hauch
*/
@Immutable
public class BooleanValueFactory extends AbstractValueFactory<Boolean> {
- public BooleanValueFactory( TextEncoder encoder, ValueFactory<String> stringValueFactory ) {
- super(PropertyType.BOOLEAN, encoder, stringValueFactory);
+ public BooleanValueFactory( TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
+ super(PropertyType.BOOLEAN, decoder, stringValueFactory);
}
/**
@@ -60,9 +61,9 @@
/**
* {@inheritDoc}
*/
- public Boolean create( String value, TextEncoder decoder ) {
+ public Boolean create( String value, TextDecoder decoder ) {
// this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
- return create(getEncoder(decoder).decode(value));
+ return create(getDecoder(decoder).decode(value));
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DecimalValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DecimalValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DecimalValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,7 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -40,13 +40,14 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#DECIMAL} values.
+ *
* @author Randall Hauch
*/
@Immutable
public class DecimalValueFactory extends AbstractValueFactory<BigDecimal> {
- public DecimalValueFactory( TextEncoder encoder, ValueFactory<String> stringValueFactory ) {
- super(PropertyType.DECIMAL, encoder, stringValueFactory);
+ public DecimalValueFactory( TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
+ super(PropertyType.DECIMAL, decoder, stringValueFactory);
}
/**
@@ -64,9 +65,9 @@
/**
* {@inheritDoc}
*/
- public BigDecimal create( String value, TextEncoder decoder ) {
+ public BigDecimal create( String value, TextDecoder decoder ) {
// this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
- return create(getEncoder(decoder).decode(value.trim()));
+ return create(getDecoder(decoder).decode(value.trim()));
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DoubleValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DoubleValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DoubleValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,7 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -40,13 +40,14 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#DOUBLE} values.
+ *
* @author Randall Hauch
*/
@Immutable
public class DoubleValueFactory extends AbstractValueFactory<Double> {
- public DoubleValueFactory( TextEncoder encoder, ValueFactory<String> stringValueFactory ) {
- super(PropertyType.DOUBLE, encoder, stringValueFactory);
+ public DoubleValueFactory( TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
+ super(PropertyType.DOUBLE, decoder, stringValueFactory);
}
/**
@@ -64,9 +65,9 @@
/**
* {@inheritDoc}
*/
- public Double create( String value, TextEncoder decoder ) {
+ public Double create( String value, TextDecoder decoder ) {
// this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
- return create(getEncoder(decoder).decode(value));
+ return create(getDecoder(decoder).decode(value));
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/InMemoryBinaryValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/InMemoryBinaryValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/InMemoryBinaryValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -30,7 +30,7 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.util.IoUtil;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Binary;
@@ -43,6 +43,7 @@
/**
* Teh standard {@link ValueFactory} for {@link PropertyType#BINARY} values.
+ *
* @author Randall Hauch
*/
@Immutable
@@ -50,8 +51,8 @@
private static final String CHAR_SET_NAME = "UTF-8";
- public InMemoryBinaryValueFactory( TextEncoder encoder, ValueFactory<String> stringValueFactory ) {
- super(PropertyType.BINARY, encoder, stringValueFactory);
+ public InMemoryBinaryValueFactory( TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
+ super(PropertyType.BINARY, decoder, stringValueFactory);
}
/**
@@ -69,9 +70,9 @@
/**
* {@inheritDoc}
*/
- public Binary create( String value, TextEncoder decoder ) throws ValueFormatException {
+ public Binary create( String value, TextDecoder decoder ) throws ValueFormatException {
if (value == null) return null;
- return create(getEncoder(decoder).decode(value));
+ return create(getDecoder(decoder).decode(value));
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,7 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.DateTime;
import org.jboss.dna.spi.graph.DateTimeFactory;
@@ -42,13 +42,14 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#DATE} values.
+ *
* @author Randall Hauch
*/
@Immutable
public class JodaDateTimeValueFactory extends AbstractValueFactory<DateTime> implements DateTimeFactory {
- public JodaDateTimeValueFactory( TextEncoder encoder, ValueFactory<String> stringValueFactory ) {
- super(PropertyType.DATE, encoder, stringValueFactory);
+ public JodaDateTimeValueFactory( TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
+ super(PropertyType.DATE, decoder, stringValueFactory);
}
/**
@@ -66,9 +67,9 @@
/**
* {@inheritDoc}
*/
- public DateTime create( String value, TextEncoder decoder ) {
+ public DateTime create( String value, TextDecoder decoder ) {
// this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
- return create(getEncoder(decoder).decode(value));
+ return create(getDecoder(decoder).decode(value));
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/LongValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/LongValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/LongValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,7 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -40,13 +40,14 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#LONG} values.
+ *
* @author Randall Hauch
*/
@Immutable
public class LongValueFactory extends AbstractValueFactory<Long> {
- public LongValueFactory( TextEncoder encoder, ValueFactory<String> stringValueFactory ) {
- super(PropertyType.LONG, encoder, stringValueFactory);
+ public LongValueFactory( TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
+ super(PropertyType.LONG, decoder, stringValueFactory);
}
/**
@@ -64,9 +65,9 @@
/**
* {@inheritDoc}
*/
- public Long create( String value, TextEncoder decoder ) {
+ public Long create( String value, TextDecoder decoder ) {
// this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
- return create(getEncoder(decoder).decode(value));
+ return create(getDecoder(decoder).decode(value));
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/NameValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/NameValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/NameValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -31,7 +31,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Name;
@@ -46,256 +46,222 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#NAME} values.
- *
+ *
* @author Randall Hauch
*/
@Immutable
public class NameValueFactory extends AbstractValueFactory<Name> implements NameFactory {
- // Non-escaped pattern: (\{([^}]*)\})?(.*)
- protected static final String FULLY_QUALFIED_NAME_PATTERN_STRING = "\\{([^}]*)\\}(.*)";
- protected static final Pattern FULLY_QUALIFIED_NAME_PATTERN = Pattern.compile(FULLY_QUALFIED_NAME_PATTERN_STRING);
+ // Non-escaped pattern: (\{([^}]*)\})?(.*)
+ protected static final String FULLY_QUALFIED_NAME_PATTERN_STRING = "\\{([^}]*)\\}(.*)";
+ protected static final Pattern FULLY_QUALIFIED_NAME_PATTERN = Pattern.compile(FULLY_QUALFIED_NAME_PATTERN_STRING);
- // Original pattern: (([^:/]*):)?(.*)
- private static final String PREFIXED_NAME_PATTERN_STRING = "(([^:/]*):)?(.*)";
- private static final Pattern PREFIXED_NAME_PATTERN = Pattern.compile(PREFIXED_NAME_PATTERN_STRING);
+ // Original pattern: (([^:/]*):)?(.*)
+ private static final String PREFIXED_NAME_PATTERN_STRING = "(([^:/]*):)?(.*)";
+ private static final Pattern PREFIXED_NAME_PATTERN = Pattern.compile(PREFIXED_NAME_PATTERN_STRING);
- private final NamespaceRegistry namespaceRegistry;
+ private final NamespaceRegistry namespaceRegistry;
- public NameValueFactory( NamespaceRegistry namespaceRegistry,
- TextEncoder encoder,
- ValueFactory<String> stringValueFactory ) {
- super(PropertyType.NAME, encoder, stringValueFactory);
- ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
- this.namespaceRegistry = namespaceRegistry;
- }
+ public NameValueFactory( NamespaceRegistry namespaceRegistry, TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
+ super(PropertyType.NAME, decoder, stringValueFactory);
+ ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
+ this.namespaceRegistry = namespaceRegistry;
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( String value ) {
- return create(value, getEncoder());
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( String value ) {
+ return create(value, getDecoder());
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( String value,
- TextEncoder decoder ) throws ValueFormatException {
- if (value == null) return null;
- if (decoder == null) decoder = getEncoder();
- try {
- // First see whether the value fits the internal pattern ...
- Matcher matcher = FULLY_QUALIFIED_NAME_PATTERN.matcher(value);
- if (matcher.matches()) {
- String namespaceUri = matcher.group(1);
- String localName = matcher.group(2);
- // Decode the parts ...
- namespaceUri = decoder.decode(namespaceUri);
- localName = decoder.decode(localName);
- return new BasicName(namespaceUri, localName);
- }
- // Second, see whether the value fits the prefixed name pattern ...
- matcher = PREFIXED_NAME_PATTERN.matcher(value);
- if (matcher.matches()) {
- String prefix = matcher.group(2);
- String localName = matcher.group(3);
- // Decode the parts ...
- prefix = prefix == null ? "" : decoder.decode(prefix);
- localName = decoder.decode(localName);
- // Look for a namespace match ...
- String namespaceUri = this.namespaceRegistry.getNamespaceForPrefix(prefix);
- // Fail if no namespace is found ...
- if (namespaceUri == null) {
- throw new NamespaceException(SpiI18n.noNamespaceRegisteredForPrefix.text(prefix));
- }
- return new BasicName(namespaceUri, localName);
- }
- } catch (Throwable t) {
- throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(),
- String.class.getSimpleName(),
- value), t);
- }
- throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(),
- String.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( String value, TextDecoder decoder ) throws ValueFormatException {
+ if (value == null) return null;
+ if (decoder == null) decoder = getDecoder();
+ try {
+ // First see whether the value fits the internal pattern ...
+ Matcher matcher = FULLY_QUALIFIED_NAME_PATTERN.matcher(value);
+ if (matcher.matches()) {
+ String namespaceUri = matcher.group(1);
+ String localName = matcher.group(2);
+ // Decode the parts ...
+ namespaceUri = decoder.decode(namespaceUri);
+ localName = decoder.decode(localName);
+ return new BasicName(namespaceUri, localName);
+ }
+ // Second, see whether the value fits the prefixed name pattern ...
+ matcher = PREFIXED_NAME_PATTERN.matcher(value);
+ if (matcher.matches()) {
+ String prefix = matcher.group(2);
+ String localName = matcher.group(3);
+ // Decode the parts ...
+ prefix = prefix == null ? "" : decoder.decode(prefix);
+ localName = decoder.decode(localName);
+ // Look for a namespace match ...
+ String namespaceUri = this.namespaceRegistry.getNamespaceForPrefix(prefix);
+ // Fail if no namespace is found ...
+ if (namespaceUri == null) {
+ throw new NamespaceException(SpiI18n.noNamespaceRegisteredForPrefix.text(prefix));
+ }
+ return new BasicName(namespaceUri, localName);
+ }
+ } catch (Throwable t) {
+ throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(), String.class.getSimpleName(), value), t);
+ }
+ throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(), String.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( String namespaceUri,
- String localName ) {
- return create(namespaceUri, localName, getEncoder());
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( String namespaceUri, String localName ) {
+ return create(namespaceUri, localName, getDecoder());
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( String namespaceUri,
- String localName,
- TextEncoder decoder ) {
- ArgCheck.isNotEmpty(localName, "localName");
- if (decoder == null) decoder = getEncoder();
- namespaceUri = namespaceUri != null ? decoder.decode(namespaceUri.trim()) : null;
- localName = decoder.decode(localName.trim());
- return new BasicName(namespaceUri, localName);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( String namespaceUri, String localName, TextDecoder decoder ) {
+ ArgCheck.isNotEmpty(localName, "localName");
+ if (decoder == null) decoder = getDecoder();
+ namespaceUri = namespaceUri != null ? decoder.decode(namespaceUri.trim()) : null;
+ localName = decoder.decode(localName.trim());
+ return new BasicName(namespaceUri, localName);
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( int value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( int value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( long value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( long value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( boolean value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( boolean value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( float value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( float value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( double value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( double value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( BigDecimal value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( BigDecimal value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( Calendar value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( Calendar value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( Date value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( Date value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( Name value ) {
- return value;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( Name value ) {
+ return value;
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( Path value ) throws ValueFormatException {
- if (value == null) return null;
- if (!value.isAbsolute() && value.size() == 1) {
- // A relative name of length 1 is converted to a name
- return value.getSegment(0).getName();
- }
- throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(),
- Path.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( Path value ) throws ValueFormatException {
+ if (value == null) return null;
+ if (!value.isAbsolute() && value.size() == 1) {
+ // A relative name of length 1 is converted to a name
+ return value.getSegment(0).getName();
+ }
+ throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(), Path.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( Reference value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Reference.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( Reference value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Reference.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( URI value ) throws ValueFormatException {
- if (value == null) return null;
- String asciiString = value.toASCIIString();
- // Remove any leading "./" ...
- if (asciiString.startsWith("./") && asciiString.length() > 2) {
- asciiString = asciiString.substring(2);
- }
- if (asciiString.indexOf('/') == -1) {
- return create(asciiString);
- }
- throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(),
- Path.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( URI value ) throws ValueFormatException {
+ if (value == null) return null;
+ String asciiString = value.toASCIIString();
+ // Remove any leading "./" ...
+ if (asciiString.startsWith("./") && asciiString.length() > 2) {
+ asciiString = asciiString.substring(2);
+ }
+ if (asciiString.indexOf('/') == -1) {
+ return create(asciiString);
+ }
+ throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(), Path.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( byte[] value ) throws ValueFormatException {
- // First attempt to create a string from the value, then a long from the string ...
- return create(getStringValueFactory().create(value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( byte[] value ) throws ValueFormatException {
+ // First attempt to create a string from the value, then a long from the string ...
+ return create(getStringValueFactory().create(value));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( InputStream stream,
- int approximateLength ) throws IOException, ValueFormatException {
- // First attempt to create a string from the value, then a double from the string ...
- return create(getStringValueFactory().create(stream, approximateLength));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( InputStream stream, int approximateLength ) throws IOException, ValueFormatException {
+ // First attempt to create a string from the value, then a double from the string ...
+ return create(getStringValueFactory().create(stream, approximateLength));
+ }
- /**
- * {@inheritDoc}
- */
- public Name create( Reader reader,
- int approximateLength ) throws IOException, ValueFormatException {
- // First attempt to create a string from the value, then a double from the string ...
- return create(getStringValueFactory().create(reader, approximateLength));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Name create( Reader reader, int approximateLength ) throws IOException, ValueFormatException {
+ // First attempt to create a string from the value, then a double from the string ...
+ return create(getStringValueFactory().create(reader, approximateLength));
+ }
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.jboss.dna.spi.graph.NameFactory#getNamespaceRegistry()
- */
- public NamespaceRegistry getNamespaceRegistry() {
- return namespaceRegistry;
- }
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.jboss.dna.spi.graph.NameFactory#getNamespaceRegistry()
+ */
+ public NamespaceRegistry getNamespaceRegistry() {
+ return namespaceRegistry;
+ }
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/ObjectValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/ObjectValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/ObjectValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,7 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.spi.graph.Binary;
import org.jboss.dna.spi.graph.Name;
@@ -41,6 +41,7 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#OBJECT} values.
+ *
* @author Randall Hauch
*/
@Immutable
@@ -48,8 +49,8 @@
private final ValueFactory<Binary> binaryValueFactory;
- public ObjectValueFactory( TextEncoder encoder, ValueFactory<String> stringValueFactory, ValueFactory<Binary> binaryValueFactory ) {
- super(PropertyType.OBJECT, encoder, stringValueFactory);
+ public ObjectValueFactory( TextDecoder decoder, ValueFactory<String> stringValueFactory, ValueFactory<Binary> binaryValueFactory ) {
+ super(PropertyType.OBJECT, decoder, stringValueFactory);
ArgCheck.isNotNull(binaryValueFactory, "binaryValueFactory");
this.binaryValueFactory = binaryValueFactory;
}
@@ -71,7 +72,7 @@
/**
* {@inheritDoc}
*/
- public Object create( String value, TextEncoder decoder ) {
+ public Object create( String value, TextDecoder decoder ) {
return this.getStringValueFactory().create(value, decoder);
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -32,7 +32,7 @@
import java.util.List;
import java.util.regex.Pattern;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Name;
@@ -53,446 +53,414 @@
@Immutable
public class PathValueFactory extends AbstractValueFactory<Path> implements PathFactory {
- /**
- * Regular expression used to identify the different segments in a path, using the standard '/' delimiter. The expression is
- * simply:
- *
- * <pre>
- * /
- * </pre>
- */
- protected static final Pattern DELIMITER_PATTERN = Pattern.compile("/");
+ /**
+ * Regular expression used to identify the different segments in a path, using the standard '/' delimiter. The expression is
+ * simply:
+ *
+ * <pre>
+ * /
+ * </pre>
+ */
+ protected static final Pattern DELIMITER_PATTERN = Pattern.compile("/");
- /**
- * Regular expression used to identify the different parts of a segment. The expression is
- *
- * <pre>
- * ([ˆ*:/\[\]|]+)(:([ˆ*:/\[\]|]+))?(\[(\d+)])?
- * </pre>
- *
- * where the first part is accessed with group 1, the second part is accessed with group 3, and the index is accessed with
- * group 5.
- */
- protected static final Pattern SEGMENT_PATTERN = Pattern.compile("([^:/]+)(:([^/\\[\\]]+))?(\\[(\\d+)])?");
+ /**
+ * Regular expression used to identify the different parts of a segment. The expression is
+ *
+ * <pre>
+ * ([ˆ*:/\[\]|]+)(:([ˆ*:/\[\]|]+))?(\[(\d+)])?
+ * </pre>
+ *
+ * where the first part is accessed with group 1, the second part is accessed with group 3, and the index is accessed with
+ * group 5.
+ */
+ protected static final Pattern SEGMENT_PATTERN = Pattern.compile("([^:/]+)(:([^/\\[\\]]+))?(\\[(\\d+)])?");
- private final ValueFactory<Name> nameValueFactory;
+ private final ValueFactory<Name> nameValueFactory;
- public PathValueFactory( TextEncoder encoder,
- ValueFactory<String> stringValueFactory,
- ValueFactory<Name> nameValueFactory ) {
- super(PropertyType.PATH, encoder, stringValueFactory);
- ArgCheck.isNotNull(nameValueFactory, "nameValueFactory");
- this.nameValueFactory = nameValueFactory;
- }
+ public PathValueFactory( TextDecoder decoder, ValueFactory<String> stringValueFactory, ValueFactory<Name> nameValueFactory ) {
+ super(PropertyType.PATH, decoder, stringValueFactory);
+ ArgCheck.isNotNull(nameValueFactory, "nameValueFactory");
+ this.nameValueFactory = nameValueFactory;
+ }
- /**
- * @return nameValueFactory
- */
- protected ValueFactory<Name> getNameValueFactory() {
- return this.nameValueFactory;
- }
+ /**
+ * @return nameValueFactory
+ */
+ protected ValueFactory<Name> getNameValueFactory() {
+ return this.nameValueFactory;
+ }
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.jboss.dna.spi.graph.PathFactory#create()
- */
- public Path create() {
- return BasicPath.ROOT;
- }
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.jboss.dna.spi.graph.PathFactory#create()
+ */
+ public Path create() {
+ return BasicPath.ROOT;
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( String value ) {
- return create(value, getEncoder());
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( String value ) {
+ return create(value, getDecoder());
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( final String value,
- TextEncoder decoder ) throws ValueFormatException {
- if (value == null) return null;
- if (decoder == null) decoder = getEncoder();
- String trimmedValue = value.trim();
- int length = trimmedValue.length();
- boolean absolute = false;
- if (length == 0) {
- return BasicPath.ROOT;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( final String value, TextDecoder decoder ) throws ValueFormatException {
+ if (value == null) return null;
+ String trimmedValue = value.trim();
+ int length = trimmedValue.length();
+ boolean absolute = false;
+ if (length == 0) {
+ return BasicPath.ROOT;
+ }
- // Remove the leading delimiter ...
- if (trimmedValue.charAt(0) == Path.DELIMITER) {
- trimmedValue = length > 1 ? trimmedValue.substring(1) : "";
- --length;
- absolute = true;
- }
- // remove the trailing delimiter ...
- if (length > 0 && trimmedValue.charAt(length - 1) == Path.DELIMITER) {
- trimmedValue = length > 1 ? trimmedValue.substring(0, length - 1) : "";
- length = trimmedValue.length();
- }
- if (length == 0) {
- return BasicPath.ROOT;
- }
+ // Remove the leading delimiter ...
+ if (trimmedValue.charAt(0) == Path.DELIMITER) {
+ trimmedValue = length > 1 ? trimmedValue.substring(1) : "";
+ --length;
+ absolute = true;
+ }
+ // remove the trailing delimiter ...
+ if (length > 0 && trimmedValue.charAt(length - 1) == Path.DELIMITER) {
+ trimmedValue = length > 1 ? trimmedValue.substring(0, length - 1) : "";
+ length = trimmedValue.length();
+ }
+ if (length == 0) {
+ return BasicPath.ROOT;
+ }
- // Parse the path into its segments ...
- List<Segment> segments = new ArrayList<Segment>();
- String[] pathSegments = DELIMITER_PATTERN.split(trimmedValue);
- if (pathSegments.length == 0) {
- throw new ValueFormatException(SpiI18n.validPathMayNotContainEmptySegment.text(value));
- }
- assert pathSegments.length != 0;
- for (String segment : pathSegments) {
- assert segment != null;
- segment = segment.trim();
- if (segment.length() == 0) {
- throw new ValueFormatException(SpiI18n.validPathMayNotContainEmptySegment.text(value));
- }
- // Create the name and add a segment with it ...
- segments.add(createSegment(segment, decoder));
- }
+ // Parse the path into its segments ...
+ List<Segment> segments = new ArrayList<Segment>();
+ String[] pathSegments = DELIMITER_PATTERN.split(trimmedValue);
+ if (pathSegments.length == 0) {
+ throw new ValueFormatException(SpiI18n.validPathMayNotContainEmptySegment.text(value));
+ }
+ if (decoder == null) decoder = getDecoder();
+ assert pathSegments.length != 0;
+ assert decoder != null;
+ for (String segment : pathSegments) {
+ assert segment != null;
+ segment = segment.trim();
+ if (segment.length() == 0) {
+ throw new ValueFormatException(SpiI18n.validPathMayNotContainEmptySegment.text(value));
+ }
+ // Create the name and add a segment with it ...
+ segments.add(createSegment(segment, decoder));
+ }
- // Create a path constructed from the supplied segments ...
- return new BasicPath(segments, absolute);
- }
+ // Create a path constructed from the supplied segments ...
+ return new BasicPath(segments, absolute);
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( int value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( int value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( long value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( long value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( boolean value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( boolean value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( float value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( float value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( double value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( double value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( BigDecimal value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( BigDecimal value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Calendar value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Calendar value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Date value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Date.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Date value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Name value ) {
- if (value == null) return null;
- List<Path.Segment> segments = new ArrayList<Path.Segment>(1);
- segments.add(new BasicPathSegment(value));
- return new BasicPath(segments, true);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Name value ) {
+ if (value == null) return null;
+ List<Path.Segment> segments = new ArrayList<Path.Segment>(1);
+ segments.add(new BasicPathSegment(value));
+ return new BasicPath(segments, true);
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Path value ) throws ValueFormatException {
- return value;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Path value ) throws ValueFormatException {
+ return value;
+ }
- /**
- * {@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( 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 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);
+ }
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.jboss.dna.spi.graph.PathFactory#createRelativePath()
- */
- public Path createRelativePath() {
- return BasicPath.SELF_PATH;
- }
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.jboss.dna.spi.graph.PathFactory#createRelativePath()
+ */
+ public Path createRelativePath() {
+ return BasicPath.SELF_PATH;
+ }
- /**
- * {@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( 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 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 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;
+ /**
+ * {@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());
- }
+ 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;
+ /**
+ * {@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());
- }
+ 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");
- if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
- if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
- return new BasicPathSegment(segmentName);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Segment createSegment( Name segmentName ) {
+ ArgCheck.isNotNull(segmentName, "segment name");
+ if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
+ if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
+ return new BasicPathSegment(segmentName);
+ }
- /**
- * {@inheritDoc}
- */
- public Segment createSegment( Name segmentName,
- int index ) {
- ArgCheck.isNotNull(segmentName, "segment name");
- if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
- if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
- return new BasicPathSegment(segmentName, index);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Segment createSegment( Name segmentName, int index ) {
+ ArgCheck.isNotNull(segmentName, "segment name");
+ if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
+ if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
+ return new BasicPathSegment(segmentName, index);
+ }
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.spi.graph.PathFactory#createSegment(java.lang.String)
- */
- public Segment createSegment( String segmentName ) {
- return createSegment(segmentName, getEncoder());
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.PathFactory#createSegment(java.lang.String)
+ */
+ public Segment createSegment( String segmentName ) {
+ return createSegment(segmentName, getDecoder());
+ }
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.jboss.dna.spi.graph.PathFactory#createSegment(java.lang.String, org.jboss.dna.common.text.TextEncoder)
- */
- public Segment createSegment( String segmentName,
- TextEncoder encoder ) {
- ArgCheck.isNotNull(segmentName, "segment name");
- if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
- if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
- int startBracketNdx = segmentName.indexOf('[');
- if (startBracketNdx < 0) {
- return new BasicPathSegment(this.nameValueFactory.create(segmentName));
- }
- int endBracketNdx = segmentName.indexOf(']', startBracketNdx);
- if (endBracketNdx < 0) {
- throw new IllegalArgumentException(SpiI18n.missingEndBracketInSegmentName.text(segmentName));
- }
- String ndx = segmentName.substring(startBracketNdx + 1, endBracketNdx);
- try {
- return new BasicPathSegment(this.nameValueFactory.create(segmentName.substring(0, startBracketNdx)),
- Integer.parseInt(ndx));
- } catch (NumberFormatException err) {
- throw new IllegalArgumentException(SpiI18n.invalidIndexInSegmentName.text(ndx, segmentName));
- }
- }
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.jboss.dna.spi.graph.PathFactory#createSegment(java.lang.String, org.jboss.dna.common.text.TextDecoder)
+ */
+ public Segment createSegment( String segmentName, TextDecoder decoder ) {
+ ArgCheck.isNotNull(segmentName, "segment name");
+ if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
+ if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
+ int startBracketNdx = segmentName.indexOf('[');
+ if (startBracketNdx < 0) {
+ return new BasicPathSegment(this.nameValueFactory.create(segmentName, decoder));
+ }
+ int endBracketNdx = segmentName.indexOf(']', startBracketNdx);
+ if (endBracketNdx < 0) {
+ throw new IllegalArgumentException(SpiI18n.missingEndBracketInSegmentName.text(segmentName));
+ }
+ String ndx = segmentName.substring(startBracketNdx + 1, endBracketNdx);
+ try {
+ return new BasicPathSegment(this.nameValueFactory.create(segmentName.substring(0, startBracketNdx), decoder), Integer.parseInt(ndx));
+ } catch (NumberFormatException err) {
+ throw new IllegalArgumentException(SpiI18n.invalidIndexInSegmentName.text(ndx, segmentName));
+ }
+ }
- /**
- * {@inheritDoc}
- */
- public Segment createSegment( String segmentName,
- int index ) {
- ArgCheck.isNotNull(segmentName, "segment name");
- if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
- if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
- return new BasicPathSegment(this.nameValueFactory.create(segmentName), index);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Segment createSegment( String segmentName, int index ) {
+ ArgCheck.isNotNull(segmentName, "segment name");
+ if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
+ if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
+ return new BasicPathSegment(this.nameValueFactory.create(segmentName), index);
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Reference value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
- Reference.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Reference value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Reference.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( URI value ) throws ValueFormatException {
- if (value == null) return null;
- String asciiString = value.toASCIIString();
- // Remove any leading "./" ...
- if (asciiString.startsWith("./") && asciiString.length() > 2) {
- asciiString = asciiString.substring(2);
- }
- if (asciiString.indexOf('/') == -1) {
- return create(asciiString);
- }
- throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(),
- Path.class.getSimpleName(),
- value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( URI value ) throws ValueFormatException {
+ if (value == null) return null;
+ String asciiString = value.toASCIIString();
+ // Remove any leading "./" ...
+ if (asciiString.startsWith("./") && asciiString.length() > 2) {
+ asciiString = asciiString.substring(2);
+ }
+ if (asciiString.indexOf('/') == -1) {
+ return create(asciiString);
+ }
+ throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(), Path.class.getSimpleName(), value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( byte[] value ) throws ValueFormatException {
- // First attempt to create a string from the value, then a long from the string ...
- return create(getStringValueFactory().create(value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( byte[] value ) throws ValueFormatException {
+ // First attempt to create a string from the value, then a long from the string ...
+ return create(getStringValueFactory().create(value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( InputStream stream,
- int approximateLength ) throws IOException, ValueFormatException {
- // First attempt to create a string from the value, then a double from the string ...
- return create(getStringValueFactory().create(stream, approximateLength));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( InputStream stream, int approximateLength ) throws IOException, ValueFormatException {
+ // First attempt to create a string from the value, then a double from the string ...
+ return create(getStringValueFactory().create(stream, approximateLength));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Reader reader,
- int approximateLength ) throws IOException, ValueFormatException {
- // First attempt to create a string from the value, then a double from the string ...
- return create(getStringValueFactory().create(reader, approximateLength));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Reader reader, int approximateLength ) throws IOException, ValueFormatException {
+ // First attempt to create a string from the value, then a double from the string ...
+ return create(getStringValueFactory().create(reader, approximateLength));
+ }
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/StandardValueFactories.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/StandardValueFactories.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/StandardValueFactories.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -28,6 +28,7 @@
import java.util.Iterator;
import java.util.Map;
import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.spi.graph.Binary;
@@ -42,6 +43,7 @@
/**
* The standard set of {@link ValueFactory value factories}.
+ *
* @author Randall Hauch
*/
@Immutable
@@ -63,28 +65,33 @@
private final Map<PropertyType, ValueFactory<?>> factories;
private final NamespaceRegistry namespaceRegistry;
+ private final TextDecoder decoder;
private final TextEncoder encoder;
/**
- * Create a standard set of value factories, using the {@link ValueFactory#DEFAULT_ENCODER default encoder/decoder}.
+ * Create a standard set of value factories, using the {@link ValueFactory#DEFAULT_DECODER default decoder}.
+ *
* @param namespaceRegistry the namespace registry
* @throws IllegalArgumentException if the namespace registry is null
*/
public StandardValueFactories( NamespaceRegistry namespaceRegistry ) {
- this(namespaceRegistry, null);
+ this(namespaceRegistry, null, null);
}
/**
* Create a standard set of value factories, using the supplied encoder/decoder.
+ *
* @param namespaceRegistry the namespace registry
+ * @param decoder the decoder that should be used; if null, the {@link ValueFactory#DEFAULT_DECODER default decoder} is used.
* @param encoder the encoder that should be used; if null, the {@link ValueFactory#DEFAULT_ENCODER default encoder} is used.
* @param extraFactories any extra factories that should be used; any factory will override the standard factories based upon
* the {@link ValueFactory#getPropertyType() factory's property type}.
* @throws IllegalArgumentException if the namespace registry is null
*/
- public StandardValueFactories( NamespaceRegistry namespaceRegistry, TextEncoder encoder, ValueFactory<?>... extraFactories ) {
+ public StandardValueFactories( NamespaceRegistry namespaceRegistry, TextDecoder decoder, TextEncoder encoder, ValueFactory<?>... extraFactories ) {
ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
this.namespaceRegistry = namespaceRegistry;
+ this.decoder = decoder != null ? decoder : ValueFactory.DEFAULT_DECODER;
this.encoder = encoder != null ? encoder : ValueFactory.DEFAULT_ENCODER;
Map<PropertyType, ValueFactory<?>> factories = new HashMap<PropertyType, ValueFactory<?>>();
@@ -95,18 +102,18 @@
}
// Now assign the members, using the factories in the map or (if null) the supplied default ...
- this.stringFactory = getFactory(factories, new StringValueFactory(this.encoder));
- this.binaryFactory = getFactory(factories, new InMemoryBinaryValueFactory(this.encoder, this.stringFactory));
- this.booleanFactory = getFactory(factories, new BooleanValueFactory(this.encoder, this.stringFactory));
- this.dateFactory = (DateTimeFactory)getFactory(factories, new JodaDateTimeValueFactory(this.encoder, this.stringFactory));
- this.decimalFactory = getFactory(factories, new DecimalValueFactory(this.encoder, this.stringFactory));
- this.doubleFactory = getFactory(factories, new DoubleValueFactory(this.encoder, this.stringFactory));
- this.longFactory = getFactory(factories, new LongValueFactory(this.encoder, this.stringFactory));
- this.nameFactory = (NameFactory)getFactory(factories, new NameValueFactory(this.namespaceRegistry, this.encoder, this.stringFactory));
- this.pathFactory = (PathFactory)getFactory(factories, new PathValueFactory(this.encoder, this.stringFactory, this.nameFactory));
- this.referenceFactory = getFactory(factories, new UuidReferenceValueFactory(this.encoder, this.stringFactory));
- this.uriFactory = getFactory(factories, new UriValueFactory(this.namespaceRegistry, this.encoder, this.stringFactory));
- this.objectFactory = getFactory(factories, new ObjectValueFactory(this.encoder, this.stringFactory, this.binaryFactory));
+ this.stringFactory = getFactory(factories, new StringValueFactory(this.decoder, this.encoder));
+ this.binaryFactory = getFactory(factories, new InMemoryBinaryValueFactory(this.decoder, this.stringFactory));
+ this.booleanFactory = getFactory(factories, new BooleanValueFactory(this.decoder, this.stringFactory));
+ this.dateFactory = (DateTimeFactory)getFactory(factories, new JodaDateTimeValueFactory(this.decoder, this.stringFactory));
+ this.decimalFactory = getFactory(factories, new DecimalValueFactory(this.decoder, this.stringFactory));
+ this.doubleFactory = getFactory(factories, new DoubleValueFactory(this.decoder, this.stringFactory));
+ this.longFactory = getFactory(factories, new LongValueFactory(this.decoder, this.stringFactory));
+ this.nameFactory = (NameFactory)getFactory(factories, new NameValueFactory(this.namespaceRegistry, this.decoder, this.stringFactory));
+ this.pathFactory = (PathFactory)getFactory(factories, new PathValueFactory(this.decoder, this.stringFactory, this.nameFactory));
+ this.referenceFactory = getFactory(factories, new UuidReferenceValueFactory(this.decoder, this.stringFactory));
+ this.uriFactory = getFactory(factories, new UriValueFactory(this.namespaceRegistry, this.decoder, this.stringFactory));
+ this.objectFactory = getFactory(factories, new ObjectValueFactory(this.decoder, this.stringFactory, this.binaryFactory));
// Wrap the factories with an unmodifiable ...
this.factories = Collections.unmodifiableMap(factories);
@@ -124,10 +131,10 @@
}
/**
- * @return encoder
+ * @return decoder
*/
- public TextEncoder getTextEncoder() {
- return this.encoder;
+ public TextDecoder getTextDecoder() {
+ return this.decoder;
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/StringValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/StringValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/StringValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -30,7 +30,9 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.common.util.IoUtil;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Name;
@@ -42,16 +44,28 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#STRING} values.
+ *
* @author Randall Hauch
*/
@Immutable
public class StringValueFactory extends AbstractValueFactory<String> {
- public StringValueFactory( TextEncoder encoder ) {
- super(PropertyType.STRING, encoder, null);
+ private final TextEncoder encoder;
+
+ public StringValueFactory( TextDecoder decoder, TextEncoder encoder ) {
+ super(PropertyType.STRING, decoder, null);
+ ArgCheck.isNotNull(encoder, "encoder");
+ this.encoder = encoder;
}
/**
+ * @return encoder
+ */
+ public TextEncoder getEncoder() {
+ return this.encoder;
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -69,9 +83,9 @@
/**
* {@inheritDoc}
*/
- public String create( String value, TextEncoder decoder ) {
+ public String create( String value, TextDecoder decoder ) {
if (value == null) return value;
- if (decoder == null) decoder = getEncoder();
+ if (decoder == null) decoder = getDecoder();
return decoder.decode(value);
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/UriValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/UriValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/UriValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -30,7 +30,7 @@
import java.util.Calendar;
import java.util.Date;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Name;
@@ -43,6 +43,7 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#URI} values.
+ *
* @author Randall Hauch
*/
@Immutable
@@ -50,8 +51,8 @@
private final NamespaceRegistry namespaceRegistry;
- public UriValueFactory( NamespaceRegistry namespaceRegistry, TextEncoder encoder, ValueFactory<String> stringValueFactory ) {
- super(PropertyType.URI, encoder, stringValueFactory);
+ public UriValueFactory( NamespaceRegistry namespaceRegistry, TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
+ super(PropertyType.URI, decoder, stringValueFactory);
ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
this.namespaceRegistry = namespaceRegistry;
}
@@ -71,9 +72,9 @@
/**
* {@inheritDoc}
*/
- public URI create( String value, TextEncoder decoder ) {
+ public URI create( String value, TextDecoder decoder ) {
// this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
- return create(getEncoder(decoder).decode(value));
+ return create(getDecoder(decoder).decode(value));
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/UuidReferenceValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/UuidReferenceValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/UuidReferenceValueFactory.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -30,7 +30,7 @@
import java.util.Date;
import java.util.UUID;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -41,13 +41,14 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#REFERENCE} values.
+ *
* @author Randall Hauch
*/
@Immutable
public class UuidReferenceValueFactory extends AbstractValueFactory<Reference> {
- public UuidReferenceValueFactory( TextEncoder encoder, ValueFactory<String> stringValueFactory ) {
- super(PropertyType.REFERENCE, encoder, stringValueFactory);
+ public UuidReferenceValueFactory( TextDecoder decoder, ValueFactory<String> stringValueFactory ) {
+ super(PropertyType.REFERENCE, decoder, stringValueFactory);
}
/**
@@ -66,9 +67,9 @@
/**
* {@inheritDoc}
*/
- public Reference create( String value, TextEncoder decoder ) {
+ public Reference create( String value, TextDecoder decoder ) {
// this probably doesn't really need to call the decoder, but by doing so then we don't care at all what the decoder does
- return create(getEncoder(decoder).decode(value));
+ return create(getDecoder(decoder).decode(value));
}
/**
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/AbstractValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/AbstractValueFactoryTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/AbstractValueFactoryTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -33,7 +33,7 @@
import java.util.Calendar;
import java.util.Date;
import org.jboss.dna.common.text.NoOpEncoder;
-import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.PropertyType;
@@ -48,19 +48,19 @@
*/
public class AbstractValueFactoryTest {
- public static final TextEncoder CUSTOM_ENCODER = new NoOpEncoder();
+ public static final TextDecoder CUSTOM_DECODER = new NoOpEncoder();
private static class MockFactory extends AbstractValueFactory<String> {
- protected MockFactory( TextEncoder encoder, StringValueFactory stringValueFactory ) {
- super(PropertyType.STRING, encoder, stringValueFactory);
+ protected MockFactory( TextDecoder decoder, StringValueFactory stringValueFactory ) {
+ super(PropertyType.STRING, decoder, stringValueFactory);
}
public String create( String value ) throws ValueFormatException {
return null;
}
- public String create( String value, TextEncoder decoder ) throws ValueFormatException {
+ public String create( String value, TextDecoder decoder ) throws ValueFormatException {
return null;
}
@@ -134,29 +134,29 @@
@Test
public void shouldHaveDefaultEncoderIfNullPassedIntoConstructor() {
- assertThat(factory.getEncoder(), is(notNullValue()));
- assertThat(factory.getEncoder(), is(sameInstance(ValueFactory.DEFAULT_ENCODER)));
+ assertThat(factory.getDecoder(), is(notNullValue()));
+ assertThat(factory.getDecoder(), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
}
@Test
public void shouldReturnTextEncoderPassedIntoConstructor() {
- factory = new MockFactory(CUSTOM_ENCODER, null);
- assertThat(factory.getEncoder(), is(notNullValue()));
- assertThat(factory.getEncoder(), is(sameInstance(CUSTOM_ENCODER)));
+ factory = new MockFactory(CUSTOM_DECODER, null);
+ assertThat(factory.getDecoder(), is(notNullValue()));
+ assertThat(factory.getDecoder(), is(sameInstance(CUSTOM_DECODER)));
}
@Test
public void shouldReturnDefaultTextEncoderWhenNullPassedToGetEncoder() {
- assertThat(factory.getEncoder(), is(sameInstance(ValueFactory.DEFAULT_ENCODER)));
- assertThat(factory.getEncoder(null), is(sameInstance(ValueFactory.DEFAULT_ENCODER)));
- assertThat(factory.getEncoder(CUSTOM_ENCODER), is(sameInstance(CUSTOM_ENCODER)));
+ assertThat(factory.getDecoder(), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
+ assertThat(factory.getDecoder(null), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
+ assertThat(factory.getDecoder(CUSTOM_DECODER), is(sameInstance(CUSTOM_DECODER)));
}
@Test
public void shouldReturnSuppliedTextEncoderWhenNonNullPassedToGetEncoder() {
- assertThat(factory.getEncoder(), is(sameInstance(ValueFactory.DEFAULT_ENCODER)));
- assertThat(factory.getEncoder(null), is(sameInstance(ValueFactory.DEFAULT_ENCODER)));
- assertThat(factory.getEncoder(CUSTOM_ENCODER), is(sameInstance(CUSTOM_ENCODER)));
+ assertThat(factory.getDecoder(), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
+ assertThat(factory.getDecoder(null), is(sameInstance(ValueFactory.DEFAULT_DECODER)));
+ assertThat(factory.getDecoder(CUSTOM_DECODER), is(sameInstance(CUSTOM_DECODER)));
}
@Test
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathSegmentTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathSegmentTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathSegmentTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -41,7 +41,6 @@
private ValueFactory<String> stringValueFactory;
private NameValueFactory nameFactory;
private PathValueFactory factory;
- private TextEncoder encoder;
private Name validName;
private Path.Segment segment;
private Path.Segment segment2;
@@ -50,11 +49,10 @@
public void beforeEach() throws Exception {
this.registry = new BasicNamespaceRegistry();
this.registry.register("dna", "http://www.jboss.org/dna/namespace");
- this.encoder = Path.DEFAULT_ENCODER;
- this.stringValueFactory = new StringValueFactory(encoder);
- this.nameFactory = new NameValueFactory(registry, encoder, stringValueFactory);
+ this.stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
+ this.nameFactory = new NameValueFactory(registry, Path.DEFAULT_DECODER, stringValueFactory);
this.validName = nameFactory.create("dna:something");
- this.factory = new PathValueFactory(encoder, stringValueFactory, nameFactory);
+ this.factory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameFactory);
}
@Test( expected = IllegalArgumentException.class )
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -46,731 +46,718 @@
*/
public class BasicPathTest {
- public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
- public static final Path ROOT = BasicPath.ROOT;
+ public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+ public static final Path ROOT = BasicPath.ROOT;
- private BasicNamespaceRegistry namespaceRegistry;
- private String validNamespaceUri;
- private Path path;
- private Path path2;
- private Path.Segment[] validSegments;
- private List<Path.Segment> validSegmentsList;
- private Name[] validSegmentNames;
- private String validNamespacePrefix;
- private PathValueFactory pathFactory;
+ private BasicNamespaceRegistry namespaceRegistry;
+ private String validNamespaceUri;
+ private Path path;
+ private Path path2;
+ private Path.Segment[] validSegments;
+ private List<Path.Segment> validSegmentsList;
+ private Name[] validSegmentNames;
+ private String validNamespacePrefix;
+ private PathValueFactory pathFactory;
- @Before
- public void beforeEach() throws Exception {
- validNamespacePrefix = "dna";
- validNamespaceUri = "http://www.jboss.org/dna";
- validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"), new BasicName(validNamespaceUri, "b"),
- new BasicName(validNamespaceUri, "c")};
- validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]),
- new BasicPathSegment(validSegmentNames[1]), new BasicPathSegment(validSegmentNames[1])};
- validSegmentsList = new ArrayList<Path.Segment>();
- for (Path.Segment segment : validSegments) {
- validSegmentsList.add(segment);
- }
- path = new BasicPath(validSegmentsList, true);
- namespaceRegistry = new BasicNamespaceRegistry();
- namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
- StringValueFactory stringValueFactory = new StringValueFactory(Path.DEFAULT_ENCODER);
- NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry, Path.DEFAULT_ENCODER, stringValueFactory);
- pathFactory = new PathValueFactory(Path.DEFAULT_ENCODER, stringValueFactory, nameValueFactory);
- }
+ @Before
+ public void beforeEach() throws Exception {
+ validNamespacePrefix = "dna";
+ validNamespaceUri = "http://www.jboss.org/dna";
+ validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"), new BasicName(validNamespaceUri, "b"), new BasicName(validNamespaceUri, "c")};
+ validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]), new BasicPathSegment(validSegmentNames[1]), new BasicPathSegment(validSegmentNames[1])};
+ validSegmentsList = new ArrayList<Path.Segment>();
+ for (Path.Segment segment : validSegments) {
+ validSegmentsList.add(segment);
+ }
+ path = new BasicPath(validSegmentsList, true);
+ namespaceRegistry = new BasicNamespaceRegistry();
+ namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
+ StringValueFactory stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
+ NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry, Path.DEFAULT_DECODER, stringValueFactory);
+ pathFactory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameValueFactory);
+ }
- @Test
- public void shouldCreateAbsolutePathFromListOfValidSegments() {
- path = new BasicPath(validSegmentsList, true);
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.isNormalized(), is(true));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateAbsolutePathFromListOfValidSegments() {
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(true));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateRelativePathFromListOfValidSegments() {
- path = new BasicPath(validSegmentsList, false);
- assertThat(path.isAbsolute(), is(false));
- assertThat(path.isNormalized(), is(true));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateRelativePathFromListOfValidSegments() {
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(true));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateAbsolutePathWithParentSegment() {
- validSegmentsList.add(Path.PARENT_SEGMENT);
- path = new BasicPath(validSegmentsList, true);
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateAbsolutePathWithParentSegment() {
+ validSegmentsList.add(Path.PARENT_SEGMENT);
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateRelativePathWithParentSegment() {
- validSegmentsList.add(Path.PARENT_SEGMENT);
- path = new BasicPath(validSegmentsList, false);
- assertThat(path.isAbsolute(), is(false));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateRelativePathWithParentSegment() {
+ validSegmentsList.add(Path.PARENT_SEGMENT);
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateAbsolutePathWithSelfSegment() {
- validSegmentsList.add(Path.SELF_SEGMENT);
- path = new BasicPath(validSegmentsList, true);
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateAbsolutePathWithSelfSegment() {
+ validSegmentsList.add(Path.SELF_SEGMENT);
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateRelativePathWithSelfSegment() {
- validSegmentsList.add(Path.SELF_SEGMENT);
- path = new BasicPath(validSegmentsList, false);
- assertThat(path.isAbsolute(), is(false));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateRelativePathWithSelfSegment() {
+ validSegmentsList.add(Path.SELF_SEGMENT);
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreatePathWithNoNamespacePrefixes() {
- path = pathFactory.create("/a/b/c/");
- assertThat(path.size(), is(3));
- assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
- }
+ @Test
+ public void shouldCreatePathWithNoNamespacePrefixes() {
+ path = pathFactory.create("/a/b/c/");
+ assertThat(path.size(), is(3));
+ assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
+ }
- @Test
- public void shouldConstructRelativePath() {
- assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
- assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
- assertThat(pathFactory.create("a/b/c").size(), is(3));
- assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry), is("a/b/c"));
- }
+ @Test
+ public void shouldConstructRelativePath() {
+ assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
+ assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
+ assertThat(pathFactory.create("a/b/c").size(), is(3));
+ assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry), is("a/b/c"));
+ }
- @Test
- public void shouldConstructRelativePathToSelf() {
- assertThat(pathFactory.create(".").isAbsolute(), is(false));
- assertThat(pathFactory.create(".").size(), is(1));
- assertThat(pathFactory.create("."), hasSegments(pathFactory, Path.SELF));
+ @Test
+ public void shouldConstructRelativePathToSelf() {
+ assertThat(pathFactory.create(".").isAbsolute(), is(false));
+ assertThat(pathFactory.create(".").size(), is(1));
+ assertThat(pathFactory.create("."), hasSegments(pathFactory, Path.SELF));
- assertThat(pathFactory.create("./").isAbsolute(), is(false));
- assertThat(pathFactory.create("./").size(), is(1));
- assertThat(pathFactory.create("./"), hasSegments(pathFactory, Path.SELF));
- }
+ assertThat(pathFactory.create("./").isAbsolute(), is(false));
+ assertThat(pathFactory.create("./").size(), is(1));
+ assertThat(pathFactory.create("./"), hasSegments(pathFactory, Path.SELF));
+ }
- @Test
- public void shouldConstructRelativePathToParent() {
- assertThat(pathFactory.create("..").isAbsolute(), is(false));
- assertThat(pathFactory.create("..").size(), is(1));
- assertThat(pathFactory.create(".."), hasSegments(pathFactory, Path.PARENT));
+ @Test
+ public void shouldConstructRelativePathToParent() {
+ assertThat(pathFactory.create("..").isAbsolute(), is(false));
+ assertThat(pathFactory.create("..").size(), is(1));
+ assertThat(pathFactory.create(".."), hasSegments(pathFactory, Path.PARENT));
- assertThat(pathFactory.create("../").isAbsolute(), is(false));
- assertThat(pathFactory.create("../").size(), is(1));
- assertThat(pathFactory.create("../"), hasSegments(pathFactory, Path.PARENT));
- }
+ assertThat(pathFactory.create("../").isAbsolute(), is(false));
+ assertThat(pathFactory.create("../").size(), is(1));
+ assertThat(pathFactory.create("../"), hasSegments(pathFactory, Path.PARENT));
+ }
- @Test
- public void shouldConstructRootPathFromStringWithSingleDelimiter() {
- assertThat(pathFactory.create("/"), is(ROOT));
- assertThat(pathFactory.create("/").isRoot(), is(true));
- }
+ @Test
+ public void shouldConstructRootPathFromStringWithSingleDelimiter() {
+ assertThat(pathFactory.create("/"), is(ROOT));
+ assertThat(pathFactory.create("/").isRoot(), is(true));
+ }
- @Test( expected = ValueFormatException.class )
- public void shouldNotConstructPathWithSuccessiveDelimiters() {
- pathFactory.create("///a/b///c//d//");
- }
+ @Test( expected = ValueFormatException.class )
+ public void shouldNotConstructPathWithSuccessiveDelimiters() {
+ pathFactory.create("///a/b///c//d//");
+ }
- @Test( expected = ValueFormatException.class )
- public void shouldNotConstructPathWithOnlyDelimiters() {
- pathFactory.create("///");
- }
+ @Test( expected = ValueFormatException.class )
+ public void shouldNotConstructPathWithOnlyDelimiters() {
+ pathFactory.create("///");
+ }
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotConstructPathFromNullList() {
- new BasicPath(null, true);
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotConstructPathFromNullList() {
+ new BasicPath(null, true);
+ }
- @Test
- public void shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
- assertThat(pathFactory.create(" \t / \t").toString(), is("/"));
- }
+ @Test
+ public void shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
+ assertThat(pathFactory.create(" \t / \t").toString(), is("/"));
+ }
- @Test
- public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
- assertThat(pathFactory.create("a"), hasSegments(pathFactory, "a"));
- }
+ @Test
+ public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
+ assertThat(pathFactory.create("a"), hasSegments(pathFactory, "a"));
+ }
- @Test
- public void shouldHaveSizeThatReflectsNumberOfSegments() {
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldHaveSizeThatReflectsNumberOfSegments() {
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldIterateOverAllSegmentsReturnedByList() {
- Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
- for (Path.Segment segment : path) {
- assertThat(segment, is(expectedIter.next()));
- }
+ @Test
+ public void shouldIterateOverAllSegmentsReturnedByList() {
+ Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
+ for (Path.Segment segment : path) {
+ assertThat(segment, is(expectedIter.next()));
+ }
- expectedIter = path.getSegmentsList().iterator();
- for (Path.Segment segment : path) {
- assertThat(segment, is(expectedIter.next()));
- }
- }
+ expectedIter = path.getSegmentsList().iterator();
+ for (Path.Segment segment : path) {
+ assertThat(segment, is(expectedIter.next()));
+ }
+ }
- @Test
- public void shouldReturnRootForAncestorOfRoot() {
- assertThat(BasicPath.ROOT.getAncestor(), is(ROOT));
- }
+ @Test
+ public void shouldReturnRootForAncestorOfRoot() {
+ assertThat(BasicPath.ROOT.getAncestor(), is(ROOT));
+ }
- @Test
- public void shouldReturnAncestorForNodeOtherThanRoot() {
- assertThat(path.getAncestor(), is(pathFactory.create("/dna:a/dna:b")));
- assertThat(path.getAncestor().getAncestor(), is(pathFactory.create("/dna:a")));
- assertThat(path.getAncestor().getAncestor().getAncestor(), is(ROOT));
- }
+ @Test
+ public void shouldReturnAncestorForNodeOtherThanRoot() {
+ assertThat(path.getAncestor(), is(pathFactory.create("/dna:a/dna:b")));
+ assertThat(path.getAncestor().getAncestor(), is(pathFactory.create("/dna:a")));
+ assertThat(path.getAncestor().getAncestor().getAncestor(), is(ROOT));
+ }
- @Test
- public void shouldReturnNthDegreeAncestor() {
- assertThat(path.getAncestor(1), is(pathFactory.create("/dna:a/dna:b")));
- assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
- assertThat(path.getAncestor(3), is(ROOT));
- }
+ @Test
+ public void shouldReturnNthDegreeAncestor() {
+ assertThat(path.getAncestor(1), is(pathFactory.create("/dna:a/dna:b")));
+ assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
+ assertThat(path.getAncestor(3), is(ROOT));
+ }
- @Test( expected = PathNotFoundException.class )
- public void shouldNotAllowAncestorDegreeLargerThanSize() {
- path.getAncestor(path.size() + 1);
- }
+ @Test( expected = PathNotFoundException.class )
+ public void shouldNotAllowAncestorDegreeLargerThanSize() {
+ path.getAncestor(path.size() + 1);
+ }
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowNegativeAncestorDegree() {
- path.getAncestor(-1);
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNegativeAncestorDegree() {
+ path.getAncestor(-1);
+ }
- @Test
- public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
- assertThat(path.getAncestor(path.size()), is(ROOT));
- assertThat(ROOT.getAncestor(0), is(ROOT));
- }
+ @Test
+ public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
+ assertThat(path.getAncestor(path.size()), is(ROOT));
+ assertThat(ROOT.getAncestor(0), is(ROOT));
+ }
- @Test
- public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
- assertThat(path.getCommonAncestor(ROOT), is(ROOT));
- assertThat(ROOT.getCommonAncestor(path), is(ROOT));
- }
+ @Test
+ public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
+ assertThat(path.getCommonAncestor(ROOT), is(ROOT));
+ assertThat(ROOT.getCommonAncestor(path), is(ROOT));
+ }
- @Test
- public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
- assertThat(path.getCommonAncestor(null), is(nullValue()));
- }
+ @Test
+ public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
+ assertThat(path.getCommonAncestor(null), is(nullValue()));
+ }
- @Test
- public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path common = pathFactory.create("/a");
- assertThat(path1.getCommonAncestor(path2), is(common));
+ @Test
+ public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(path1.getCommonAncestor(path2), is(common));
- path1 = pathFactory.create("/a/b/c");
- path2 = pathFactory.create("/a/b/c/d");
- common = path1;
- assertThat(path1.getCommonAncestor(path2), is(common));
+ path1 = pathFactory.create("/a/b/c");
+ path2 = pathFactory.create("/a/b/c/d");
+ common = path1;
+ assertThat(path1.getCommonAncestor(path2), is(common));
- path1 = pathFactory.create("/a/b/c/x/y/");
- path2 = pathFactory.create("/a/b/c/d/e/f/");
- common = pathFactory.create("/a/b/c");
- assertThat(path1.getCommonAncestor(path2), is(common));
- }
+ path1 = pathFactory.create("/a/b/c/x/y/");
+ path2 = pathFactory.create("/a/b/c/d/e/f/");
+ common = pathFactory.create("/a/b/c");
+ assertThat(path1.getCommonAncestor(path2), is(common));
+ }
- @Test
- public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
- Path path1 = pathFactory.create("/x/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path common = ROOT;
- assertThat(path1.getCommonAncestor(path2), is(common));
- }
+ @Test
+ public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
+ Path path1 = pathFactory.create("/x/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path common = ROOT;
+ assertThat(path1.getCommonAncestor(path2), is(common));
+ }
- @Test
- public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- Path common = pathFactory.create("/a");
- assertThat(common.isAncestorOf(path1), is(true));
- assertThat(common.isAncestorOf(path2), is(true));
- assertThat(common.isAncestorOf(path3), is(false));
+ @Test
+ public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ Path common = pathFactory.create("/a");
+ assertThat(common.isAncestorOf(path1), is(true));
+ assertThat(common.isAncestorOf(path2), is(true));
+ assertThat(common.isAncestorOf(path3), is(false));
- assertThat(path1.getAncestor().isAncestorOf(path1), is(true));
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
- }
- }
+ assertThat(path1.getAncestor().isAncestorOf(path1), is(true));
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
+ }
+ }
- @Test
- public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- Path common = pathFactory.create("/a");
- assertThat(path1.isDecendantOf(common), is(true));
- assertThat(path2.isDecendantOf(common), is(true));
- assertThat(path3.isDecendantOf(common), is(false));
+ @Test
+ public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ Path common = pathFactory.create("/a");
+ assertThat(path1.isDecendantOf(common), is(true));
+ assertThat(path2.isDecendantOf(common), is(true));
+ assertThat(path3.isDecendantOf(common), is(false));
- assertThat(path1.getAncestor().isAncestorOf(path1), is(true));
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
- }
- }
+ assertThat(path1.getAncestor().isAncestorOf(path1), is(true));
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
+ }
+ }
- @Test
- public void shouldNotConsiderNodeToBeAncestorOfItself() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- assertThat(path1.isAncestorOf(path1), is(false));
- assertThat(path2.isAncestorOf(path2), is(false));
- assertThat(path3.isAncestorOf(path3), is(false));
- assertThat(ROOT.isAncestorOf(ROOT), is(false));
- }
+ @Test
+ public void shouldNotConsiderNodeToBeAncestorOfItself() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ assertThat(path1.isAncestorOf(path1), is(false));
+ assertThat(path2.isAncestorOf(path2), is(false));
+ assertThat(path3.isAncestorOf(path3), is(false));
+ assertThat(ROOT.isAncestorOf(ROOT), is(false));
+ }
- @Test
- public void shouldNotConsiderNodeToBeDecendantOfItself() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- assertThat(path1.isDecendantOf(path1), is(false));
- assertThat(path2.isDecendantOf(path2), is(false));
- assertThat(path3.isDecendantOf(path3), is(false));
- assertThat(ROOT.isDecendantOf(ROOT), is(false));
- }
+ @Test
+ public void shouldNotConsiderNodeToBeDecendantOfItself() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ assertThat(path1.isDecendantOf(path1), is(false));
+ assertThat(path2.isDecendantOf(path2), is(false));
+ assertThat(path3.isDecendantOf(path3), is(false));
+ assertThat(ROOT.isDecendantOf(ROOT), is(false));
+ }
- @Test
- public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path common = pathFactory.create("/a");
- assertThat(ROOT.isDecendantOf(path1), is(false));
- assertThat(ROOT.isDecendantOf(path2), is(false));
- assertThat(ROOT.isDecendantOf(path3), is(false));
- assertThat(ROOT.isDecendantOf(common), is(false));
- }
+ @Test
+ public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(ROOT.isDecendantOf(path1), is(false));
+ assertThat(ROOT.isDecendantOf(path2), is(false));
+ assertThat(ROOT.isDecendantOf(path3), is(false));
+ assertThat(ROOT.isDecendantOf(common), is(false));
+ }
- @Test
- public void shouldConsiderRootToBeAncestorOfAnyNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path common = pathFactory.create("/a");
- assertThat(ROOT.isAncestorOf(path1), is(true));
- assertThat(ROOT.isAncestorOf(path2), is(true));
- assertThat(ROOT.isAncestorOf(path3), is(true));
- assertThat(ROOT.isAncestorOf(common), is(true));
- }
+ @Test
+ public void shouldConsiderRootToBeAncestorOfAnyNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(ROOT.isAncestorOf(path1), is(true));
+ assertThat(ROOT.isAncestorOf(path2), is(true));
+ assertThat(ROOT.isAncestorOf(path3), is(true));
+ assertThat(ROOT.isAncestorOf(common), is(true));
+ }
- @Test
- public void shouldNotConsiderRootToBeAncestorOfItself() {
- assertThat(ROOT.isAncestorOf(ROOT), is(false));
- }
+ @Test
+ public void shouldNotConsiderRootToBeAncestorOfItself() {
+ assertThat(ROOT.isAncestorOf(ROOT), is(false));
+ }
- @Test
- public void shouldNotConsiderRootToBeDecendantOfItself() {
- assertThat(ROOT.isDecendantOf(ROOT), is(false));
- }
+ @Test
+ public void shouldNotConsiderRootToBeDecendantOfItself() {
+ assertThat(ROOT.isDecendantOf(ROOT), is(false));
+ }
- @Test
- public void shouldNeverBeDecendantOfNullPath() {
- assertThat(path.isDecendantOf(null), is(false));
- assertThat(ROOT.isDecendantOf(null), is(false));
- }
+ @Test
+ public void shouldNeverBeDecendantOfNullPath() {
+ assertThat(path.isDecendantOf(null), is(false));
+ assertThat(ROOT.isDecendantOf(null), is(false));
+ }
- @Test
- public void shouldReturnNullForLastSegmentOfRoot() {
- assertThat(ROOT.getLastSegment(), is(nullValue()));
- }
+ @Test
+ public void shouldReturnNullForLastSegmentOfRoot() {
+ assertThat(ROOT.getLastSegment(), is(nullValue()));
+ }
- @Test
- public void shouldReturnLastSegmentOfNonRootPath() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
- assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
- assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
- assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
- assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
- }
+ @Test
+ public void shouldReturnLastSegmentOfNonRootPath() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
+ assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
+ assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
+ assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
+ assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
+ }
- @Test
- public void shouldNormalizePathWithSelfAndParentReferences() {
- path = pathFactory.create("/a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(true));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ @Test
+ public void shouldNormalizePathWithSelfAndParentReferences() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
- path = pathFactory.create("a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(false));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
- }
+ path = pathFactory.create("a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
- @Test
- public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
- assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
- assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
- assertThat(pathFactory.create("a").isNormalized(), is(true));
- assertThat(pathFactory.create("/a").isNormalized(), is(true));
- assertThat(ROOT.isNormalized(), is(true));
- }
+ @Test
+ public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
+ assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
+ assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
+ assertThat(pathFactory.create("a").isNormalized(), is(true));
+ assertThat(pathFactory.create("/a").isNormalized(), is(true));
+ assertThat(ROOT.isNormalized(), is(true));
+ }
- @Test
- public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
- assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(), is(false));
- assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(), is(false));
- assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
- assertThat(pathFactory.create("/a/b/c/../d").isNormalized(), is(false));
- assertThat(pathFactory.create(".").isNormalized(), is(false));
- assertThat(pathFactory.create("/.").isNormalized(), is(false));
- }
+ @Test
+ public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
+ assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(), is(false));
+ assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(), is(false));
+ assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
+ assertThat(pathFactory.create("/a/b/c/../d").isNormalized(), is(false));
+ assertThat(pathFactory.create(".").isNormalized(), is(false));
+ assertThat(pathFactory.create("/.").isNormalized(), is(false));
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
- path = pathFactory.create("/a/../../../..");
- assertThat(path.isNormalized(), is(false));
- path.getNormalizedPath();
- }
+ @Test( expected = InvalidPathException.class )
+ public void shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
+ path = pathFactory.create("/a/../../../..");
+ assertThat(path.isNormalized(), is(false));
+ path.getNormalizedPath();
+ }
- @Test
- public void shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
- // "/a/../b/../c/.." => "/"
- path = pathFactory.create("/a/../b/../c/../");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), is(ROOT));
- }
+ @Test
+ public void shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
+ // "/a/../b/../c/.." => "/"
+ path = pathFactory.create("/a/../b/../c/../");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), is(ROOT));
+ }
- @Test
- public void shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
- // "a/../b/../c/.." => "."
- path = pathFactory.create("a/../b/../c/../");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath().size(), is(1));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
- }
+ @Test
+ public void shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
+ // "a/../b/../c/.." => "."
+ path = pathFactory.create("a/../b/../c/../");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath().size(), is(1));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
+ }
- @Test
- public void shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
- path = pathFactory.create("/a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(true));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
- }
+ @Test
+ public void shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
- @Test
- public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
- path = pathFactory.create("a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(false));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
- }
+ @Test
+ public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
+ path = pathFactory.create("a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
- pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
- }
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
+ pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
+ }
- @Test
- public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
- path = pathFactory.create("/a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getCanonicalPath().isAbsolute(), is(true));
- assertThat(path.getCanonicalPath().isNormalized(), is(true));
- }
+ @Test
+ public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getCanonicalPath().isAbsolute(), is(true));
+ assertThat(path.getCanonicalPath().isNormalized(), is(true));
+ }
- @Test
- public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
- testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
- testSegmentsByIteratorAndListAndArray("/a/b/c", "a", "b", "c");
- testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
- testSegmentsByIteratorAndListAndArray("a/b/c", "a", "b", "c");
- testSegmentsByIteratorAndListAndArray("");
- testSegmentsByIteratorAndListAndArray(ROOT.getString());
- }
+ @Test
+ public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
+ testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
+ testSegmentsByIteratorAndListAndArray("/a/b/c", "a", "b", "c");
+ testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
+ testSegmentsByIteratorAndListAndArray("a/b/c", "a", "b", "c");
+ testSegmentsByIteratorAndListAndArray("");
+ testSegmentsByIteratorAndListAndArray(ROOT.getString());
+ }
- public void testSegmentsByIteratorAndListAndArray( String pathStr,
- String... expectedSegmentStrings ) {
- path = pathFactory.create(pathStr);
- assertThat(expectedSegmentStrings.length, is(path.size()));
- Path.Segment[] segmentArray = path.getSegmentsArray();
- List<Path.Segment> segmentList = path.getSegmentsList();
- assertThat(segmentArray.length, is(path.size()));
- assertThat(segmentList.size(), is(path.size()));
- Iterator<Path.Segment> iter = path.iterator();
- Iterator<Path.Segment> listIter = segmentList.iterator();
- for (int i = 0; i != path.size(); ++i) {
- Path.Segment expected = pathFactory.createSegment(expectedSegmentStrings[i]);
- assertThat(path.getSegment(i), is(expected));
- assertThat(segmentArray[i], is(expected));
- assertThat(segmentList.get(i), is(expected));
- assertThat(iter.next(), is(expected));
- assertThat(listIter.next(), is(expected));
- }
- assertThat(iter.hasNext(), is(false));
- assertThat(listIter.hasNext(), is(false));
- }
+ public void testSegmentsByIteratorAndListAndArray( String pathStr, String... expectedSegmentStrings ) {
+ path = pathFactory.create(pathStr);
+ assertThat(expectedSegmentStrings.length, is(path.size()));
+ Path.Segment[] segmentArray = path.getSegmentsArray();
+ List<Path.Segment> segmentList = path.getSegmentsList();
+ assertThat(segmentArray.length, is(path.size()));
+ assertThat(segmentList.size(), is(path.size()));
+ Iterator<Path.Segment> iter = path.iterator();
+ Iterator<Path.Segment> listIter = segmentList.iterator();
+ for (int i = 0; i != path.size(); ++i) {
+ Path.Segment expected = pathFactory.createSegment(expectedSegmentStrings[i]);
+ assertThat(path.getSegment(i), is(expected));
+ assertThat(segmentArray[i], is(expected));
+ assertThat(segmentList.get(i), is(expected));
+ assertThat(iter.next(), is(expected));
+ assertThat(listIter.next(), is(expected));
+ }
+ assertThat(iter.hasNext(), is(false));
+ assertThat(listIter.hasNext(), is(false));
+ }
- @Test
- public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.getString(NO_OP_ENCODER),
- is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../{}d/./{http://www.jboss.org/dna}e/../.."));
- }
+ @Test
+ public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.getString(NO_OP_ENCODER), is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../{}d/./{http://www.jboss.org/dna}e/../.."));
+ }
- @Test
- public void shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna:a/b/dna:c/../d/./dna:e/../.."));
- namespaceRegistry.register("dna2", validNamespaceUri);
- assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
- }
+ @Test
+ public void shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna:a/b/dna:c/../d/./dna:e/../.."));
+ namespaceRegistry.register("dna2", validNamespaceUri);
+ assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(-1);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(-1);
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(path.size() + 1);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(path.size() + 1);
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(path.size() + 1, path.size() + 2);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(path.size() + 1, path.size() + 2);
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(2, 1);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(2, 1);
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(2, path.size() + 1);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(2, path.size() + 1);
+ }
- @Test
- public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0, 0), is(ROOT));
- }
+ @Test
+ public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0, 0), is(ROOT));
+ }
- @Test
- public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(0), is(path));
- assertThat(path.subpath(0), is(sameInstance(path)));
- assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
- assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
- assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
- assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+ @Test
+ public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(0), is(path));
+ assertThat(path.subpath(0), is(sameInstance(path)));
+ assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
+ assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
+ assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
- path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(0), is(path));
- assertThat(path.subpath(0), is(sameInstance(path)));
- assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
- assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
- assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
- assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
- }
+ path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(0), is(path));
+ assertThat(path.subpath(0), is(sameInstance(path)));
+ assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
+ assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
+ assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+ }
- @Test
- public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0, path.size()), hasSegments(pathFactory,
- "dna:a",
- "b",
- "dna:c",
- "..",
- "d",
- ".",
- "dna:e",
- "..",
- ".."));
- assertThat(path.subpath(0, path.size()), is(path));
- assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
- assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(2, path.size()), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
- assertThat(path.subpath(6, path.size()), hasSegments(pathFactory, "dna:e", "..", ".."));
- assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..", ".."));
- assertThat(path.subpath(8, path.size()), hasSegments(pathFactory, ".."));
+ @Test
+ public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0, path.size()), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(0, path.size()), is(path));
+ assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
+ assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(2, path.size()), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(6, path.size()), hasSegments(pathFactory, "dna:e", "..", ".."));
+ assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..", ".."));
+ assertThat(path.subpath(8, path.size()), hasSegments(pathFactory, ".."));
- assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a", "b"));
- assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
- assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b", "dna:c", "..", "d"));
- assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c", "..", "d"));
- assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..", "d"));
- }
+ assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a", "b"));
+ assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
+ assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b", "dna:c", "..", "d"));
+ assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c", "..", "d"));
+ assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..", "d"));
+ }
- @Test
- public void shouldFindRelativePaths() {
- path = pathFactory.create("/a/b/c/d");
- assertThat(path.relativeTo(pathFactory.create("/a/e/f")), is(pathFactory.create("../../b/c/d")));
- assertThat(path.relativeTo(pathFactory.create("/e/f")), is(pathFactory.create("../../a/b/c/d")));
+ @Test
+ public void shouldFindRelativePaths() {
+ path = pathFactory.create("/a/b/c/d");
+ assertThat(path.relativeTo(pathFactory.create("/a/e/f")), is(pathFactory.create("../../b/c/d")));
+ assertThat(path.relativeTo(pathFactory.create("/e/f")), is(pathFactory.create("../../a/b/c/d")));
- }
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
- path = pathFactory.create("a/b/c/d");
- path.relativeTo(pathFactory.create("/e/f"));
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
+ path = pathFactory.create("a/b/c/d");
+ path.relativeTo(pathFactory.create("/e/f"));
- }
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotResolveRelativePathToAnotherRelativePath() {
- path = pathFactory.create("/a/b/c/d");
- path.relativeTo(pathFactory.create("e/f"));
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotResolveRelativePathToAnotherRelativePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path.relativeTo(pathFactory.create("e/f"));
- }
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
- path = pathFactory.create("/a/b/c/d");
- path.resolve(pathFactory.create("/e/f"));
- }
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path.resolve(pathFactory.create("/e/f"));
+ }
- @Test
- public void shouldResolveRelativePathToAbsolutePath() {
- path = pathFactory.create("/a/b/c/d");
- path2 = path.resolve(pathFactory.create("../../e/f"));
- assertThat(path2, is(pathFactory.create("/a/b/e/f")));
- assertThat(path2.isAbsolute(), is(true));
- assertThat(path2.isNormalized(), is(true));
- }
+ @Test
+ public void shouldResolveRelativePathToAbsolutePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path2 = path.resolve(pathFactory.create("../../e/f"));
+ assertThat(path2, is(pathFactory.create("/a/b/e/f")));
+ assertThat(path2.isAbsolute(), is(true));
+ assertThat(path2.isNormalized(), is(true));
+ }
- @Test
- public void shouldOrderPathsCorrectly() {
- List<Path> paths = new ArrayList<Path>();
- paths.add(pathFactory.create("/a"));
- paths.add(pathFactory.create("/a/b"));
- paths.add(pathFactory.create("/a/b/alpha"));
- paths.add(pathFactory.create("/a/b/beta"));
- paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
- paths.add(pathFactory.create("/a/b/dna:name"));
- paths.add(pathFactory.create("/a/b/dna:primaryType"));
- paths.add(pathFactory.create("/a/c[1]"));
- paths.add(pathFactory.create("/a/c[1]/alpha"));
- paths.add(pathFactory.create("/a/c[1]/beta"));
- paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
- paths.add(pathFactory.create("/a/c[1]/dna:name"));
- paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
- paths.add(pathFactory.create("/a/c[2]"));
- paths.add(pathFactory.create("/a/c[2]/alpha"));
- paths.add(pathFactory.create("/a/c[2]/beta"));
- paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
- paths.add(pathFactory.create("/a/c[2]/dna:name"));
- paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
+ @Test
+ public void shouldOrderPathsCorrectly() {
+ List<Path> paths = new ArrayList<Path>();
+ paths.add(pathFactory.create("/a"));
+ paths.add(pathFactory.create("/a/b"));
+ paths.add(pathFactory.create("/a/b/alpha"));
+ paths.add(pathFactory.create("/a/b/beta"));
+ paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/b/dna:name"));
+ paths.add(pathFactory.create("/a/b/dna:primaryType"));
+ paths.add(pathFactory.create("/a/c[1]"));
+ paths.add(pathFactory.create("/a/c[1]/alpha"));
+ paths.add(pathFactory.create("/a/c[1]/beta"));
+ paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/c[1]/dna:name"));
+ paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
+ paths.add(pathFactory.create("/a/c[2]"));
+ paths.add(pathFactory.create("/a/c[2]/alpha"));
+ paths.add(pathFactory.create("/a/c[2]/beta"));
+ paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/c[2]/dna:name"));
+ paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
- // Randomize the list of paths, so we have something to sort ...
- List<Path> randomizedPaths = new ArrayList<Path>(paths);
- Collections.shuffle(randomizedPaths);
- assertThat(randomizedPaths, is(not(paths)));
+ // Randomize the list of paths, so we have something to sort ...
+ List<Path> randomizedPaths = new ArrayList<Path>(paths);
+ Collections.shuffle(randomizedPaths);
+ assertThat(randomizedPaths, is(not(paths)));
- // Sort ...
- Collections.sort(randomizedPaths);
- assertThat(randomizedPaths, is(paths));
- }
+ // Sort ...
+ Collections.sort(randomizedPaths);
+ assertThat(randomizedPaths, is(paths));
+ }
- @Test
- public void shouldGetNormalizedPathOfSelfShouldBeSame() {
- assertThat(pathFactory.create(".").getNormalizedPath(), is(pathFactory.create(".")));
- assertThat(pathFactory.create("./").getNormalizedPath(), is(pathFactory.create(".")));
- assertThat(pathFactory.create("./././").getNormalizedPath(), is(pathFactory.create(".")));
- }
+ @Test
+ public void shouldGetNormalizedPathOfSelfShouldBeSame() {
+ assertThat(pathFactory.create(".").getNormalizedPath(), is(pathFactory.create(".")));
+ assertThat(pathFactory.create("./").getNormalizedPath(), is(pathFactory.create(".")));
+ assertThat(pathFactory.create("./././").getNormalizedPath(), is(pathFactory.create(".")));
+ }
- @Test
- public void shouldGetNormalizedPathWithParentReferences() {
- assertThat(pathFactory.create("..").getNormalizedPath(), is(pathFactory.create("..")));
- assertThat(pathFactory.create("../").getNormalizedPath(), is(pathFactory.create("../")));
- assertThat(pathFactory.create("../../../../../..").getNormalizedPath(), is(pathFactory.create("../../../../../..")));
- }
+ @Test
+ public void shouldGetNormalizedPathWithParentReferences() {
+ assertThat(pathFactory.create("..").getNormalizedPath(), is(pathFactory.create("..")));
+ assertThat(pathFactory.create("../").getNormalizedPath(), is(pathFactory.create("../")));
+ assertThat(pathFactory.create("../../../../../..").getNormalizedPath(), is(pathFactory.create("../../../../../..")));
+ }
- @Test
- public void shouldGetRelativePathUsingSelf() {
- path = pathFactory.create("/a/b/c/d/e/f");
- assertThat(path.resolve(pathFactory.create(".")), is(sameInstance(path)));
- assertThat(path.resolve(pathFactory.create("././.")), is(sameInstance(path)));
- }
+ @Test
+ public void shouldGetRelativePathUsingSelf() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create(".")), is(sameInstance(path)));
+ assertThat(path.resolve(pathFactory.create("././.")), is(sameInstance(path)));
+ }
- @Test
- public void shouldResolveRelativePathToParent() {
- path = pathFactory.create("/a/b/c/d/e/f");
- assertThat(path.resolve(pathFactory.create("..")), is(path.getAncestor()));
- assertThat(path.resolve(pathFactory.create("..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
- }
+ @Test
+ public void shouldResolveRelativePathToParent() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create("..")), is(path.getAncestor()));
+ assertThat(path.resolve(pathFactory.create("..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
+ }
- @Test
- public void shouldResolveRelativePaths() {
- path = pathFactory.create("/a/b/c/d/e/f");
- assertThat(path.resolve(pathFactory.create("../../../../../..")), is(sameInstance(ROOT)));
- assertThat(path.resolve(pathFactory.create("../..")), is(path.getAncestor().getAncestor()));
- assertThat(path.resolve(pathFactory.create("../..")), hasSegments(pathFactory, "a", "b", "c", "d"));
- assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), is(path.getAncestor()));
- assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
- assertThat(path.resolve(pathFactory.create("../x")), hasSegments(pathFactory, "a", "b", "c", "d", "e", "x"));
- }
+ @Test
+ public void shouldResolveRelativePaths() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create("../../../../../..")), is(sameInstance(ROOT)));
+ assertThat(path.resolve(pathFactory.create("../..")), is(path.getAncestor().getAncestor()));
+ assertThat(path.resolve(pathFactory.create("../..")), hasSegments(pathFactory, "a", "b", "c", "d"));
+ assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), is(path.getAncestor()));
+ assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
+ assertThat(path.resolve(pathFactory.create("../x")), hasSegments(pathFactory, "a", "b", "c", "d", "e", "x"));
+ }
- public void shouldResolveNonAbsolutePaths() {
- path = pathFactory.create("a/b/c");
- assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
- }
+ public void shouldResolveNonAbsolutePaths() {
+ path = pathFactory.create("a/b/c");
+ assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
+ }
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BooleanValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BooleanValueFactoryTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BooleanValueFactoryTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -28,7 +28,6 @@
import java.net.URI;
import java.util.Calendar;
import java.util.Date;
-import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Reference;
@@ -51,9 +50,8 @@
*/
@Before
public void setUp() throws Exception {
- TextEncoder encoder = Path.URL_ENCODER;
- stringFactory = new StringValueFactory(encoder);
- factory = new BooleanValueFactory(encoder, stringFactory);
+ stringFactory = new StringValueFactory(Path.URL_DECODER, Path.DEFAULT_ENCODER);
+ factory = new BooleanValueFactory(Path.URL_DECODER, stringFactory);
context = new Mockery();
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DecimalValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DecimalValueFactoryTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DecimalValueFactoryTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,6 @@
import java.net.URI;
import java.util.Calendar;
import java.util.Date;
-import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Reference;
@@ -52,9 +51,8 @@
*/
@Before
public void setUp() throws Exception {
- TextEncoder encoder = Path.URL_ENCODER;
- stringFactory = new StringValueFactory(encoder);
- factory = new DecimalValueFactory(encoder, stringFactory);
+ stringFactory = new StringValueFactory(Path.URL_DECODER, Path.DEFAULT_ENCODER);
+ factory = new DecimalValueFactory(Path.URL_DECODER, stringFactory);
context = new Mockery();
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DoubleValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DoubleValueFactoryTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DoubleValueFactoryTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,6 @@
import java.net.URI;
import java.util.Calendar;
import java.util.Date;
-import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Reference;
@@ -52,9 +51,8 @@
*/
@Before
public void setUp() throws Exception {
- TextEncoder encoder = Path.URL_ENCODER;
- stringFactory = new StringValueFactory(encoder);
- factory = new DoubleValueFactory(encoder, stringFactory);
+ stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
+ factory = new DoubleValueFactory(Path.URL_DECODER, stringFactory);
context = new Mockery();
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/InMemoryBinaryValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/InMemoryBinaryValueFactoryTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/InMemoryBinaryValueFactoryTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -56,13 +56,13 @@
@Before
public void setUp() throws Exception {
encoder = Path.URL_ENCODER;
- stringFactory = new StringValueFactory(encoder);
- factory = new InMemoryBinaryValueFactory(encoder, stringFactory);
+ stringFactory = new StringValueFactory(Path.URL_DECODER, encoder);
+ factory = new InMemoryBinaryValueFactory(Path.URL_DECODER, stringFactory);
namespaceRegistry = new BasicNamespaceRegistry();
namespaceRegistry.register("jboss", "http://www.jboss.org");
namespaceRegistry.register("dna", "http://www.jboss.org/dna");
- nameFactory = new NameValueFactory(namespaceRegistry, encoder, stringFactory);
- pathFactory = new PathValueFactory(encoder, stringFactory, nameFactory);
+ nameFactory = new NameValueFactory(namespaceRegistry, Path.URL_DECODER, stringFactory);
+ pathFactory = new PathValueFactory(Path.URL_DECODER, stringFactory, nameFactory);
}
@Test
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactoryTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactoryTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -28,7 +28,6 @@
import java.math.BigDecimal;
import java.net.URI;
import java.util.Calendar;
-import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.spi.graph.DateTime;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -61,9 +60,8 @@
*/
@Before
public void setUp() throws Exception {
- TextEncoder encoder = Path.URL_ENCODER;
- stringFactory = new StringValueFactory(encoder);
- factory = new JodaDateTimeValueFactory(encoder, stringFactory);
+ stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
+ factory = new JodaDateTimeValueFactory(Path.URL_DECODER, stringFactory);
context = new Mockery();
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/LongValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/LongValueFactoryTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/LongValueFactoryTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -29,7 +29,6 @@
import java.net.URI;
import java.util.Calendar;
import java.util.Date;
-import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Reference;
@@ -52,9 +51,8 @@
*/
@Before
public void setUp() throws Exception {
- TextEncoder encoder = Path.URL_ENCODER;
- stringFactory = new StringValueFactory(encoder);
- factory = new LongValueFactory(encoder, stringFactory);
+ stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
+ factory = new LongValueFactory(Path.URL_DECODER, stringFactory);
context = new Mockery();
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/NameValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/NameValueFactoryTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/NameValueFactoryTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -23,6 +23,7 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
+import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.NamespaceRegistry;
@@ -37,84 +38,86 @@
*/
public class NameValueFactoryTest {
- public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+ public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
- private NamespaceRegistry registry;
- private ValueFactory<String> stringValueFactory;
- private NameValueFactory factory;
- private TextEncoder encoder;
- private Name name;
+ private NamespaceRegistry registry;
+ private ValueFactory<String> stringValueFactory;
+ private NameValueFactory factory;
+ private TextEncoder encoder;
+ private TextDecoder decoder;
+ private Name name;
- @Before
- public void beforeEach() throws Exception {
- this.registry = new BasicNamespaceRegistry();
- this.registry.register("dna", "http://www.jboss.org/dna/namespace");
- this.encoder = Path.DEFAULT_ENCODER;
- this.stringValueFactory = new StringValueFactory(encoder);
- this.factory = new NameValueFactory(registry, encoder, stringValueFactory);
- }
+ @Before
+ public void beforeEach() throws Exception {
+ this.registry = new BasicNamespaceRegistry();
+ this.registry.register("dna", "http://www.jboss.org/dna/namespace");
+ this.encoder = Path.DEFAULT_ENCODER;
+ this.decoder = Path.DEFAULT_DECODER;
+ this.stringValueFactory = new StringValueFactory(decoder, encoder);
+ this.factory = new NameValueFactory(registry, decoder, stringValueFactory);
+ }
- @Test
- public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormatWithoutPrefix() {
- name = factory.create("a");
- assertThat(name.getLocalName(), is("a"));
- assertThat(name.getNamespaceUri(), is(this.registry.getNamespaceForPrefix("")));
- }
+ @Test
+ public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormatWithoutPrefix() {
+ name = factory.create("a");
+ assertThat(name.getLocalName(), is("a"));
+ assertThat(name.getNamespaceUri(), is(this.registry.getNamespaceForPrefix("")));
+ }
- @Test
- public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormat() {
- name = factory.create("dna:something");
- assertThat(name.getLocalName(), is("something"));
- assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
- assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
- }
+ @Test
+ public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormat() {
+ name = factory.create("dna:something");
+ assertThat(name.getLocalName(), is("something"));
+ assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+ assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
+ }
- @Test
- public void shouldCreateNameFromSingleEncodedStringInPrefixedNamespaceFormat() {
- name = factory.create(encoder.encode("dna") + ":" + encoder.encode("some/thing"));
- assertThat(name.getLocalName(), is("some/thing"));
- assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
- assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
- }
+ @Test
+ public void shouldCreateNameFromSingleEncodedStringInPrefixedNamespaceFormat() {
+ name = factory.create(encoder.encode("dna") + ":" + encoder.encode("some/thing"));
+ assertThat(name.getLocalName(), is("some/thing"));
+ assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+ assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
+ }
- @Test
- public void shouldCreateNameFromSingleStringInStandardFullNamespaceFormat() {
- name = factory.create("{http://www.jboss.org/dna/namespace}something");
- assertThat(name.getLocalName(), is("something"));
- assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
- assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
- }
+ @Test
+ public void shouldCreateNameFromSingleStringInStandardFullNamespaceFormat() {
+ name = factory.create("{http://www.jboss.org/dna/namespace}something");
+ assertThat(name.getLocalName(), is("something"));
+ assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+ assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
+ }
- @Test
- public void shouldCreateNameFromSingleEncodedStringInStandardFullNamespaceFormat() {
- name = factory.create("{" + encoder.encode("http://www.jboss.org/dna/namespace") + "}" + encoder.encode("some/thing"));
- assertThat(name.getLocalName(), is("some/thing"));
- assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
- assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
- }
+ @Test
+ public void shouldCreateNameFromSingleEncodedStringInStandardFullNamespaceFormat() {
+ name = factory.create("{" + encoder.encode("http://www.jboss.org/dna/namespace") + "}" + encoder.encode("some/thing"));
+ assertThat(name.getLocalName(), is("some/thing"));
+ assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+ assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
+ }
- @Test
- public void shouldProvideAccessToNamespaceRegistryPassedInConstructor() {
- assertThat(factory.getNamespaceRegistry(), is(registry));
- }
+ @Test
+ public void shouldProvideAccessToNamespaceRegistryPassedInConstructor() {
+ assertThat(factory.getNamespaceRegistry(), is(registry));
+ }
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowNullLocalName() {
- factory.create("a", (String)null);
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNullLocalName() {
+ factory.create("a", (String)null);
+ }
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowNullLocalNameWithEncoder() {
- factory.create("a", null, encoder);
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNullLocalNameWithEncoder() {
+ factory.create("a", null, decoder);
+ }
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowEmptyLocalName() {
- factory.create("a", "");
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowEmptyLocalName() {
+ factory.create("a", "");
+ }
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowEmptyLocalNameWithEncoder() {
- factory.create("a", "", encoder);
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowEmptyLocalNameWithEncoder() {
+ factory.create("a", "", decoder);
+ }
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/PathValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/PathValueFactoryTest.java 2008-06-02 20:19:51 UTC (rev 234)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/PathValueFactoryTest.java 2008-06-03 17:32:57 UTC (rev 235)
@@ -44,7 +44,6 @@
private ValueFactory<String> stringValueFactory;
private NameValueFactory nameFactory;
private PathValueFactory factory;
- private TextEncoder encoder;
private Path path;
private Path path2;
@@ -52,10 +51,9 @@
public void beforeEach() throws Exception {
this.registry = new BasicNamespaceRegistry();
this.registry.register("dna", "http://www.jboss.org/dna/namespace");
- this.encoder = Path.DEFAULT_ENCODER;
- this.stringValueFactory = new StringValueFactory(encoder);
- this.nameFactory = new NameValueFactory(registry, encoder, stringValueFactory);
- this.factory = new PathValueFactory(encoder, stringValueFactory, nameFactory);
+ this.stringValueFactory = new StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
+ this.nameFactory = new NameValueFactory(registry, Path.DEFAULT_DECODER, stringValueFactory);
+ this.factory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory, nameFactory);
}
protected List<Path.Segment> getSegments( String... segments ) {
17 years, 6 months
DNA SVN: r234 - in trunk/dna-spi/src: main/java/org/jboss/dna/spi/graph/impl and 1 other directories.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-06-02 16:19:51 -0400 (Mon, 02 Jun 2008)
New Revision: 234
Modified:
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java
Log:
DNA-79: Changed both PathFactory (interface) and PathValueFactory (impl) to have create() and createRelativePath() methods.
DNA-93: Added missing createSegment(String, TextEncoder) method by moving code from createSegment(String). Also modified method to correctly build indexed segments from string.
DNA-95: Changed create method to throw correct exceptions
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java 2008-06-02 20:12:41 UTC (rev 233)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java 2008-06-02 20:19:51 UTC (rev 234)
@@ -2,7 +2,7 @@
* 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.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -21,110 +21,159 @@
*/
package org.jboss.dna.spi.graph;
+import org.jboss.dna.common.text.TextEncoder;
+
/**
* A factory for creating {@link Path paths}. This interface extends the {@link ValueFactory} generic interface and adds specific
* methods for creating paths (and relative paths) from a series of names, segments, or combinations.
+ *
* @author Randall Hauch
+ * @author John Verhaeg
*/
public interface PathFactory extends ValueFactory<Path> {
- /**
- * Create an absolute 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 root path. Subsequent calls will always return the same instance.
+ *
+ * @return the new path
+ */
+ Path create();
- /**
- * 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 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 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 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 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 an empty relative path (i.e., equivalent to {@link #createRelativePath(Path.Segment...) createRelativePath}({@link Path#SELF_SEGMENT})).
+ * Subsequent calls will always return the same instance.
+ *
+ * @return the new path
+ */
+ Path createRelativePath();
- /**
- * Create a 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 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 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 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. If no names are appended, the parent path is returned.
- * @param parentPath the path that is to provide the basis for the new path
- * @param segments the segments that are to be appended, in order, to the parent path
- * @return the new path
- * @throws IllegalArgumentException if the parent path reference is null, or if at least one segment name is provided and if
- * any of the supplied segment names are null
- */
- Path create( Path parentPath, Path.Segment... segments );
+ /**
+ * Create a path by appending the supplied names to the parent path.
+ *
+ * @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 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( String segmentName );
+ /**
+ * 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 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( String 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 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. 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 <code>null</code> or the value could not be created
+ * from the supplied string
+ */
+ Path.Segment createSegment( String 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 );
+ /**
+ * Create a path segment given the supplied segment name. The resulting segment will have no index.
+ *
+ * @param segmentName the name of the segment
+ * @param encoder the encoder that should be used to decode the qualified name
+ * @return the segment
+ * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created
+ * from the supplied string
+ */
+ Path.Segment createSegment( String segmentName,
+ TextEncoder encoder );
+ /**
+ * Create a path segment given the supplied segment name and index.
+ *
+ * @param segmentName the name of the new segment
+ * @param index the index of the new segment
+ * @return the segment
+ * @throws IllegalArgumentException if the segment name reference is <code>null</code> or if the index is invalid
+ */
+ Path.Segment createSegment( String segmentName,
+ int index );
+
+ /**
+ * Create a path segment given the supplied segment name. The resulting segment will have no index.
+ *
+ * @param segmentName the name of the segment
+ * @return the segment
+ * @throws IllegalArgumentException if the segment name reference is null
+ */
+ Path.Segment createSegment( Name segmentName );
+
+ /**
+ * Create a path segment given the supplied segment name and index.
+ *
+ * @param segmentName the name of the new segment
+ * @param index the index of the new segment
+ * @return the segment
+ * @throws IllegalArgumentException if the segment name reference is null or if the index is invalid
+ */
+ Path.Segment createSegment( Name segmentName,
+ int index );
+
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java 2008-06-02 20:12:41 UTC (rev 233)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java 2008-06-02 20:19:51 UTC (rev 234)
@@ -2,7 +2,7 @@
* 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.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -35,7 +35,6 @@
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.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.PathFactory;
@@ -47,373 +46,453 @@
/**
* The standard {@link ValueFactory} for {@link PropertyType#NAME} values.
+ *
* @author Randall Hauch
+ * @author John Verhaeg
*/
@Immutable
public class PathValueFactory extends AbstractValueFactory<Path> implements PathFactory {
- protected static final char DELIMITER = Path.DELIMITER;
+ /**
+ * Regular expression used to identify the different segments in a path, using the standard '/' delimiter. The expression is
+ * simply:
+ *
+ * <pre>
+ * /
+ * </pre>
+ */
+ protected static final Pattern DELIMITER_PATTERN = Pattern.compile("/");
- /**
- * Regular expression used to identify the different segments in a path, using the standard '/' delimiter. The expression is
- * simply:
- *
- * <pre>
- * /
- * </pre>
- */
- protected static final Pattern DELIMITER_PATTERN = Pattern.compile("/");
+ /**
+ * Regular expression used to identify the different parts of a segment. The expression is
+ *
+ * <pre>
+ * ([ˆ*:/\[\]|]+)(:([ˆ*:/\[\]|]+))?(\[(\d+)])?
+ * </pre>
+ *
+ * where the first part is accessed with group 1, the second part is accessed with group 3, and the index is accessed with
+ * group 5.
+ */
+ protected static final Pattern SEGMENT_PATTERN = Pattern.compile("([^:/]+)(:([^/\\[\\]]+))?(\\[(\\d+)])?");
- /**
- * Regular expression used to identify the different parts of a segment. The expression is
- *
- * <pre>
- * ([ˆ*:/\[\]|]+)(:([ˆ*:/\[\]|]+))?(\[(\d+)])?
- * </pre>
- *
- * where the first part is accessed with group 1, the second part is accessed with group 3, and the index is accessed with
- * group 5.
- */
- protected static final Pattern SEGMENT_PATTERN = Pattern.compile("([^:/]+)(:([^/\\[\\]]+))?(\\[(\\d+)])?");
+ private final ValueFactory<Name> nameValueFactory;
- private final ValueFactory<Name> nameValueFactory;
+ public PathValueFactory( TextEncoder encoder,
+ ValueFactory<String> stringValueFactory,
+ ValueFactory<Name> nameValueFactory ) {
+ super(PropertyType.PATH, encoder, stringValueFactory);
+ ArgCheck.isNotNull(nameValueFactory, "nameValueFactory");
+ this.nameValueFactory = nameValueFactory;
+ }
- public PathValueFactory( TextEncoder encoder, ValueFactory<String> stringValueFactory, ValueFactory<Name> nameValueFactory ) {
- super(PropertyType.PATH, encoder, stringValueFactory);
- ArgCheck.isNotNull(nameValueFactory, "nameValueFactory");
- this.nameValueFactory = nameValueFactory;
- }
+ /**
+ * @return nameValueFactory
+ */
+ protected ValueFactory<Name> getNameValueFactory() {
+ return this.nameValueFactory;
+ }
- /**
- * @return nameValueFactory
- */
- protected ValueFactory<Name> getNameValueFactory() {
- return this.nameValueFactory;
- }
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.jboss.dna.spi.graph.PathFactory#create()
+ */
+ public Path create() {
+ return BasicPath.ROOT;
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( String value ) {
- return create(value, getEncoder());
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( String value ) {
+ return create(value, getEncoder());
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( final String value, TextEncoder decoder ) throws ValueFormatException {
- if (value == null) return null;
- if (decoder == null) decoder = getEncoder();
- String trimmedValue = value.trim();
- int length = trimmedValue.length();
- boolean absolute = false;
- if (length == 0) {
- return BasicPath.ROOT;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( final String value,
+ TextEncoder decoder ) throws ValueFormatException {
+ if (value == null) return null;
+ if (decoder == null) decoder = getEncoder();
+ String trimmedValue = value.trim();
+ int length = trimmedValue.length();
+ boolean absolute = false;
+ if (length == 0) {
+ return BasicPath.ROOT;
+ }
- // Remove the leading delimiter ...
- if (trimmedValue.charAt(0) == DELIMITER) {
- trimmedValue = length > 1 ? trimmedValue.substring(1) : "";
- --length;
- absolute = true;
- }
- // remove the trailing delimiter ...
- if (length > 0 && trimmedValue.charAt(length - 1) == DELIMITER) {
- trimmedValue = length > 1 ? trimmedValue.substring(0, length - 1) : "";
- length = trimmedValue.length();
- }
- if (length == 0) {
- return BasicPath.ROOT;
- }
+ // Remove the leading delimiter ...
+ if (trimmedValue.charAt(0) == Path.DELIMITER) {
+ trimmedValue = length > 1 ? trimmedValue.substring(1) : "";
+ --length;
+ absolute = true;
+ }
+ // remove the trailing delimiter ...
+ if (length > 0 && trimmedValue.charAt(length - 1) == Path.DELIMITER) {
+ trimmedValue = length > 1 ? trimmedValue.substring(0, length - 1) : "";
+ length = trimmedValue.length();
+ }
+ if (length == 0) {
+ return BasicPath.ROOT;
+ }
- // Parse the path into its segments ...
- List<Segment> segments = new ArrayList<Segment>();
- String[] pathSegments = DELIMITER_PATTERN.split(trimmedValue);
- if (pathSegments.length == 0) {
- throw new InvalidPathException(SpiI18n.validPathMayNotContainEmptySegment.text(value));
- }
- assert pathSegments.length != 0;
- for (String segment : pathSegments) {
- assert segment != null;
- segment = segment.trim();
- if (segment.length() == 0) {
- throw new InvalidPathException(SpiI18n.validPathMayNotContainEmptySegment.text(value));
- }
- // Create the name and add a segment with it ...
- Name segmentName = this.getNameValueFactory().create(segment, decoder);
- segments.add(new BasicPathSegment(segmentName));
- }
+ // Parse the path into its segments ...
+ List<Segment> segments = new ArrayList<Segment>();
+ String[] pathSegments = DELIMITER_PATTERN.split(trimmedValue);
+ if (pathSegments.length == 0) {
+ throw new ValueFormatException(SpiI18n.validPathMayNotContainEmptySegment.text(value));
+ }
+ assert pathSegments.length != 0;
+ for (String segment : pathSegments) {
+ assert segment != null;
+ segment = segment.trim();
+ if (segment.length() == 0) {
+ throw new ValueFormatException(SpiI18n.validPathMayNotContainEmptySegment.text(value));
+ }
+ // Create the name and add a segment with it ...
+ segments.add(createSegment(segment, decoder));
+ }
- // Create a path constructed from the supplied segments ...
- return new BasicPath(segments, absolute);
- }
+ // Create a path constructed from the supplied segments ...
+ return new BasicPath(segments, absolute);
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( int value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( int value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
+ Date.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( long value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( long value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
+ Date.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( boolean value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( boolean value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
+ Date.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( float value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( float value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
+ Date.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( double value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( double value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
+ Date.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( BigDecimal value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( BigDecimal value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
+ Date.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Calendar value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Calendar value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
+ Date.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Date value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Date.class.getSimpleName(), value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Date value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
+ Date.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Name value ) {
- if (value == null) return null;
- List<Path.Segment> segments = new ArrayList<Path.Segment>(1);
- segments.add(new BasicPathSegment(value));
- return new BasicPath(segments, true);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Name value ) {
+ if (value == null) return null;
+ List<Path.Segment> segments = new ArrayList<Path.Segment>(1);
+ segments.add(new BasicPathSegment(value));
+ return new BasicPath(segments, true);
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Path value ) throws ValueFormatException {
- return value;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Path value ) throws ValueFormatException {
+ return value;
+ }
- /**
- * {@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( 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 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);
- }
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.jboss.dna.spi.graph.PathFactory#createRelativePath()
+ */
+ public Path createRelativePath() {
+ return BasicPath.SELF_PATH;
+ }
- /**
- * {@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 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 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 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... segmentNames ) {
- ArgCheck.isNotNull(parentPath, "parent path");
- if (segmentNames == null || segmentNames.length == 0) return parentPath;
+ /**
+ * {@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());
+ }
- 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,
+ Name... segmentNames ) {
+ ArgCheck.isNotNull(parentPath, "parent path");
+ if (segmentNames == null || segmentNames.length == 0) return parentPath;
- /**
- * {@inheritDoc}
- */
- public Path create( Path parentPath, Segment... segments ) {
- ArgCheck.isNotNull(parentPath, "parent path");
- if (segments == null || segments.length == 0) return BasicPath.ROOT;
+ 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());
+ }
- 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 Path create( Path parentPath,
+ Segment... segments ) {
+ ArgCheck.isNotNull(parentPath, "parent path");
+ if (segments == null || segments.length == 0) return BasicPath.ROOT;
- /**
- * {@inheritDoc}
- */
- public Segment createSegment( Name segmentName ) {
- ArgCheck.isNotNull(segmentName, "segment name");
- if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
- if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
- return new BasicPathSegment(segmentName);
- }
+ 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, int index ) {
- ArgCheck.isNotNull(segmentName, "segment name");
- if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
- if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
- return new BasicPathSegment(segmentName, index);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Segment createSegment( Name segmentName ) {
+ ArgCheck.isNotNull(segmentName, "segment name");
+ if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
+ if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
+ return new BasicPathSegment(segmentName);
+ }
- /**
- * {@inheritDoc}
- */
- public Segment createSegment( String segmentName ) {
- ArgCheck.isNotNull(segmentName, "segment name");
- if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
- if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
- return new BasicPathSegment(this.nameValueFactory.create(segmentName));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Segment createSegment( Name segmentName,
+ int index ) {
+ ArgCheck.isNotNull(segmentName, "segment name");
+ if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
+ if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
+ return new BasicPathSegment(segmentName, index);
+ }
- /**
- * {@inheritDoc}
- */
- public Segment createSegment( String segmentName, int index ) {
- ArgCheck.isNotNull(segmentName, "segment name");
- if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
- if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
- return new BasicPathSegment(this.nameValueFactory.create(segmentName), index);
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.PathFactory#createSegment(java.lang.String)
+ */
+ public Segment createSegment( String segmentName ) {
+ return createSegment(segmentName, getEncoder());
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Reference value ) throws ValueFormatException {
- throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(), Reference.class.getSimpleName(), value));
- }
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.jboss.dna.spi.graph.PathFactory#createSegment(java.lang.String, org.jboss.dna.common.text.TextEncoder)
+ */
+ public Segment createSegment( String segmentName,
+ TextEncoder encoder ) {
+ ArgCheck.isNotNull(segmentName, "segment name");
+ if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
+ if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
+ int startBracketNdx = segmentName.indexOf('[');
+ if (startBracketNdx < 0) {
+ return new BasicPathSegment(this.nameValueFactory.create(segmentName));
+ }
+ int endBracketNdx = segmentName.indexOf(']', startBracketNdx);
+ if (endBracketNdx < 0) {
+ throw new IllegalArgumentException(SpiI18n.missingEndBracketInSegmentName.text(segmentName));
+ }
+ String ndx = segmentName.substring(startBracketNdx + 1, endBracketNdx);
+ try {
+ return new BasicPathSegment(this.nameValueFactory.create(segmentName.substring(0, startBracketNdx)),
+ Integer.parseInt(ndx));
+ } catch (NumberFormatException err) {
+ throw new IllegalArgumentException(SpiI18n.invalidIndexInSegmentName.text(ndx, segmentName));
+ }
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( URI value ) throws ValueFormatException {
- if (value == null) return null;
- String asciiString = value.toASCIIString();
- // Remove any leading "./" ...
- if (asciiString.startsWith("./") && asciiString.length() > 2) {
- asciiString = asciiString.substring(2);
- }
- if (asciiString.indexOf('/') == -1) {
- return create(asciiString);
- }
- throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(), Path.class.getSimpleName(), value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Segment createSegment( String segmentName,
+ int index ) {
+ ArgCheck.isNotNull(segmentName, "segment name");
+ if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
+ if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
+ return new BasicPathSegment(this.nameValueFactory.create(segmentName), index);
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( byte[] value ) throws ValueFormatException {
- // First attempt to create a string from the value, then a long from the string ...
- return create(getStringValueFactory().create(value));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Reference value ) throws ValueFormatException {
+ throw new ValueFormatException(SpiI18n.unableToCreateValue.text(getPropertyType().getName(),
+ Reference.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( InputStream stream, int approximateLength ) throws IOException, ValueFormatException {
- // First attempt to create a string from the value, then a double from the string ...
- return create(getStringValueFactory().create(stream, approximateLength));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( URI value ) throws ValueFormatException {
+ if (value == null) return null;
+ String asciiString = value.toASCIIString();
+ // Remove any leading "./" ...
+ if (asciiString.startsWith("./") && asciiString.length() > 2) {
+ asciiString = asciiString.substring(2);
+ }
+ if (asciiString.indexOf('/') == -1) {
+ return create(asciiString);
+ }
+ throw new ValueFormatException(SpiI18n.errorCreatingValue.text(getPropertyType().getName(),
+ Path.class.getSimpleName(),
+ value));
+ }
- /**
- * {@inheritDoc}
- */
- public Path create( Reader reader, int approximateLength ) throws IOException, ValueFormatException {
- // First attempt to create a string from the value, then a double from the string ...
- return create(getStringValueFactory().create(reader, approximateLength));
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( byte[] value ) throws ValueFormatException {
+ // First attempt to create a string from the value, then a long from the string ...
+ return create(getStringValueFactory().create(value));
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( InputStream stream,
+ int approximateLength ) throws IOException, ValueFormatException {
+ // First attempt to create a string from the value, then a double from the string ...
+ return create(getStringValueFactory().create(stream, approximateLength));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Path create( Reader reader,
+ int approximateLength ) throws IOException, ValueFormatException {
+ // First attempt to create a string from the value, then a double from the string ...
+ return create(getStringValueFactory().create(reader, approximateLength));
+ }
+
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java 2008-06-02 20:12:41 UTC (rev 233)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java 2008-06-02 20:19:51 UTC (rev 234)
@@ -2,7 +2,7 @@
* 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.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -36,726 +36,741 @@
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.PathNotFoundException;
+import org.jboss.dna.spi.graph.ValueFormatException;
import org.junit.Before;
import org.junit.Test;
/**
* @author Randall Hauch
+ * @author John Verhaeg
*/
public class BasicPathTest {
- public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
- public static final Path ROOT = BasicPath.ROOT;
+ public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+ public static final Path ROOT = BasicPath.ROOT;
- private BasicNamespaceRegistry namespaceRegistry;
- private String validNamespaceUri;
- private Path path;
- private Path path2;
- private Path.Segment[] validSegments;
- private List<Path.Segment> validSegmentsList;
- private Name[] validSegmentNames;
- private String validNamespacePrefix;
- private PathValueFactory pathFactory;
+ private BasicNamespaceRegistry namespaceRegistry;
+ private String validNamespaceUri;
+ private Path path;
+ private Path path2;
+ private Path.Segment[] validSegments;
+ private List<Path.Segment> validSegmentsList;
+ private Name[] validSegmentNames;
+ private String validNamespacePrefix;
+ private PathValueFactory pathFactory;
- @Before
- public void beforeEach() throws Exception {
- validNamespacePrefix = "dna";
- validNamespaceUri = "http://www.jboss.org/dna";
- validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"), new BasicName(validNamespaceUri, "b"), new BasicName(validNamespaceUri, "c")};
- validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]), new BasicPathSegment(validSegmentNames[1]), new BasicPathSegment(validSegmentNames[1])};
- validSegmentsList = new ArrayList<Path.Segment>();
- for (Path.Segment segment : validSegments) {
- validSegmentsList.add(segment);
- }
- path = new BasicPath(validSegmentsList, true);
- namespaceRegistry = new BasicNamespaceRegistry();
- namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
- StringValueFactory stringValueFactory = new StringValueFactory(Path.DEFAULT_ENCODER);
- NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry, Path.DEFAULT_ENCODER, stringValueFactory);
- pathFactory = new PathValueFactory(Path.DEFAULT_ENCODER, stringValueFactory, nameValueFactory);
- }
+ @Before
+ public void beforeEach() throws Exception {
+ validNamespacePrefix = "dna";
+ validNamespaceUri = "http://www.jboss.org/dna";
+ validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"), new BasicName(validNamespaceUri, "b"),
+ new BasicName(validNamespaceUri, "c")};
+ validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]),
+ new BasicPathSegment(validSegmentNames[1]), new BasicPathSegment(validSegmentNames[1])};
+ validSegmentsList = new ArrayList<Path.Segment>();
+ for (Path.Segment segment : validSegments) {
+ validSegmentsList.add(segment);
+ }
+ path = new BasicPath(validSegmentsList, true);
+ namespaceRegistry = new BasicNamespaceRegistry();
+ namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
+ StringValueFactory stringValueFactory = new StringValueFactory(Path.DEFAULT_ENCODER);
+ NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry, Path.DEFAULT_ENCODER, stringValueFactory);
+ pathFactory = new PathValueFactory(Path.DEFAULT_ENCODER, stringValueFactory, nameValueFactory);
+ }
- @Test
- public void shouldCreateAbsolutePathFromListOfValidSegments() {
- path = new BasicPath(validSegmentsList, true);
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.isNormalized(), is(true));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateAbsolutePathFromListOfValidSegments() {
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(true));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateRelativePathFromListOfValidSegments() {
- path = new BasicPath(validSegmentsList, false);
- assertThat(path.isAbsolute(), is(false));
- assertThat(path.isNormalized(), is(true));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateRelativePathFromListOfValidSegments() {
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(true));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateAbsolutePathWithParentSegment() {
- validSegmentsList.add(Path.PARENT_SEGMENT);
- path = new BasicPath(validSegmentsList, true);
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateAbsolutePathWithParentSegment() {
+ validSegmentsList.add(Path.PARENT_SEGMENT);
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateRelativePathWithParentSegment() {
- validSegmentsList.add(Path.PARENT_SEGMENT);
- path = new BasicPath(validSegmentsList, false);
- assertThat(path.isAbsolute(), is(false));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateRelativePathWithParentSegment() {
+ validSegmentsList.add(Path.PARENT_SEGMENT);
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateAbsolutePathWithSelfSegment() {
- validSegmentsList.add(Path.SELF_SEGMENT);
- path = new BasicPath(validSegmentsList, true);
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateAbsolutePathWithSelfSegment() {
+ validSegmentsList.add(Path.SELF_SEGMENT);
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreateRelativePathWithSelfSegment() {
- validSegmentsList.add(Path.SELF_SEGMENT);
- path = new BasicPath(validSegmentsList, false);
- assertThat(path.isAbsolute(), is(false));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldCreateRelativePathWithSelfSegment() {
+ validSegmentsList.add(Path.SELF_SEGMENT);
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldCreatePathWithNoNamespacePrefixes() {
- path = pathFactory.create("/a/b/c/");
- assertThat(path.size(), is(3));
- assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
- }
+ @Test
+ public void shouldCreatePathWithNoNamespacePrefixes() {
+ path = pathFactory.create("/a/b/c/");
+ assertThat(path.size(), is(3));
+ assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
+ }
- @Test
- public void shouldConstructRelativePath() {
- assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
- assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
- assertThat(pathFactory.create("a/b/c").size(), is(3));
- assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry), is("a/b/c"));
- }
+ @Test
+ public void shouldConstructRelativePath() {
+ assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
+ assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
+ assertThat(pathFactory.create("a/b/c").size(), is(3));
+ assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry), is("a/b/c"));
+ }
- @Test
- public void shouldConstructRelativePathToSelf() {
- assertThat(pathFactory.create(".").isAbsolute(), is(false));
- assertThat(pathFactory.create(".").size(), is(1));
- assertThat(pathFactory.create("."), hasSegments(pathFactory, Path.SELF));
+ @Test
+ public void shouldConstructRelativePathToSelf() {
+ assertThat(pathFactory.create(".").isAbsolute(), is(false));
+ assertThat(pathFactory.create(".").size(), is(1));
+ assertThat(pathFactory.create("."), hasSegments(pathFactory, Path.SELF));
- assertThat(pathFactory.create("./").isAbsolute(), is(false));
- assertThat(pathFactory.create("./").size(), is(1));
- assertThat(pathFactory.create("./"), hasSegments(pathFactory, Path.SELF));
- }
+ assertThat(pathFactory.create("./").isAbsolute(), is(false));
+ assertThat(pathFactory.create("./").size(), is(1));
+ assertThat(pathFactory.create("./"), hasSegments(pathFactory, Path.SELF));
+ }
- @Test
- public void shouldConstructRelativePathToParent() {
- assertThat(pathFactory.create("..").isAbsolute(), is(false));
- assertThat(pathFactory.create("..").size(), is(1));
- assertThat(pathFactory.create(".."), hasSegments(pathFactory, Path.PARENT));
+ @Test
+ public void shouldConstructRelativePathToParent() {
+ assertThat(pathFactory.create("..").isAbsolute(), is(false));
+ assertThat(pathFactory.create("..").size(), is(1));
+ assertThat(pathFactory.create(".."), hasSegments(pathFactory, Path.PARENT));
- assertThat(pathFactory.create("../").isAbsolute(), is(false));
- assertThat(pathFactory.create("../").size(), is(1));
- assertThat(pathFactory.create("../"), hasSegments(pathFactory, Path.PARENT));
- }
+ assertThat(pathFactory.create("../").isAbsolute(), is(false));
+ assertThat(pathFactory.create("../").size(), is(1));
+ assertThat(pathFactory.create("../"), hasSegments(pathFactory, Path.PARENT));
+ }
- @Test
- public void shouldConstructRootPathFromStringWithSingleDelimiter() {
- assertThat(pathFactory.create("/"), is(ROOT));
- assertThat(pathFactory.create("/").isRoot(), is(true));
- }
+ @Test
+ public void shouldConstructRootPathFromStringWithSingleDelimiter() {
+ assertThat(pathFactory.create("/"), is(ROOT));
+ assertThat(pathFactory.create("/").isRoot(), is(true));
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotConstructPathWithSuccessiveDelimiters() {
- pathFactory.create("///a/b///c//d//");
- }
+ @Test( expected = ValueFormatException.class )
+ public void shouldNotConstructPathWithSuccessiveDelimiters() {
+ pathFactory.create("///a/b///c//d//");
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotConstructPathWithOnlyDelimiters() {
- pathFactory.create("///");
- }
+ @Test( expected = ValueFormatException.class )
+ public void shouldNotConstructPathWithOnlyDelimiters() {
+ pathFactory.create("///");
+ }
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotConstructPathFromNullList() {
- new BasicPath(null, true);
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotConstructPathFromNullList() {
+ new BasicPath(null, true);
+ }
- @Test
- public void shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
- assertThat(pathFactory.create(" \t / \t").toString(), is("/"));
- }
+ @Test
+ public void shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
+ assertThat(pathFactory.create(" \t / \t").toString(), is("/"));
+ }
- @Test
- public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
- assertThat(pathFactory.create("a"), hasSegments(pathFactory, "a"));
- }
+ @Test
+ public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
+ assertThat(pathFactory.create("a"), hasSegments(pathFactory, "a"));
+ }
- @Test
- public void shouldHaveSizeThatReflectsNumberOfSegments() {
- assertThat(path.size(), is(validSegmentsList.size()));
- }
+ @Test
+ public void shouldHaveSizeThatReflectsNumberOfSegments() {
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
- @Test
- public void shouldIterateOverAllSegmentsReturnedByList() {
- Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
- for (Path.Segment segment : path) {
- assertThat(segment, is(expectedIter.next()));
- }
+ @Test
+ public void shouldIterateOverAllSegmentsReturnedByList() {
+ Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
+ for (Path.Segment segment : path) {
+ assertThat(segment, is(expectedIter.next()));
+ }
- expectedIter = path.getSegmentsList().iterator();
- for (Path.Segment segment : path) {
- assertThat(segment, is(expectedIter.next()));
- }
- }
+ expectedIter = path.getSegmentsList().iterator();
+ for (Path.Segment segment : path) {
+ assertThat(segment, is(expectedIter.next()));
+ }
+ }
- @Test
- public void shouldReturnRootForAncestorOfRoot() {
- assertThat(BasicPath.ROOT.getAncestor(), is(ROOT));
- }
+ @Test
+ public void shouldReturnRootForAncestorOfRoot() {
+ assertThat(BasicPath.ROOT.getAncestor(), is(ROOT));
+ }
- @Test
- public void shouldReturnAncestorForNodeOtherThanRoot() {
- assertThat(path.getAncestor(), is(pathFactory.create("/dna:a/dna:b")));
- assertThat(path.getAncestor().getAncestor(), is(pathFactory.create("/dna:a")));
- assertThat(path.getAncestor().getAncestor().getAncestor(), is(ROOT));
- }
+ @Test
+ public void shouldReturnAncestorForNodeOtherThanRoot() {
+ assertThat(path.getAncestor(), is(pathFactory.create("/dna:a/dna:b")));
+ assertThat(path.getAncestor().getAncestor(), is(pathFactory.create("/dna:a")));
+ assertThat(path.getAncestor().getAncestor().getAncestor(), is(ROOT));
+ }
- @Test
- public void shouldReturnNthDegreeAncestor() {
- assertThat(path.getAncestor(1), is(pathFactory.create("/dna:a/dna:b")));
- assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
- assertThat(path.getAncestor(3), is(ROOT));
- }
+ @Test
+ public void shouldReturnNthDegreeAncestor() {
+ assertThat(path.getAncestor(1), is(pathFactory.create("/dna:a/dna:b")));
+ assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
+ assertThat(path.getAncestor(3), is(ROOT));
+ }
- @Test( expected = PathNotFoundException.class )
- public void shouldNotAllowAncestorDegreeLargerThanSize() {
- path.getAncestor(path.size() + 1);
- }
+ @Test( expected = PathNotFoundException.class )
+ public void shouldNotAllowAncestorDegreeLargerThanSize() {
+ path.getAncestor(path.size() + 1);
+ }
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowNegativeAncestorDegree() {
- path.getAncestor(-1);
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNegativeAncestorDegree() {
+ path.getAncestor(-1);
+ }
- @Test
- public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
- assertThat(path.getAncestor(path.size()), is(ROOT));
- assertThat(ROOT.getAncestor(0), is(ROOT));
- }
+ @Test
+ public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
+ assertThat(path.getAncestor(path.size()), is(ROOT));
+ assertThat(ROOT.getAncestor(0), is(ROOT));
+ }
- @Test
- public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
- assertThat(path.getCommonAncestor(ROOT), is(ROOT));
- assertThat(ROOT.getCommonAncestor(path), is(ROOT));
- }
+ @Test
+ public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
+ assertThat(path.getCommonAncestor(ROOT), is(ROOT));
+ assertThat(ROOT.getCommonAncestor(path), is(ROOT));
+ }
- @Test
- public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
- assertThat(path.getCommonAncestor(null), is(nullValue()));
- }
+ @Test
+ public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
+ assertThat(path.getCommonAncestor(null), is(nullValue()));
+ }
- @Test
- public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path common = pathFactory.create("/a");
- assertThat(path1.getCommonAncestor(path2), is(common));
+ @Test
+ public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(path1.getCommonAncestor(path2), is(common));
- path1 = pathFactory.create("/a/b/c");
- path2 = pathFactory.create("/a/b/c/d");
- common = path1;
- assertThat(path1.getCommonAncestor(path2), is(common));
+ path1 = pathFactory.create("/a/b/c");
+ path2 = pathFactory.create("/a/b/c/d");
+ common = path1;
+ assertThat(path1.getCommonAncestor(path2), is(common));
- path1 = pathFactory.create("/a/b/c/x/y/");
- path2 = pathFactory.create("/a/b/c/d/e/f/");
- common = pathFactory.create("/a/b/c");
- assertThat(path1.getCommonAncestor(path2), is(common));
- }
+ path1 = pathFactory.create("/a/b/c/x/y/");
+ path2 = pathFactory.create("/a/b/c/d/e/f/");
+ common = pathFactory.create("/a/b/c");
+ assertThat(path1.getCommonAncestor(path2), is(common));
+ }
- @Test
- public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
- Path path1 = pathFactory.create("/x/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path common = ROOT;
- assertThat(path1.getCommonAncestor(path2), is(common));
- }
+ @Test
+ public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
+ Path path1 = pathFactory.create("/x/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path common = ROOT;
+ assertThat(path1.getCommonAncestor(path2), is(common));
+ }
- @Test
- public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- Path common = pathFactory.create("/a");
- assertThat(common.isAncestorOf(path1), is(true));
- assertThat(common.isAncestorOf(path2), is(true));
- assertThat(common.isAncestorOf(path3), is(false));
+ @Test
+ public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ Path common = pathFactory.create("/a");
+ assertThat(common.isAncestorOf(path1), is(true));
+ assertThat(common.isAncestorOf(path2), is(true));
+ assertThat(common.isAncestorOf(path3), is(false));
- assertThat(path1.getAncestor().isAncestorOf(path1), is(true));
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
- }
- }
+ assertThat(path1.getAncestor().isAncestorOf(path1), is(true));
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
+ }
+ }
- @Test
- public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- Path common = pathFactory.create("/a");
- assertThat(path1.isDecendantOf(common), is(true));
- assertThat(path2.isDecendantOf(common), is(true));
- assertThat(path3.isDecendantOf(common), is(false));
+ @Test
+ public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ Path common = pathFactory.create("/a");
+ assertThat(path1.isDecendantOf(common), is(true));
+ assertThat(path2.isDecendantOf(common), is(true));
+ assertThat(path3.isDecendantOf(common), is(false));
- assertThat(path1.getAncestor().isAncestorOf(path1), is(true));
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
- }
- }
+ assertThat(path1.getAncestor().isAncestorOf(path1), is(true));
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
+ }
+ }
- @Test
- public void shouldNotConsiderNodeToBeAncestorOfItself() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- assertThat(path1.isAncestorOf(path1), is(false));
- assertThat(path2.isAncestorOf(path2), is(false));
- assertThat(path3.isAncestorOf(path3), is(false));
- assertThat(ROOT.isAncestorOf(ROOT), is(false));
- }
+ @Test
+ public void shouldNotConsiderNodeToBeAncestorOfItself() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ assertThat(path1.isAncestorOf(path1), is(false));
+ assertThat(path2.isAncestorOf(path2), is(false));
+ assertThat(path3.isAncestorOf(path3), is(false));
+ assertThat(ROOT.isAncestorOf(ROOT), is(false));
+ }
- @Test
- public void shouldNotConsiderNodeToBeDecendantOfItself() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- assertThat(path1.isDecendantOf(path1), is(false));
- assertThat(path2.isDecendantOf(path2), is(false));
- assertThat(path3.isDecendantOf(path3), is(false));
- assertThat(ROOT.isDecendantOf(ROOT), is(false));
- }
+ @Test
+ public void shouldNotConsiderNodeToBeDecendantOfItself() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ assertThat(path1.isDecendantOf(path1), is(false));
+ assertThat(path2.isDecendantOf(path2), is(false));
+ assertThat(path3.isDecendantOf(path3), is(false));
+ assertThat(ROOT.isDecendantOf(ROOT), is(false));
+ }
- @Test
- public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path common = pathFactory.create("/a");
- assertThat(ROOT.isDecendantOf(path1), is(false));
- assertThat(ROOT.isDecendantOf(path2), is(false));
- assertThat(ROOT.isDecendantOf(path3), is(false));
- assertThat(ROOT.isDecendantOf(common), is(false));
- }
+ @Test
+ public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(ROOT.isDecendantOf(path1), is(false));
+ assertThat(ROOT.isDecendantOf(path2), is(false));
+ assertThat(ROOT.isDecendantOf(path3), is(false));
+ assertThat(ROOT.isDecendantOf(common), is(false));
+ }
- @Test
- public void shouldConsiderRootToBeAncestorOfAnyNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path common = pathFactory.create("/a");
- assertThat(ROOT.isAncestorOf(path1), is(true));
- assertThat(ROOT.isAncestorOf(path2), is(true));
- assertThat(ROOT.isAncestorOf(path3), is(true));
- assertThat(ROOT.isAncestorOf(common), is(true));
- }
+ @Test
+ public void shouldConsiderRootToBeAncestorOfAnyNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(ROOT.isAncestorOf(path1), is(true));
+ assertThat(ROOT.isAncestorOf(path2), is(true));
+ assertThat(ROOT.isAncestorOf(path3), is(true));
+ assertThat(ROOT.isAncestorOf(common), is(true));
+ }
- @Test
- public void shouldNotConsiderRootToBeAncestorOfItself() {
- assertThat(ROOT.isAncestorOf(ROOT), is(false));
- }
+ @Test
+ public void shouldNotConsiderRootToBeAncestorOfItself() {
+ assertThat(ROOT.isAncestorOf(ROOT), is(false));
+ }
- @Test
- public void shouldNotConsiderRootToBeDecendantOfItself() {
- assertThat(ROOT.isDecendantOf(ROOT), is(false));
- }
+ @Test
+ public void shouldNotConsiderRootToBeDecendantOfItself() {
+ assertThat(ROOT.isDecendantOf(ROOT), is(false));
+ }
- @Test
- public void shouldNeverBeDecendantOfNullPath() {
- assertThat(path.isDecendantOf(null), is(false));
- assertThat(ROOT.isDecendantOf(null), is(false));
- }
+ @Test
+ public void shouldNeverBeDecendantOfNullPath() {
+ assertThat(path.isDecendantOf(null), is(false));
+ assertThat(ROOT.isDecendantOf(null), is(false));
+ }
- @Test
- public void shouldReturnNullForLastSegmentOfRoot() {
- assertThat(ROOT.getLastSegment(), is(nullValue()));
- }
+ @Test
+ public void shouldReturnNullForLastSegmentOfRoot() {
+ assertThat(ROOT.getLastSegment(), is(nullValue()));
+ }
- @Test
- public void shouldReturnLastSegmentOfNonRootPath() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
- assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
- assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
- assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
- assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
- }
+ @Test
+ public void shouldReturnLastSegmentOfNonRootPath() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
+ assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
+ assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
+ assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
+ assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
+ }
- @Test
- public void shouldNormalizePathWithSelfAndParentReferences() {
- path = pathFactory.create("/a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(true));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ @Test
+ public void shouldNormalizePathWithSelfAndParentReferences() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
- path = pathFactory.create("a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(false));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
- }
+ path = pathFactory.create("a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
- @Test
- public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
- assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
- assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
- assertThat(pathFactory.create("a").isNormalized(), is(true));
- assertThat(pathFactory.create("/a").isNormalized(), is(true));
- assertThat(ROOT.isNormalized(), is(true));
- }
+ @Test
+ public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
+ assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
+ assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
+ assertThat(pathFactory.create("a").isNormalized(), is(true));
+ assertThat(pathFactory.create("/a").isNormalized(), is(true));
+ assertThat(ROOT.isNormalized(), is(true));
+ }
- @Test
- public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
- assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(), is(false));
- assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(), is(false));
- assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
- assertThat(pathFactory.create("/a/b/c/../d").isNormalized(), is(false));
- assertThat(pathFactory.create(".").isNormalized(), is(false));
- assertThat(pathFactory.create("/.").isNormalized(), is(false));
- }
+ @Test
+ public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
+ assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(), is(false));
+ assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(), is(false));
+ assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
+ assertThat(pathFactory.create("/a/b/c/../d").isNormalized(), is(false));
+ assertThat(pathFactory.create(".").isNormalized(), is(false));
+ assertThat(pathFactory.create("/.").isNormalized(), is(false));
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
- path = pathFactory.create("/a/../../../..");
- assertThat(path.isNormalized(), is(false));
- path.getNormalizedPath();
- }
+ @Test( expected = InvalidPathException.class )
+ public void shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
+ path = pathFactory.create("/a/../../../..");
+ assertThat(path.isNormalized(), is(false));
+ path.getNormalizedPath();
+ }
- @Test
- public void shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
- // "/a/../b/../c/.." => "/"
- path = pathFactory.create("/a/../b/../c/../");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), is(ROOT));
- }
+ @Test
+ public void shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
+ // "/a/../b/../c/.." => "/"
+ path = pathFactory.create("/a/../b/../c/../");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), is(ROOT));
+ }
- @Test
- public void shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
- // "a/../b/../c/.." => "."
- path = pathFactory.create("a/../b/../c/../");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath().size(), is(1));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
- }
+ @Test
+ public void shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved() {
+ // "a/../b/../c/.." => "."
+ path = pathFactory.create("a/../b/../c/../");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath().size(), is(1));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
+ }
- @Test
- public void shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
- path = pathFactory.create("/a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(true));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
- }
+ @Test
+ public void shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
- @Test
- public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
- path = pathFactory.create("a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(false));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
- }
+ @Test
+ public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
+ path = pathFactory.create("a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
- pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
- }
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
+ pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
+ }
- @Test
- public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
- path = pathFactory.create("/a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a", "b"));
- assertThat(path.getCanonicalPath().isAbsolute(), is(true));
- assertThat(path.getCanonicalPath().isNormalized(), is(true));
- }
+ @Test
+ public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a", "b"));
+ assertThat(path.getCanonicalPath().isAbsolute(), is(true));
+ assertThat(path.getCanonicalPath().isNormalized(), is(true));
+ }
- @Test
- public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
- testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
- testSegmentsByIteratorAndListAndArray("/a/b/c", "a", "b", "c");
- testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
- testSegmentsByIteratorAndListAndArray("a/b/c", "a", "b", "c");
- testSegmentsByIteratorAndListAndArray("");
- testSegmentsByIteratorAndListAndArray(ROOT.getString());
- }
+ @Test
+ public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
+ testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
+ testSegmentsByIteratorAndListAndArray("/a/b/c", "a", "b", "c");
+ testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..", "a", "b", "c", "..", "d", ".", "e", "..", "..");
+ testSegmentsByIteratorAndListAndArray("a/b/c", "a", "b", "c");
+ testSegmentsByIteratorAndListAndArray("");
+ testSegmentsByIteratorAndListAndArray(ROOT.getString());
+ }
- public void testSegmentsByIteratorAndListAndArray( String pathStr, String... expectedSegmentStrings ) {
- path = pathFactory.create(pathStr);
- assertThat(expectedSegmentStrings.length, is(path.size()));
- Path.Segment[] segmentArray = path.getSegmentsArray();
- List<Path.Segment> segmentList = path.getSegmentsList();
- assertThat(segmentArray.length, is(path.size()));
- assertThat(segmentList.size(), is(path.size()));
- Iterator<Path.Segment> iter = path.iterator();
- Iterator<Path.Segment> listIter = segmentList.iterator();
- for (int i = 0; i != path.size(); ++i) {
- Path.Segment expected = pathFactory.createSegment(expectedSegmentStrings[i]);
- assertThat(path.getSegment(i), is(expected));
- assertThat(segmentArray[i], is(expected));
- assertThat(segmentList.get(i), is(expected));
- assertThat(iter.next(), is(expected));
- assertThat(listIter.next(), is(expected));
- }
- assertThat(iter.hasNext(), is(false));
- assertThat(listIter.hasNext(), is(false));
- }
+ public void testSegmentsByIteratorAndListAndArray( String pathStr,
+ String... expectedSegmentStrings ) {
+ path = pathFactory.create(pathStr);
+ assertThat(expectedSegmentStrings.length, is(path.size()));
+ Path.Segment[] segmentArray = path.getSegmentsArray();
+ List<Path.Segment> segmentList = path.getSegmentsList();
+ assertThat(segmentArray.length, is(path.size()));
+ assertThat(segmentList.size(), is(path.size()));
+ Iterator<Path.Segment> iter = path.iterator();
+ Iterator<Path.Segment> listIter = segmentList.iterator();
+ for (int i = 0; i != path.size(); ++i) {
+ Path.Segment expected = pathFactory.createSegment(expectedSegmentStrings[i]);
+ assertThat(path.getSegment(i), is(expected));
+ assertThat(segmentArray[i], is(expected));
+ assertThat(segmentList.get(i), is(expected));
+ assertThat(iter.next(), is(expected));
+ assertThat(listIter.next(), is(expected));
+ }
+ assertThat(iter.hasNext(), is(false));
+ assertThat(listIter.hasNext(), is(false));
+ }
- @Test
- public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.getString(NO_OP_ENCODER), is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../{}d/./{http://www.jboss.org/dna}e/../.."));
- }
+ @Test
+ public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.getString(NO_OP_ENCODER),
+ is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../{}d/./{http://www.jboss.org/dna}e/../.."));
+ }
- @Test
- public void shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna:a/b/dna:c/../d/./dna:e/../.."));
- namespaceRegistry.register("dna2", validNamespaceUri);
- assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
- }
+ @Test
+ public void shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna:a/b/dna:c/../d/./dna:e/../.."));
+ namespaceRegistry.register("dna2", validNamespaceUri);
+ assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER), is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(-1);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(-1);
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(path.size() + 1);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(path.size() + 1);
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(path.size() + 1, path.size() + 2);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(path.size() + 1, path.size() + 2);
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(2, 1);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(2, 1);
+ }
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(2, path.size() + 1);
- }
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(2, path.size() + 1);
+ }
- @Test
- public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0, 0), is(ROOT));
- }
+ @Test
+ public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0, 0), is(ROOT));
+ }
- @Test
- public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(0), is(path));
- assertThat(path.subpath(0), is(sameInstance(path)));
- assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
- assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
- assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
- assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+ @Test
+ public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(0), is(path));
+ assertThat(path.subpath(0), is(sameInstance(path)));
+ assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
+ assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
+ assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
- path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(0), is(path));
- assertThat(path.subpath(0), is(sameInstance(path)));
- assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
- assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
- assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
- assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
- }
+ path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(0), is(path));
+ assertThat(path.subpath(0), is(sameInstance(path)));
+ assertThat(path.subpath(1), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e", "..", ".."));
+ assertThat(path.subpath(7), hasSegments(pathFactory, "..", ".."));
+ assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+ }
- @Test
- public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0, path.size()), hasSegments(pathFactory, "dna:a", "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(0, path.size()), is(path));
- assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
- assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(2, path.size()), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
- assertThat(path.subpath(6, path.size()), hasSegments(pathFactory, "dna:e", "..", ".."));
- assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..", ".."));
- assertThat(path.subpath(8, path.size()), hasSegments(pathFactory, ".."));
+ @Test
+ public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0, path.size()), hasSegments(pathFactory,
+ "dna:a",
+ "b",
+ "dna:c",
+ "..",
+ "d",
+ ".",
+ "dna:e",
+ "..",
+ ".."));
+ assertThat(path.subpath(0, path.size()), is(path));
+ assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
+ assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b", "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(2, path.size()), hasSegments(pathFactory, "dna:c", "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..", "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(6, path.size()), hasSegments(pathFactory, "dna:e", "..", ".."));
+ assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..", ".."));
+ assertThat(path.subpath(8, path.size()), hasSegments(pathFactory, ".."));
- assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a", "b"));
- assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
- assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b", "dna:c", "..", "d"));
- assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c", "..", "d"));
- assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..", "d"));
- }
+ assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a", "b"));
+ assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
+ assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b", "dna:c", "..", "d"));
+ assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c", "..", "d"));
+ assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..", "d"));
+ }
- @Test
- public void shouldFindRelativePaths() {
- path = pathFactory.create("/a/b/c/d");
- assertThat(path.relativeTo(pathFactory.create("/a/e/f")), is(pathFactory.create("../../b/c/d")));
- assertThat(path.relativeTo(pathFactory.create("/e/f")), is(pathFactory.create("../../a/b/c/d")));
+ @Test
+ public void shouldFindRelativePaths() {
+ path = pathFactory.create("/a/b/c/d");
+ assertThat(path.relativeTo(pathFactory.create("/a/e/f")), is(pathFactory.create("../../b/c/d")));
+ assertThat(path.relativeTo(pathFactory.create("/e/f")), is(pathFactory.create("../../a/b/c/d")));
- }
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
- path = pathFactory.create("a/b/c/d");
- path.relativeTo(pathFactory.create("/e/f"));
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
+ path = pathFactory.create("a/b/c/d");
+ path.relativeTo(pathFactory.create("/e/f"));
- }
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotResolveRelativePathToAnotherRelativePath() {
- path = pathFactory.create("/a/b/c/d");
- path.relativeTo(pathFactory.create("e/f"));
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotResolveRelativePathToAnotherRelativePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path.relativeTo(pathFactory.create("e/f"));
- }
+ }
- @Test( expected = InvalidPathException.class )
- public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
- path = pathFactory.create("/a/b/c/d");
- path.resolve(pathFactory.create("/e/f"));
- }
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path.resolve(pathFactory.create("/e/f"));
+ }
- @Test
- public void shouldResolveRelativePathToAbsolutePath() {
- path = pathFactory.create("/a/b/c/d");
- path2 = path.resolve(pathFactory.create("../../e/f"));
- assertThat(path2, is(pathFactory.create("/a/b/e/f")));
- assertThat(path2.isAbsolute(), is(true));
- assertThat(path2.isNormalized(), is(true));
- }
+ @Test
+ public void shouldResolveRelativePathToAbsolutePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path2 = path.resolve(pathFactory.create("../../e/f"));
+ assertThat(path2, is(pathFactory.create("/a/b/e/f")));
+ assertThat(path2.isAbsolute(), is(true));
+ assertThat(path2.isNormalized(), is(true));
+ }
- @Test
- public void shouldOrderPathsCorrectly() {
- List<Path> paths = new ArrayList<Path>();
- paths.add(pathFactory.create("/a"));
- paths.add(pathFactory.create("/a/b"));
- paths.add(pathFactory.create("/a/b/alpha"));
- paths.add(pathFactory.create("/a/b/beta"));
- paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
- paths.add(pathFactory.create("/a/b/dna:name"));
- paths.add(pathFactory.create("/a/b/dna:primaryType"));
- paths.add(pathFactory.create("/a/c[1]"));
- paths.add(pathFactory.create("/a/c[1]/alpha"));
- paths.add(pathFactory.create("/a/c[1]/beta"));
- paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
- paths.add(pathFactory.create("/a/c[1]/dna:name"));
- paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
- paths.add(pathFactory.create("/a/c[2]"));
- paths.add(pathFactory.create("/a/c[2]/alpha"));
- paths.add(pathFactory.create("/a/c[2]/beta"));
- paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
- paths.add(pathFactory.create("/a/c[2]/dna:name"));
- paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
+ @Test
+ public void shouldOrderPathsCorrectly() {
+ List<Path> paths = new ArrayList<Path>();
+ paths.add(pathFactory.create("/a"));
+ paths.add(pathFactory.create("/a/b"));
+ paths.add(pathFactory.create("/a/b/alpha"));
+ paths.add(pathFactory.create("/a/b/beta"));
+ paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/b/dna:name"));
+ paths.add(pathFactory.create("/a/b/dna:primaryType"));
+ paths.add(pathFactory.create("/a/c[1]"));
+ paths.add(pathFactory.create("/a/c[1]/alpha"));
+ paths.add(pathFactory.create("/a/c[1]/beta"));
+ paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/c[1]/dna:name"));
+ paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
+ paths.add(pathFactory.create("/a/c[2]"));
+ paths.add(pathFactory.create("/a/c[2]/alpha"));
+ paths.add(pathFactory.create("/a/c[2]/beta"));
+ paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/c[2]/dna:name"));
+ paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
- // Randomize the list of paths, so we have something to sort ...
- List<Path> randomizedPaths = new ArrayList<Path>(paths);
- Collections.shuffle(randomizedPaths);
- assertThat(randomizedPaths, is(not(paths)));
+ // Randomize the list of paths, so we have something to sort ...
+ List<Path> randomizedPaths = new ArrayList<Path>(paths);
+ Collections.shuffle(randomizedPaths);
+ assertThat(randomizedPaths, is(not(paths)));
- // Sort ...
- Collections.sort(randomizedPaths);
- assertThat(randomizedPaths, is(paths));
- }
+ // Sort ...
+ Collections.sort(randomizedPaths);
+ assertThat(randomizedPaths, is(paths));
+ }
- @Test
- public void shouldGetNormalizedPathOfSelfShouldBeSame() {
- assertThat(pathFactory.create(".").getNormalizedPath(), is(pathFactory.create(".")));
- assertThat(pathFactory.create("./").getNormalizedPath(), is(pathFactory.create(".")));
- assertThat(pathFactory.create("./././").getNormalizedPath(), is(pathFactory.create(".")));
- }
+ @Test
+ public void shouldGetNormalizedPathOfSelfShouldBeSame() {
+ assertThat(pathFactory.create(".").getNormalizedPath(), is(pathFactory.create(".")));
+ assertThat(pathFactory.create("./").getNormalizedPath(), is(pathFactory.create(".")));
+ assertThat(pathFactory.create("./././").getNormalizedPath(), is(pathFactory.create(".")));
+ }
- @Test
- public void shouldGetNormalizedPathWithParentReferences() {
- assertThat(pathFactory.create("..").getNormalizedPath(), is(pathFactory.create("..")));
- assertThat(pathFactory.create("../").getNormalizedPath(), is(pathFactory.create("../")));
- assertThat(pathFactory.create("../../../../../..").getNormalizedPath(), is(pathFactory.create("../../../../../..")));
- }
+ @Test
+ public void shouldGetNormalizedPathWithParentReferences() {
+ assertThat(pathFactory.create("..").getNormalizedPath(), is(pathFactory.create("..")));
+ assertThat(pathFactory.create("../").getNormalizedPath(), is(pathFactory.create("../")));
+ assertThat(pathFactory.create("../../../../../..").getNormalizedPath(), is(pathFactory.create("../../../../../..")));
+ }
- @Test
- public void shouldGetRelativePathUsingSelf() {
- path = pathFactory.create("/a/b/c/d/e/f");
- assertThat(path.resolve(pathFactory.create(".")), is(sameInstance(path)));
- assertThat(path.resolve(pathFactory.create("././.")), is(sameInstance(path)));
- }
+ @Test
+ public void shouldGetRelativePathUsingSelf() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create(".")), is(sameInstance(path)));
+ assertThat(path.resolve(pathFactory.create("././.")), is(sameInstance(path)));
+ }
- @Test
- public void shouldResolveRelativePathToParent() {
- path = pathFactory.create("/a/b/c/d/e/f");
- assertThat(path.resolve(pathFactory.create("..")), is(path.getAncestor()));
- assertThat(path.resolve(pathFactory.create("..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
- }
+ @Test
+ public void shouldResolveRelativePathToParent() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create("..")), is(path.getAncestor()));
+ assertThat(path.resolve(pathFactory.create("..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
+ }
- @Test
- public void shouldResolveRelativePaths() {
- path = pathFactory.create("/a/b/c/d/e/f");
- assertThat(path.resolve(pathFactory.create("../../../../../..")), is(sameInstance(ROOT)));
- assertThat(path.resolve(pathFactory.create("../..")), is(path.getAncestor().getAncestor()));
- assertThat(path.resolve(pathFactory.create("../..")), hasSegments(pathFactory, "a", "b", "c", "d"));
- assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), is(path.getAncestor()));
- assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
- assertThat(path.resolve(pathFactory.create("../x")), hasSegments(pathFactory, "a", "b", "c", "d", "e", "x"));
- }
+ @Test
+ public void shouldResolveRelativePaths() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create("../../../../../..")), is(sameInstance(ROOT)));
+ assertThat(path.resolve(pathFactory.create("../..")), is(path.getAncestor().getAncestor()));
+ assertThat(path.resolve(pathFactory.create("../..")), hasSegments(pathFactory, "a", "b", "c", "d"));
+ assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), is(path.getAncestor()));
+ assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")), hasSegments(pathFactory, "a", "b", "c", "d", "e"));
+ assertThat(path.resolve(pathFactory.create("../x")), hasSegments(pathFactory, "a", "b", "c", "d", "e", "x"));
+ }
- public void shouldResolveNonAbsolutePaths() {
- path = pathFactory.create("a/b/c");
- assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
- }
+ public void shouldResolveNonAbsolutePaths() {
+ path = pathFactory.create("a/b/c");
+ assertThat(path, hasSegments(pathFactory, "a", "b", "c"));
+ }
}
17 years, 6 months
DNA SVN: r233 - trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-06-02 16:12:41 -0400 (Mon, 02 Jun 2008)
New Revision: 233
Modified:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/NameValueFactoryTest.java
Log:
DNA-89: Added getNamespaceRegistry() to NameFactory, SequencerOutput, and impls, as well as constant for "jcr:primaryType" to NameFactory
DNA-94: Changed to throw IAE if name is null or empty
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/NameValueFactoryTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/NameValueFactoryTest.java 2008-06-02 20:11:36 UTC (rev 232)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/NameValueFactoryTest.java 2008-06-02 20:12:41 UTC (rev 233)
@@ -2,7 +2,7 @@
* 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.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertThat;
import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.NamespaceRegistry;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.ValueFactory;
import org.junit.Before;
@@ -32,63 +33,88 @@
/**
* @author Randall Hauch
+ * @author John Verhaeg
*/
public class NameValueFactoryTest {
- public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+ public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
- private BasicNamespaceRegistry registry;
- private ValueFactory<String> stringValueFactory;
- private NameValueFactory factory;
- private TextEncoder encoder;
- private Name name;
+ private NamespaceRegistry registry;
+ private ValueFactory<String> stringValueFactory;
+ private NameValueFactory factory;
+ private TextEncoder encoder;
+ private Name name;
- @Before
- public void beforeEach() throws Exception {
- this.registry = new BasicNamespaceRegistry();
- this.registry.register("dna", "http://www.jboss.org/dna/namespace");
- this.encoder = Path.DEFAULT_ENCODER;
- this.stringValueFactory = new StringValueFactory(encoder);
- this.factory = new NameValueFactory(registry, encoder, stringValueFactory);
- }
+ @Before
+ public void beforeEach() throws Exception {
+ this.registry = new BasicNamespaceRegistry();
+ this.registry.register("dna", "http://www.jboss.org/dna/namespace");
+ this.encoder = Path.DEFAULT_ENCODER;
+ this.stringValueFactory = new StringValueFactory(encoder);
+ this.factory = new NameValueFactory(registry, encoder, stringValueFactory);
+ }
- @Test
- public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormatWithoutPrefix() {
- name = factory.create("a");
- assertThat(name.getLocalName(), is("a"));
- assertThat(name.getNamespaceUri(), is(this.registry.getNamespaceForPrefix("")));
- }
+ @Test
+ public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormatWithoutPrefix() {
+ name = factory.create("a");
+ assertThat(name.getLocalName(), is("a"));
+ assertThat(name.getNamespaceUri(), is(this.registry.getNamespaceForPrefix("")));
+ }
- @Test
- public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormat() {
- name = factory.create("dna:something");
- assertThat(name.getLocalName(), is("something"));
- assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
- assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
- }
+ @Test
+ public void shouldCreateNameFromSingleStringInPrefixedNamespaceFormat() {
+ name = factory.create("dna:something");
+ assertThat(name.getLocalName(), is("something"));
+ assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+ assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
+ }
- @Test
- public void shouldCreateNameFromSingleEncodedStringInPrefixedNamespaceFormat() {
- name = factory.create(encoder.encode("dna") + ":" + encoder.encode("some/thing"));
- assertThat(name.getLocalName(), is("some/thing"));
- assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
- assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
- }
+ @Test
+ public void shouldCreateNameFromSingleEncodedStringInPrefixedNamespaceFormat() {
+ name = factory.create(encoder.encode("dna") + ":" + encoder.encode("some/thing"));
+ assertThat(name.getLocalName(), is("some/thing"));
+ assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+ assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
+ }
- @Test
- public void shouldCreateNameFromSingleStringInStandardFullNamespaceFormat() {
- name = factory.create("{http://www.jboss.org/dna/namespace}something");
- assertThat(name.getLocalName(), is("something"));
- assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
- assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
- }
+ @Test
+ public void shouldCreateNameFromSingleStringInStandardFullNamespaceFormat() {
+ name = factory.create("{http://www.jboss.org/dna/namespace}something");
+ assertThat(name.getLocalName(), is("something"));
+ assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+ assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}something"));
+ }
- @Test
- public void shouldCreateNameFromSingleEncodedStringInStandardFullNamespaceFormat() {
- name = factory.create("{" + encoder.encode("http://www.jboss.org/dna/namespace") + "}" + encoder.encode("some/thing"));
- assertThat(name.getLocalName(), is("some/thing"));
- assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
- assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
- }
+ @Test
+ public void shouldCreateNameFromSingleEncodedStringInStandardFullNamespaceFormat() {
+ name = factory.create("{" + encoder.encode("http://www.jboss.org/dna/namespace") + "}" + encoder.encode("some/thing"));
+ assertThat(name.getLocalName(), is("some/thing"));
+ assertThat(name.getNamespaceUri(), is("http://www.jboss.org/dna/namespace"));
+ assertThat(name.getString(NO_OP_ENCODER), is("{http://www.jboss.org/dna/namespace}some/thing"));
+ }
+ @Test
+ public void shouldProvideAccessToNamespaceRegistryPassedInConstructor() {
+ assertThat(factory.getNamespaceRegistry(), is(registry));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNullLocalName() {
+ factory.create("a", (String)null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNullLocalNameWithEncoder() {
+ factory.create("a", null, encoder);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowEmptyLocalName() {
+ factory.create("a", "");
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowEmptyLocalNameWithEncoder() {
+ factory.create("a", "", encoder);
+ }
}
17 years, 6 months
DNA SVN: r232 - trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-06-02 16:11:36 -0400 (Mon, 02 Jun 2008)
New Revision: 232
Modified:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicNameTest.java
Log:
DNA-94: Changed to throw IAE if name is null or empty
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicNameTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicNameTest.java 2008-06-02 20:08:01 UTC (rev 231)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicNameTest.java 2008-06-02 20:11:36 UTC (rev 232)
@@ -2,7 +2,7 @@
* 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.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -32,6 +32,7 @@
/**
* @author Randall Hauch
+ * @author John Verhaeg
*/
public class BasicNameTest {
@@ -74,16 +75,14 @@
assertThat(name.getNamespaceUri(), is(""));
}
- @Test
- public void shouldAllowNullLocalNameInConstructorAndConvertToEmptyString() {
- name = new BasicName(validNamespaceUri, null);
- assertThat(name.getLocalName(), is(""));
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNullLocalNameInConstructor() {
+ new BasicName(validNamespaceUri, null);
}
- @Test
- public void shouldAllowEmptyLocalNameInConstructorAndConvertToEmptyString() {
- name = new BasicName(validNamespaceUri, "");
- assertThat(name.getLocalName(), is(""));
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldAllowEmptyLocalNameInConstructor() {
+ new BasicName(validNamespaceUri, "");
}
@Test
17 years, 6 months
DNA SVN: r231 - in trunk/dna-spi/src/main: java/org/jboss/dna/spi/graph/impl and 1 other directories.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-06-02 16:08:01 -0400 (Mon, 02 Jun 2008)
New Revision: 231
Modified:
trunk/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java
trunk/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties
Log:
DNA-92: Corrected misspelling
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java 2008-06-02 19:56:43 UTC (rev 230)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java 2008-06-02 20:08:01 UTC (rev 231)
@@ -2,7 +2,7 @@
* 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.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -28,29 +28,29 @@
/**
* @author Randall Hauch
+ * @author John Verhaeg
*/
public final class SpiI18n {
- public static I18n unableToDiscoverPropertyTypeForNullValue;
- public static I18n errorReadingPropertyValueBytes;
- public static I18n valueJavaTypeNotCompatibleWithPropertyType;
-
public static I18n errorConvertingBinaryValueToString;
public static I18n errorCreatingValue;
- public static I18n unableToCreateValue;
- public static I18n validPathMayNotContainEmptySegment;
+ public static I18n errorReadingPropertyValueBytes;
+ public static I18n invalidIndexInSegmentName;
+ public static I18n invalidQualifiedNameString;
+ public static I18n missingEndBracketInSegmentName;
public static I18n noNamespaceRegisteredForPrefix;
-
public static I18n pathAncestorDegreeIsInvalid;
+ public static I18n pathCannotBeNormalized;
public static I18n pathIsAlreadyAbsolute;
public static I18n pathIsNotAbsolute;
public static I18n pathIsNotRelative;
- public static I18n pathCannotBeNormalized;
- public static I18n unbleToCreateSubpathBeginIndexGreaterThanOrEqualToSize;
- public static I18n unbleToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex;
+ public static I18n unableToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex;
+ public static I18n unableToCreateSubpathBeginIndexGreaterThanOrEqualToSize;
+ public static I18n unableToCreateValue;
+ public static I18n unableToDiscoverPropertyTypeForNullValue;
+ public static I18n validPathMayNotContainEmptySegment;
+ public static I18n valueJavaTypeNotCompatibleWithPropertyType;
- public static I18n invalidQualifiedNameString;
-
public static I18n maximumPoolSizeMayNotBeSmallerThanCorePoolSize;
public static I18n repositoryConnectionPoolIsNotRunning;
public static I18n unableToObtainValidRepositoryAfterAttempts;
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java 2008-06-02 19:56:43 UTC (rev 230)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java 2008-06-02 20:08:01 UTC (rev 231)
@@ -2,7 +2,7 @@
* 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.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -39,459 +39,470 @@
/**
* A basic implementation of {@link Path}.
+ *
* @author Randall Hauch
+ * @author John Verhaeg
*/
@Immutable
public class BasicPath implements Path {
- private static final List<Segment> EMPTY_SEGMENTS = Collections.emptyList();
+ private static final List<Segment> EMPTY_SEGMENTS = Collections.emptyList();
- public static final Path ROOT = new BasicPath(EMPTY_SEGMENTS, true);
+ public static final Path ROOT = new BasicPath(EMPTY_SEGMENTS, true);
- protected static final Path SELF_PATH = new BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
+ protected static final Path SELF_PATH = new BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
- private final List<Segment> segments;
- private final boolean absolute;
- private final boolean normalized;
- private transient String path;
+ 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 ) {
- ArgCheck.isNotNull(segments, "segments");
- this.segments = segments.isEmpty() ? EMPTY_SEGMENTS : Collections.unmodifiableList(segments);
- this.absolute = absolute;
- this.normalized = isNormalized(this.segments);
- }
+ /**
+ * @param segments the segments
+ * @param absolute true if this path is absolute, or false otherwise
+ */
+ public BasicPath( List<Segment> segments,
+ boolean absolute ) {
+ ArgCheck.isNotNull(segments, "segments");
+ this.segments = segments.isEmpty() ? EMPTY_SEGMENTS : Collections.unmodifiableList(segments);
+ this.absolute = absolute;
+ this.normalized = isNormalized(this.segments);
+ }
- protected boolean isNormalized( List<Segment> segments ) {
- for (Segment segment : segments) {
- if (segment.isSelfReference() || segment.isParentReference()) return false;
- }
- return true;
- }
+ 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() {
+ 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;
- if (degree == 0) 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 getAncestor( int degree ) {
+ ArgCheck.isNonNegative(degree, "degree");
+ if (this.isRoot()) return this;
+ if (degree == 0) 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 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;
- if (this.isRoot() || that.isRoot()) return ROOT;
- Path normalizedPath = this.getNormalizedPath();
- int lastIndex = 0;
- Iterator<Segment> thisIter = normalizedPath.iterator();
- Iterator<Segment> thatIter = that.getNormalizedPath().iterator();
- while (thisIter.hasNext() && thatIter.hasNext()) {
- Segment thisSeg = thisIter.next();
- Segment thatSeg = thatIter.next();
- if (thisSeg.equals(thatSeg)) {
- ++lastIndex;
- } else {
- break;
- }
- }
- if (lastIndex == 0) return ROOT;
- return normalizedPath.subpath(0, lastIndex);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path getCommonAncestor( Path that ) {
+ if (that == null) return null;
+ if (this.isRoot() || that.isRoot()) return ROOT;
+ Path normalizedPath = this.getNormalizedPath();
+ int lastIndex = 0;
+ Iterator<Segment> thisIter = normalizedPath.iterator();
+ Iterator<Segment> thatIter = that.getNormalizedPath().iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ Segment thisSeg = thisIter.next();
+ Segment thatSeg = thatIter.next();
+ if (thisSeg.equals(thatSeg)) {
+ ++lastIndex;
+ } else {
+ break;
+ }
+ }
+ if (lastIndex == 0) return 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.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.isEmpty()) {
- if (this.isAbsolute()) {
- throw new InvalidPathException(CommonI18n.pathCannotBeNormalized.text(this));
- }
- } else if (!newSegments.getLast().isParentReference()) {
- newSegments.removeLast();
- continue;
- }
- }
- newSegments.add(segment);
- }
- if (newSegments.isEmpty()) {
- if (this.isAbsolute()) return ROOT;
- // Otherwise relative and it had contained nothing but self references ...
- return SELF_PATH;
- }
- return new BasicPath(newSegments, this.isAbsolute());
- }
+ /**
+ * {@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.isEmpty()) {
+ if (this.isAbsolute()) {
+ throw new InvalidPathException(CommonI18n.pathCannotBeNormalized.text(this));
+ }
+ } else if (!newSegments.getLast().isParentReference()) {
+ newSegments.removeLast();
+ continue;
+ }
+ }
+ newSegments.add(segment);
+ }
+ if (newSegments.isEmpty()) {
+ if (this.isAbsolute()) return 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 getSegment( int index ) {
+ return this.segments.get(index);
+ }
- /**
- * {@inheritDoc}
- */
- public Segment[] getSegmentsArray() {
- return this.segments.toArray(new Path.Segment[this.segments.size()]);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Segment[] getSegmentsArray() {
+ return this.segments.toArray(new Path.Segment[this.segments.size()]);
+ }
- /**
- * {@inheritDoc}
- */
- public List<Segment> getSegmentsList() {
- return this.segments;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public List<Segment> getSegmentsList() {
+ return this.segments;
+ }
- /**
- * {@inheritDoc}
- */
- public String getString() {
- return doGetString(null, DEFAULT_ENCODER);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public String getString() {
+ return doGetString(null, DEFAULT_ENCODER);
+ }
- /**
- * {@inheritDoc}
- */
- public String getString( TextEncoder encoder ) {
- return doGetString(null, encoder);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public String getString( TextEncoder encoder ) {
+ return doGetString(null, encoder);
+ }
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry ) {
- ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
- return doGetString(namespaceRegistry, null);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public String getString( NamespaceRegistry namespaceRegistry ) {
+ ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
+ return doGetString(namespaceRegistry, null);
+ }
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry, TextEncoder encoder ) {
- ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
- return doGetString(namespaceRegistry, encoder);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public String getString( NamespaceRegistry namespaceRegistry,
+ TextEncoder encoder ) {
+ ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
+ return doGetString(namespaceRegistry, encoder);
+ }
- /**
- * Method that creates the string representation. This method works two different ways depending upon whether the namespace
- * registry is provided.
- * @param namespaceRegistry
- * @param encoder
- * @return
- */
- protected String doGetString( NamespaceRegistry namespaceRegistry, TextEncoder encoder ) {
- if (encoder == null) encoder = DEFAULT_ENCODER;
- if (encoder == DEFAULT_ENCODER && this.path != null) return this.path;
+ /**
+ * Method that creates the string representation. This method works two different ways depending upon whether the namespace
+ * registry is provided.
+ *
+ * @param namespaceRegistry
+ * @param encoder
+ * @return
+ */
+ protected String doGetString( NamespaceRegistry namespaceRegistry,
+ 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;
- if (namespaceRegistry != null) {
- sb.append(segment.getString(namespaceRegistry, encoder));
- } else {
- 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;
- }
+ // 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;
+ if (namespaceRegistry != null) {
+ sb.append(segment.getString(namespaceRegistry, encoder));
+ } else {
+ 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 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 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;
+ /**
+ * {@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;
- }
+ 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 isDecendantOf( Path ancestor ) {
+ if (ancestor == null) return false;
+ return ancestor.isAncestorOf(this);
+ }
- /**
- * {@inheritDoc}
- */
- public boolean isNormalized() {
- return this.normalized;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isNormalized() {
+ return this.normalized;
+ }
- /**
- * {@inheritDoc}
- */
- public boolean isRoot() {
- return this == ROOT || this.segments.isEmpty();
- }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isRoot() {
+ return this == ROOT || this.segments.isEmpty();
+ }
- /**
- * {@inheritDoc}
- */
- public boolean isSame( Path other ) {
- return this.compareTo(other) == 0;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSame( Path other ) {
+ return this.compareTo(other) == 0;
+ }
- /**
- * {@inheritDoc}
- */
- public Iterator<Segment> iterator() {
- return this.segments.iterator();
- }
+ /**
+ * {@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);
- }
+ /**
+ * {@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(Path.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(Path.SELF_SEGMENT);
- }
- return new BasicPath(relativeSegments, false);
- }
+ // Count the number of segments up to the common ancestor (relative path is what remains) ...
+ int lengthOfCommonAncestor = 0;
+ Iterator<Segment> thisIter = this.getNormalizedPath().iterator();
+ Iterator<Segment> toIter = startingPath.getNormalizedPath().iterator();
+ while (thisIter.hasNext() && toIter.hasNext()) {
+ Segment thisSeg = thisIter.next();
+ Segment toSeg = toIter.next();
+ if (thisSeg.equals(toSeg)) {
+ ++lengthOfCommonAncestor;
+ } else {
+ break;
+ }
+ }
+ // Create the relative path, starting with parent references to the common ancestor ...
+ int numberOfParentReferences = startingPath.size() - lengthOfCommonAncestor;
+ List<Segment> relativeSegments = new ArrayList<Segment>();
+ for (int i = 0; i != numberOfParentReferences; ++i) {
+ relativeSegments.add(Path.PARENT_SEGMENT);
+ }
+ // Add the segments of this path from the common ancestor ...
+ for (int i = lengthOfCommonAncestor; i < this.size(); ++i) {
+ relativeSegments.add(this.segments.get(i));
+ }
+ if (relativeSegments.isEmpty()) {
+ relativeSegments.add(Path.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 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 Path resolveAgainst( Path absolutePath ) {
+ ArgCheck.isNotNull(absolutePath, "absolute path");
+ return absolutePath.resolve(this);
+ }
- /**
- * {@inheritDoc}
- */
- public int size() {
- return this.segments.size();
- }
+ /**
+ * {@inheritDoc}
+ */
+ public int size() {
+ return this.segments.size();
+ }
- /**
- * {@inheritDoc}
- */
- public Path subpath( int beginIndex ) {
- if (beginIndex == 0) return this;
- int size = size();
- if (beginIndex >= size) {
- throw new IndexOutOfBoundsException(SpiI18n.unbleToCreateSubpathBeginIndexGreaterThanOrEqualToSize.text(beginIndex, size));
- }
- if (size == 0) return ROOT;
- return new BasicPath(this.segments.subList(beginIndex, size), this.isAbsolute());
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path subpath( int beginIndex ) {
+ if (beginIndex == 0) return this;
+ int size = size();
+ if (beginIndex >= size) {
+ throw new IndexOutOfBoundsException(SpiI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToSize.text(beginIndex,
+ size));
+ }
+ if (size == 0) return ROOT;
+ return new BasicPath(this.segments.subList(beginIndex, size), this.isAbsolute());
+ }
- /**
- * {@inheritDoc}
- */
- public Path subpath( int beginIndex, int endIndex ) {
- int size = size();
- if (beginIndex == 0) {
- if (endIndex == 0) return ROOT;
- if (endIndex == size) return this;
- }
- if (beginIndex >= size) {
- throw new IndexOutOfBoundsException(SpiI18n.unbleToCreateSubpathBeginIndexGreaterThanOrEqualToSize.text(beginIndex, size));
- }
- if (beginIndex > endIndex) {
- throw new IndexOutOfBoundsException(SpiI18n.unbleToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex.text(beginIndex, endIndex));
- }
- // This reuses the same list, so it's pretty efficient ...
- return new BasicPath(this.segments.subList(beginIndex, endIndex), this.isAbsolute());
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Path subpath( int beginIndex,
+ int endIndex ) {
+ int size = size();
+ if (beginIndex == 0) {
+ if (endIndex == 0) return ROOT;
+ if (endIndex == size) return this;
+ }
+ if (beginIndex >= size) {
+ throw new IndexOutOfBoundsException(SpiI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToSize.text(beginIndex,
+ size));
+ }
+ if (beginIndex > endIndex) {
+ throw new IndexOutOfBoundsException(
+ SpiI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex.text(beginIndex,
+ endIndex));
+ }
+ // 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 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}
+ */
+ @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 (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}
+ */
+ public int compareTo( Path that ) {
+ 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);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return getString(Path.URL_ENCODER);
+ }
}
Modified: trunk/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties
===================================================================
--- trunk/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties 2008-06-02 19:56:43 UTC (rev 230)
+++ trunk/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties 2008-06-02 20:08:01 UTC (rev 231)
@@ -19,27 +19,25 @@
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
#
-unableToDiscoverPropertyTypeForNullValue = Unable to discover property type for null value
-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
+closedConnectionMayNotBeUsed = The connection has been closed an may not be used
+errorConvertingBinaryValueToString = Error while interpreting binary value as a UTF-8 string
errorCreatingValue = Error creating {0} value from {1} "{2}"
-unableToCreateValue = Unable to create {0} value from {1} "{2}": undefined type conversion
-validPathMayNotContainEmptySegment = The path "{0}" is not valid because it contains an empty segment
+errorReadingPropertyValueBytes = Error reading bytes
+invalidIndexInSegmentName = Invalid index, "{0}", in segment name: {1}
+invalidQualifiedNameString = Unable to parse qualified name from "{0}"
+maximumPoolSizeMayNotBeSmallerThanCorePoolSize = The maximum pool size may not be smaller than the core pool size
+missingEndBracketInSegmentName = Missing end bracket in segment name: {0}
noNamespaceRegisteredForPrefix = There is no namespace registered for the prefix "{0}"
-
pathAncestorDegreeIsInvalid = Unable to obtain the {1} ancestor for {0}
+pathCannotBeNormalized = The path {0} is invalid and cannot be normalized
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
-unbleToCreateSubpathBeginIndexGreaterThanOrEqualToSize = Unable to create subpath: fromIndex({0}) >= size({1})
-unbleToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex = Unable to create subpath: fromIndex({0}) >= toIndex({1})
-
-invalidQualifiedNameString = Unable to parse qualified name from "{0}"
-
-maximumPoolSizeMayNotBeSmallerThanCorePoolSize = The maximum pool size may not be smaller than the core pool size
repositoryConnectionPoolIsNotRunning = The repository connection pool is not running
+unableToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex = Unable to create subpath: fromIndex({0}) >= toIndex({1})
+unableToCreateSubpathBeginIndexGreaterThanOrEqualToSize = Unable to create subpath: fromIndex({0}) >= size({1})
+unableToCreateValue = Unable to create {0} value from {1} "{2}": undefined type conversion
+unableToDiscoverPropertyTypeForNullValue = Unable to discover property type for null value
unableToObtainValidRepositoryAfterAttempts = Unable to obtain a valid repository after {0} attempts
-closedConnectionMayNotBeUsed = The connection has been closed an may not be used
+validPathMayNotContainEmptySegment = The path "{0}" is not valid because it contains an empty segment
+valueJavaTypeNotCompatibleWithPropertyType = Value is instance of Java type "{0}" and is not compatible with the "{1}" property type
17 years, 6 months
DNA SVN: r230 - trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-06-02 15:56:43 -0400 (Mon, 02 Jun 2008)
New Revision: 230
Modified:
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
Log:
DNA-81: Changed SELF and PARENT constants to use appropriate instances of BasicXXX
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java 2008-06-02 19:54:56 UTC (rev 229)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java 2008-06-02 19:56:43 UTC (rev 230)
@@ -2,7 +2,7 @@
* 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.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -29,6 +29,8 @@
import org.jboss.dna.common.text.NoOpEncoder;
import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.text.UrlEncoder;
+import org.jboss.dna.spi.graph.impl.BasicName;
+import org.jboss.dna.spi.graph.impl.BasicPathSegment;
/**
* An object representation of a node path within a repository.
@@ -64,718 +66,416 @@
* {@link #isAncestorOf(Path) ancestor} or {@link #isDecendantOf(Path) decendent} of another path, and
* {@link #getCommonAncestor(Path) finding a common ancestor}.
* </p>
+ *
* @author Randall Hauch
+ * @author John Verhaeg
*/
@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 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 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 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 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 = '/';
+ /**
+ * 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 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 a parent.
+ */
+ public static final String PARENT = "..";
- /**
- * String representation of the segment that references the same segment.
- */
- public static final String SELF = ".";
+ /**
+ * String representation of the segment that references the same segment.
+ */
+ public static final String SELF = ".";
- /**
- * The index that will be returned for a {@link Segment} that {@link Segment#hasIndex() has no index}.
- */
- public static final int NO_INDEX = -1;
+ /**
+ * The index that will be returned for a {@link Segment} that {@link Segment#hasIndex() has no index}.
+ */
+ public static final int NO_INDEX = -1;
- /**
- * Representation of the segments that occur within a path.
- * @author Randall Hauch
- */
- @Immutable
- public static interface Segment extends Cloneable, Comparable<Segment>, Serializable {
+ /**
+ * 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 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();
+ /**
+ * 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 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 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();
+ /**
+ * 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 string form of the segment. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each
+ * of the path segments.
+ *
+ * @return the encoded string
+ * @see #getString(TextEncoder)
+ */
+ public String getString();
- /**
- * Get the encoded string form of the segment, using the supplied encoder to encode characters in each of the path
- * segments.
- * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
- * @return the encoded string
- * @see #getString()
- */
- public String getString( TextEncoder encoder );
+ /**
+ * Get the encoded string form of the segment, using the supplied encoder to encode characters in each of the path
+ * segments.
+ *
+ * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
+ * @return the encoded string
+ * @see #getString()
+ */
+ public String getString( TextEncoder encoder );
- /**
- * Get the string form of the segment, using the supplied namespace registry to convert the name's namespace URI to a
- * prefix. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
- * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
- * {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
- * @return the encoded string
- * @throws IllegalArgumentException if the namespace registry is null
- * @see #getString(NamespaceRegistry,TextEncoder)
- */
- public String getString( NamespaceRegistry namespaceRegistry );
+ /**
+ * Get the string form of the segment, using the supplied namespace registry to convert the name's namespace URI to a
+ * prefix. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
+ *
+ * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+ * {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
+ * @return the encoded string
+ * @throws IllegalArgumentException if the namespace registry is null
+ * @see #getString(NamespaceRegistry,TextEncoder)
+ */
+ public String getString( NamespaceRegistry namespaceRegistry );
- /**
- * Get the encoded string form of the segment, using the supplied namespace registry to convert the name's namespace URI
- * to a prefix and the supplied encoder to encode characters in each of the path segments.
- * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
- * {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
- * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
- * @return the encoded string
- * @throws IllegalArgumentException if the namespace registry is null
- * @see #getString(NamespaceRegistry)
- */
- public String getString( NamespaceRegistry namespaceRegistry, TextEncoder encoder );
- }
+ /**
+ * Get the encoded string form of the segment, using the supplied namespace registry to convert the name's namespace URI
+ * to a prefix and the supplied encoder to encode characters in each of the path segments.
+ *
+ * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+ * {@link Name#getNamespaceUri() namespace URI} in the segment's {@link #getName() name}
+ * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
+ * @return the encoded string
+ * @throws IllegalArgumentException if the namespace registry is null
+ * @see #getString(NamespaceRegistry)
+ */
+ public String getString( NamespaceRegistry namespaceRegistry,
+ TextEncoder encoder );
+ }
- /**
- * Singleton instance of the name referencing a self, provided as a convenience.
- */
- public static final Name SELF_NAME = new Name() {
+ /**
+ * Singleton instance of the name referencing a self, provided as a convenience.
+ */
+ public static final Name SELF_NAME = new BasicName(null, SELF);
- /**
- * {@inheritDoc}
- */
- public String getLocalName() {
- return SELF;
- }
+ /**
+ * Singleton instance of the name referencing a parent, provided as a convenience.
+ */
+ public static final Name PARENT_NAME = new BasicName(null, PARENT);
- /**
- * {@inheritDoc}
- */
- public String getNamespaceUri() {
- return "";
- }
+ /**
+ * Singleton instance of the path segment referencing a parent, provided as a convenience.
+ */
+ public static final Path.Segment SELF_SEGMENT = new BasicPathSegment(SELF_NAME);
- /**
- * {@inheritDoc}
- */
- public String getString() {
- return getString(DEFAULT_ENCODER);
- }
+ /**
+ * Singleton instance of the path segment referencing a parent, provided as a convenience.
+ */
+ public static final Path.Segment PARENT_SEGMENT = new BasicPathSegment(PARENT_NAME);
- /**
- * {@inheritDoc}
- */
- public String getString( TextEncoder encoder ) {
- return encoder.encode(SELF);
- }
+ /**
+ * Return the number of segments in this path.
+ *
+ * @return the number of path segments
+ */
+ public int size();
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry ) {
- return getString(namespaceRegistry, DEFAULT_ENCODER);
- }
+ /**
+ * Return whether this path represents the root path.
+ *
+ * @return true if this path is the root path, or false otherwise
+ */
+ public boolean isRoot();
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry, TextEncoder encoder ) {
- return encoder.encode(SELF);
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- public int compareTo( Name that ) {
- if (this == that) return 0;
- int diff = this.getLocalName().compareTo(that.getLocalName());
- if (diff != 0) return diff;
- return this.getNamespaceUri().compareTo(that.getNamespaceUri());
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals( Object obj ) {
- if (this == obj) return true;
- if (obj instanceof Name) {
- Name that = (Name)obj;
- if (!this.getLocalName().equals(that.getLocalName())) return false;
- return this.getNamespaceUri().equals(that.getNamespaceUri());
- }
- return false;
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- return SELF;
- }
+ /**
+ * 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();
- /**
- * Singleton instance of the name referencing a parent, provided as a convenience.
- */
- public static final Name PARENT_NAME = new Name() {
+ /**
+ * 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();
- /**
- * {@inheritDoc}
- */
- public String getLocalName() {
- return PARENT;
- }
+ /**
+ * 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();
- /**
- * {@inheritDoc}
- */
- public String getNamespaceUri() {
- return "";
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- public String getString() {
- return getString(DEFAULT_ENCODER);
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- public String getString( TextEncoder encoder ) {
- return encoder.encode(PARENT);
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry ) {
- return getString(namespaceRegistry, DEFAULT_ENCODER);
- }
+ /**
+ * 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();
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry, TextEncoder encoder ) {
- return encoder.encode(PARENT);
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- public int compareTo( Name that ) {
- if (this == that) return 0;
- int diff = this.getLocalName().compareTo(that.getLocalName());
- if (diff != 0) return diff;
- return this.getNamespaceUri().compareTo(that.getNamespaceUri());
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals( Object obj ) {
- if (this == obj) return true;
- if (obj instanceof Name) {
- Name that = (Name)obj;
- if (!this.getLocalName().equals(that.getLocalName())) return false;
- return this.getNamespaceUri().equals(that.getNamespaceUri());
- }
- return false;
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- return PARENT;
- }
+ /**
+ * 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 );
- /**
- * Singleton instance of the path segment referencing a parent, provided as a convenience.
- */
- public static final Path.Segment SELF_SEGMENT = new Path.Segment() {
+ /**
+ * Return a new path consisting of the segments starting at <code>beginIndex</code> index (inclusive). This is equivalent to
+ * calling <code>path.subpath(beginIndex,path.size()-1)</code>.
+ *
+ * @param beginIndex the beginning index, inclusive.
+ * @return the specified subpath
+ * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative or larger than the length of this
+ * <code>Path</code> object
+ */
+ public Path subpath( int beginIndex );
- /**
- * {@inheritDoc}
- */
- public int getIndex() {
- return NO_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 subpath
+ * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative, or <code>endIndex</code> is larger
+ * than the length of this <code>Path</code> object, or <code>beginIndex</code> is larger than
+ * <code>endIndex</code>.
+ */
+ public Path subpath( int beginIndex,
+ int endIndex );
- /**
- * {@inheritDoc}
- */
- public Name getName() {
- return SELF_NAME;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator<Segment> iterator();
- /**
- * {@inheritDoc}
- */
- public String getString() {
- return SELF_NAME.getString();
- }
+ /**
+ * 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();
- /**
- * {@inheritDoc}
- */
- public String getString( TextEncoder encoder ) {
- return SELF_NAME.getString(encoder);
- }
+ /**
+ * Get an unmodifiable list of the path segments.
+ *
+ * @return the unmodifiable list of path segments; never null
+ */
+ public List<Segment> getSegmentsList();
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry ) {
- return SELF_NAME.getString(namespaceRegistry);
- }
+ /**
+ * 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();
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry, TextEncoder encoder ) {
- return SELF_NAME.getString(namespaceRegistry, encoder);
- }
+ /**
+ * 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 );
- /**
- * {@inheritDoc}
- */
- public boolean hasIndex() {
- return false;
- }
+ /**
+ * Get the string form of the path, using the supplied namespace registry to convert the names' namespace URIs to prefixes.
+ * The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
+ *
+ * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+ * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
+ * @return the encoded string
+ * @throws IllegalArgumentException if the namespace registry is null
+ * @see #getString(NamespaceRegistry,TextEncoder)
+ */
+ public String getString( NamespaceRegistry namespaceRegistry );
- /**
- * {@inheritDoc}
- */
- public boolean isParentReference() {
- return false;
- }
+ /**
+ * Get the encoded string form of the path, using the supplied namespace registry to convert the names' namespace URIs to
+ * prefixes and the supplied encoder to encode characters in each of the path segments.
+ *
+ * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
+ * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
+ * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
+ * @return the encoded string
+ * @throws IllegalArgumentException if the namespace registry is null
+ * @see #getString(NamespaceRegistry)
+ */
+ public String getString( NamespaceRegistry namespaceRegistry,
+ TextEncoder encoder );
- /**
- * {@inheritDoc}
- */
- public boolean isSelfReference() {
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- public int compareTo( 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 boolean equals( Object obj ) {
- if (this == obj) return true;
- if (obj instanceof Segment) {
- Segment that = (Segment)obj;
- if (!this.getName().equals(that.getName())) return false;
- return this.hasIndex() == that.hasIndex();
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- return SELF_NAME.toString();
- }
- };
-
- /**
- * Singleton instance of the path segment referencing a parent, provided as a convenience.
- */
- public static final Path.Segment PARENT_SEGMENT = new Path.Segment() {
-
- /**
- * {@inheritDoc}
- */
- public int getIndex() {
- return NO_INDEX;
- }
-
- /**
- * {@inheritDoc}
- */
- public Name getName() {
- return PARENT_NAME;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getString() {
- return PARENT_NAME.getString();
- }
-
- /**
- * {@inheritDoc}
- */
- public String getString( TextEncoder encoder ) {
- return PARENT_NAME.getString(encoder);
- }
-
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry ) {
- return PARENT_NAME.getString(namespaceRegistry);
- }
-
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry, TextEncoder encoder ) {
- return PARENT_NAME.getString(namespaceRegistry, encoder);
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean hasIndex() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isParentReference() {
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isSelfReference() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- public int compareTo( 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 boolean equals( Object obj ) {
- if (this == obj) return true;
- if (obj instanceof Segment) {
- Segment that = (Segment)obj;
- if (!this.getName().equals(that.getName())) return false;
- return this.hasIndex() == that.hasIndex();
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- return PARENT_NAME.toString();
- }
- };
-
- /**
- * 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 starting at <code>beginIndex</code> index (inclusive). This is equivalent to
- * calling <code>path.subpath(beginIndex,path.size()-1)</code>.
- * @param beginIndex the beginning index, inclusive.
- * @return the specified subpath
- * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative or larger than the length of this
- * <code>Path</code> object
- */
- public Path subpath( int beginIndex );
-
- /**
- * Return a new path consisting of the segments between the <code>beginIndex</code> index (inclusive) and the
- * <code>endIndex</code> index (exclusive).
- * @param beginIndex the beginning index, inclusive.
- * @param endIndex the ending index, exclusive.
- * @return the specified subpath
- * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative, or <code>endIndex</code> is larger
- * than the length of this <code>Path</code> object, or <code>beginIndex</code> is larger than <code>endIndex</code>.
- */
- public Path subpath( int beginIndex, int endIndex );
-
- /**
- * {@inheritDoc}
- */
- public Iterator<Segment> iterator();
-
- /**
- * Obtain a copy of the segments in this path. None of the segments are encoded.
- * @return the array of segments as a copy
- */
- public Segment[] getSegmentsArray();
-
- /**
- * Get an unmodifiable list of the path segments.
- * @return the unmodifiable list of path segments; never null
- */
- public List<Segment> getSegmentsList();
-
- /**
- * Get the string form of the path. The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the
- * path segments.
- * @return the encoded string
- * @see #getString(TextEncoder)
- */
- public String getString();
-
- /**
- * Get the encoded string form of the path, using the supplied encoder to encode characters in each of the path segments.
- * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
- * @return the encoded string
- * @see #getString()
- */
- public String getString( TextEncoder encoder );
-
- /**
- * Get the string form of the path, using the supplied namespace registry to convert the names' namespace URIs to prefixes.
- * The {@link #DEFAULT_ENCODER default encoder} is used to encode characters in each of the path segments.
- * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
- * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
- * @return the encoded string
- * @throws IllegalArgumentException if the namespace registry is null
- * @see #getString(NamespaceRegistry,TextEncoder)
- */
- public String getString( NamespaceRegistry namespaceRegistry );
-
- /**
- * Get the encoded string form of the path, using the supplied namespace registry to convert the names' namespace URIs to
- * prefixes and the supplied encoder to encode characters in each of the path segments.
- * @param namespaceRegistry the namespace registry that should be used to obtain the prefix for the
- * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link Segment#getName() names}
- * @param encoder the encoder to use, or null if the {@link #DEFAULT_ENCODER default encoder} should be used
- * @return the encoded string
- * @throws IllegalArgumentException if the namespace registry is null
- * @see #getString(NamespaceRegistry)
- */
- public String getString( NamespaceRegistry namespaceRegistry, TextEncoder encoder );
-
}
17 years, 6 months