jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r772659 [2/3] - in /jackrabbit/trunk: jackrabbit-core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetyp...
Date Thu, 07 May 2009 14:29:48 GMT
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/value/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/value/TestAll.java?rev=772659&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/value/TestAll.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/value/TestAll.java Thu May  7 14:29:34 2009
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.value;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all testcases for package org.apache.jackrabbit.core.value.
+ */
+public class TestAll extends TestCase {
+
+    /**
+     * Returns a <code>Test</code> suite that executes all tests inside this
+     * package.
+     */
+    public static Test suite() {
+        TestSuite suite = new TestSuite("org.apache.jackrabbit.core.value tests");
+
+        suite.addTestSuite(InternalValueFactoryTest.class);
+        suite.addTestSuite(InternalValueTest.class);
+
+        return suite;
+    }
+}

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/ISO8601.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/ISO8601.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/ISO8601.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/ISO8601.java Thu May  7 14:29:34 2009
@@ -197,6 +197,10 @@
              * if any of the set values are illegal or out of range
              */
             cal.getTime();
+            /**
+             * in addition check the validity of the year
+             */
+            getYear(cal);
         } catch (IllegalArgumentException e) {
             return null;
         }

Added: jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/NameTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/NameTest.java?rev=772659&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/NameTest.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/NameTest.java Thu May  7 14:29:34 2009
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.test.api;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.RepositoryStub;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFactory;
+import javax.jcr.Value;
+import javax.jcr.PropertyType;
+import javax.jcr.Property;
+import javax.jcr.Workspace;
+
+/**
+ * <code>NameTest</code>...
+ */
+public class NameTest extends AbstractJCRTest {
+
+    private String getExpandedName(String jcrName) throws RepositoryException {
+        if (jcrName.startsWith("{")) {
+            return jcrName;
+        } else {
+            int pos = jcrName.indexOf(":");
+            String prefix = (pos > -1) ? jcrName.substring(0, pos) : "";
+            String uri = superuser.getNamespaceURI(prefix);
+            return  "{" + uri + "}" + jcrName.substring(pos+1);
+        }
+    }
+
+    /**
+     * Expanded names must always be resolved.
+     * Test NAME-value creation.
+     * 
+     * @throws RepositoryException
+     */
+    public void testExpandedNameValue() throws RepositoryException {
+        ValueFactory vf = superuser.getValueFactory();
+        Value nameValue = vf.createValue(Workspace.NAME_VERSION_STORAGE_NODE, PropertyType.NAME);
+
+        assertEquals(PropertyType.NAME, nameValue.getType());
+        assertEquals(nameValue.getString(), vf.createValue("jcr:versionStorage", PropertyType.NAME).getString());
+        assertEquals(nameValue, vf.createValue("jcr:versionStorage", PropertyType.NAME));
+        assertEquals("jcr:versionStorage", nameValue.getString());
+    }
+    
+    /**
+     * Expanded names must always be resolved.
+     * Test setting a NAME-value property.
+     *
+     * @throws RepositoryException
+     */
+    public void testExpandedNameValueProperty() throws RepositoryException {
+        ValueFactory vf = superuser.getValueFactory();
+        Value nameValue = vf.createValue(Workspace.NAME_VERSION_STORAGE_NODE, PropertyType.NAME);
+
+        Property p = testRootNode.setProperty(propertyName1, nameValue);
+        assertEquals(PropertyType.NAME, p.getType());
+        assertEquals(nameValue.getString(), p.getValue().getString());
+        assertEquals(nameValue, p.getValue());
+        assertEquals("jcr:versionStorage", p.getString());
+    }
+
+    /**
+     * Test if the name of property created with an expanded name is properly
+     * return as standard JCR name.
+     * 
+     * @throws RepositoryException
+     */
+    public void testExpandedNameItem() throws RepositoryException {
+        String propName = getExpandedName(propertyName1);
+        Property p = testRootNode.setProperty(propName, getJcrValue(superuser, RepositoryStub.PROP_PROP_VALUE1, RepositoryStub.PROP_PROP_TYPE1, "test"));
+
+        assertEquals(propertyName1, p.getName());
+    }
+
+    /**
+     * Test if creating a node with an expanded node type name returns the proper
+     * standard JCR node type name.
+     * 
+     * @throws RepositoryException
+     */
+    public void testExpandedNodeTypeName() throws RepositoryException {
+        String nodeName = getExpandedName(nodeName1);
+        String ntName = getExpandedName(testNodeType);
+        Node n = testRootNode.addNode(nodeName, ntName);
+
+        assertEquals(nodeName1, n.getName());
+        assertEquals(testNodeType, n.getPrimaryNodeType().getName());
+    }
+}
\ No newline at end of file

