You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2009/05/07 16:29:48 UTC

svn commit: r772659 [3/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...

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java Thu May  7 14:29:34 2009
@@ -16,6 +16,16 @@
  */
 package org.apache.jackrabbit.spi.commons.value;
 
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.QValueFactory;
+import org.apache.jackrabbit.util.ISO8601;
+import org.apache.jackrabbit.util.TransientFileFactory;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -31,41 +41,14 @@
 import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
 import java.util.Calendar;
-import java.util.TimeZone;
-
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
-
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.NameFactory;
-import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.spi.PathFactory;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
-import org.apache.jackrabbit.spi.QValue;
-import org.apache.jackrabbit.spi.QValueFactory;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
-import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
-import org.apache.jackrabbit.util.ISO8601;
-import org.apache.jackrabbit.util.TransientFileFactory;
-import org.apache.jackrabbit.uuid.UUID;
 
 /**
  * <code>QValueFactoryImpl</code>...
  */
-public final class QValueFactoryImpl implements QValueFactory {
+public final class QValueFactoryImpl extends AbstractQValueFactory {
 
     private static final QValueFactory INSTANCE = new QValueFactoryImpl();
 
-    private static final PathFactory PATH_FACTORY = PathFactoryImpl.getInstance();
-    private static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
-
-    /**
-     * the default encoding
-     */
-    private static final String DEFAULT_ENCODING = "UTF-8";
-
     private QValueFactoryImpl() {
     }
 
@@ -136,14 +119,14 @@
      * @see QValueFactory#create(double)
      */
     public QValue create(double value) {
-        return new QValueImpl(new Double(value));
+        return new QValueImpl(Double.valueOf(value));
     }
 
     /**
      * @see QValueFactory#create(long)
      */
     public QValue create(long value) {
-        return new QValueImpl(new Long(value));
+        return new QValueImpl(Long.valueOf(value));
     }
 
     /**
@@ -207,96 +190,52 @@
         return new BinaryQValue(value);
     }
 
-    /**
-     * @see QValueFactory#computeAutoValues(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);
-        }
-    }
 
     //--------------------------------------------------------< Inner Class >---
     /**
      * <code>QValue</code> implementation for all valid <code>PropertyType</code>s
-     * except for BINARY.
+     * except for BINARY and DATE.
      * @see QValueFactoryImpl.BinaryQValue
      */
-    private static class QValueImpl implements QValue, Serializable {
+    private static class QValueImpl extends AbstractQValue implements Serializable {
 
         private static final QValue TRUE = new QValueImpl(Boolean.TRUE);
-
         private static final QValue FALSE = new QValueImpl(Boolean.FALSE);
 
-        private final Object val;
-        private final int type;
 
         private QValueImpl(Object value, int type) {
-            val = value;
-            this.type = type;
+            super(value, type);
         }
 
         private QValueImpl(String value, int type) {
-            if (!(type == PropertyType.STRING || type == PropertyType.REFERENCE)) {
-                throw new IllegalArgumentException();
-            }
-            val = value;
-            this.type = type;
+            super(value, type);
         }
 
         private QValueImpl(Long value) {
-            val = value;
-            type = PropertyType.LONG;
+            super(value);
         }
 
         private QValueImpl(Double value) {
-            val = value;
-            type = PropertyType.DOUBLE;
+            super(value);
         }
 
         private QValueImpl(Boolean value) {
-            val = value;
-            type = PropertyType.BOOLEAN;
+            super(value);
         }
 
         private QValueImpl(Name value) {
-            val = value;
-            type = PropertyType.NAME;
+            super(value);
         }
 
         private QValueImpl(Path value) {
-            val = value;
-            type = PropertyType.PATH;
+            super(value);
         }
 
         //---------------------------------------------------------< QValue >---
         /**
-         * @see QValue#getType()
-         */
-        public int getType() {
-            return type;
-        }
-
-        /**
-         * @see QValue#getLength()
-         */
-        public long getLength() throws RepositoryException {
-            return getString().length();
-        }
-
-        /**
          * @see QValue#getString()
          */
-        public String getString() throws RepositoryException {
+        public String getString() {
             return val.toString();
         }
 
@@ -306,156 +245,11 @@
         public InputStream getStream() throws RepositoryException {
             try {
                 // convert via string
-                return new ByteArrayInputStream(getString().getBytes(QValueFactoryImpl.DEFAULT_ENCODING));
+                return new ByteArrayInputStream(getString().getBytes(DEFAULT_ENCODING));
             } catch (UnsupportedEncodingException e) {
                 throw new RepositoryException(QValueFactoryImpl.DEFAULT_ENCODING + " is not supported encoding on this platform", e);
             }
-        }
-
-        /**
-         * @see QValue#getName()
-         */
-        public Name getName() throws RepositoryException {
-            if (type == PropertyType.NAME) {
-                return (Name) val;
-            } else {
-                try {
-                    return 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 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();
-        }
-
-        /**
-         *
-         * @param obj
-         * @see Object#equals(Object)
-         */
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj instanceof QValueImpl) {
-                QValueImpl other = (QValueImpl) obj;
-                return type == other.type && val.equals(other.val);
-            }
-            return false;
-        }
-
-        /**
-         * @return the hashCode of the internal value object.
-         * @see Object#hashCode()
-         */
-        public int hashCode() {
-            return val.hashCode();
-        }
-
+    }
     }
 
     //--------------------------------------------------------< Inner Class >---
@@ -473,11 +267,10 @@
 
         /**
          * @return The formatted String of the internal Calendar value.
-         * @throws RepositoryException
          * @see QValue#getString()
          * @see ISO8601#format(Calendar)
          */
-        public String getString() throws RepositoryException {
+        public String getString() {
             return formattedStr;
         }
 

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueValue.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueValue.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueValue.java Thu May  7 14:29:34 2009
@@ -177,8 +177,7 @@
     public boolean equals(Object obj) {
         if (obj instanceof QValueValue) {
             return qvalue.equals(((QValueValue) obj).qvalue);
-        }
-        else {
+        } else {
             return false;
         }
     }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/ValueFactoryQImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/ValueFactoryQImpl.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/ValueFactoryQImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/ValueFactoryQImpl.java Thu May  7 14:29:34 2009
@@ -37,6 +37,7 @@
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.QValueFactory;
+import org.apache.jackrabbit.util.ISO8601;
 
 /**
  * This class implements the <code>ValueFactory</code> interface,
@@ -64,6 +65,16 @@
     }
 
     /**
+     * The <code>QValueFactory</code> that is wrapped by this <code>ValueFactory</code>
+     * instance.
+     *
+     * @return qfactory The <code>QValueFactory</code> wrapped by this instance.
+     */
+    public QValueFactory getQValueFactory() {
+        return qfactory;
+    }
+
+    /**
      * Create a new <code>Value</code> based on an existing
      * <code>QValue</code>
      * @param qvalue existing <code>QValue</code>
@@ -128,6 +139,7 @@
      */
     public Value createValue(Calendar value) {
         try {
+            ISO8601.getYear(value);
             QValue qvalue = qfactory.create(value);
             return new QValueValue(qvalue, resolver);
         } catch (RepositoryException ex) {
@@ -168,7 +180,7 @@
                 Name name = resolver.getQName(value);
                 qvalue = qfactory.create(name);
             } else if (type == PropertyType.PATH) {
-                Path path = resolver.getQPath(value);
+                Path path = resolver.getQPath(value, false);
                 qvalue = qfactory.create(path);
             } else {
                 qvalue = qfactory.create(value, type);

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/ValueFormat.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/ValueFormat.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/ValueFormat.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/ValueFormat.java Thu May  7 14:29:34 2009
@@ -119,7 +119,7 @@
                 qValue = factory.create(qName);
                 break;
             case PropertyType.PATH:
-                Path qPath = resolver.getQPath(jcrValue).getNormalizedPath();
+                Path qPath = resolver.getQPath(jcrValue, false);
                 qValue = factory.create(qPath);
                 break;
             default:
@@ -131,7 +131,8 @@
     /**
      * @param qualifiedValue
      * @param resolver
-     * @return
+     * @param factory
+     * @return the JCR value created from the given <code>qualifiedValue</code>.
      * @throws RepositoryException
      */
     public static Value getJCRValue(QValue qualifiedValue,

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatedBatchTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatedBatchTest.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatedBatchTest.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatedBatchTest.java Thu May  7 14:29:34 2009
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.spi.commons.batch;
 
-import javax.jcr.PathNotFoundException;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 
@@ -379,7 +378,7 @@
         return createNodeId(createPath(nodeId));
     }
 
-    public PropertyId createPropertyId(String propertyId) throws PathNotFoundException {
+    public PropertyId createPropertyId(String propertyId) throws RepositoryException {
         Path path = createPath(propertyId);
         return idFactory.createPropertyId(createNodeId(path.getAncestor(1)), path.getNameElement().getName());
     }

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/DummyIdentifierResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/DummyIdentifierResolver.java?rev=772659&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/DummyIdentifierResolver.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/DummyIdentifierResolver.java Thu May  7 14:29:34 2009
@@ -0,0 +1,117 @@
+/*
+ * 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;
+import org.apache.jackrabbit.spi.PathFactory;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.apache.jackrabbit.uuid.UUID;
+
+import javax.jcr.RepositoryException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * <code>DummyIdentifierResolver</code>...
+ */
+class DummyIdentifierResolver implements IdentifierResolver {
+
+    private static final PathFactory FACTORY = PathFactoryImpl.getInstance();
+    public static final String JCR_PATH = "/a/b/c";
+
+    private final List validIds;
+    private final List invalidFormats;
+    private final List invalidPaths;
+    private final Path path;
+
+    DummyIdentifierResolver() throws RepositoryException {
+        path = FACTORY.create(FACTORY.getRootPath(), FACTORY.create("{}a\t{}b\t{}c"), true);
+        validIds = new ArrayList();
+        validIds.add(UUID.randomUUID().toString());
+        validIds.add("a:b");
+        validIds.add("a[3]");
+        validIds.add("34a[2[");
+        validIds.add("34a/]");
+        validIds.add(" 3-4a/'\"]");
+        validIds.add("/a[3]/b/c:d/");
+        validIds.add("{}\"\"\t{}a[3]\t{}b\t{}c:d");
+
+        String invalidID = UUID.randomUUID().toString();
+        String invalidIdSegment = "["+invalidID+"]";
+        String validSegment = "[" + validIds.get(0).toString() + "]";
+        
+        invalidFormats = new ArrayList();
+        invalidPaths = new ArrayList();
+
+        for (Iterator it = validIds.iterator(); it.hasNext();) {
+            String validId = it.next().toString();
+            if (!validId.endsWith("]")) {
+                invalidFormats.add("[" + validId);
+            } else {
+                invalidPaths.add("[" + validId);
+            }
+
+            if (!validId.startsWith("[")) {
+                invalidFormats.add(validId + "]");
+            } else {
+                invalidPaths.add(validId + "]");
+            }
+        }
+        invalidFormats.add(validSegment + "abc/abc");
+        invalidFormats.add(validSegment + "/a/b/c");
+        invalidFormats.add("/" + validSegment);
+        invalidFormats.add("/a/b/" + validSegment + "/c");
+        invalidFormats.add("/a/b/c" + validSegment);
+        invalidFormats.add("/" + invalidIdSegment);
+
+        // path starting with [ and ending with ] -> valid format but
+        // might be invalid path. 
+        invalidPaths.add(validSegment + "/a/b[2]");        
+        invalidPaths.add(validSegment + "/" + validSegment);        
+        invalidPaths.add(validSegment + "[2]");
+        invalidPaths.add(invalidIdSegment);
+        invalidPaths.addAll(invalidFormats);
+    }
+
+    List getValidIdentifiers() {
+        return validIds;
+    }
+
+    List getInvalidIdentifierPaths() {
+        return invalidPaths;
+    }
+
+    List getInvalidIdentifierFormats() {
+        return invalidFormats;
+    }
+    
+    public Path getPath(String identifier) throws MalformedPathException {
+        if (validIds.contains(identifier)) {
+            return path;
+        } else {
+            throw new MalformedPathException("Invalid path: identifier '"+ identifier +"' cannot be resolved.");
+        }
+    }
+
+    public void checkFormat(String identifier) throws MalformedPathException {
+        if (validIds.contains(identifier)) {
+            return;
+        }
+        throw new MalformedPathException("Invalid identifier.");
+    }
+}
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/ParsingPathResolverTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/ParsingPathResolverTest.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/ParsingPathResolverTest.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/ParsingPathResolverTest.java Thu May  7 14:29:34 2009
@@ -18,22 +18,36 @@
 
 import junit.framework.TestCase;
 
+import javax.jcr.RepositoryException;
 import javax.jcr.NamespaceException;
 
 import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
 import org.apache.jackrabbit.spi.Path;
 
+import java.util.List;
+import java.util.Iterator;
+
 /**
  * Test cases for the {@link ParsingPathResolver} class.
  */
 public class ParsingPathResolverTest extends TestCase {
 
+    private static NameResolver nameResolver = new ParsingNameResolver(NameFactoryImpl.getInstance(), new DummyNamespaceResolver());
+    private DummyIdentifierResolver idResolver;
+
     /**
      * Path resolver being tested.
      */
-    private PathResolver resolver = new ParsingPathResolver(PathFactoryImpl.getInstance(),
-            new ParsingNameResolver(NameFactoryImpl.getInstance(), new DummyNamespaceResolver()));
+    private PathResolver resolver = new ParsingPathResolver(PathFactoryImpl.getInstance(), nameResolver);
+    private PathResolver resolverV2;
+
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        idResolver = new DummyIdentifierResolver();
+        resolverV2 = new ParsingPathResolver(PathFactoryImpl.getInstance(), nameResolver, idResolver);
+    }
 
     /**
      * Checks that the given path resolves properly.
@@ -41,12 +55,21 @@
      * @param path JCR path
      */
     private void assertValidPath(String path) {
+        assertValidPath(path, path);
+    }
+
+    private void assertValidPath(String path, String expectedResult) {
         try {
             Path qpath = resolver.getQPath(path);
-            assertEquals(path, path, resolver.getJCRPath(qpath));
-        } catch (NameException e) {
+            assertEquals(path, expectedResult, resolver.getJCRPath(qpath));
+        } catch (RepositoryException e) {
             fail(path);
-        } catch (NamespaceException e) {
+        }
+
+        try {
+            Path qpath = resolverV2.getQPath(path);
+            assertEquals(path, expectedResult, resolver.getJCRPath(qpath));
+        } catch (RepositoryException e) {
             fail(path);
         }
     }
@@ -60,8 +83,14 @@
         try {
             resolver.getQPath(path);
             fail(path);
-        } catch (NameException e) {
-        } catch (NamespaceException e) {
+        } catch (RepositoryException e) {
+            // success
+        }
+        try {
+            resolverV2.getQPath(path);
+            fail(path);
+        } catch (RepositoryException e) {
+            // success
         }
     }
 
@@ -87,6 +116,12 @@
         assertValidPath("name[2]/name[2]");
         assertValidPath("prefix:name[2]/prefix:name[2]");
 
+        // trailing slash is valid
+        assertValidPath("a/", "a");
+        assertValidPath("prefix:name/", "prefix:name");
+        assertValidPath("/prefix:name[1]/", "/prefix:name");
+        assertValidPath("/a/../b/", "/a/../b");
+
         assertValidPath("/a/../b");
         assertValidPath("./../.");
         assertValidPath("/a/./b");
@@ -103,12 +138,9 @@
     public void testInvalidPaths() {
         assertInvalidPath("");
         assertInvalidPath("//");
-        //assertInvalidPath("x/");  // TODO: was valid with jcr-commons-path but not with pathresolver? check again
         assertInvalidPath("x:");
         assertInvalidPath("x:/");
         assertInvalidPath("x[]");
-        //assertInvalidPath("x:y/"); // TODO: was valid with jcr-commons-path but not with pathresolver? check again
-        //assertInvalidPath("x:y[1]/"); // TODO: was valid with jcr-commons-path but not with pathresolver? check again
         assertInvalidPath("x:y[");
         assertInvalidPath("x:y[]");
         assertInvalidPath("x:y[1");
@@ -129,4 +161,38 @@
         assertInvalidPath("prefix:name[2]foo/prefix:name[2]");
     }
 
+    public void testValidIdentifierPaths() throws MalformedPathException, IllegalNameException, NamespaceException {
+        for (Iterator it = idResolver.getValidIdentifiers().iterator(); it.hasNext();) {
+            String jcrPath = "[" + it.next().toString() + "]";
+
+            Path p = resolverV2.getQPath(jcrPath, true);
+            assertFalse(p.denotesIdentifier());
+            assertTrue(p.isAbsolute());
+            assertTrue(p.isNormalized());
+            assertTrue(p.isCanonical());
+            assertEquals(DummyIdentifierResolver.JCR_PATH, resolverV2.getJCRPath(p));
+
+            p = resolverV2.getQPath(jcrPath, false);
+            assertTrue(p.denotesIdentifier());
+            assertEquals(1, p.getLength());
+            assertTrue(p.isAbsolute());
+            assertFalse(p.isNormalized());
+            assertFalse(p.isCanonical());
+            assertEquals(jcrPath, resolverV2.getJCRPath(p));
+        }
+    }
+
+    public void testInvalidIdentifierPaths() throws MalformedPathException, IllegalNameException, NamespaceException {
+        List l = idResolver.getInvalidIdentifierPaths();
+
+        for (Iterator it = l.iterator(); it.hasNext();) {
+            String path = it.next().toString();
+            try {
+                resolverV2.getQPath(path);
+                fail(path);
+            } catch (MalformedPathException e) {
+                // success
+            }
+        }
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/PathParserTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/PathParserTest.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/PathParserTest.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/PathParserTest.java Thu May  7 14:29:34 2009
@@ -28,6 +28,8 @@
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.PathFactory;
 
+import javax.jcr.RepositoryException;
+
 /**
  * PathParserTest
  */
@@ -207,4 +209,86 @@
             assertFalse("path is canonical: " + path, path.isCanonical());
         }
     }
+
+    public void testIdentifierParse() throws RepositoryException {
+        DummyIdentifierResolver idResolver = new DummyIdentifierResolver();
+        List valid = idResolver.getValidIdentifiers();
+        for (Iterator it = valid.iterator(); it.hasNext();) {
+            String jcrPath = "[" + it.next() + "]";
+            try {                
+                PathParser.parse(jcrPath, resolver, factory);
+                fail("Parsing an identifier-based jcr path needs a IdentifierResolver");
+            } catch (MalformedPathException e) {
+                // success: cannot parse identifier path if idResolver is missing.
+            }
+            try {
+                PathParser.parse(factory.getRootPath(), jcrPath, resolver, factory);
+                fail("Parsing an identifier-based jcr path needs a IdentifierResolver");
+            } catch (MalformedPathException e) {
+                // success: cannot parse identifier path if idResolver is missing.
+            }
+
+            Path p = PathParser.parse(jcrPath, resolver, idResolver, factory, true);
+            assertFalse(p.denotesIdentifier());
+
+            p = PathParser.parse(jcrPath, resolver, idResolver, factory, false);
+            assertTrue(p.denotesIdentifier());
+
+            try {
+                PathParser.parse(factory.getRootPath(), jcrPath, resolver, idResolver, factory);
+                fail("Cannot parser an identifier-based path to a relative path.");
+            } catch (MalformedPathException e) {
+                // success: invalid argument parent-path if the jcr-path is an identifier-based path.
+            }
+
+            try {
+                PathParser.parse(jcrPath, resolver, factory);
+                fail("Parsing an identifier-based jcr path needs a IdentifierResolver");
+            } catch (MalformedPathException e) {
+                // success: cannot parse identifier path if idResolver is missing.
+            }
+        }
+    }
+
+    public void testInvalidIdentifierParse() throws RepositoryException {
+        DummyIdentifierResolver idResolver = new DummyIdentifierResolver();
+
+        List invalid = idResolver.getInvalidIdentifierPaths();
+        for (Iterator it = invalid.iterator(); it.hasNext();) {
+            String jcrPath = it.next().toString();
+            try {
+                Path p = PathParser.parse(jcrPath, resolver, idResolver, factory, true);
+                fail("Invalid identifier based path");
+            } catch (MalformedPathException e) {
+                // ok
+            }
+            try {
+                Path p = PathParser.parse(jcrPath, resolver, idResolver, factory, false);
+                fail("Invalid identifier based path");
+            } catch (MalformedPathException e) {
+                // ok
+            }
+        }       
+    }
+    
+    public void testIdentifierCheckFormat() throws RepositoryException {
+        DummyIdentifierResolver idResolver = new DummyIdentifierResolver();
+        List valid = idResolver.getValidIdentifiers();
+        for (Iterator it = valid.iterator(); it.hasNext();) {
+            String jcrPath = "[" + it.next() + "]";
+            PathParser.checkFormat(jcrPath);
+        }
+
+        List invalid = idResolver.getInvalidIdentifierFormats();
+        for (Iterator it = invalid.iterator(); it.hasNext();) {
+            String jcrPath = it.next().toString();
+            try {
+                // passing null-nameResolver -> executes check-format only
+                PathParser.checkFormat(jcrPath);
+                fail(jcrPath);
+            } catch (MalformedPathException e) {
+                // success
+            }
+        }
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathFactoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathFactoryTest.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathFactoryTest.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathFactoryTest.java Thu May  7 14:29:34 2009
@@ -23,8 +23,10 @@
 import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
 import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
+import org.apache.jackrabbit.uuid.UUID;
 
 import javax.jcr.NamespaceException;
+import javax.jcr.RepositoryException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -84,7 +86,7 @@
 
     public void testCreateElementNullName() {
         try {
-            factory.createElement(null);
+            factory.createElement((Name) null);
             fail("Creating element with null name is invalid");
         } catch (IllegalArgumentException e) {
             // ok
@@ -197,6 +199,87 @@
         }
     }
 
+    public void testIdentifier() {
+        String identifier = UUID.randomUUID().toString();
+
+        Path.Element elem = factory.createElement(identifier);
+        assertTrue(elem.denotesIdentifier());
+        assertFalse(elem.denotesCurrent());
+        assertFalse(elem.denotesName());
+        assertFalse(elem.denotesParent());
+        assertFalse(elem.denotesRoot());
+        assertNull(elem.getName());
+        assertNotNull(elem.getString());
+        assertEquals(Path.INDEX_UNDEFINED, elem.getIndex());
+        assertEquals(Path.INDEX_DEFAULT, elem.getNormalizedIndex());
+
+        Path p = factory.create(new Path.Element[] {elem});
+        assertTrue(p.denotesIdentifier());
+        assertTrue(p.isAbsolute());
+
+        assertFalse(p.denotesRoot());
+        assertFalse(p.isCanonical());
+        assertFalse(p.isNormalized());
+
+        assertEquals(1, p.getLength());
+        assertEquals(-1, p.getAncestorCount());
+
+        Path.Element lastElem = p.getNameElement();
+        assertNotNull(lastElem);
+        assertTrue(lastElem.denotesIdentifier());
+
+        assertEquals(1, p.getElements().length);
+
+        try {
+            p.getDepth();
+            fail();
+        } catch (RepositoryException e) {
+            //expected
+        }
+        try {
+            p.getNormalizedPath();
+            fail();
+        } catch (RepositoryException e) {
+            //expected
+        }
+        try {
+            p.getAncestor(1);
+            fail();
+        } catch (RepositoryException e) {
+            //expected
+        }
+        try {
+            p.isAncestorOf(factory.getRootPath());
+            fail();
+        } catch (RepositoryException e) {
+            //expected
+        }
+        try {
+            p.computeRelativePath(factory.getRootPath());
+            fail();
+        } catch (RepositoryException e) {
+            //expected
+        }
+        try {
+            p.getCanonicalPath();
+            fail();
+        } catch (RepositoryException e) {
+            //expected
+        }
+        try {
+            p.isDescendantOf(factory.getRootPath());
+            fail();
+        } catch (RepositoryException e) {
+            //expected
+        }
+        try {
+            p.isEquivalentTo(factory.getRootPath());
+            fail();
+        } catch (RepositoryException e) {
+            //expected
+        }
+    }
+
     public void testCreateInvalidPath() throws NamespaceException {
 
         Path.Element rootEl = factory.getRootElement();

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/value/ValueFormatTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/value/ValueFormatTest.java?rev=772659&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/value/ValueFormatTest.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/value/ValueFormatTest.java Thu May  7 14:29:34 2009
@@ -0,0 +1,93 @@
+/*
+ * 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.apache.jackrabbit.uuid.UUID;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.ParsingPathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.IdentifierResolver;
+import org.apache.jackrabbit.spi.commons.conversion.ParsingNameResolver;
+import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
+import org.apache.jackrabbit.spi.commons.conversion.DummyNamespaceResolver;
+import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.apache.jackrabbit.spi.QValueFactory;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.QValue;
+import junit.framework.TestCase;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
+import javax.jcr.ValueFactory;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * <code>ValueFormatTest</code>...
+ */
+public class ValueFormatTest extends TestCase {
+
+    private IdentifierResolver idResolver;
+    private NamePathResolver resolver;
+    private QValueFactory qvFactory;
+    private ValueFactory vFactory;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        idResolver = new IdentifierResolver() {
+            public Path getPath(String identifier) throws MalformedPathException {
+                throw new UnsupportedOperationException();
+            }
+
+            public void checkFormat(String identifier) throws MalformedPathException {
+                // nop
+            }
+        };
+
+        NameResolver nResolver = new ParsingNameResolver(NameFactoryImpl.getInstance(), new DummyNamespaceResolver());
+        PathResolver pResolver = new ParsingPathResolver(PathFactoryImpl.getInstance(), nResolver, idResolver);
+        resolver = new DefaultNamePathResolver(nResolver, pResolver);
+        qvFactory = QValueFactoryImpl.getInstance();
+        vFactory = new ValueFactoryQImpl(qvFactory, resolver);
+    }
+
+    /**
+     * Path values must never be normalized.
+     *
+     * @throws RepositoryException
+     */
+    public void testGetPathQValue() throws RepositoryException {
+        List<String> l = new ArrayList();
+        // a non-normalized absolute path
+        l.add("/a/.././b/c/.");
+        // an identifier based path
+        l.add("["+ UUID.randomUUID().toString()+"]");
+
+
+        for (String jcrPath : l) {
+            QValue qv = ValueFormat.getQValue(jcrPath, PropertyType.PATH, resolver, qvFactory);
+            assertFalse(qv.getPath().isNormalized());
+            assertEquals("Path values must not be normalized",jcrPath, ValueFormat.getJCRValue(qv, resolver, vFactory).getString());
+        }
+    }
+
+}
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java Thu May  7 14:29:34 2009
@@ -138,7 +138,16 @@
     public boolean denotesRoot();
 
     /**
-     * Tests whether this path is absolute, i.e. whether it starts with "/".
+     * Test if this path represents an unresolved identifier-based path.
+     *
+     * @return <code>true</code> if this path represents an unresolved
+     * identifier-based path.
+     */
+    public boolean denotesIdentifier();
+
+    /**
+     * Tests whether this path is absolute, i.e. whether it starts with "/" or
+     * is an identifier based path.
      *
      * @return true if this path is absolute; false otherwise.
      */
@@ -229,8 +238,10 @@
      * that there is no ancestor of the specified degree. In case of this
      * being an absolute path, this would be the case if <code>degree</code> is
      * greater that the {@link #getDepth() depth} of this path.
+     * @throws RepositoryException If the implementation is not able to determine
+     * the ancestor of the specified degree for some other reason.
      */
-    public Path getAncestor(int degree) throws IllegalArgumentException, PathNotFoundException;
+    public Path getAncestor(int degree) throws IllegalArgumentException, PathNotFoundException, RepositoryException;
 
     /**
      * Returns the number of ancestors of this path. This is the equivalent
@@ -273,10 +284,11 @@
      * canonical, e.g. the depth of "../../a" is -1.
      *
      * @return the depth this path
+     * @throws RepositoryException If the depths cannot be determined.
      * @see #getLength()
      * @see #getAncestorCount()
      */
-    public int getDepth();
+    public int getDepth() throws RepositoryException;
 
     /**
      * Determines if the the <code>other</code> path would be equal to <code>this</code>
@@ -447,6 +459,14 @@
         public boolean denotesName();
 
         /**
+         * Returns <code>true</code> if this element represents an identifier element.
+         * 
+         * @return <code>true</code> if this element represents an identifier element.
+         * @since JCR 2.0
+         */
+        public boolean denotesIdentifier();
+
+        /**
          * Return the String presentation of a {@link Path.Element}. It must be
          * in the format "<code>{namespaceURI}localPart</code>" or
          * "<code>{namespaceURI}localPart[index]</code>" in case of an index

Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java Thu May  7 14:29:34 2009
@@ -152,6 +152,16 @@
     public Path.Element createElement(Name name, int index) throws IllegalArgumentException;
 
     /**
+     * Creates a path element from the given <code>identifier</code>.
+     *
+     * @param identifier Node identifier for which the path element should be created.
+     * @return a path element.
+     * @throws IllegalArgumentException If the <code>identifier</code> is <code>null</code>.
+     * @since JCR 2.0
+     */
+    public Path.Element createElement(String identifier) throws IllegalArgumentException;
+
+    /**
      * Return the current element.
      *
      * @return the current element.

Modified: jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/QValueFactoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/QValueFactoryTest.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/QValueFactoryTest.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/QValueFactoryTest.java Thu May  7 14:29:34 2009
@@ -36,12 +36,12 @@
 
     private static Logger log = LoggerFactory.getLogger(QValueFactoryTest.class);
 
-    private QValueFactory factory;
+    protected QValueFactory factory;
 
     private final Calendar calendar = Calendar.getInstance();
-    private Path rootPath;
-    private Name testName;
-    private String reference;
+    protected Path rootPath;
+    protected Name testName;
+    protected String reference;
 
     protected void setUp() throws Exception {
         super.setUp();

Added: jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/QValueTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/QValueTest.java?rev=772659&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/QValueTest.java (added)
+++ jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/QValueTest.java Thu May  7 14:29:34 2009
@@ -0,0 +1,494 @@
+/*
+ * 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;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.FileWriter;
+import java.util.Calendar;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+
+/**
+ * <code>QValueTest</code>...
+ */
+public class QValueTest extends AbstractSPITest {
+
+    private static Logger log = LoggerFactory.getLogger(QValueTest.class);
+
+    private final Calendar CALENDAR = Calendar.getInstance();
+    protected Path rootPath;
+    protected Name testName;
+    protected String reference;
+    protected QValueFactory factory;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        RepositoryService service = helper.getRepositoryService();
+        factory = service.getQValueFactory();
+
+        rootPath = service.getPathFactory().getRootPath();
+        testName = service.getNameFactory().create(Name.NS_JCR_URI, "data");
+        reference = getProperty("reference");
+    }
+
+    public void testIllegalType() throws RepositoryException {
+        try {
+            factory.create("any", 54);
+            fail("54 is not a valid property type");
+        } catch (IllegalArgumentException e) {
+            // ok
+        }
+    }
+
+    //-------------------------------------------------------------< DOUBLE >---
+
+    public void testCreateInvalidDoubleValue() throws RepositoryException {
+        try {
+            factory.create("any", PropertyType.DOUBLE);
+            fail("'any' cannot be converted to a valid double value.");
+        } catch (ValueFormatException e) {
+            // ok
+        }
+    }
+
+    public void testGetDoubleOnBooleanValue() throws RepositoryException {
+        try {
+            QValue v = factory.create(true);
+            v.getDouble();
+            fail("'true' cannot be converted to a valid double value.");
+        } catch (ValueFormatException e) {
+            // ok
+        }
+    }
+
+    //---------------------------------------------------------------< LONG >---
+
+    public void testCreateInvalidLongValue() throws RepositoryException {
+        try {
+            factory.create("any", PropertyType.LONG);
+            fail("'any' cannot be converted to a valid long value.");
+        } catch (ValueFormatException e) {
+            // ok
+        }
+    }
+
+    public void testGetLongOnBooleanValue() throws RepositoryException {
+        try {
+            QValue v = factory.create(true);
+            v.getLong();
+            fail("'true' cannot be converted to a valid long value.");
+        } catch (ValueFormatException e) {
+            // ok
+        }
+    }
+
+    //------------------------------------------------------------< BOOLEAN >---
+    /**
+     * QValueImpl has a final static constant for the TRUE and the FALSE boolean
+     * values. Test if the various create methods use the constants (thus always
+     * return the 'same' object.
+     *
+     * @throws javax.jcr.RepositoryException
+     */
+    public void testFinalBooleanValue() throws RepositoryException {
+        assertSame(factory.create(true), factory.create(Boolean.TRUE.toString(), PropertyType.BOOLEAN));
+        assertSame(factory.create(true), factory.create(true));
+
+        assertSame(factory.create(false), factory.create(Boolean.FALSE.toString(), PropertyType.BOOLEAN));
+        assertSame(factory.create(false), factory.create(false));
+    }
+
+    /**
+     * Test if creating Boolean QValue from boolean and from String with boolean
+     * type return equal objects.
+     *
+     * @throws javax.jcr.RepositoryException
+     */
+    public void testCreateBooleanValueFromString() throws RepositoryException {
+        QValue v = factory.create(Boolean.TRUE.toString(), PropertyType.BOOLEAN);
+        assertEquals("Creating boolean type QValue from boolean or String must be equal.",
+                factory.create(true), v);
+
+        v = factory.create(Boolean.FALSE.toString(), PropertyType.BOOLEAN);
+        assertEquals("Creating boolean type QValue from boolean or String must be equal.",
+                factory.create(false), v);
+    }
+
+    public void testCreateTrueBooleanValue() throws RepositoryException {
+        QValue v = factory.create(true);
+        assertEquals("Boolean value must be true", Boolean.TRUE.toString(), v.getString());
+        assertEquals("Boolean value must be true", true, v.getBoolean());
+    }
+
+    public void testCreateFalseBooleanValue() throws RepositoryException {
+        QValue v = factory.create(false);
+        assertEquals("Boolean value must be false", Boolean.FALSE.toString(), v.getString());
+        assertEquals("Boolean value must be false", false, v.getBoolean());
+    }
+
+    public void testCreateTrueFromString() throws ValueFormatException, RepositoryException {
+        QValue v = factory.create(Boolean.TRUE.toString(), PropertyType.STRING);
+        assertEquals("Boolean value must be true", true, v.getBoolean());
+    }
+
+    public void testCreateFalseFromString() throws ValueFormatException, RepositoryException {
+        QValue v = factory.create("any", PropertyType.STRING);
+        assertEquals("Boolean value must be false", false, v.getBoolean());
+    }
+
+    public void testReadBooleanAsLong() throws RepositoryException {
+        try {
+            QValue v = factory.create(true);
+            v.getLong();
+        }
+        catch (ValueFormatException e) {
+            return; // ok
+        }
+        assertTrue("Cannot convert value to long", false);
+    }
+
+    //---------------------------------------------------------------< DATE >---
+    public void testNullDateValue() throws IOException, RepositoryException {
+        try {
+            factory.create((Calendar) null);
+            fail();
+        } catch (RuntimeException e) {
+            // ok
+        }
+        try {
+            factory.create(null, PropertyType.DATE);
+            fail();
+        } catch (RuntimeException e) {
+            // ok
+        }
+    }
+
+    public void testDateValueType() throws RepositoryException {
+        QValue v = factory.create(CALENDAR);
+        assertTrue("Type of a date value must be PropertyType.DATE", v.getType() == PropertyType.DATE);
+    }
+    public void testDateValueEquality() throws RepositoryException {
+        QValue v = factory.create(CALENDAR);
+        QValue otherV = factory.create(CALENDAR);
+        assertEquals("Equality of qualified date value must be calculated based on their String representation.", v, otherV);
+    }
+
+    public void testDateValueEquality2() throws RepositoryException {
+        QValue v = factory.create(CALENDAR);
+        QValue otherV = factory.create(v.getString(), PropertyType.DATE);
+        assertEquals("Equality of qualified date value must be calculated based on their String representation.", v, otherV);
+    }
+
+    //----------------------------------------------------------< REFERENCE >---
+
+    public void testNullReferenceValue() throws IOException, RepositoryException {
+        try {
+            factory.create(null, PropertyType.REFERENCE);
+            fail();
+        } catch (RuntimeException e) {
+            // ok
+        }
+    }
+
+    public void testReferenceValueType() throws RepositoryException {
+        if (reference != null) {
+            QValue v = factory.create(reference, PropertyType.REFERENCE);
+            assertTrue("Type of a date value must be PropertyType.REFERENCE.", v.getType() == PropertyType.REFERENCE);
+        } else {
+            log.warn("Configuration entry 'QValueFactoryTest.reference' is missing -> skip test 'testReferenceValueType'.");
+        }
+    }
+
+    public void testReferenceValueEquality() throws RepositoryException {
+        if (reference != null) {
+            QValue v = factory.create(reference, PropertyType.REFERENCE);
+            QValue otherV = factory.create(reference, PropertyType.REFERENCE);
+            assertEquals("Qualified ref values created from the same string must be equal.", v, otherV);
+        } else {
+            log.warn("Configuration entry 'QValueFactoryTest.reference' is missing -> skip test 'testReferenceValueEquality'.");
+        }
+    }
+
+    public void testEqualityDifferentTypes() throws RepositoryException {
+        if (reference != null) {
+            QValue v = factory.create(reference, PropertyType.REFERENCE);
+            QValue v2 = factory.create(reference, PropertyType.STRING);
+            assertFalse(v.equals(v2));
+        } else {
+            log.warn("Configuration entry 'QValueFactoryTest.reference' is missing -> skip test 'testEqualityDifferentTypes'.");
+        }
+    }
+
+
+    //---------------------------------------------------------------< Name >---
+
+    public void testNullNameValue() throws IOException, RepositoryException {
+        try {
+            factory.create((Name) null);
+            fail();
+        } catch (RuntimeException e) {
+            // ok
+        }
+    }
+
+    public void testNameValueType() throws IOException, RepositoryException {
+        QValue v = factory.create(testName);
+        assertTrue(v.getType() == PropertyType.NAME);
+        v = factory.create(testName.toString(), PropertyType.NAME);
+        assertTrue(v.getType() == PropertyType.NAME);
+    }
+
+    public void testNameValueEquality() throws IOException, RepositoryException {
+        QValue v = factory.create(testName);
+        QValue v2 = factory.create(testName.toString(), PropertyType.NAME);
+        assertTrue(v.equals(v2));
+    }
+
+    public void testNameValueGetString() throws IOException, RepositoryException {
+        QValue v = factory.create(testName);
+        assertTrue(v.getString().equals(testName.toString()));
+    }
+
+    public void testNameValueGetName() throws RepositoryException {
+        QValue v = factory.create(testName);
+        assertTrue(v.getName().equals(testName));
+    }
+
+    public void testInvalidNameValue() throws RepositoryException {
+        try {
+            factory.create("abc", PropertyType.NAME);
+            fail("'abc' is not a valid Name -> creating QValue should fail.");
+        } catch (ValueFormatException e) {
+            // ok
+        }
+    }
+
+    public void testAnyValueGetName() throws RepositoryException {
+        try {
+            factory.create(12345).getName();
+            fail("12345 is not a valid Name value -> QValue.getName() should fail.");
+        } catch (ValueFormatException e) {
+            // ok
+        }
+    }
+
+    //---------------------------------------------------------------< Path >---
+
+    public void testNullPathValue() throws IOException, RepositoryException {
+        try {
+            factory.create((Path) null);
+            fail();
+        } catch (RuntimeException e) {
+            // ok
+        }
+    }
+
+    public void testPathValueType() throws IOException, RepositoryException {
+        QValue v = factory.create(rootPath);
+        assertTrue(v.getType() == PropertyType.PATH);
+        v = factory.create(rootPath.toString(), PropertyType.PATH);
+        assertTrue(v.getType() == PropertyType.PATH);
+    }
+
+
+    public void testPathValueEquality() throws IOException, RepositoryException {
+        QValue v = factory.create(rootPath);
+        QValue v2 = factory.create(rootPath.toString(), PropertyType.PATH);
+        assertTrue(v.equals(v2));
+    }
+
+    public void testPathValueGetString() throws IOException, RepositoryException {
+        QValue v = factory.create(rootPath);
+        assertTrue(v.getString().equals(rootPath.toString()));
+    }
+
+    public void testPathValueGetPath() throws RepositoryException {
+        QValue v = factory.create(rootPath);
+        assertTrue(v.getPath().equals(rootPath));
+    }
+
+    public void testInvalidPathValue() throws RepositoryException {
+        try {
+            factory.create("abc", PropertyType.PATH);
+            fail("'abc' is not a valid Path -> creating QValue should fail.");
+        } catch (ValueFormatException e) {
+            // ok
+        }
+    }
+
+    public void testAnyValueGetPath() throws RepositoryException {
+        try {
+            factory.create(12345).getPath();
+            fail("12345 is not a valid Path value -> QValue.getPath() should fail.");
+        } catch (ValueFormatException e) {
+            // ok
+        }
+    }
+
+    //-------------------------------------------------------------< BINARY >---
+
+    public void testNullBinaryValue() throws IOException, RepositoryException {
+        try {
+            factory.create((byte[]) null);
+            fail();
+        } catch (RuntimeException e) {
+            // ok
+        }
+        try {
+            factory.create((InputStream) null);
+            fail();
+        } catch (RuntimeException e) {
+            // ok
+        }
+        try {
+            factory.create((File) null);
+            fail();
+        } catch (RuntimeException e) {
+            // ok
+        }
+    }
+
+    public void testBinaryValueType() throws IOException, RepositoryException {
+        QValue v = factory.create(new byte[] {'a', 'b', 'c'});
+        assertTrue(v.getType() == PropertyType.BINARY);
+    }
+
+
+    public void testBinaryFromByteArray() throws RepositoryException, IOException {
+        QValue v = factory.create(new byte[] {'a', 'b', 'c'});
+
+        assertEquals(PropertyType.BINARY, v.getType());
+        assertEquals(3, v.getLength());
+
+        assertEquals("abc", v.getString());
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        spool(out, v.getStream());
+        assertEquals("abc", new String(out.toByteArray()));
+    }
+
+    public void testEmptyBinaryFromByteArray() throws RepositoryException, IOException {
+        QValue v = factory.create(new byte[0]);
+
+        assertEquals(PropertyType.BINARY, v.getType());
+        assertEquals(0, v.getLength());
+
+        assertEquals("", v.getString());
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        spool(out, v.getStream());
+        assertEquals("", new String(out.toByteArray()));
+    }
+
+    public void testBinaryFromInputStream() throws RepositoryException, IOException {
+        InputStream in = new ByteArrayInputStream(new byte[] {'a', 'b', 'c'});
+
+        QValue v = factory.create(in);
+
+        assertEquals(PropertyType.BINARY, v.getType());
+        assertEquals(3, v.getLength());
+
+        assertEquals("abc", v.getString());
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        spool(out, v.getStream());
+        assertEquals("abc", new String(out.toByteArray()));
+    }
+
+    public void testEmptyBinaryFromInputStream() throws RepositoryException, IOException {
+        InputStream in = new ByteArrayInputStream(new byte[0]);
+
+        QValue v = factory.create(in);
+
+        assertEquals(PropertyType.BINARY, v.getType());
+        assertEquals(0, v.getLength());
+
+        assertEquals("", v.getString());
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        spool(out, v.getStream());
+        assertEquals("", new String(out.toByteArray()));
+    }
+
+
+    public void testBinaryFromFile() throws RepositoryException, IOException {
+        File f = File.createTempFile("QValueFactoryImplTest", ".txt");
+        f.deleteOnExit();
+        FileWriter fw = new FileWriter(f);
+        fw.write("abc");
+        fw.close();
+
+        QValue v = factory.create(f);
+
+        assertEquals(PropertyType.BINARY, v.getType());
+        assertEquals(3, v.getLength());
+
+        assertEquals("abc", v.getString());
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        spool(out, v.getStream());
+        assertEquals("abc", new String(out.toByteArray()));
+    }
+
+    public void testEmptyBinaryFromFile() throws RepositoryException, IOException {
+        File f = File.createTempFile("QValueFactoryImplTest", ".txt");
+        f.deleteOnExit();
+
+        QValue v = factory.create(f);
+
+        assertEquals(PropertyType.BINARY, v.getType());
+        assertEquals(0, v.getLength());
+
+        assertEquals("", v.getString());
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        spool(out, v.getStream());
+        assertEquals("", new String(out.toByteArray()));
+    }
+
+    /**
+     *
+     * @param out
+     * @param in
+     * @throws javax.jcr.RepositoryException
+     * @throws java.io.IOException
+     */
+    private static void spool(OutputStream out, InputStream in) throws RepositoryException, IOException {
+        try {
+            byte[] buffer = new byte[0x2000];
+            int read;
+            while ((read = in.read(buffer)) > 0) {
+                out.write(buffer, 0, read);
+            }
+        } finally {
+            try {
+                in.close();
+            } catch (IOException ignore) {
+            }
+        }
+    }
+}
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/TestAll.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/TestAll.java Thu May  7 14:29:34 2009
@@ -30,6 +30,7 @@
         suite.addTestSuite(RepositoryServiceTest.class);
         suite.addTestSuite(SessionInfoTest.class);
         suite.addTestSuite(QValueFactoryTest.class);
+        suite.addTestSuite(QValueTest.class);
 
         return suite;
     }

Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java Thu May  7 14:29:34 2009
@@ -65,6 +65,7 @@
 import org.apache.jackrabbit.spi.commons.conversion.ParsingNameResolver;
 import org.apache.jackrabbit.spi.commons.conversion.ParsingPathResolver;
 import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.IdentifierResolver;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.namespace.AbstractNamespaceResolver;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
@@ -2359,7 +2360,11 @@
         }
     }
 
-
+    //----------------------------------------------< NamespaceResolverImpl >---
+    /**
+     * NamespaceResolver implementation that uses a sessionInfo to determine
+     * namespace mappings either from cache or from the server.
+     */
     private class NamespaceResolverImpl implements NamespaceResolver {
 
         private final SessionInfo sessionInfo;
@@ -2398,6 +2403,53 @@
         }
     }
 
+    //---------------------------------------------< IdentifierResolverImpl >---
+    private class IdentifierResolverImpl implements IdentifierResolver {
+
+        private final SessionInfo sessionInfo;
+        
+        private IdentifierResolverImpl(SessionInfo sessionInfo) {
+            this.sessionInfo = sessionInfo;
+        }
+
+        private Path buildPath(String uniqueID) throws RepositoryException {
+            String uri = uriResolver.getItemUri(getIdFactory().createNodeId(uniqueID), sessionInfo.getWorkspaceName(), sessionInfo);
+            return uriResolver.getQPath(uri, sessionInfo);
+        }
+
+        private Path resolvePath(String jcrPath) throws RepositoryException {
+            return ((SessionInfoImpl) sessionInfo).getNamePathResolver().getQPath(jcrPath);
+        }
+        
+        /**
+         * @inheritDoc
+         */
+        public Path getPath(String identifier) throws MalformedPathException {
+            try {
+                int pos = identifier.indexOf('/');
+                if (pos == -1) {
+                    // unique id identifier
+                    return buildPath(identifier);
+                } else if (pos == 0) {
+                    // jcr-path identifier
+                    return resolvePath(identifier);
+                } else {
+                    Path p1 = buildPath(identifier.substring(0, pos));
+                    Path p2 = resolvePath(identifier.substring(pos));
+                    return getPathFactory().create(p1, p2, true);
+                }
+            } catch (RepositoryException e) {
+                throw new MalformedPathException(identifier);
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void checkFormat(String identifier) throws MalformedPathException {
+            // cannot be determined. assume ok.
+        }
+    }
     //-----------------------------------------------< NamePathResolverImpl >---
     /**
      * Implements a namespace resolver based on a session info.
@@ -2410,7 +2462,8 @@
         private NamePathResolverImpl(SessionInfo sessionInfo) {
             NamespaceResolver nsResolver = new NamespaceResolverImpl(sessionInfo);
             nResolver = new ParsingNameResolver(getNameFactory(), nsResolver);
-            pResolver = new ParsingPathResolver(getPathFactory(), nResolver);
+            IdentifierResolver idResolver = new IdentifierResolverImpl(sessionInfo);
+            pResolver = new ParsingPathResolver(getPathFactory(), nResolver, idResolver);
         }
 
         private NamePathResolverImpl(NamespaceResolver nsResolver) {
@@ -2442,11 +2495,21 @@
         /**
          * @inheritDoc
          */
+        public Path getQPath(String path, boolean normalizeIdentifier) throws MalformedPathException, IllegalNameException, NamespaceException {
+            return pResolver.getQPath(path, normalizeIdentifier);
+        }
+
+        /**
+         * @inheritDoc
+         */
         public String getJCRPath(Path path) throws NamespaceException {
             return pResolver.getJCRPath(path);
         }
     }
 
+    /**
+     * Namespace Cache
+     */
     private static class NamespaceCache extends AbstractNamespaceResolver {
 
         private final HashMap prefixToURI = new HashMap();

Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/QValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/QValueFactoryImpl.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/QValueFactoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/QValueFactoryImpl.java Thu May  7 14:29:34 2009
@@ -17,26 +17,21 @@
 package org.apache.jackrabbit.spi2davex;
 
 import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.NameFactory;
 import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.spi.PathFactory;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
 import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.QValueFactory;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
-import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.apache.jackrabbit.spi.commons.value.AbstractQValueFactory;
+import org.apache.jackrabbit.spi.commons.value.AbstractQValue;
 import org.apache.jackrabbit.util.ISO8601;
 import org.apache.jackrabbit.util.TransientFileFactory;
-import org.apache.jackrabbit.uuid.UUID;
 import org.apache.jackrabbit.value.ValueFactoryImpl;
+import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants;
 import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty;
 import org.apache.jackrabbit.webdav.property.DavProperty;
 import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
 import org.apache.jackrabbit.webdav.xml.DomUtil;
-import org.apache.jackrabbit.webdav.DavException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
@@ -67,11 +62,7 @@
 /**
  * <code>ValueFactoryImpl</code>...
  */
-class QValueFactoryImpl implements QValueFactory {
-
-    private static final PathFactory PATH_FACTORY = PathFactoryImpl.getInstance();
-    private static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
-    private static final String DEFAULT_ENCODING = "UTF-8";
+class QValueFactoryImpl extends AbstractQValueFactory {
 
     private final NamePathResolver resolver;
     private final ValueLoader loader;
@@ -173,14 +164,14 @@
      * @see QValueFactory#create(double)
      */
     public QValue create(double value) {
-        return new QValueImpl(new Double(value));
+        return new QValueImpl(Double.valueOf(value));
     }
 
     /**
      * @see QValueFactory#create(long)
      */
     public QValue create(long value) {
-        return new QValueImpl(new Long(value));
+        return new QValueImpl(Long.valueOf(value));
     }
 
     /**
@@ -240,92 +231,47 @@
         return new BinaryQValue(value);
     }
 
-    /**
-     * @see QValueFactory#computeAutoValues(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);
-        }
-    }
-
     //--------------------------------------------------------< Inner Class >---
     /**
      * <code>QValue</code> implementation for all valid <code>PropertyType</code>s
      * except for BINARY.
      * @see QValueFactoryImpl.BinaryQValue
      */
-    private static class QValueImpl implements QValue, Serializable {
+    private static class QValueImpl extends AbstractQValue implements Serializable {
 
         private static final QValue TRUE = new QValueImpl(Boolean.TRUE);
         private static final QValue FALSE = new QValueImpl(Boolean.FALSE);
 
-        private final Object val;
-        private final int type;
-
         private QValueImpl(String value, int type) {
-            val = value;
-            this.type = type;
+            super(value, type);
         }
 
         private QValueImpl(Long value) {
-            val = value;
-            type = PropertyType.LONG;
+            super(value);
         }
 
         private QValueImpl(Double value) {
-            val = value;
-            type = PropertyType.DOUBLE;
+            super(value);
         }
 
         private QValueImpl(Boolean value) {
-            val = value;
-            type = PropertyType.BOOLEAN;
+            super(value);
         }
 
         private QValueImpl(Calendar value) {
-            val = value;
-            this.type = PropertyType.DATE;
+            super(value);
         }
 
         private QValueImpl(Name value) {
-            val = value;
-            type = PropertyType.NAME;
+            super(value);
         }
 
         private QValueImpl(Path value) {
-            val = value;
-            type = PropertyType.PATH;
+            super(value);
         }
 
-        protected String getQString(int type) throws RepositoryException {
-            return getString();
-        }
         //---------------------------------------------------------< QValue >---
         /**
-         * @see QValue#getType()
-         */
-        public int getType() {
-            return type;
-        }
-
-        /**
-         * @see QValue#getLength()
-         */
-        public long getLength() throws RepositoryException {
-            return getString().length();
-        }
-
-        /**
          * @see QValue#getString()
          */
         public String getString() {
@@ -338,7 +284,7 @@
         public InputStream getStream() throws RepositoryException {
             try {
                 // convert via string
-                return new ByteArrayInputStream(getString().getBytes(QValueFactoryImpl.DEFAULT_ENCODING));
+                return new ByteArrayInputStream(getString().getBytes(DEFAULT_ENCODING));
             } catch (UnsupportedEncodingException e) {
                 throw new RepositoryException(QValueFactoryImpl.DEFAULT_ENCODING + " is not supported encoding on this platform", e);
             }
@@ -429,92 +375,6 @@
                 }
             }
         }
-
-        public boolean getBoolean() throws RepositoryException {
-            if (val instanceof Boolean) {
-                return ((Boolean) val).booleanValue();
-            } else {
-                return new Boolean(getString()).booleanValue();
-            }
-        }
-
-        /**
-         * @see QValue#getName()
-         */
-        public Name getName() throws RepositoryException {
-            if (val instanceof Name) {
-                return (Name) val;
-            } else {
-                try {
-                    return NAME_FACTORY.create(getString());
-                } catch (IllegalArgumentException e) {
-                    throw new ValueFormatException("not a valid Name value: " + getString(), e);
-                }
-            }
-        }
-
-        /**
-         * @see QValue#getPath()
-         */
-        public Path getPath() throws RepositoryException {
-            if (val instanceof Path) {
-                return (Path) val;
-            } else {
-                try {
-                    return PATH_FACTORY.create(getString());
-                } catch (IllegalArgumentException e) {
-                    throw new ValueFormatException("not a valid Path value: " + 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.
-         * @see Object#toString() 
-         */
-        public String toString() {
-            return val.toString();
-        }
-
-        /**
-         * @see Object#equals(Object)
-         */
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj instanceof QValueImpl) {
-                QValueImpl other = (QValueImpl) obj;
-                if (type == other.type && type != PropertyType.UNDEFINED) {
-                    return getString().equals(other.getString());
-                }
-                try {
-                    int type = getType();
-                    return type == other.getType() && getQString(type).equals(other.getQString(type));
-                } catch (RepositoryException e) {
-                    // should never get here. return false.
-                }
-            }
-            return false;
-        }
-
-        /**
-         * @return the hashCode of the internal value object.
-         * @see Object#hashCode()
-         */
-        public int hashCode() {
-            return val.hashCode();
-        }
     }
 
     //--------------------------------------------------------< Inner Class >---
@@ -555,8 +415,7 @@
                 return formattedStr.equals(other.formattedStr);
             } else if (obj instanceof QValueImpl) {
                 QValueImpl other = (QValueImpl) obj;
-                return formattedStr.equals(other.getString()) &&
-                       other.getType() == PropertyType.DATE;
+                return other.getType() == PropertyType.DATE && formattedStr.equals(other.getString());
             }
             return false;
         }

Modified: jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java?rev=772659&r1=772658&r2=772659&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java Thu May  7 14:29:34 2009
@@ -48,6 +48,7 @@
 import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
 import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
 import org.apache.jackrabbit.spi.commons.value.ValueFormat;
+import org.apache.jackrabbit.spi.commons.value.ValueFactoryQImpl;
 import org.apache.jackrabbit.JcrConstants;
 
 import javax.jcr.RepositoryException;
@@ -74,6 +75,8 @@
 import javax.jcr.ImportUUIDBehavior;
 import javax.jcr.Value;
 import javax.jcr.ItemVisitor;
+import javax.jcr.ValueFactory;
+import javax.jcr.GuestCredentials;
 import javax.jcr.util.TraversingItemVisitor;
 import javax.jcr.observation.ObservationManager;
 import javax.jcr.observation.EventListener;
@@ -128,6 +131,11 @@
     private final IdFactoryImpl idFactory = (IdFactoryImpl) IdFactoryImpl.getInstance();
 
     /**
+     * The QValueFactory
+     */
+    private QValueFactory qValueFactory = QValueFactoryImpl.getInstance();
+
+    /**
      * Set to <code>true</code> if the underlying JCR repository supports
      * observation.
      */
@@ -145,6 +153,16 @@
         this.repository = repository;
         this.batchReadConfig = batchReadConfig;
         this.supportsObservation = "true".equals(repository.getDescriptor(Repository.OPTION_OBSERVATION_SUPPORTED));
+
+        try {
+            Session s = repository.login(new GuestCredentials());
+            ValueFactory vf = s.getValueFactory();
+            if (vf instanceof ValueFactoryQImpl) {
+                qValueFactory = ((ValueFactoryQImpl) vf).getQValueFactory();
+            }
+        } catch (RepositoryException e) {
+            // ignore            
+        }
     }
 
     /**
@@ -172,7 +190,7 @@
      * {@inheritDoc}
      */
     public QValueFactory getQValueFactory() {
-        return QValueFactoryImpl.getInstance();
+        return qValueFactory;
     }
 
     /**