You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2012/04/23 17:22:24 UTC

svn commit: r1329281 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/api/ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ oak-jcr/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/

Author: angela
Date: Mon Apr 23 15:22:24 2012
New Revision: 1329281

URL: http://svn.apache.org/viewvc?rev=1329281&view=rev
Log:
OAK-16 : Proper ValueFactory implementation and Value handling (WIP)

NOTE: this is a proposal drafting how we could combine a reasonable
implementation of the JCR value handling with the needs we have within oak-core. i tried to take the work thomas made with his corevalue into account. however, i didn't yet remove those nor did i touch the Scalar interface so far.

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/BinaryValue.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueFactoryImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueImpl.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentRepository.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentSession.java
    jackrabbit/oak/trunk/oak-jcr/pom.xml
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueFactoryImpl.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java?rev=1329281&r1=1329280&r2=1329281&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java Mon Apr 23 15:22:24 2012
@@ -94,6 +94,8 @@ public interface ContentSession extends 
      */
     QueryEngine getQueryEngine();
 
+    CoreValueFactory getCoreValueFactory();
+
     // TODO : add versioning operations
 
 }
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/BinaryValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/BinaryValue.java?rev=1329281&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/BinaryValue.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/BinaryValue.java Mon Apr 23 15:22:24 2012
@@ -0,0 +1,51 @@
+/*
+ * 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.oak.core;
+
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.util.MicroKernelInputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+
+/**
+ * BinaryValue... TODO: review name (BlobValue? BlobCoreValue? BinaryCoreValue?)
+ */
+public class BinaryValue {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(BinaryValue.class);
+
+    private String binaryID;
+    private MicroKernel mk;
+
+    BinaryValue(String binaryID, MicroKernel mk) {
+        this.binaryID = binaryID;
+        this.mk = mk;
+    }
+
+    InputStream getStream() {
+        return new MicroKernelInputStream(mk, binaryID);
+    }
+
+    long length() {
+        return mk.getLength(binaryID);
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueFactoryImpl.java?rev=1329281&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueFactoryImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueFactoryImpl.java Mon Apr 23 15:22:24 2012
@@ -0,0 +1,83 @@
+/*
+ * 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.oak.core;
+
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.CoreValueFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.PropertyType;
+import java.io.InputStream;
+import java.math.BigDecimal;
+
+/**
+ * CoreValueFactoryImpl... TODO javadoc
+ */
+public class CoreValueFactoryImpl implements CoreValueFactory {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(CoreValueFactoryImpl.class);
+
+    private final MicroKernel mk;
+
+    CoreValueFactoryImpl(MicroKernel mk) {
+        this.mk = mk;
+    }
+
+    //-----------------------------------------< javax.jcr.CoreValueFactory >---
+    @Override
+    public CoreValue createValue(String value) {
+        return new CoreValueImpl(value, PropertyType.STRING);
+    }
+
+    @Override
+    public CoreValue createValue(double value) {
+        return new CoreValueImpl(value);
+    }
+
+    @Override
+    public CoreValue createValue(long value) {
+        return new CoreValueImpl(value);
+    }
+
+    @Override
+    public CoreValue createValue(boolean value) {
+        return new CoreValueImpl(value);
+    }
+
+    @Override
+    public CoreValue createValue(BigDecimal value) {
+        return new CoreValueImpl(value);
+    }
+
+    @Override
+    public CoreValue createValue(InputStream value) {
+        String binaryID = mk.write(value);
+        return new CoreValueImpl(new BinaryValue(binaryID, mk));
+    }
+
+    @Override
+    public CoreValue createValue(String value, int type) {
+        return new CoreValueImpl(value, type);
+    }
+
+
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueImpl.java?rev=1329281&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/CoreValueImpl.java Mon Apr 23 15:22:24 2012
@@ -0,0 +1,308 @@
+/*
+ * 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.oak.core;
+
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.PropertyType;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+
+/**
+ * CoreValueImpl... TODO: javadoc
+ */
+class CoreValueImpl implements CoreValue, Comparable<CoreValue>{
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(CoreValueImpl.class);
+
+    private final Object value;
+    private final int type;
+
+    /**
+     * Create a new instance.
+     *
+     * @param value The value.
+     * @param type The property type.
+     * @throws IllegalArgumentException if the passed {@code value} is {@code null}.
+     */
+    private CoreValueImpl(Object value, int type) {
+        if (value == null) {
+            throw new IllegalArgumentException("null value");
+        }
+        this.value = value;
+        this.type = type;
+    }
+
+    /**
+     * Create a new instance.
+     *
+     * @param value
+     * @param type
+     * @throws IllegalArgumentException if the specified type cannot be created
+     * from a string value.
+     */
+    CoreValueImpl(String value, int type) {
+        if (value == null) {
+            throw new IllegalArgumentException("null value");
+        }
+        switch (type) {
+            case PropertyType.STRING:
+            case PropertyType.NAME:
+            case PropertyType.PATH:
+            case PropertyType.DATE:
+            case PropertyType.REFERENCE:
+            case PropertyType.WEAKREFERENCE:
+            case PropertyType.URI:
+                this.value = value;
+                this.type = type;
+                break;
+
+            default:
+                throw new IllegalArgumentException("Illegal type " + PropertyType.nameFromValue(type));
+        }
+
+    }
+
+    /**
+     * Create a new instance.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed {@code value}
+     * is {@code null}.
+     */
+    CoreValueImpl(Long value) {
+        this(value, PropertyType.LONG);
+    }
+
+    /**
+     * Create a new instance.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed {@code value}
+     * is {@code null}.
+     */
+    CoreValueImpl(Double value) {
+        this(value, PropertyType.DOUBLE);
+    }
+
+    /**
+     * Create a new instance.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed {@code value}
+     * is {@code null}.
+     */
+    CoreValueImpl(Boolean value) {
+        this(value, PropertyType.BOOLEAN);
+    }
+
+    /**
+     * Create a new instance.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed {@code value}
+     * is {@code null}.
+     */
+    CoreValueImpl(BigDecimal value) {
+        this(value, PropertyType.DECIMAL);
+    }
+
+    /**
+     * Create a new instance.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed {@code value}
+     * is {@code null}.
+     */
+    CoreValueImpl(BinaryValue value) {
+        this(value, PropertyType.BINARY);
+    }
+
+    //----------------------------------------------------------< CoreValue >---
+    @Override
+    public int getType() {
+        return type;
+    }
+
+    @Override
+    public String getString() {
+        return value.toString();
+    }
+
+    @Override
+    public long getLong() {
+        long l;
+        switch (getType()) {
+            case PropertyType.LONG:
+                l = (Long) value;
+                break;
+            case PropertyType.DOUBLE:
+                l = ((Double) value).longValue();
+                break;
+            case PropertyType.DECIMAL:
+                l = ((BigDecimal) value).longValue();
+                break;
+            default:
+                l = Long.parseLong(getString());
+        }
+        return l;
+    }
+
+    @Override
+    public double getDouble() {
+        double d;
+        switch (getType()) {
+            case PropertyType.DOUBLE:
+                d = (Double) value;
+                break;
+            case PropertyType.LONG:
+                d = ((Long) value).doubleValue();
+                break;
+            case PropertyType.DECIMAL:
+                d = ((BigDecimal) value).doubleValue();
+                break;
+            default:
+                d = Double.parseDouble(getString());
+        }
+        return d;
+    }
+
+    @Override
+    public boolean getBoolean() {
+        boolean b;
+        switch (getType()) {
+            case PropertyType.BOOLEAN:
+                b = (Boolean) value;
+                break;
+            case PropertyType.STRING:
+            case PropertyType.BINARY:
+                b = Boolean.parseBoolean(getString());
+                break;
+            default:
+                throw new UnsupportedOperationException("Unsupported conversion.");
+
+        }
+        return b;
+    }
+
+    @Override
+    public BigDecimal getDecimal() {
+        BigDecimal decimal;
+        switch (getType()) {
+            case PropertyType.DECIMAL:
+                decimal = (BigDecimal) value;
+                break;
+            case PropertyType.DOUBLE:
+                decimal = new BigDecimal(getDouble());
+                break;
+            case PropertyType.LONG:
+                decimal = new BigDecimal(getLong());
+                break;
+            default:
+                decimal = new BigDecimal(getString());
+        }
+        return decimal;
+    }
+
+    @Override
+    public InputStream getNewStream() {
+        InputStream in;
+        switch (type) {
+            case PropertyType.BINARY:
+                in = ((BinaryValue) value).getStream();
+                break;
+            default:
+                try {
+                    in = new ByteArrayInputStream(getString().getBytes("UTF-8"));
+                } catch (UnsupportedEncodingException e) {
+                    // TODO: proper log output and exception handling
+                    throw new RuntimeException(e);
+                }
+        }
+        return in;
+    }
+
+    @Override
+    public long length() {
+        long length;
+        switch (type) {
+            case PropertyType.BINARY:
+                length = ((BinaryValue) value).length();
+                break;
+            default:
+                length = getString().length();
+        }
+        return length;
+    }
+
+    //---------------------------------------------------------< Comparable >---
+    @Override
+    public int compareTo(CoreValue o) {
+        if (this == o) {
+            return 0;
+        }
+        if (type != o.getType()) {
+            // TODO convert?
+            return type - o.getType();
+        }
+        switch (type) {
+            case PropertyType.LONG:
+                return ((Long) value).compareTo(o.getLong());
+            case PropertyType.DOUBLE:
+                return ((Double) value).compareTo(o.getDouble());
+            case PropertyType.DECIMAL:
+                return ((BigDecimal) value).compareTo(o.getDecimal());
+            case PropertyType.BOOLEAN:
+                return ((Boolean) value).compareTo(o.getBoolean());
+            default:
+                return value.toString().compareTo(o.toString());
+        }
+
+    }
+
+    //-------------------------------------------------------------< Object >---
+    @Override
+    public int hashCode() {
+        return type ^ value.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+
+        if (o instanceof CoreValueImpl) {
+            CoreValueImpl other = (CoreValueImpl) o;
+            return type == other.type && value.equals(other.value);
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return value.toString();
+    }
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentRepository.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentRepository.java?rev=1329281&r1=1329280&r2=1329281&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentRepository.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentRepository.java Mon Apr 23 15:22:24 2012
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.core;
 
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.CoreValueFactory;
 import org.apache.jackrabbit.oak.kernel.NodeState;
 import org.apache.jackrabbit.oak.api.Branch;
 import org.apache.jackrabbit.oak.api.QueryEngine;
@@ -93,8 +94,10 @@ public class KernelContentRepository imp
             throw new NoSuchWorkspaceException(workspaceName);
         }
 
+        CoreValueFactory valueFactory = new CoreValueFactoryImpl(microKernel);
+
         return new KernelContentSession(
-                sc, workspaceName, nodeStore, wspRoot, queryEngine);
+                sc, workspaceName, nodeStore, wspRoot, queryEngine, valueFactory);
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentSession.java?rev=1329281&r1=1329280&r2=1329281&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentSession.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/KernelContentSession.java Mon Apr 23 15:22:24 2012
@@ -21,6 +21,7 @@ import org.apache.jackrabbit.mk.api.Micr
 import org.apache.jackrabbit.oak.api.AuthInfo;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.CoreValueFactory;
 import org.apache.jackrabbit.oak.kernel.NodeState;
 import org.apache.jackrabbit.oak.api.Branch;
 import org.apache.jackrabbit.oak.kernel.NodeStore;
@@ -45,17 +46,20 @@ class KernelContentSession implements Co
     private final String workspaceName;
     private final NodeStore store;
     private final QueryEngine queryEngine;
+    private final CoreValueFactory valueFactory;
 
     private NodeState root;
 
     public KernelContentSession(
             SimpleCredentials credentials, String workspaceName,
-            NodeStore store, NodeState root, QueryEngine queryEngine) {
+            NodeStore store, NodeState root, QueryEngine queryEngine,
+            CoreValueFactory valueFactory) {
         this.credentials = credentials;
         this.workspaceName = workspaceName;
         this.store = store;
         this.queryEngine = queryEngine;
         this.root = root;
+        this.valueFactory = valueFactory;
     }
 
     @Override
@@ -113,4 +117,9 @@ class KernelContentSession implements Co
         return queryEngine;
     }
 
+    @Override
+    public CoreValueFactory getCoreValueFactory() {
+        return valueFactory;
+    }
+
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1329281&r1=1329280&r2=1329281&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Mon Apr 23 15:22:24 2012
@@ -59,6 +59,11 @@
       <version>3.2.1</version>
     </dependency>
     <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>1.4</version>
+    </dependency>
+    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
       <version>1.6.4</version>

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java?rev=1329281&r1=1329280&r2=1329281&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java Mon Apr 23 15:22:24 2012
@@ -69,7 +69,7 @@ public class SessionImpl extends Abstrac
     SessionImpl(GlobalContext globalContext, ContentSession contentSession) {
         this.globalContext = globalContext;
         this.contentSession = contentSession;
-        this.valueFactory = new ValueFactoryImpl();
+        this.valueFactory = new ValueFactoryImpl(contentSession.getCoreValueFactory());
         workspace = new WorkspaceImpl(sessionContext);
         this.branch = contentSession.branchRoot();
     }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueFactoryImpl.java?rev=1329281&r1=1329280&r2=1329281&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueFactoryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueFactoryImpl.java Mon Apr 23 15:22:24 2012
@@ -16,34 +16,163 @@
  */
 package org.apache.jackrabbit.oak.jcr;
 
-import org.apache.jackrabbit.value.AbstractValueFactory;
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.CoreValueFactory;
+import org.apache.jackrabbit.util.ISO8601;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
 import javax.jcr.ValueFormatException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.Calendar;
 
 /**
- * ValueFactoryImpl...
+ * CoreValueFactoryImpl...
  */
-class ValueFactoryImpl extends AbstractValueFactory {
+class ValueFactoryImpl implements ValueFactory {
 
     /**
      * logger instance
      */
     private static final Logger log = LoggerFactory.getLogger(ValueFactoryImpl.class);
 
-    ValueFactoryImpl() {
+    private final CoreValueFactory factory;
+    private final DummyNamePathResolver resolver; // TODO: add proper name/path conversion
 
+    /**
+     *
+     * @param factory
+     */
+    public ValueFactoryImpl(CoreValueFactory factory/*, NamePathResolver resolver*/) {
+        this.factory = factory;
+        this.resolver = new DummyNamePathResolver();
+    }
+
+    //-------------------------------------------------------< ValueFactory >---
+    @Override
+    public Value createValue(String value) {
+        CoreValue cv = factory.createValue(value, PropertyType.STRING);
+        return new ValueImpl(cv, resolver);
+    }
+
+    @Override
+    public Value createValue(long value) {
+        CoreValue cv = factory.createValue(value);
+        return new ValueImpl(cv, resolver);
+    }
+
+    @Override
+    public Value createValue(double value) {
+        CoreValue cv = factory.createValue(value);
+        return new ValueImpl(cv, resolver);
     }
 
     @Override
-    protected void checkPathFormat(String s) throws ValueFormatException {
-        // TODO : path validation
+    public Value createValue(boolean value) {
+        CoreValue cv = factory.createValue(value);
+        return new ValueImpl(cv, resolver);
+    }
 
+    @Override
+    public Value createValue(Calendar value) {
+        String dateStr = ISO8601.format(value);
+        CoreValue cv = factory.createValue(dateStr, PropertyType.DATE);
+        return new ValueImpl(cv, resolver);
     }
 
     @Override
-    protected void checkNameFormat(String s) throws ValueFormatException {
-        // TODO : name validation
+    public Value createValue(InputStream value) {
+        try {
+            CoreValue cv = factory.createValue(value);
+            return new ValueImpl(cv, resolver);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        } finally {
+            // JCR-2903
+            IOUtils.closeQuietly(value);
+        }
+    }
+
+    @Override
+    public Value createValue(Node value) throws RepositoryException {
+        return createValue(value, false);
+    }
+
+    @Override
+    public Value createValue(String value, int type) throws ValueFormatException {
+        CoreValue cv;
+        if (type == PropertyType.NAME) {
+            cv = factory.createValue(resolver.getInternalName(value), type);
+        } else if (type == PropertyType.PATH) {
+            cv = factory.createValue(resolver.getInternalPath(value), type);
+        } else {
+            cv = factory.createValue(value, type);
+        }
+
+        return new ValueImpl(cv, resolver);
+    }
+
+    @Override
+    public Binary createBinary(InputStream stream) throws RepositoryException {
+        try {
+            CoreValue value = factory.createValue(stream);
+            // TODO: BINARY implementation missing
+            throw new UnsupportedOperationException("BINARY handling");
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        } finally {
+            IOUtils.closeQuietly(stream);
+        }
+    }
+
+    @Override
+    public Value createValue(Binary value) {
+        try {
+            return createValue(value.getStream());
+        } catch (RepositoryException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    @Override
+    public Value createValue(BigDecimal value) {
+        CoreValue cv = factory.createValue(value);
+        return new ValueImpl(cv, resolver);
+    }
+
+    @Override
+    public Value createValue(Node value, boolean weak) throws RepositoryException {
+        CoreValue cv = factory.createValue(value.getUUID(), weak ? PropertyType.WEAKREFERENCE : PropertyType.REFERENCE);
+        return new ValueImpl(cv, resolver);
+    }
+
+
+    //--------------------------------------------------------------------------
+    // TODO: replace by reasonable implementation taking namespace mappings etc. into account.
+    public class DummyNamePathResolver {
+        String getJCRPath(String internalPath) {
+            return internalPath;
+        }
+
+        String getInternalPath(String jcrPath) {
+            return jcrPath;
+        }
+
+        String getJCRName(String internalName) {
+            return internalName;
+        }
+
+        String getInternalName(String jcrName) {
+            return jcrName;
+        }
     }
 }
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueImpl.java?rev=1329281&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueImpl.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ValueImpl.java Mon Apr 23 15:22:24 2012
@@ -0,0 +1,253 @@
+/*
+ * 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.oak.jcr;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.util.ISO8601;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Binary;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * ValueImpl...
+ */
+public class ValueImpl implements Value {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(ValueImpl.class);
+
+    private final CoreValue value;
+
+    // TODO need utility to convert the internal NAME/PATH format to JCR format
+    private final ValueFactoryImpl.DummyNamePathResolver resolver;
+
+    /**
+     * Constructs a <code>ValueImpl</code> object representing an SPI
+     * <codeQValue</code>.
+     *
+     * @param value the value object this <code>ValueImpl</code> should represent
+     * @param resolver
+     */
+    public ValueImpl(CoreValue value, ValueFactoryImpl.DummyNamePathResolver resolver) {
+        this.value = value;
+        this.resolver = resolver;
+    }
+
+    //--------------------------------------------------------------< Value >---
+    /**
+     * @see javax.jcr.Value#getType()
+     */
+    public int getType() {
+        return value.getType();
+    }
+
+    /**
+     * @see javax.jcr.Value#getBoolean()
+     */
+    public boolean getBoolean() throws RepositoryException {
+        if (getType() == PropertyType.STRING || getType() == PropertyType.BINARY || getType() == PropertyType.BOOLEAN) {
+            return value.getBoolean();
+        } else {
+            throw new ValueFormatException("Incompatible type " + PropertyType.nameFromValue(getType()));
+        }
+    }
+
+    /**
+     * @see javax.jcr.Value#getDate()
+     */
+    public Calendar getDate() throws RepositoryException {
+        Calendar cal;
+        switch (getType()) {
+            case PropertyType.DOUBLE:
+            case PropertyType.LONG:
+            case PropertyType.DECIMAL:
+                cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00"));
+                cal.setTimeInMillis(getLong());
+                break;
+            default:
+                cal = ISO8601.parse(getString());
+                if (cal == null) {
+                    throw new ValueFormatException("Not a date string: " + getString());
+                }
+        }
+        return cal;
+    }
+
+    /**
+     * @see javax.jcr.Value#getDecimal()
+     */
+    public BigDecimal getDecimal() throws RepositoryException {
+        try {
+            return value.getDecimal();
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("Incompatible type " + PropertyType.nameFromValue(getType()));
+        }
+    }
+
+    /**
+     * @see javax.jcr.Value#getDouble()
+     */
+    public double getDouble() throws RepositoryException {
+        try {
+            return value.getDouble();
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("Incompatible type " + PropertyType.nameFromValue(getType()));
+        }
+    }
+
+    /**
+     * @see javax.jcr.Value#getLong()
+     */
+    public long getLong() throws RepositoryException {
+        try {
+            return value.getLong();
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("Incompatible type " + PropertyType.nameFromValue(getType()));
+        }
+    }
+
+    /**
+     * @see javax.jcr.Value#getString()
+     */
+    public String getString() throws RepositoryException {
+        switch (getType()) {
+            case PropertyType.NAME :
+                return resolver.getJCRName(value.toString());
+            case PropertyType.PATH:
+                return resolver.getJCRPath(value.toString());
+            case PropertyType.BINARY:
+                InputStream stream = getStream();
+                try {
+                    return IOUtils.toString(stream, "UTF-8");
+                } catch (IOException e) {
+                    throw new RepositoryException("conversion from stream to string failed", e);
+                } finally {
+                    IOUtils.closeQuietly(stream);
+                }
+            default:
+                return value.toString();
+        }
+    }
+
+
+    /**
+     * @see javax.jcr.Value#getStream()
+     */
+    public InputStream getStream() throws IllegalStateException, RepositoryException {
+        InputStream stream;
+        switch (getType()) {
+            case PropertyType.NAME:
+            case PropertyType.PATH:
+                try {
+                    stream = new ByteArrayInputStream(getString().getBytes("UTF-8"));
+                } catch (UnsupportedEncodingException ex) {
+                    throw new RepositoryException("UTF-8 is not supported", ex);
+                }
+                break;
+            default:
+                stream = value.getNewStream();
+        }
+        return stream;
+    }
+
+    /**
+     * @see javax.jcr.Value#getBinary()
+     */
+    public Binary getBinary() throws RepositoryException {
+        return new BinaryImpl();
+    }
+
+    //-------------------------------------------------------------< Object >---
+    /**
+     * @see Object#equals(Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof ValueImpl) {
+            return value.equals(((ValueImpl) obj).value);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @see Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return value.hashCode();
+    }
+
+    //------------------------------------------------------------< Binary >----
+    private class BinaryImpl implements Binary {
+
+        @Override
+        public InputStream getStream() throws RepositoryException {
+            switch (value.getType()) {
+                case PropertyType.NAME:
+                case PropertyType.PATH:
+                    // need to respect namespace remapping
+                    try {
+                        final String strValue = getString();
+                        return new ByteArrayInputStream(strValue.getBytes("utf-8"));
+                    } catch (UnsupportedEncodingException e) {
+                        throw new RepositoryException(e.getMessage());
+                    }
+                default:
+                    return value.getNewStream();
+            }
+        }
+
+        @Override
+        public int read(byte[] b, long position) throws IOException, RepositoryException {
+            // TODO
+            throw new UnsupportedOperationException("implementation missing");
+        }
+
+        @Override
+        public long getSize() throws RepositoryException {
+            switch (value.getType()) {
+                case PropertyType.NAME:
+                case PropertyType.PATH:
+                    // need to respect namespace remapping
+                    return getString().length();
+                default:
+                    return value.length();
+            }
+        }
+
+        @Override
+        public void dispose() {
+            // nothing to do
+        }
+    }
+}
\ No newline at end of file