Added: jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/PathTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/PathTest.java?rev=772659&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/PathTest.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/PathTest.java Thu May  7 14:29:34 2009
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.test.api;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import javax.jcr.Item;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFactory;
+import javax.jcr.Value;
+import javax.jcr.PropertyType;
+import javax.jcr.Property;
+import javax.jcr.Workspace;
+
+/**
+ * <code>PathTest</code>...
+ */
+public class PathTest extends AbstractJCRTest {
+
+    private String identifier;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        identifier = testRootNode.getIdentifier();
+    }
+
+    public void testGetItem() throws RepositoryException {
+        Item item = superuser.getItem("[" + identifier + "]");
+        assertTrue(item.isSame(testRootNode));
+    }
+    
+    public void testCreatePathValue() throws RepositoryException {
+        ValueFactory vf = superuser.getValueFactory();
+        Value pathValue = vf.createValue("[" +identifier+ "]", PropertyType.PATH);
+
+        assertEquals(PropertyType.PATH, pathValue.getType());
+        assertEquals("[" +identifier+ "]", pathValue.getString());
+        assertFalse(pathValue.equals(vf.createValue(testRootNode.getPath(), PropertyType.PATH)));
+    }
+
+    public void testCreateMultiplePathValue() throws RepositoryException {
+        ValueFactory vf = superuser.getValueFactory();
+        Value vID1 = vf.createValue("[" +identifier+ "]", PropertyType.PATH);
+        Value v = vf.createValue(testRootNode.getPath(), PropertyType.PATH);
+        Value vID2 = vf.createValue("[" +identifier+ "]", PropertyType.PATH);
+        Value v2 = vf.createValue(testRootNode.getPath(), PropertyType.PATH);
+
+        assertEquals(vID1, vID2);
+        assertEquals(v, v2);
+
+        assertFalse(v.equals(vID1));
+        assertFalse(v.equals(vID2));
+    }
+    
+    public void testIdentifierBasedPropertyValue() throws RepositoryException {
+        ValueFactory vf = superuser.getValueFactory();
+        Value pathValue = vf.createValue("[" +identifier+ "]", PropertyType.PATH);
+
+        Property p = testRootNode.setProperty(propertyName1, pathValue);
+
+        assertEquals(PropertyType.PATH, p.getType());
+        assertEquals(pathValue.getString(), p.getValue().getString());
+        assertEquals(pathValue, p.getValue());
+    }
+
+    public void testResolveeIdentifierBasedPropertyValue() throws RepositoryException {
+        ValueFactory vf = superuser.getValueFactory();
+        Value pathValue = vf.createValue("[" +identifier+ "]", PropertyType.PATH);
+
+        Property p = testRootNode.setProperty(propertyName1, pathValue);
+        assertTrue("Identifier-based PATH value must resolve to the Node the identifier has been obtained from.",
+                testRootNode.isSame(p.getNode()));
+    }
+
+    public void testExtendedNameBasedPathValue() throws RepositoryException {
+        ValueFactory vf = superuser.getValueFactory();
+        Value pathValue = vf.createValue(Workspace.PATH_VERSION_STORAGE_NODE, PropertyType.PATH);
+
+        Property p = testRootNode.setProperty(propertyName1, pathValue);
+        assertEquals("/jcr:system/jcr:versionStorage", p.getString());
+
+        String path = Workspace.PATH_VERSION_STORAGE_NODE + "/a/b/c/jcr:frozenNode";
+        pathValue = vf.createValue(path, PropertyType.PATH);
+
+        p = testRootNode.setProperty(propertyName1, pathValue);
+        assertEquals("/jcr:system/jcr:versionStorage/a/b/c/jcr:frozenNode", p.getString());
+    }
+
+    public void testNotNormalizedPathValue() throws RepositoryException {
+        ValueFactory vf = superuser.getValueFactory();
+        Value pathValue = vf.createValue("/a/../b/./c/dd/..", PropertyType.PATH);
+
+        Property p = testRootNode.setProperty(propertyName1, pathValue);
+
+        assertEquals(PropertyType.PATH, p.getType());
+        assertEquals(pathValue.getString(), p.getValue().getString());
+        assertEquals(pathValue, p.getValue());                
+    }
+}
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/TestAll.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/TestAll.java Thu May  7 14:29:34 2009
@@ -67,6 +67,9 @@
         suite.addTestSuite(ExportSysViewTest.class);
         suite.addTestSuite(ExportDocViewTest.class);
 
+        suite.addTestSuite(NameTest.class);
+        suite.addTestSuite(PathTest.class);
+
         // level 2 tests
         suite.addTestSuite(AddNodeTest.class);
         suite.addTestSuite(NamespaceRegistryTest.class);

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java Thu May  7 14:29:34 2009
@@ -502,11 +502,6 @@
         }
     }
 
-    public String getIdentifier() throws RepositoryException {
-        // FIXME: Support the UUID/path identifiers
-        return getUUID();
-    }
-
     /**
      * @see Node#getUUID()
      */
@@ -1149,6 +1144,14 @@
         // lock can be inherited from a parent > do not check for node being lockable.
         checkStatus();
         return session.getLockStateManager().isLocked(getNodeState());
+    }         
+
+    /**
+     * @see Node#getIdentifier()
+     */
+    public String getIdentifier() throws RepositoryException {
+        // TODO: implementation missing
+        throw new UnsupportedRepositoryOperationException("JCR-1104");
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java Thu May  7 14:29:34 2009
@@ -89,6 +89,8 @@
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
 import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.IdentifierResolver;
+import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
 import org.apache.jackrabbit.spi.commons.value.ValueFactoryQImpl;
@@ -139,7 +141,8 @@
         workspace = createWorkspaceInstance(config, sessionInfo);
 
         // build local name-mapping
-        npResolver = new DefaultNamePathResolver(this, true);
+        IdentifierResolver idResolver = new IdResolver();
+        npResolver = new DefaultNamePathResolver(this, idResolver, true);
 
         // build ValueFactory
         valueFactory = new ValueFactoryQImpl(config.getRepositoryService().getQValueFactory(), npResolver);
@@ -601,7 +604,6 @@
     }
 
     //--------------------------------------------------< NamespaceResolver >---
-
     public String getPrefix(String uri) throws NamespaceException {
         try {
             return getNamespacePrefix(uri);
@@ -967,4 +969,35 @@
             throw new NoSuchWorkspaceException("Unknown workspace: '" + workspaceName + "'.");
         }
     }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Inner class implementing the <code>IdentifierResolver</code> interface
+     */
+    private final class IdResolver implements IdentifierResolver {
+
+        //---------------------------------------------< IdentifierResolver >---
+        /**
+         * @see IdentifierResolver#getPath(String)
+         */
+        public Path getPath(String identifier) throws MalformedPathException {
+            try {
+                NodeId id = getIdFactory().createNodeId(identifier);
+                return getHierarchyManager().getNodeEntry(id).getPath();
+            } catch (RepositoryException e) {
+                throw new MalformedPathException("Invalid identifier '" + identifier + "'.");
+            }
+        }
+
+        /**
+         * @see IdentifierResolver#checkFormat(String)
+         */
+        public void checkFormat(String identifier) throws MalformedPathException {
+            try {
+                NodeId id = getIdFactory().createNodeId(identifier);
+            } catch (Exception e) {
+                throw new MalformedPathException("Invalid identifier '" + identifier + "'.");
+            }
+        }
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java Thu May  7 14:29:34 2009
@@ -28,7 +28,6 @@
 import org.apache.jackrabbit.spi.Path;
 
 import javax.jcr.RepositoryException;
-import javax.jcr.PathNotFoundException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Set;
@@ -153,7 +152,7 @@
                         try {
                             Path parentPath = ev.getPath().getAncestor(1);
                             parent = hierarchyMgr.lookup(parentPath);
-                        } catch (PathNotFoundException e) {
+                        } catch (RepositoryException e) {
                             // should not occur
                             log.debug(e.getMessage());
                         }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/CachingPathResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/CachingPathResolver.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/CachingPathResolver.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/CachingPathResolver.java Thu May  7 14:29:34 2009
@@ -72,12 +72,33 @@
      * @throws NamespaceException if a namespace prefix can not be resolved
      */
     public Path getQPath(String path) throws MalformedPathException, IllegalNameException, NamespaceException {
-        Path qpath = (Path) cache.get(path);
-        if (qpath == null) {
-            qpath = resolver.getQPath(path);
-            cache.put(path, qpath);
+        return getQPath(path, true);
+    }
+
+    /**
+     * @see PathResolver#getQPath(String, boolean) 
+     */
+    public Path getQPath(String path, boolean normalizeIdentifier) throws MalformedPathException, IllegalNameException, NamespaceException {
+        Path qpath;
+        /*
+         * Jcr paths consisting of an identifier segment have 2 different
+         * path object representations depending on the given resolution flag:
+         * 1) a normalized absolute path if resolveIdentifier is true
+         * 2) a path denoting an identifier if resolveIdentifier is false.
+         * The latter are not cached in order not to return a wrong resolution
+         * when calling getQPath with the same identifier-jcr-path.
+         */
+        if (path.startsWith("[") && !normalizeIdentifier) {
+            qpath = resolver.getQPath(path, normalizeIdentifier);
+        } else {
+            qpath = (Path) cache.get(path);
+            if (qpath == null) {
+                qpath = resolver.getQPath(path, normalizeIdentifier);
+                cache.put(path, qpath);
+            }
         }
         return qpath;
+
     }
 
 

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/DefaultNamePathResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/DefaultNamePathResolver.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/DefaultNamePathResolver.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/DefaultNamePathResolver.java Thu May  7 14:29:34 2009
@@ -42,7 +42,7 @@
     }
 
     public DefaultNamePathResolver(Session session) {
-        this(new SessionNamespaceResolver(session));
+        this(new SessionNamespaceResolver(session), ((session instanceof IdentifierResolver)? (IdentifierResolver) session : null), false);
     }
 
     public DefaultNamePathResolver(NamespaceRegistry registry) {
@@ -50,8 +50,12 @@
     }
 
     public DefaultNamePathResolver(NamespaceResolver nsResolver, boolean enableCaching) {
+        this(nsResolver, null, enableCaching);
+    }
+
+    public DefaultNamePathResolver(NamespaceResolver nsResolver, IdentifierResolver idResolver, boolean enableCaching) {
         NameResolver nr = new ParsingNameResolver(NameFactoryImpl.getInstance(), nsResolver);
-        PathResolver pr = new ParsingPathResolver(PathFactoryImpl.getInstance(), nr);
+        PathResolver pr = new ParsingPathResolver(PathFactoryImpl.getInstance(), nr, idResolver);
         if (enableCaching) {
             this.nResolver = new CachingNameResolver(nr);
             this.pResolver = new CachingPathResolver(pr);
@@ -78,6 +82,10 @@
         return pResolver.getQPath(path);
     }
 
+    public Path getQPath(String path, boolean normalizeIdentifier) throws MalformedPathException, IllegalNameException, NamespaceException {
+        return pResolver.getQPath(path, normalizeIdentifier);
+    }
+
     public String getJCRPath(Path path) throws NamespaceException {
         return pResolver.getJCRPath(path);
     }

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/IdentifierResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/IdentifierResolver.java?rev=772659&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/IdentifierResolver.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/IdentifierResolver.java Thu May  7 14:29:34 2009
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.spi.commons.conversion;
+
+import org.apache.jackrabbit.spi.Path;
+
+/**
+ * <code>IdentifierResolver</code> ....
+ */
+public interface IdentifierResolver {
+    
+    public Path getPath(String identifier) throws MalformedPathException;
+
+    public void checkFormat(String identifier) throws MalformedPathException;
+}

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/ParsingPathResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/ParsingPathResolver.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/ParsingPathResolver.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/ParsingPathResolver.java Thu May  7 14:29:34 2009
@@ -35,20 +35,40 @@
     /**
      * Name resolver.
      */
-    private final NameResolver resolver;
+    private final NameResolver nameResolver;
+
+    /**
+     * Identifier resolver.
+     */
+    private final IdentifierResolver idResolver;
 
     /**
      * Creates a parsing path resolver.
      *
+     * @param pathFactory path factory.
      * @param resolver name resolver
      */
     public ParsingPathResolver(PathFactory pathFactory, NameResolver resolver) {
+        this(pathFactory, resolver, null);
+    }
+
+    /**
+     * Creates a parsing path resolver.
+     *
+     * @param pathFactory path factory.
+     * @param nameResolver name resolver.
+     * @param idResolver identifier resolver.
+     * @since JCR 2.0
+     */
+    public ParsingPathResolver(PathFactory pathFactory, NameResolver nameResolver,
+                               IdentifierResolver idResolver) {
         this.pathFactory = pathFactory;
-        this.resolver = resolver;
+        this.nameResolver = nameResolver;
+        this.idResolver = idResolver;
     }
 
     /**
-     * Parses the prefixed JCR path and returns the resolved qualified path.
+     * Parses the given JCR path and returns the resolved qualified path.
      *
      * @param path prefixed JCR path
      * @return qualified path
@@ -57,12 +77,22 @@
      * @throws NamespaceException if a namespace prefix can not be resolved
      */
     public Path getQPath(String path) throws MalformedPathException, IllegalNameException, NamespaceException {
-        return PathParser.parse(path, resolver, pathFactory);
+        return PathParser.parse(path, nameResolver, idResolver, pathFactory);
+    }
+
+    /**
+     * Calls {@link PathParser#parse(String, NameResolver, IdentifierResolver, org.apache.jackrabbit.spi.PathFactory)}
+     * from the given <code>path</code>.
+     * 
+     * @see PathResolver#getQPath(String, boolean)
+     */
+    public Path getQPath(String path, boolean normalizeIdentifier) throws MalformedPathException, IllegalNameException, NamespaceException {
+        return PathParser.parse(path, nameResolver, idResolver, pathFactory, normalizeIdentifier);
     }
 
 
     /**
-     * Returns the prefixed JCR path for the given qualified path.
+     * Returns the given JCR path for the given qualified path.
      *
      * @param path qualified path
      * @return prefixed JCR path
@@ -82,8 +112,10 @@
                 buffer.append('.');
             } else if (elements[i].denotesParent()) {
                 buffer.append("..");
+            } else if (elements[i].denotesIdentifier()) {
+                buffer.append(elements[i].getString());
             } else {
-                buffer.append(resolver.getJCRName(elements[i].getName()));
+                buffer.append(nameResolver.getJCRName(elements[i].getName()));
                 /**
                  * FIXME the [1] subscript should only be suppressed if the
                  * item in question can't have same-name siblings.

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/PathParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/PathParser.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/PathParser.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/PathParser.java Thu May  7 14:29:34 2009
@@ -39,15 +39,20 @@
     private static final int STATE_INDEX_END = 5;
     private static final int STATE_DOT = 6;
     private static final int STATE_DOTDOT = 7;
+    private static final int STATE_IDENTIFIER = 8;
+    private static final int STATE_URI = 9;
+    private static final int STATE_URI_END = 10;
 
     /**
      * Parses <code>jcrPath</code> into a qualified path using
-     * <code>resolver</code> to convert prefixes into namespace URI's.
+     * <code>resolver</code> to convert prefixes into namespace URI's. If
+     * resolver is <code>null</code> this method only checks the format of the
+     * passed String and returns <code>null</code>.
      *
      * @param jcrPath the jcr path.
      * @param resolver the namespace resolver.
      * @param factory
-     * @return qualified path.
+     * @return A path object.
      * @throws MalformedPathException If the <code>jcrPath</code> is malformed.
      * @throws IllegalNameException if any of the jcrNames is malformed.
      * @throws NamespaceException If an unresolvable prefix is encountered.
@@ -58,17 +63,76 @@
     }
 
     /**
-     * Parses the give <code>jcrPath</code> and returns a <code>Path</code>. If
+     * Parses <code>jcrPath</code> into a qualified path using
+     * <code>resolver</code> to convert prefixes into namespace URI's. If the
+     * specified <code>jcrPath</code> is an identifier based absolute path
+     * beginning with an identifier segment the specified
+     * <code>IdentifierResolver</code> will be used to resolve it to an
+     * absolute path.<p/>
+     * If <code>namResolver</code> is <code>null</code> or if <code>identifierResolver</code>
+     * is <code>null</code> and the path starts with an identifier segment, this
+     * method only checks the format of the string and returns <code>null</code>.
+     *
+     * @param jcrPath the jcr path.
+     * @param nameResolver the namespace resolver.
+     * @param identifierResolver the resolver to validate any trailing identifier
+     * segment and resolve to an absolute path.
+     * @param factory
+     * @return A path object.
+     * @throws MalformedPathException If the <code>jcrPath</code> is malformed.
+     * @throws IllegalNameException if any of the jcrNames is malformed.
+     * @throws NamespaceException If an unresolvable prefix is encountered.
+     * @since JCR 2.0
+     */
+    public static Path parse(String jcrPath, NameResolver nameResolver,
+                             IdentifierResolver identifierResolver, PathFactory factory)
+            throws MalformedPathException, IllegalNameException, NamespaceException {
+        return parse(null, jcrPath, nameResolver, identifierResolver, factory);
+    }
+
+    /**
+     * Parses <code>jcrPath</code> into a qualified path using
+     * <code>resolver</code> to convert prefixes into namespace URI's. If the
+     * specified <code>jcrPath</code> is an identifier based absolute path
+     * beginning with an identifier segment the specified
+     * <code>IdentifierResolver</code> will be used to resolve it to an
+     * absolute path.<p/>
+     * If <code>namResolver</code> is <code>null</code> or if <code>identifierResolver</code>
+     * is <code>null</code> and the path starts with an identifier segment, this
+     * method only checks the format of the string and returns <code>null</code>.
+     *
+     * @param jcrPath the jcr path.
+     * @param nameResolver the namespace resolver.
+     * @param identifierResolver the resolver to validate any trailing identifier
+     * segment and resolve to an absolute path.
+     * @param factory
+     * @param normalizeIdentifier
+     * @return A path object.
+     * @throws MalformedPathException If the <code>jcrPath</code> is malformed.
+     * @throws IllegalNameException if any of the jcrNames is malformed.
+     * @throws NamespaceException If an unresolvable prefix is encountered.
+     * @since JCR 2.0
+     */
+    public static Path parse(String jcrPath, NameResolver nameResolver,
+                             IdentifierResolver identifierResolver,
+                             PathFactory factory, boolean normalizeIdentifier)
+            throws MalformedPathException, IllegalNameException, NamespaceException {
+        return parse(null, jcrPath, nameResolver, identifierResolver, factory, normalizeIdentifier);
+    }
+
+    /**
+     * Parses the given <code>jcrPath</code> and returns a <code>Path</code>. If
      * <code>parent</code> is not <code>null</code>, it is prepended to the
-     * returned list. If <code>resolver</code> is <code>null</code>, this method
-     * only checks the format of the string and returns <code>null</code>.
+     * built path before it is returned. If <code>resolver</code> is
+     * <code>null</code>, this method only checks the format of the string and
+     * returns <code>null</code>.
      *
      * @param parent   the parent path
      * @param jcrPath  the JCR path
      * @param resolver the namespace resolver to get prefixes for namespace
      *                 URI's.
      * @param factory
-     * @return the fully qualified Path.
+     * @return the <code>Path</code> object.
      * @throws MalformedPathException If the <code>jcrPath</code> is malformed.
      * @throws IllegalNameException if any of the jcrNames is malformed.
      * @throws NamespaceException If an unresolvable prefix is encountered.
@@ -76,6 +140,65 @@
     public static Path parse(Path parent, String jcrPath,
                              NameResolver resolver,
                              PathFactory factory) throws MalformedPathException, IllegalNameException, NamespaceException {
+        return parse(parent, jcrPath, resolver, null, factory);
+    }
+
+    /**
+     * Parses the given <code>jcrPath</code> and returns a <code>Path</code>. If
+     * <code>parent</code> is not <code>null</code>, it is prepended to the
+     * built path before it is returned. If the specifed <code>jcrPath</code>
+     * is an identifier based absolute path beginning with an identifier segment
+     * the given <code>identifierResolver</code> will be used to resolve it to an
+     * absolute path.<p/>
+     * If <code>nameResolver</code> is <code>null</code> or if <code>identifierResolver</code>
+     * is <code>null</code> and the path starts with an identifier segment, this
+     * method only checks the format of the string and returns <code>null</code>.
+     *
+     * @param parent the parent path.
+     * @param jcrPath the jcr path.
+     * @param nameResolver the namespace resolver.
+     * @param identifierResolver the resolver to validate any trailing identifier
+     * segment and resolve it to an absolute path.
+     * @param factory The path factory.
+     * @return the <code>Path</code> object.
+     * @throws MalformedPathException
+     * @throws IllegalNameException
+     * @throws NamespaceException
+     */
+    public static Path parse(Path parent, String jcrPath, NameResolver nameResolver,
+                             IdentifierResolver identifierResolver, PathFactory factory)
+            throws MalformedPathException, IllegalNameException, NamespaceException {
+        return parse(parent, jcrPath, nameResolver, identifierResolver, factory, true);
+    }
+
+    /**
+     * Parses the given <code>jcrPath</code> and returns a <code>Path</code>. If
+     * <code>parent</code> is not <code>null</code>, it is prepended to the
+     * built path before it is returned. If the specifed <code>jcrPath</code>
+     * is an identifier based absolute path beginning with an identifier segment
+     * the given <code>identifierResolver</code> will be used to resolve it to an
+     * absolute path.<p/>
+     * If <code>nameResolver</code> is <code>null</code> or if <code>identifierResolver</code>
+     * is <code>null</code> and the path starts with an identifier segment, this
+     * method only checks the format of the string and returns <code>null</code>.
+     *
+     * @param parent the parent path.
+     * @param jcrPath the jcr path.
+     * @param nameResolver the namespace resolver.
+     * @param identifierResolver the resolver to validate any trailing identifier
+     * segment and resolve it to an absolute path.
+     * @param factory The path factory.
+     * @param normalizeIdentifier
+     * @return the <code>Path</code> object.
+     * @throws MalformedPathException
+     * @throws IllegalNameException
+     * @throws NamespaceException
+     */
+    private static Path parse(Path parent, String jcrPath, NameResolver nameResolver,
+                             IdentifierResolver identifierResolver, PathFactory factory,
+                             boolean normalizeIdentifier)
+            throws MalformedPathException, IllegalNameException, NamespaceException {
+        
         final char EOF = (char) -1;
 
         // check for length
@@ -95,7 +218,7 @@
         int pos = 0;
         if (jcrPath.charAt(0) == '/') {
             if (parent != null) {
-                throw new MalformedPathException("'" + jcrPath + "' is not a relative path");
+                throw new MalformedPathException("'" + jcrPath + "' is not a relative path.");
             }
             builder.addRoot();
             pos++;
@@ -107,12 +230,26 @@
         }
 
         // parse the path
-        int state = STATE_PREFIX_START;
+        int state;
+        if (jcrPath.charAt(0) == '[') {
+            if (parent != null) {
+                throw new MalformedPathException("'" + jcrPath + "' is not a relative path.");
+            }
+            state = STATE_IDENTIFIER;
+            pos++;
+        } else {
+            state = STATE_PREFIX_START;
+        }
+
         int lastPos = pos;
+
         String name = null;
+
         int index = Path.INDEX_UNDEFINED;
         boolean wasSlash = false;
 
+        boolean checkFormat = (nameResolver == null);
+
         while (pos <= len) {
             char c = pos == len ? EOF : jcrPath.charAt(pos);
             pos++;
@@ -128,7 +265,8 @@
                     }
                     if (state == STATE_PREFIX
                             || state == STATE_NAME
-                            || state == STATE_INDEX_END) {
+                            || state == STATE_INDEX_END
+                            || state == STATE_URI_END) {
 
                         // eof pathelement
                         if (name == null) {
@@ -140,14 +278,38 @@
 
                         // only add element if resolver not null. otherwise this
                         // is just a check for valid format.
-                        if (resolver != null) {
-                            Name qName = resolver.getQName(name);
+                        if (checkFormat) {
+                            NameParser.checkFormat(name);
+                        } else {
+                            Name qName = nameResolver.getQName(name);
                             builder.addLast(qName, index);
                         }
                         state = STATE_PREFIX_START;
                         lastPos = pos;
                         name = null;
                         index = Path.INDEX_UNDEFINED;
+                    } else if (state == STATE_IDENTIFIER) {
+                        if (c == EOF) {
+                            // eof identifier reached                            
+                            if (jcrPath.charAt(pos - 2) != ']') {
+                                throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Unterminated identifier segment.");
+                            }
+                            String identifier = jcrPath.substring(lastPos, pos - 2);
+                            if (checkFormat) {
+                                if (identifierResolver != null) {
+                                    identifierResolver.checkFormat(identifier);
+                                } // else ignore. TODO: rather throw?
+                            } else if (identifierResolver == null) {
+                                throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Identifier segments are not supported.");
+                            } else if (normalizeIdentifier) {
+                                builder.addAll(identifierResolver.getPath(identifier).getElements());
+                            } else {
+                                identifierResolver.checkFormat(identifier);
+                                builder.addLast(factory.createElement(identifier));
+                            }
+                            state = STATE_PREFIX_START;
+                            lastPos = pos;
+                        }
                     } else if (state == STATE_DOT) {
                         builder.addLast(factory.getCurrentElement());
                         lastPos = pos;
@@ -158,7 +320,7 @@
                         state = STATE_PREFIX_START;
                     } else if (state == STATE_PREFIX_START && c == EOF) {
                         // ignore trailing slash
-                    } else {
+                    } else if (state != STATE_URI) {
                         throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character.");
                     }
                     break;
@@ -184,6 +346,8 @@
                         }
                         state = STATE_NAME_START;
                         // don't reset the lastPos/pos since prefix+name are passed together to the NameResolver
+                    } else if (state == STATE_IDENTIFIER || state == STATE_URI) {
+                        // nothing do
                     } else {
                         throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid name character");
                     }
@@ -197,6 +361,8 @@
                         state = STATE_INDEX;
                         name = jcrPath.substring(lastPos, pos - 1);
                         lastPos = pos;
+                    } else if (state == STATE_IDENTIFIER) {
+                        // nothing do
                     } else {
                         throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character.");
                     }
@@ -213,6 +379,8 @@
                             throw new MalformedPathException("'" + jcrPath + "' is not a valid path. Index number invalid: " + index);
                         }
                         state = STATE_INDEX_END;
+                    } else if (state == STATE_IDENTIFIER) {
+                        // nothing do
                     } else {
                         throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character.");
                     }
@@ -225,19 +393,32 @@
                         throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid after index. '/' expected.");
                     } else if (state == STATE_DOT || state == STATE_DOTDOT) {
                         state = STATE_PREFIX;
-                    } else if (state == STATE_INDEX_END) {
-                        throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid after index. '/' expected.");
                     }
                     break;
 
                 case '\t':
-                    throw new MalformedPathException("'" + jcrPath + "' is not a valid path. Whitespace not a allowed in name.");
-
+                    if (state != STATE_IDENTIFIER) {
+                        throw new MalformedPathException("'" + jcrPath + "' is not a valid path. Whitespace not a allowed in name.");
+                    }
                 case '*':
                 case '\'':
                 case '\"':
-                    throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character.");
+                    if (state != STATE_IDENTIFIER) {
+                        // TODO for JCR 2.0 remove limitation of ' and "
+                        throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character.");
+                    }
+                case '{':
+                    if (state == STATE_PREFIX_START) {
+                        state = STATE_URI;
+                    }
+                    break;
 
+                case '}':
+                    if (state == STATE_URI) {
+                        state = STATE_URI_END;
+                    }
+                    break;
+                
                 default:
                     if (state == STATE_PREFIX_START || state == STATE_DOT || state == STATE_DOTDOT) {
                         state = STATE_PREFIX;
@@ -250,7 +431,7 @@
             wasSlash = c == ' ';
         }
 
-        if (resolver == null) {
+        if (checkFormat) {
             // this was only for checking the format
             return null;
         } else {
@@ -269,7 +450,7 @@
     public static void checkFormat(String jcrPath) throws MalformedPathException {
         try {
             // since no path is created -> use default factory
-            parse(jcrPath, null, PathFactoryImpl.getInstance());
+            parse(jcrPath, null, null, PathFactoryImpl.getInstance());
         } catch (NamespaceException e) {
             // will never occur
         } catch (IllegalNameException e) {

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/PathResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/PathResolver.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/PathResolver.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/conversion/PathResolver.java Thu May  7 14:29:34 2009
@@ -26,10 +26,10 @@
 public interface PathResolver {
 
     /**
-     * Returns the qualified path for the given prefixed JCR path.
+     * Returns the path object for the given JCR path string.
      *
      * @param path prefixed JCR path
-     * @return qualified path
+     * @return a <code>Path</code> object.
      * @throws MalformedPathException if the JCR path format is invalid.
      * @throws IllegalNameException if any of the JCR names contained in the path are invalid.
      * @throws NamespaceException if a namespace prefix can not be resolved.
@@ -37,10 +37,22 @@
     Path getQPath(String path) throws MalformedPathException, IllegalNameException, NamespaceException;
 
     /**
-     * Returns the prefixed JCR path for the given qualified path.
+     * Returns the path object for the given JCR path string.
      *
-     * @param path qualified path
-     * @return prefixed JCR path
+     * @param path prefixed JCR path
+     * @param normalizeIdentifier
+     * @return a <code>Path</code> object.
+     * @throws MalformedPathException if the JCR path format is invalid.
+     * @throws IllegalNameException if any of the JCR names contained in the path are invalid.
+     * @throws NamespaceException if a namespace prefix can not be resolved.
+     */
+    Path getQPath(String path, boolean normalizeIdentifier) throws MalformedPathException, IllegalNameException, NamespaceException;
+
+    /**
+     * Returns the given JCR path string for the given path object.
+     *
+     * @param path a <code>Path</code> object.
+     * @return a JCR path string
      * @throws NamespaceException if a namespace URI can not be resolved
      */
     String getJCRPath(Path path) throws NamespaceException;

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/PathFactoryLogger.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/PathFactoryLogger.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/PathFactoryLogger.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/PathFactoryLogger.java Thu May  7 14:29:34 2009
@@ -117,6 +117,13 @@
             }}, "createElement(Name)", new Object[]{name, new Integer(index)});
     }
 
+    public Element createElement(final String identifier) throws IllegalArgumentException {
+        return (Element) execute(new SafeCallable() {
+            public Object call() {
+                return pathFactory.createElement(identifier);
+            }}, "createElement(String)", new Object[]{identifier});
+    }
+
     public Element getCurrentElement() {
         return (Element) execute(new SafeCallable() {
             public Object call() {

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathBuilder.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathBuilder.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathBuilder.java Thu May  7 14:29:34 2009
@@ -46,16 +46,6 @@
     private final LinkedList queue;
 
     /**
-     * flag indicating if the current path is normalized
-     */
-    boolean isNormalized = true;
-
-    /**
-     * flag indicating if the current path has leading parent '..' elements
-     */
-    boolean leadingParent = true;
-
-    /**
      * Creates a new PathBuilder to create a Path using the
      * {@link PathFactoryImpl default PathFactory}. See
      * {@link PathBuilder#PathBuilder(PathFactory)} for a constructor explicitely
@@ -121,13 +111,6 @@
      * @param elem
      */
     public void addFirst(Path.Element elem) {
-        if (queue.isEmpty()) {
-            isNormalized &= !elem.denotesCurrent();
-            leadingParent = elem.denotesParent();
-        } else {
-            isNormalized &= !elem.denotesCurrent() && (!leadingParent || elem.denotesParent());
-            leadingParent |= elem.denotesParent();
-        }
         queue.addFirst(elem);
     }
 
@@ -157,8 +140,6 @@
      */
     public void addLast(Path.Element elem) {
         queue.addLast(elem);
-        leadingParent &= elem.denotesParent();
-        isNormalized &= !elem.denotesCurrent() && (leadingParent || !elem.denotesParent());
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java Thu May  7 14:29:34 2009
@@ -137,7 +137,7 @@
     }
 
     /**
-     * @see PathFactory#create(Path.Element[])
+     * @see PathFactory#create(org.apache.jackrabbit.spi.Path.Element[])
      */
     public Path create(Path.Element[] elements) throws IllegalArgumentException {
         return new Builder(elements).getPath();
@@ -157,11 +157,11 @@
         while (lastPos >= 0) {
             Path.Element elem;
             if (pos >= 0) {
-                elem = createElement(pathString.substring(lastPos, pos));
+                elem = createElementFromString(pathString.substring(lastPos, pos));
                 lastPos = pos + 1;
                 pos = pathString.indexOf(Path.DELIMITER, lastPos);
             } else {
-                elem = createElement(pathString.substring(lastPos));
+                elem = createElementFromString(pathString.substring(lastPos));
                 lastPos = -1;
             }
             list.add(elem);
@@ -204,10 +204,18 @@
         }
     }
 
+    public Path.Element createElement(String identifier) throws IllegalArgumentException {
+        if (identifier == null) {
+            throw new IllegalArgumentException("The id must not be null.");
+        } else {
+            return new IdentifierElement(identifier);
+        }
+    }
+
     /**
      * Create an element from the element string
      */
-    private Path.Element createElement(String elementString) {
+    private Path.Element createElementFromString(String elementString) {
         if (elementString == null) {
             throw new IllegalArgumentException("null PathElement literal");
         }
@@ -217,6 +225,8 @@
             return CURRENT_ELEMENT;
         } else if (elementString.equals(PARENT_LITERAL)) {
             return PARENT_ELEMENT;
+        } else if (elementString.startsWith("[") && elementString.endsWith("]") && elementString.length() > 2) {
+            return new IdentifierElement(elementString.substring(1, elementString.length()-1));
         }
 
         int pos = elementString.indexOf('[');
@@ -301,7 +311,7 @@
                 throw new IllegalArgumentException("Empty paths are not allowed");
             }
             this.elements = elements;
-            this.absolute = elements[0].denotesRoot();
+            this.absolute = elements[0].denotesRoot() || elements[0].denotesIdentifier();
             this.normalized = isNormalized;
         }
 
@@ -309,7 +319,14 @@
          * @see Path#denotesRoot()
          */
         public boolean denotesRoot() {
-            return absolute && elements.length == 1;
+            return absolute && elements.length == 1 && elements[0].denotesRoot();
+        }
+
+        /**
+         * @see Path#denotesIdentifier()
+         */
+        public boolean denotesIdentifier() {
+            return elements.length == 1 && elements[0].denotesIdentifier();
         }
 
         /**
@@ -336,10 +353,13 @@
         /**
          * @see Path#getNormalizedPath()
          */
-        public Path getNormalizedPath() {
+        public Path getNormalizedPath() throws RepositoryException {
             if (isNormalized()) {
                 return this;
             }
+            if (denotesIdentifier()) {
+                throw new RepositoryException("Identifier-based path cannot be normalized.");                 
+            }
             LinkedList queue = new LinkedList();
             Path.Element last = PARENT_ELEMENT;
             for (int i = 0; i < elements.length; i++) {
@@ -373,6 +393,9 @@
             if (!isAbsolute()) {
                 throw new RepositoryException("Only an absolute path can be canonicalized.");
             }
+            if (denotesIdentifier()) {
+                throw new RepositoryException("Identifier-based path cannot be canonicalized.");
+            }
             return getNormalizedPath();
         }
 
@@ -384,10 +407,13 @@
                 throw new IllegalArgumentException("null argument");
             }
 
-            // make sure both paths are absolute
+            // make sure both paths are absolute and not id-based
             if (!isAbsolute() || !other.isAbsolute()) {
                 throw new RepositoryException("Cannot compute relative path from relative paths");
             }
+            if (denotesIdentifier() || other.denotesIdentifier()) {
+                throw new RepositoryException("Cannot compute relative path from identifier-based paths");                
+            }
 
             // make sure we're comparing canonical paths
             Path p0 = getCanonicalPath();
@@ -430,11 +456,11 @@
         /**
          * @see Path#getAncestor(int)
          */
-        public Path getAncestor(int degree) throws IllegalArgumentException, PathNotFoundException {
+        public Path getAncestor(int degree) throws IllegalArgumentException, PathNotFoundException, RepositoryException {
             if (degree < 0) {
                 throw new IllegalArgumentException("degree must be >= 0");
             } else if (degree == 0) {
-                return this.getNormalizedPath();
+                return getNormalizedPath();
             }
 
             if (isAbsolute()) {
@@ -461,7 +487,12 @@
          * @see Path#getAncestorCount()
          */
         public int getAncestorCount() {
-            return (isAbsolute()) ? getDepth() : -1;
+            try {
+                return (isAbsolute() && !denotesIdentifier()) ? getDepth() : -1;
+            } catch (RepositoryException e) {
+                // never gets here.
+                return -1;
+            }
         }
 
         /**
@@ -474,7 +505,10 @@
         /**
          * @see Path#getDepth()
          */
-        public int getDepth() {
+        public int getDepth() throws RepositoryException {
+            if (denotesIdentifier()) {
+                throw new RepositoryException("Cannot determine depth of an identifier based path.");
+            }
             int depth = ROOT_DEPTH;
             for (int i = 0; i < elements.length; i++) {
                 if (elements[i].denotesParent()) {
@@ -750,6 +784,14 @@
         }
 
         /**
+         * @return always returns false.
+         * @see Path.Element#denotesIdentifier()
+         */
+        public boolean denotesIdentifier() {
+            return false;
+        }
+
+        /**
          * @see Path.Element#getString()
          */
         public String getString() {
@@ -871,6 +913,86 @@
     }
 
     /**
+     * 
+     */
+    private static final class IdentifierElement extends Element {
+
+        private final String identifier;
+        /**
+         * 
+         * @param identifier
+         */
+        private IdentifierElement(String identifier) {
+            super(null, Path.INDEX_UNDEFINED);
+            this.identifier = identifier;
+        }
+
+        /**
+         * @return Always returns true.
+         * @see Path.Element#denotesIdentifier()
+         */
+        public boolean denotesIdentifier() {
+            return true;
+        }
+
+        /**
+         * @return Always returns false.
+         * @see Path.Element#denotesName()
+         */
+        public boolean denotesName() {
+            return false;
+        }
+
+        /**
+         * Returns a string representation of this path element. Note that
+         * the path element name is expressed using the <code>{uri}name</code>
+         * syntax.
+         *
+         * @return string representation of the path element
+         * @see Object#toString()
+         */
+        public String toString() {
+            StringBuffer sb = new StringBuffer();
+            sb.append('[');
+            sb.append(identifier);
+            sb.append(']');
+            return sb.toString();
+        }
+
+        /**
+         * Computes a hash code for this path element.
+         *
+         * @return hash code
+         * @see Object#hashCode()
+         */
+        public int hashCode() {
+            int h = 37 * 17 + identifier.hashCode();
+            return h;
+        }
+
+        /**
+         * Check for path element equality. Returns true if the given
+         * object is a PathElement and contains the same name and index
+         * as this one.
+         *
+         * @param obj the object to compare with
+         * @return <code>true</code> if the path elements are equal
+         * @see Object#equals(Object)
+         */
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof IdentifierElement) {
+                return identifier.equals(((IdentifierElement) obj).identifier);
+            } if (obj instanceof Path.Element) {
+                Path.Element other = (Path.Element) obj;
+                return other.denotesIdentifier() && getString().equals(other.getString());
+            }
+            return false;
+        }
+    }
+    /**
      * Builder internal class
      */
     private static final class Builder {
@@ -912,7 +1034,7 @@
 
             this.elements = elements;
             if (elements.length == 1) {
-                isNormalized = true;
+                isNormalized = !elements[0].denotesIdentifier();
             } else {
                 boolean absolute = elements[0].denotesRoot();
                 isNormalized = true;
@@ -926,6 +1048,8 @@
                         if (i > 0) {
                             throw new IllegalArgumentException("Invalid path: The root element may only occur at the beginning.");
                         }
+                    } else if (elem.denotesIdentifier()) {
+                        throw new IllegalArgumentException("Invalid path: The identifier element may only occur at the beginning of a single element path.");
                     } else  if (elem.denotesParent()) {
                         parents++;
                         if (absolute || named > 0) {

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java?rev=772659&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java Thu May  7 14:29:34 2009
@@ -0,0 +1,319 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.spi.commons.value;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.util.ISO8601;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * <code>AbstractQValue</code>...
+ */
+public abstract class AbstractQValue implements QValue {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(AbstractQValue.class);
+
+    protected Object val;
+    protected final int type;
+
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value The value.
+     * @param type The property type.
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code>.
+     */
+    protected AbstractQValue(Object value, int type) {
+        if (value == null) {
+            throw new IllegalArgumentException("null value");
+        }
+        val = value;
+        this.type = type;
+    }
+
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value
+     * @param type
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code> or if the <code>type</code> is neither STRING nor REFERENCE.
+     */
+    protected AbstractQValue(String value, int type) {
+        if (value == null) {
+            throw new IllegalArgumentException("null value");
+        }
+        if (!(type == PropertyType.STRING || type == PropertyType.REFERENCE)) {
+            throw new IllegalArgumentException();
+        }
+        val = value;
+        this.type = type;
+    }
+
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code>.
+     */
+    protected AbstractQValue(Long value) {
+        this(value, PropertyType.LONG);
+    }
+
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code>.
+     */
+    protected AbstractQValue(Double value) {
+        this(value, PropertyType.DOUBLE);
+    }
+
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code>.
+     */
+    protected AbstractQValue(Boolean value) {
+        this(value, PropertyType.BOOLEAN);
+    }
+
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code>.
+     */
+    protected AbstractQValue(Calendar value) {
+        this(value, PropertyType.DATE);
+    }
+
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code>.
+     */
+    protected AbstractQValue(Name value) {
+        this(value, PropertyType.NAME);
+    }
+
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code>.
+     */
+    protected AbstractQValue(Path value) {
+        this(value, PropertyType.PATH);
+    }
+
+    //---------------------------------------------------------< QValue >---
+    /**
+     * @see QValue#getType()
+     */
+    public int getType() {
+        return type;
+    }
+
+    /**
+     * @see QValue#getLength()
+     */
+    public long getLength() throws RepositoryException {
+        return getString().length();
+    }
+
+    /**
+     * @see QValue#getName()
+     */
+    public Name getName() throws RepositoryException {
+        if (type == PropertyType.NAME) {
+            return (Name) val;
+        } else {
+            try {
+                return AbstractQValueFactory.NAME_FACTORY.create(getString());
+            } catch (IllegalArgumentException e) {
+                throw new ValueFormatException("not a valid Name value: " + getString(), e);
+            }
+        }
+    }
+
+    /**
+     * @see QValue#getCalendar()
+     */
+    public Calendar getCalendar() throws RepositoryException {
+        if (type == PropertyType.DATE) {
+            return (Calendar) ((Calendar) val).clone();
+        } else if (type == PropertyType.DOUBLE) {
+            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00"));
+            cal.setTimeInMillis(((Double) val).longValue());
+            return cal;
+        } else if (type == PropertyType.LONG) {
+            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00"));
+            cal.setTimeInMillis(((Long) val).longValue());
+            return cal;
+        } else {
+            Calendar cal = ISO8601.parse(getString());
+            if (cal == null) {
+                throw new ValueFormatException("not a date string: " + getString());
+            } else {
+                return cal;
+            }
+        }
+    }
+
+    /**
+     * @see QValue#getDouble()
+     */
+    public double getDouble() throws RepositoryException {
+        if (type == PropertyType.DOUBLE) {
+            return ((Double) val).doubleValue();
+        } else if (type == PropertyType.DATE) {
+            return ((Calendar) val).getTimeInMillis();
+        } else {
+            try {
+                return Double.parseDouble(getString());
+            } catch (NumberFormatException ex) {
+                throw new ValueFormatException("not a double: " + getString(), ex);
+            }
+        }
+    }
+
+    /**
+     * @see QValue#getLong()
+     */
+    public long getLong() throws RepositoryException {
+        if (type == PropertyType.LONG) {
+            return ((Long) val).longValue();
+        } else if (type == PropertyType.DOUBLE) {
+            return ((Double) val).longValue();
+        } else if (type == PropertyType.DATE) {
+            return ((Calendar) val).getTimeInMillis();
+        } else {
+            try {
+                return Long.parseLong(getString());
+            } catch (NumberFormatException ex) {
+                throw new ValueFormatException("not a long: " + getString(), ex);
+            }
+        }
+    }
+
+    /**
+     * @throws RepositoryException
+     * @see QValue#getBoolean()
+     */
+    public boolean getBoolean() throws RepositoryException {
+        if (type == PropertyType.BOOLEAN) {
+            return ((Boolean) val).booleanValue();
+        } else {
+            return Boolean.valueOf(getString()).booleanValue();
+        }
+    }
+
+    /**
+     * @see QValue#getPath()
+     */
+    public Path getPath() throws RepositoryException {
+        if (type == PropertyType.PATH) {
+            return (Path) val;
+        } else {
+            try {
+                return AbstractQValueFactory.PATH_FACTORY.create(getString());
+            } catch (IllegalArgumentException e) {
+                throw new ValueFormatException("not a valid Path: " + getString(), e);
+            }
+        }
+    }
+
+    /**
+     * @see QValue#discard()
+     */
+    public void discard() {
+        // nothing to do
+    }
+
+    //---------------------------------------------------------< Object >---
+    /**
+     * Returns the string representation of this internal value.
+     *
+     * @return string representation of this internal value
+     */
+    public String toString() {
+        return val.toString();
+    }
+
+    /**
+     * Default implementation of the equals method. Subclasses may optimize
+     * this e.g. by special handling for DATE properties.
+     *
+     * @param obj
+     * @see Object#equals(Object)
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof AbstractQValue) {
+            AbstractQValue other = (AbstractQValue) obj;
+            if (type != other.type) {
+                return false;
+            }
+            if (PropertyType.DATE == type) {
+                return ISO8601.format((Calendar) val).equals(ISO8601.format((Calendar) other.val));
+            } else {
+                return val.equals(other.val);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Default calculation of the hashCode. Subclasses may optimize
+     * this e.g. by special handling for DATE properties.
+     *
+     * @return the hashCode of the internal value object.
+     * @see Object#hashCode()
+     */
+    public int hashCode() {
+        if (PropertyType.DATE == type) {
+            return ISO8601.format((Calendar) val).hashCode();
+        } else {
+            return val.hashCode();
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValueFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValueFactory.java?rev=772659&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValueFactory.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValueFactory.java Thu May  7 14:29:34 2009
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.spi.commons.value;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.spi.QValueFactory;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.PathFactory;
+import org.apache.jackrabbit.spi.NameFactory;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.apache.jackrabbit.uuid.UUID;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
+import java.util.Calendar;
+
+/**
+ * <code>AbstractQValueFactory</code>...
+ */
+public abstract class AbstractQValueFactory implements QValueFactory {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(AbstractQValueFactory.class);
+
+
+    /**
+     * the default encoding
+     */
+    public static final String DEFAULT_ENCODING = "UTF-8";
+
+    protected static final PathFactory PATH_FACTORY = PathFactoryImpl.getInstance();
+    protected static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
+
+
+    //------------------------------------------------------< QValueFactory >---
+    /**
+     * @see QValueFactory#computeAutoValues(org.apache.jackrabbit.spi.QPropertyDefinition)
+     */
+    public QValue[] computeAutoValues(QPropertyDefinition propertyDefinition) throws RepositoryException {
+        Name nodeType = propertyDefinition.getDeclaringNodeType();
+        Name name = propertyDefinition.getName();
+
+        if (NameConstants.NT_HIERARCHYNODE.equals(nodeType) && NameConstants.JCR_CREATED.equals(name)) {
+            return new QValue[] { create(Calendar.getInstance()) };
+        } else if (NameConstants.NT_RESOURCE.equals(nodeType) && NameConstants.JCR_LASTMODIFIED.equals(name)) {
+            return new QValue[] { create(Calendar.getInstance()) };
+        } else if (NameConstants.MIX_REFERENCEABLE.equals(nodeType) && NameConstants.JCR_UUID.equals(name)) {
+            return new QValue[] { create(UUID.randomUUID().toString(), PropertyType.STRING) };
+        } else {
+            throw new RepositoryException("createFromDefinition not implemented for: " + name);
+        }
+    }
+}
\ No newline at end of file



Mime
View raw message