jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r1394002 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak: api/ core/ plugins/memory/ spi/state/
Date Thu, 04 Oct 2012 11:52:31 GMT
Author: mduerig
Date: Thu Oct  4 11:52:30 2012
New Revision: 1394002

URL: http://svn.apache.org/viewvc?rev=1394002&view=rev
Log:
OAK-350: Unify PropertyState and CoreValue
- Introduce new methods for setting values to Tree and NodeBuilder and related classes
- Introduce static PropertyState factory
- Mark CoreValue as deprecated
- Mark methods using CoreValue as deprecated where alternatives exist

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Blob.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/BlobImpl.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyStates.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CoreValue.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyPropertyState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MultiPropertyState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/SinglePropertyState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Blob.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Blob.java?rev=1394002&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Blob.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Blob.java Thu Oct  4 11:52:30 2012
@@ -0,0 +1,22 @@
+package org.apache.jackrabbit.oak.api;
+
+import java.io.InputStream;
+
+import javax.annotation.Nonnull;
+
+public interface Blob {
+
+    /**
+     * Returns a new stream for this value object.
+     * @return a new stream for this value based on an internal conversion.
+     */
+    @Nonnull
+    InputStream getNewStream();
+
+    /**
+     * Returns the length of this blob.
+     *
+     * @return the length of this bloc.
+     */
+    long length();
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Blob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Blob.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CoreValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CoreValue.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CoreValue.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/CoreValue.java Thu Oct  4 11:52:30 2012
@@ -16,15 +16,17 @@
  */
 package org.apache.jackrabbit.oak.api;
 
-import javax.annotation.Nonnull;
 import java.io.InputStream;
 import java.math.BigDecimal;
 
+import javax.annotation.Nonnull;
+
 /**
  * {@code CoreValue} is the internal representation of a {@link javax.jcr.Value
  * JCR value}. It is therefore isolated from session-specific namespace mappings
  * and relies on the internal representation of JCR names and paths.
  */
+@Deprecated
 public interface CoreValue extends Comparable<CoreValue> {
 
     /**
@@ -116,4 +118,4 @@ public interface CoreValue extends Compa
      * @return the length of this value.
      */
     long length();
-}
\ No newline at end of file
+}

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java Thu Oct  4 11:52:30 2012
@@ -21,13 +21,13 @@ import java.util.List;
 import javax.annotation.Nonnull;
 
 /**
- * Immutable property state. A property consists of a name and
- * a JSON-encoded value.
+ * Immutable property state. A property consists of a name and a value.
+ * A value is either an atom or an array of atoms.
  *
  * <h2>Equality and hash codes</h2>
  * <p>
  * Two property states are considered equal if and only if their names and
- * encoded values match. The {@link Object#equals(Object)} method needs to
+ * values match. The {@link Object#equals(Object)} method needs to
  * be implemented so that it complies with this definition. And while
  * property states are not meant for use as hash keys, the
  * {@link Object#hashCode()} method should still be implemented according
@@ -45,7 +45,7 @@ public interface PropertyState {
      * // TODO: Expose this a API method on the Tree interface (see http://markmail.org/message/kzt7csiz2bd5n3ww) ?
      * // TODO: Define if/how this internal property is exposed on the JCR API
      */
-    public static final String OAK_CHILD_ORDER = "childOrder";
+    String OAK_CHILD_ORDER = "childOrder";
 
     /**
      * @return the name of this property state
@@ -54,8 +54,8 @@ public interface PropertyState {
     String getName();
 
     /**
-     * Determine whether this is a multi valued property
-     * @return  {@code true} if and only if this is a multi valued property.
+     * Determine whether the value if an array of atoms
+     * @return  {@code true} if and only if the value is an array of atoms.
      */
     boolean isArray();
 
@@ -65,6 +65,7 @@ public interface PropertyState {
      * @throws IllegalStateException  if {@code isArray()} is {@code true}.
      */
     @Nonnull
+    @Deprecated
     CoreValue getValue();
 
     /**
@@ -76,6 +77,76 @@ public interface PropertyState {
      * @return immutable list of the values of this property
      */
     @Nonnull
+    @Deprecated
     List<CoreValue> getValues();
 
+    /**
+     * Determine the type of this property
+     * @return  the type of this property
+     */
+    Type<?> getType();
+
+    /**
+     * Value of this property.
+     * The type of the return value is determined by the target {@code type}
+     * argument. If {@code type.isArray()} is true, this method returns an
+     * {@code Iterable} of the {@link Type#getBaseType() base type} of
+     * {@code type} containing all values of this property.
+     * If the target type is not the same as the type of this property an attempt
+     * is made to convert the value to the target type. If the conversion fails an
+     * exception is thrown.
+     * @param type target type
+     * @param <T>
+     * @return the value of this property
+     * @throws IllegalStateException  if {@code type.isArray() == false} and
+     *         {@code this.isArray() == true}. In other words, when trying to convert
+     *         from an array to an atom.
+     * @throws IllegalArgumentException  if {@code type} refers to an unkown type.
+     * @throws NumberFormatException  if conversion to a number failed.
+     * @throws UnsupportedOperationException  if conversion to boolean failed.
+     */
+    @Nonnull
+    <T> T getValue(Type<T> type);
+
+    /**
+     * Value at the given {@code index}.
+     * The type of the return value is determined by the target {@code type}
+     * argument.
+     * If the target type is not the same as the type of this property an attempt
+     * is made to convert the value to the target type. If the conversion fails an
+     * exception is thrown.
+     * @param type  target type
+     * @param index
+     * @param <T>
+     * @return the value of this property at the given {@code index}
+     * @throws IndexOutOfBoundsException  if {@code index} is less than {@code 0} or
+     *         greater or equals {@code count()}.
+     * @throws IllegalArgumentException  if {@code type} refers to an unkown type or if
+     *         {@code type.isArray()} is true.
+     */
+    @Nonnull
+    <T> T getValue(Type<T> type, int index);
+
+    /**
+     * The size of the value of this property.
+     * @return  size of the value of this property
+     * @throws  IllegalStateException  if the value is an array
+     */
+    long size();
+
+    /**
+     * The size of the value at the given {@code index}.
+     * @param index
+     * @return  size of the value at the given {@code index}.
+     * @throws IndexOutOfBoundsException  if {@code index} is less than {@code 0} or
+     *         greater or equals {@code count()}.
+     */
+    long size(int index);
+
+    /**
+     * The number of values of this property. {@code 1} for atoms.
+     * @return  number of values
+     */
+    long count();
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java Thu Oct  4 11:52:30 2012
@@ -226,6 +226,7 @@ public interface Tree {
      * @return the affected property state
      */
     @Nonnull
+    @Deprecated
     PropertyState setProperty(String name, @Nonnull CoreValue value);
 
     /**
@@ -236,9 +237,33 @@ public interface Tree {
      * @return the affected property state
      */
     @Nonnull
+    @Deprecated
     PropertyState setProperty(String name, @Nonnull List<CoreValue> values);
 
     /**
+     * Set a property state
+     * @param property  The property state to set
+     */
+    void setProperty(PropertyState property);
+
+    /**
+     * Set a property state
+     * @param name  The name of this property
+     * @param value  The value of this property
+     * @param <T>  The type of this property. Must be one of {@code String, Blob, byte[], Long, Integer, Double, Boolean, BigDecimal}
+     * @throws IllegalArgumentException if {@code T} is not one of the above types.
+     */
+    <T> void setProperty(String name, T value);
+
+    /**
+     * Set a property state
+     * @param name  The name of this property
+     * @param value  The value of this property
+     * @param <T>  The type of this property.
+     */
+    <T> void setProperty(String name, T value, Type<T> type);
+
+    /**
      * Remove the property with the given name. This method has no effect if a
      * property of the given {@code name} does not exist.
      *

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.java?rev=1394002&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.java Thu Oct  4 11:52:30 2012
@@ -0,0 +1,171 @@
+package org.apache.jackrabbit.oak.api;
+
+import java.math.BigDecimal;
+
+import javax.jcr.PropertyType;
+
+import com.google.common.base.Objects;
+
+/**
+ * Instances of this class map Java types to {@link PropertyType property types}.
+ * Passing an instance of this class to {@link PropertyState#getValue(Type)} determines
+ * the return type of that method.
+ * @param <T>
+ */
+public final class Type<T> {
+
+    /** Map {@code String} to {@link PropertyType#STRING} */
+    public static final Type<String> STRING = create(PropertyType.STRING, false);
+
+    /** Map {@code Blob} to {@link PropertyType#BINARY} */
+    public static final Type<Blob> BINARY = create(PropertyType.BINARY, false);
+
+    /** Map {@code Long} to {@link PropertyType#LONG} */
+    public static final Type<Long> LONG = create(PropertyType.LONG, false);
+
+    /** Map {@code Double} to {@link PropertyType#DOUBLE} */
+    public static final Type<Double> DOUBLE = create(PropertyType.DOUBLE, false);
+
+    /** Map {@code String} to {@link PropertyType#DATE} */
+    public static final Type<String> DATE = create(PropertyType.DATE, false);
+
+    /** Map {@code Boolean} to {@link PropertyType#BOOLEAN} */
+    public static final Type<Boolean> BOOLEAN = create(PropertyType.BOOLEAN, false);
+
+    /** Map {@code String} to {@link PropertyType#STRING} */
+    public static final Type<String> NAME = create(PropertyType.NAME, false);
+
+    /** Map {@code String} to {@link PropertyType#PATH} */
+    public static final Type<String> PATH = create(PropertyType.PATH, false);
+
+    /** Map {@code String} to {@link PropertyType#REFERENCE} */
+    public static final Type<String> REFERENCE = create(PropertyType.REFERENCE, false);
+
+    /** Map {@code String} to {@link PropertyType#WEAKREFERENCE} */
+    public static final Type<String> WEAKREFERENCE = create(PropertyType.WEAKREFERENCE, false);
+
+    /** Map {@code String} to {@link PropertyType#URI} */
+    public static final Type<String> URI = create(PropertyType.URI, false);
+
+    /** Map {@code BigDecimal} to {@link PropertyType#DECIMAL} */
+    public static final Type<BigDecimal> DECIMAL = create(PropertyType.DECIMAL, false);
+
+    /** Map {@code Iterable<String>} to array of {@link PropertyType#STRING} */
+    public static final Type<Iterable<String>> STRINGS = create(PropertyType.STRING, true);
+
+    /** Map {@code Iterable<Blob} to array of {@link PropertyType#BINARY} */
+    public static final Type<Iterable<Blob>> BINARIES = create(PropertyType.BINARY, true);
+
+    /** Map {@code Iterable<Long>} to array of {@link PropertyType#LONG} */
+    public static final Type<Iterable<Long>> LONGS = create(PropertyType.LONG, true);
+
+    /** Map {@code Iterable<Double>} to array of {@link PropertyType#DOUBLE} */
+    public static final Type<Iterable<Double>> DOUBLES = create(PropertyType.DOUBLE, true);
+
+    /** Map {@code Iterable<String>} to array of {@link PropertyType#DATE} */
+    public static final Type<Iterable<String>> DATES = create(PropertyType.DATE, true);
+
+    /** Map {@code Iterable<Boolean>} to array of {@link PropertyType#BOOLEAN} */
+    public static final Type<Iterable<Boolean>> BOOLEANS = create(PropertyType.BOOLEAN, true);
+
+    /** Map {@code Iterable<String>} to array of {@link PropertyType#NAME} */
+    public static final Type<Iterable<String>> NAMES = create(PropertyType.NAME, true);
+
+    /** Map {@code Iterable<String>} to array of {@link PropertyType#PATH} */
+    public static final Type<Iterable<String>> PATHS = create(PropertyType.PATH, true);
+
+    /** Map {@code Iterable<String>} to array of {@link PropertyType#REFERENCE} */
+    public static final Type<Iterable<String>> REFERENCES = create(PropertyType.REFERENCE, true);
+
+    /** Map {@code Iterable<String>} to array of {@link PropertyType#WEAKREFERENCE} */
+    public static final Type<Iterable<String>> WEAKREFERENCES = create(PropertyType.WEAKREFERENCE, true);
+
+    /** Map {@code Iterable<String>} to array of {@link PropertyType#URI} */
+    public static final Type<Iterable<String>> URIS = create(PropertyType.URI, true);
+
+    /** Map {@code Iterable<BigDecimal>} to array of {@link PropertyType#DECIMAL} */
+    public static final Type<Iterable<BigDecimal>> DECIMALS = create(PropertyType.DECIMAL, true);
+
+    private final int tag;
+    private final boolean array;
+
+    private Type(int tag, boolean array){
+        this.tag = tag;
+        this.array = array;
+    }
+
+    private static <T> Type<T> create(int tag, boolean array) {
+        return new Type<T>(tag, array);
+    }
+
+    /**
+     * Corresponding type tag as defined in {@link PropertyType}.
+     * @return  type tag
+     */
+    public int tag() {
+        return tag;
+    }
+
+    /**
+     * Determine whether this is an array type
+     * @return  {@code true} if and only if this is an array type
+     */
+    public boolean isArray() {
+        return array;
+    }
+
+    /**
+     * Corresponding {@code Type} for a given type tag and array flag.
+     * @param tag  type tag as defined in {@link PropertyType}.
+     * @param array  whether this is an array or not
+     * @return  {@code Type} instance
+     * @throws IllegalArgumentException if tag is not valid as per definition in {@link PropertyType}.
+     */
+    public static Type<?> fromTag(int tag, boolean array) {
+        switch (tag) {
+            case PropertyType.STRING: return array ? STRINGS : STRING;
+            case PropertyType.BINARY: return array ? BINARY : BINARIES;
+            case PropertyType.LONG: return array ? LONG : LONGS;
+            case PropertyType.DOUBLE: return array ? DOUBLE : DOUBLES;
+            case PropertyType.DATE: return array ? DATE: DATES;
+            case PropertyType.BOOLEAN: return array ? BOOLEAN: BOOLEANS;
+            case PropertyType.NAME: return array ? NAME : NAMES;
+            case PropertyType.PATH: return array ? PATH: PATHS;
+            case PropertyType.REFERENCE: return array ? REFERENCE : REFERENCES;
+            case PropertyType.WEAKREFERENCE: return array ? WEAKREFERENCE : WEAKREFERENCES;
+            case PropertyType.URI: return array ? URI: URIS;
+            case PropertyType.DECIMAL: return array ? DECIMAL : DECIMALS;
+            default: throw new IllegalArgumentException("Invalid type tag: " + tag);
+        }
+    }
+
+    /**
+     * Determine the base type of array types
+     * @return  base type
+     * @throws IllegalStateException if {@code isArray} is false.
+     */
+    public Type<?> getBaseType() {
+        if (!isArray()) {
+            throw new IllegalStateException("Not an array: " + this);
+        }
+        return fromTag(tag, false);
+    }
+
+    @Override
+    public String toString() {
+        return isArray()
+            ? "[]" + PropertyType.nameFromValue(getBaseType().tag)
+            : PropertyType.nameFromValue(tag);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(tag, array);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        return this == other;
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java Thu Oct  4 11:52:30 2012
@@ -25,6 +25,7 @@ import org.apache.jackrabbit.oak.api.Cor
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.TreeLocation;
+import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
@@ -186,16 +187,33 @@ public class ReadOnlyTree implements Tre
     }
 
     @Override
+    @Deprecated
     public PropertyState setProperty(String name, CoreValue value) {
         throw new UnsupportedOperationException();
     }
 
     @Override
+    @Deprecated
     public PropertyState setProperty(String name, List<CoreValue> values) {
         throw new UnsupportedOperationException();
     }
 
     @Override
+    public void setProperty(PropertyState property) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <T> void setProperty(String name, T value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <T> void setProperty(String name, T value, Type<T> type) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void removeProperty(String name) {
         throw new UnsupportedOperationException();
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java Thu Oct  4 11:52:30 2012
@@ -32,6 +32,7 @@ import org.apache.jackrabbit.oak.api.Cor
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.TreeLocation;
+import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.core.RootImpl.PurgeListener;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -262,6 +263,7 @@ public class TreeImpl implements Tree, P
     }
 
     @Override
+    @Deprecated
     public PropertyState setProperty(String name, CoreValue value) {
         NodeBuilder builder = getNodeBuilder();
         builder.setProperty(name, value);
@@ -272,6 +274,7 @@ public class TreeImpl implements Tree, P
     }
 
     @Override
+    @Deprecated
     public PropertyState setProperty(String name, List<CoreValue> values) {
         NodeBuilder builder = getNodeBuilder();
         builder.setProperty(name, values);
@@ -282,6 +285,27 @@ public class TreeImpl implements Tree, P
     }
 
     @Override
+    public void setProperty(PropertyState property) {
+        NodeBuilder builder = getNodeBuilder();
+        builder.setProperty(property);
+        root.purge();
+    }
+
+    @Override
+    public <T> void setProperty(String name, T value) {
+        NodeBuilder builder = getNodeBuilder();
+        builder.setProperty(name, value);
+        root.purge();
+    }
+
+    @Override
+    public <T> void setProperty(String name, T value, Type<T> type) {
+        NodeBuilder builder = getNodeBuilder();
+        builder.setProperty(name, value, type);
+        root.purge();
+    }
+
+    @Override
     public void removeProperty(String name) {
         NodeBuilder builder = getNodeBuilder();
         builder.removeProperty(name);

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/BlobImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/BlobImpl.java?rev=1394002&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/BlobImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/BlobImpl.java Thu Oct  4 11:52:30 2012
@@ -0,0 +1,24 @@
+package org.apache.jackrabbit.oak.plugins.memory;
+
+import java.io.InputStream;
+
+import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.api.CoreValue;
+
+public class BlobImpl implements Blob {
+    private final CoreValue value;
+
+    public BlobImpl(CoreValue value) {
+        this.value = value;
+    }
+
+    @Override
+    public InputStream getNewStream() {
+        return value.getNewStream();
+    }
+
+    @Override
+    public long length() {
+        return value.length();
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/BlobImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/BlobImpl.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyPropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyPropertyState.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyPropertyState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyPropertyState.java Thu Oct  4 11:52:30 2012
@@ -23,8 +23,10 @@ import java.util.List;
 
 import javax.annotation.Nonnull;
 
+import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
@@ -35,9 +37,15 @@ import static com.google.common.base.Pre
 class EmptyPropertyState implements PropertyState {
 
     private final String name;
+    private final Type<?> type;
 
-    public EmptyPropertyState(String name) {
+    public EmptyPropertyState(String name, Type<?> type) {
         this.name = checkNotNull(name);
+        this.type = type;
+    }
+
+    protected static Blob getBlob(CoreValue value) {
+        return new BlobImpl(value);
     }
 
     @Override
@@ -52,16 +60,54 @@ class EmptyPropertyState implements Prop
 
     @Override
     @Nonnull
+    @Deprecated
     public CoreValue getValue() {
         throw new IllegalStateException("Not a single valued property");
     }
 
     @Override
     @Nonnull
+    @Deprecated
     public List<CoreValue> getValues() {
         return Collections.emptyList();
     }
 
+    @Override
+    public Type<?> getType() {
+        return type;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getValue(Type<T> type) {
+        if (type.isArray()) {
+            return (T) Collections.emptyList();
+        }
+        else {
+            throw new IllegalStateException("Not a single valued property");
+        }
+    }
+
+    @Override
+    public <T> T getValue(Type<T> type, int index) {
+        throw new IndexOutOfBoundsException(String.valueOf(index));
+    }
+
+    @Override
+    public long size() {
+        throw new IllegalStateException("Not a single valued property");
+    }
+
+    @Override
+    public long size(int index) {
+        throw new IndexOutOfBoundsException(String.valueOf(index));
+    }
+
+    @Override
+    public long count() {
+        return 0;
+    }
+
     //------------------------------------------------------------< Object >--
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java Thu Oct  4 11:52:30 2012
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.oak.plugins.memory;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -25,14 +23,6 @@ import java.util.Set;
 
 import javax.annotation.Nonnull;
 
-import org.apache.jackrabbit.oak.api.CoreValue;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
-import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
-
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Collections2;
@@ -42,6 +32,17 @@ import com.google.common.collect.Immutab
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.api.Type.STRING;
 
 /**
  * In-memory node state builder. The following two builder states are used
@@ -279,22 +280,20 @@ public class MemoryNodeBuilder implement
         return read().getProperty(name);
     }
 
-    @Override @Nonnull
+    @Override @Nonnull @Deprecated
     public NodeBuilder setProperty(String name, CoreValue value) {
         MutableNodeState mstate = write();
-
         mstate.props.put(name, new SinglePropertyState(name, value));
-
         updated();
         return this;
     }
 
-    @Override @Nonnull
+    @Override @Nonnull @Deprecated
     public NodeBuilder setProperty(String name, List<CoreValue> values) {
         MutableNodeState mstate = write();
 
         if (values.isEmpty()) {
-            mstate.props.put(name, new EmptyPropertyState(name));
+            mstate.props.put(name, new EmptyPropertyState(name, STRING));
         } else {
             mstate.props.put(name, new MultiPropertyState(name, values));
         }
@@ -303,12 +302,12 @@ public class MemoryNodeBuilder implement
         return this;
     }
 
-    @Override @Nonnull
+    @Override @Nonnull @Deprecated
     public NodeBuilder set(@Nonnull String name, @Nonnull String value) {
         return setProperty(name, new StringValue(value));
     }
 
-    @Override @Nonnull
+    @Override @Nonnull @Deprecated
     public NodeBuilder set(
             @Nonnull String name, @Nonnull String... values) {
         List<CoreValue> list = Lists.newArrayListWithCapacity(values.length);
@@ -333,6 +332,26 @@ public class MemoryNodeBuilder implement
     }
 
     @Override
+    public NodeBuilder setProperty(PropertyState property) {
+        MutableNodeState mstate = write();
+        mstate.props.put(property.getName(), property);
+        updated();
+        return this;
+    }
+
+    @Override
+    public <T> NodeBuilder setProperty(String name, T value) {
+        setProperty(PropertyStates.createProperty(name, value));
+        return this;
+    }
+
+    @Override
+    public <T> NodeBuilder setProperty(String name, T value, Type<T> type) {
+        setProperty(PropertyStates.createProperty(name, value, type));
+        return this;
+    }
+
+    @Override
     public NodeBuilder getChildBuilder(String name) {
         NodeState state = read();
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MultiPropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MultiPropertyState.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MultiPropertyState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MultiPropertyState.java Thu Oct  4 11:52:30 2012
@@ -18,15 +18,20 @@
  */
 package org.apache.jackrabbit.oak.plugins.memory;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 import javax.annotation.Nonnull;
+import javax.jcr.PropertyType;
 
+import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.Type;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.api.Type.*;
 
 /**
  * Multi-valued property state.
@@ -36,15 +41,130 @@ public class MultiPropertyState extends 
     private final List<CoreValue> values;
 
     public MultiPropertyState(String name, List<CoreValue> values) {
-        super(name);
+        super(name, getBaseType(values));
         this.values = Collections.unmodifiableList(
                 new ArrayList<CoreValue>(checkNotNull(values)));
     }
 
+    private static Type<?> getBaseType(List<CoreValue> values) {
+        if (values.isEmpty()) {
+            return STRINGS;
+        }
+        else {
+            return Type.fromTag(values.get(0).getType(), true);
+        }
+    }
+
     @Override
     @Nonnull
+    @Deprecated
     public List<CoreValue> getValues() {
         return values;
     }
 
+    @Override
+    public long size(int index) {
+        return values.get(index).length();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getValue(Type<T> type) {
+        if (!type.isArray()) {
+            throw new IllegalStateException("Not a single valued property");
+        }
+
+        switch (type.tag()) {
+            case PropertyType.STRING: return (T) getStrings();
+            case PropertyType.BINARY: return (T) getBinaries();
+            case PropertyType.LONG: return (T) getLongs();
+            case PropertyType.DOUBLE: return (T) getDoubles();
+            case PropertyType.DATE: return (T) getStrings();
+            case PropertyType.BOOLEAN: return (T) getBooleans();
+            case PropertyType.NAME: return (T) getStrings();
+            case PropertyType.PATH: return (T) getStrings();
+            case PropertyType.REFERENCE: return (T) getStrings();
+            case PropertyType.WEAKREFERENCE: return (T) getStrings();
+            case PropertyType.URI: return (T) getStrings();
+            case PropertyType.DECIMAL: return (T) getDecimals();
+            default: throw new IllegalArgumentException("Invalid type:" + type);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getValue(Type<T> type, int index) {
+        if (type.isArray()) {
+            throw new IllegalArgumentException("Nested arrays not supported");
+        }
+
+        switch (type.tag()) {
+            case PropertyType.STRING: return (T) values.get(index).getString();
+            case PropertyType.BINARY: return (T) getBlob(values.get(index));
+            case PropertyType.LONG: return (T) (Long) values.get(index).getLong();
+            case PropertyType.DOUBLE: return (T) (Double) values.get(index).getDouble();
+            case PropertyType.DATE: return (T) values.get(index).getString();
+            case PropertyType.BOOLEAN: return (T) (Boolean) values.get(index).getBoolean();
+            case PropertyType.NAME: return (T) values.get(index).getString();
+            case PropertyType.PATH: return (T) values.get(index).getString();
+            case PropertyType.REFERENCE: return (T) values.get(index).getString();
+            case PropertyType.WEAKREFERENCE: return (T) values.get(index).getString();
+            case PropertyType.URI: return (T) values.get(index).getString();
+            case PropertyType.DECIMAL: return (T) values.get(index).getDecimal();
+            default: throw new IllegalArgumentException("Invalid type:" + type);
+        }
+    }
+
+    @Override
+    public long count() {
+        return values.size();
+    }
+
+    private List<String> getStrings() {
+        List<String> strings = new ArrayList<String>();
+        for (CoreValue value: values) {
+            strings.add(value.getString());
+        }
+        return strings;
+    }
+
+    private List<Long> getLongs() {
+        List<Long> longs = new ArrayList<Long>();
+        for (CoreValue value: values) {
+            longs.add(value.getLong());
+        }
+        return longs;
+    }
+
+    private List<Double> getDoubles() {
+        List<Double> doubles = new ArrayList<Double>();
+        for (CoreValue value: values) {
+            doubles.add(value.getDouble());
+        }
+        return doubles;
+    }
+
+    private List<Boolean> getBooleans() {
+        List<Boolean> booleans = new ArrayList<Boolean>();
+        for (CoreValue value: values) {
+            booleans.add(value.getBoolean());
+        }
+        return booleans;
+    }
+
+    private List<BigDecimal> getDecimals() {
+        List<BigDecimal> decimals = new ArrayList<BigDecimal>();
+        for (CoreValue value: values) {
+            decimals.add(value.getDecimal());
+        }
+        return decimals;
+    }
+
+    private List<Blob> getBinaries() {
+        List<Blob> binaries = new ArrayList<Blob>();
+        for (CoreValue value: values) {
+            binaries.add(getBlob(value));
+        }
+        return binaries;
+    }
 }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyStates.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyStates.java?rev=1394002&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyStates.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyStates.java Thu Oct  4 11:52:30 2012
@@ -0,0 +1,278 @@
+package org.apache.jackrabbit.oak.plugins.memory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.jcr.PropertyType;
+
+import com.google.common.collect.Lists;
+import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+
+public final class PropertyStates {
+    private PropertyStates() {}
+
+    @SuppressWarnings("unchecked")
+    @Nonnull
+    public static <T> PropertyState createProperty(String name, T value, Type<T> type) {
+        switch (type.tag()) {
+            case PropertyType.STRING: return type.isArray()
+                ? stringProperty(name, (Iterable<String>) value)
+                : stringProperty(name, (String) value);
+            case PropertyType.BINARY: return type.isArray()
+                ? binaryPropertyFromBlob(name, (Iterable<Blob>) value)
+                : binaryProperty(name, (Blob) value);
+            case PropertyType.LONG: return type.isArray()
+                ? longProperty(name, (Iterable<Long>) value)
+                : longProperty(name, (Long) value);
+            case PropertyType.DOUBLE: return type.isArray()
+                ? doubleProperty(name, (Iterable<Double>) value)
+                : doubleProperty(name, (Double) value);
+            case PropertyType.DATE: return type.isArray()
+                ? dateProperty(name, (Iterable<String>) value)
+                : dateProperty(name, (String) value);
+            case PropertyType.BOOLEAN: return type.isArray()
+                ? booleanProperty(name, (Iterable<Boolean>) value)
+                : booleanProperty(name, (Boolean) value);
+            case PropertyType.NAME: return type.isArray()
+                ? nameProperty(name, (Iterable<String>) value)
+                : nameProperty(name, (String) value);
+            case PropertyType.PATH: return type.isArray()
+                ? pathProperty(name, (Iterable<String>) value)
+                : pathProperty(name, (String) value);
+            case PropertyType.REFERENCE: return type.isArray()
+                ? referenceProperty(name, (Iterable<String>) value)
+                : referenceProperty(name, (String) value);
+            case PropertyType.WEAKREFERENCE: return type.isArray()
+                ? weakreferenceProperty(name, (Iterable<String>) value)
+                : weakreferenceProperty(name, (String) value);
+            case PropertyType.URI: return type.isArray()
+                ? uriProperty(name, (Iterable<String>) value)
+                : uriProperty(name, (String) value);
+            case PropertyType.DECIMAL: return type.isArray()
+                ? decimalProperty(name, (Iterable<BigDecimal>) value)
+                : decimalProperty(name, (BigDecimal) value);
+            default: throw new IllegalArgumentException("Invalid type: " + type);
+        }
+    }
+
+    @Nonnull
+    public static <T> PropertyState createProperty(String name, T value) {
+        if (value instanceof String) {
+            return stringProperty(name, (String) value);
+        }
+        else if (value instanceof Blob) {
+            return binaryProperty(name, (Blob) value);
+        }
+        else if (value instanceof byte[]) {
+            return binaryProperty(name, (byte[]) value);
+        }
+        else if (value instanceof Long) {
+            return longProperty(name, (Long) value);
+        }
+        else if (value instanceof Integer) {
+            return longProperty(name, (Integer) value);
+        }
+        else if (value instanceof Double) {
+            return doubleProperty(name, (Double) value);
+        }
+        else if (value instanceof Boolean) {
+            return booleanProperty(name, (Boolean) value);
+        }
+        else if (value instanceof BigDecimal) {
+            return decimalProperty(name, (BigDecimal) value);
+        }
+        else {
+            throw new IllegalArgumentException("Can't infer type of value of class '" + value.getClass() + '\'');
+        }
+    }
+
+    public static PropertyState emptyProperty(String name, Type<?> type) {
+        return new EmptyPropertyState(name, type);
+    }
+
+    public static PropertyState stringProperty(String name, String value) {
+        return new SinglePropertyState(name, new StringValue(value));
+    }
+
+    public static PropertyState binaryProperty(String name, byte[] value) {
+        return new SinglePropertyState(name, new BinaryValue(value));
+    }
+
+    public static PropertyState longProperty(String name, long value) {
+        return new SinglePropertyState(name, new LongValue(value));
+    }
+
+    public static PropertyState doubleProperty(String name, double value) {
+        return new SinglePropertyState(name, new DoubleValue(value));
+    }
+
+    public static PropertyState dateProperty(String name, String value) {
+        return new SinglePropertyState(name, new GenericValue(PropertyType.DATE, value));
+    }
+
+    public static PropertyState booleanProperty(String name, boolean value) {
+        return new SinglePropertyState(name, value ? BooleanValue.TRUE : BooleanValue.FALSE);
+    }
+
+    public static PropertyState nameProperty(String name, String value) {
+        return new SinglePropertyState(name, new GenericValue(PropertyType.NAME, value));
+    }
+
+    public static PropertyState pathProperty(String name, String value) {
+        return new SinglePropertyState(name, new GenericValue(PropertyType.PATH, value));
+    }
+
+    public static PropertyState referenceProperty(String name, String value) {
+        return new SinglePropertyState(name, new GenericValue(PropertyType.REFERENCE, value));
+    }
+
+    public static PropertyState weakreferenceProperty(String name, String value) {
+        return new SinglePropertyState(name, new GenericValue(PropertyType.WEAKREFERENCE, value));
+    }
+
+    public static PropertyState uriProperty(String name, String value) {
+        return new SinglePropertyState(name, new GenericValue(PropertyType.URI, value));
+    }
+
+    public static PropertyState decimalProperty(String name, BigDecimal value) {
+        return new SinglePropertyState(name, new DecimalValue(value));
+    }
+
+    public static PropertyState binaryProperty(String name, Blob value) {
+        return new SinglePropertyState(name, new BinaryValue(toBytes(value)));
+    }
+
+    public static PropertyState stringProperty(String name, Iterable<String> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (String value : values) {
+            cvs.add(new StringValue(value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState binaryPropertyFromBlob(String name, Iterable<Blob> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (Blob value : values) {
+            cvs.add(new BinaryValue(toBytes(value)));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState longProperty(String name, Iterable<Long> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (long value : values) {
+            cvs.add(new LongValue(value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState doubleProperty(String name, Iterable<Double> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (double value : values) {
+            cvs.add(new DoubleValue(value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState dateProperty(String name, Iterable<String> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (String value : values) {
+            cvs.add(new GenericValue(PropertyType.DATE, value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState booleanProperty(String name, Iterable<Boolean> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (boolean value : values) {
+            cvs.add(value ? BooleanValue.TRUE : BooleanValue.FALSE);
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState nameProperty(String name, Iterable<String> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (String value : values) {
+            cvs.add(new GenericValue(PropertyType.NAME, value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState pathProperty(String name, Iterable<String> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (String value : values) {
+            cvs.add(new GenericValue(PropertyType.PATH, value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState referenceProperty(String name, Iterable<String> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (String value : values) {
+            cvs.add(new GenericValue(PropertyType.REFERENCE, value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState weakreferenceProperty(String name, Iterable<String> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (String value : values) {
+            cvs.add(new GenericValue(PropertyType.WEAKREFERENCE, value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState uriProperty(String name, Iterable<String> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (String value : values) {
+            cvs.add(new GenericValue(PropertyType.URI, value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState decimalProperty(String name, Iterable<BigDecimal> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (BigDecimal value : values) {
+            cvs.add(new DecimalValue(value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    public static PropertyState binaryPropertyFromArray(String name, Iterable<byte[]> values) {
+        List<CoreValue> cvs = Lists.newArrayList();
+        for (byte[] value : values) {
+            cvs.add(new BinaryValue(value));
+        }
+        return new MultiPropertyState(name, cvs);
+    }
+
+    private static byte[] toBytes(Blob blob) {
+        try {
+            InputStream is = blob.getNewStream();
+            try {
+                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+                byte[] b = new byte[4096];
+                int n = is.read(b);
+                while (n != -1) {
+                    buffer.write(b, 0, n);
+                    n = is.read(b);
+                }
+                return buffer.toByteArray();
+            }
+            finally {
+                is.close();
+            }
+        }
+        catch (IOException e) {
+            // TODO
+            return null;
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyStates.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyStates.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/SinglePropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/SinglePropertyState.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/SinglePropertyState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/SinglePropertyState.java Thu Oct  4 11:52:30 2012
@@ -18,15 +18,17 @@
  */
 package org.apache.jackrabbit.oak.plugins.memory;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import java.util.Collections;
 import java.util.List;
 
 import javax.annotation.Nonnull;
+import javax.jcr.PropertyType;
 
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Single-valued property state.
@@ -52,7 +54,7 @@ public class SinglePropertyState extends
     private final CoreValue value;
 
     public SinglePropertyState(String name, CoreValue value) {
-        super(name);
+        super(name, Type.fromTag(value.getType(), false));
         this.value = checkNotNull(value);
     }
 
@@ -63,14 +65,84 @@ public class SinglePropertyState extends
 
     @Override
     @Nonnull
+    @Deprecated
     public CoreValue getValue() {
         return value;
     }
 
     @Override
     @Nonnull
+    @Deprecated
     public List<CoreValue> getValues() {
         return Collections.singletonList(value);
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getValue(Type<T> type) {
+        if (type.isArray()) {
+            switch (type.tag()) {
+                case PropertyType.STRING: return (T) Collections.singleton(value.getString());
+                case PropertyType.BINARY: return (T) Collections.singleton(getBlob(value));
+                case PropertyType.LONG: return (T) Collections.singleton(value.getLong());
+                case PropertyType.DOUBLE: return (T) Collections.singleton(value.getDouble());
+                case PropertyType.DATE: return (T) Collections.singleton(value.getString());
+                case PropertyType.BOOLEAN: return (T) Collections.singleton(value.getBoolean());
+                case PropertyType.NAME: return (T) Collections.singleton(value.getString());
+                case PropertyType.PATH: return (T) Collections.singleton(value.getString());
+                case PropertyType.REFERENCE: return (T) Collections.singleton(value.getString());
+                case PropertyType.WEAKREFERENCE: return (T) Collections.singleton(value.getString());
+                case PropertyType.URI: return (T) Collections.singleton(value.getString());
+                case PropertyType.DECIMAL: return (T) Collections.singleton(value.getDecimal());
+                default: throw new IllegalArgumentException("Invalid primitive type:" + type);
+            }
+        }
+        else {
+            switch (type.tag()) {
+                case PropertyType.STRING: return (T) value.getString();
+                case PropertyType.BINARY: return (T) getBlob(value);
+                case PropertyType.LONG: return (T) (Long) value.getLong();
+                case PropertyType.DOUBLE: return (T) (Double) value.getDouble();
+                case PropertyType.DATE: return (T) value.getString();
+                case PropertyType.BOOLEAN: return (T) (Boolean) value.getBoolean();
+                case PropertyType.NAME: return (T) value.getString();
+                case PropertyType.PATH: return (T) value.getString();
+                case PropertyType.REFERENCE: return (T) value.getString();
+                case PropertyType.WEAKREFERENCE: return (T) value.getString();
+                case PropertyType.URI: return (T) value.getString();
+                case PropertyType.DECIMAL: return (T) value.getDecimal();
+                default: throw new IllegalArgumentException("Invalid array type:" + type);
+            }
+        }
+    }
+
+    @Override
+    public <T> T getValue(Type<T> type, int index) {
+        if (type.isArray()) {
+            throw new IllegalArgumentException("Nested arrows not supported");
+        }
+        if (index != 0) {
+            throw new IndexOutOfBoundsException(String.valueOf(index));
+        }
+
+        return getValue(type);
+    }
+
+    @Override
+    public long size() {
+        return value.length();
+    }
+
+    @Override
+    public long size(int index) {
+        if (index != 0) {
+            throw new IndexOutOfBoundsException(String.valueOf(index));
+        }
+        return size();
+    }
+
+    @Override
+    public long count() {
+        return 1;
+    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java Thu Oct  4 11:52:30 2012
@@ -22,6 +22,7 @@ import javax.annotation.Nonnull;
 
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
 
 /**
  * Builder interface for constructing new {@link NodeState node states}.
@@ -110,6 +111,7 @@ public interface NodeBuilder {
      * @param value
      * @return this builder
      */
+    @Deprecated
     @Nonnull
     NodeBuilder setProperty(String name, @Nonnull CoreValue value);
 
@@ -120,22 +122,51 @@ public interface NodeBuilder {
      * @param values
      * @return this builder
      */
+    @Deprecated
     @Nonnull
     NodeBuilder setProperty(String name, @Nonnull List<CoreValue> values);
 
+    @Deprecated
     @Nonnull
     NodeBuilder set(String name, String value);
 
+    @Deprecated
     @Nonnull
     NodeBuilder set(String name, String... values);
 
     /**
-     * Remove the named property. This method has no effect if a
-     * property of the given {@code name} does not exist.
+     * Set a property state
+     * @param property  The property state to set
+     * @return this builder
+     */
+    NodeBuilder setProperty(PropertyState property);
+
+    /**
+     * Set a property state
+     * @param name  The name of this property
+     * @param value  The value of this property
+     * @param <T>  The type of this property. Must be one of {@code String, Blob, byte[], Long, Integer, Double, Boolean, BigDecimal}
+     * @throws IllegalArgumentException if {@code T} is not one of the above types.
      *
      * @param name  name of the property
      * @return this builder
      */
+    <T> NodeBuilder setProperty(String name, T value);
+
+    /**
+     * Set a property state
+     * @param name  The name of this property
+     * @param value  The value of this property
+     * @param <T>  The type of this property.
+     * @return this builder
+     */
+    <T> NodeBuilder setProperty(String name, T value, Type<T> type);
+
+    /**
+    * Remove the named property. This method has no effect if a
+    * property of the given {@code name} does not exist.
+    * @param name  name of the property
+    */
     @Nonnull
     NodeBuilder removeProperty(String name);
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java?rev=1394002&r1=1394001&r2=1394002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java Thu Oct  4 11:52:30 2012
@@ -22,6 +22,7 @@ import javax.annotation.Nonnull;
 
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
 
 /**
  * A node builder that throws an {@link UnsupportedOperationException} on
@@ -84,22 +85,22 @@ public class ReadOnlyBuilder implements 
         return state.getProperty(name);
     }
 
-    @Override @Nonnull
+    @Override @Nonnull @Deprecated
     public NodeBuilder setProperty(String name, CoreValue value) {
         throw unsupported();
     }
 
-    @Override @Nonnull
+    @Override @Nonnull @Deprecated
     public NodeBuilder setProperty(String name, List<CoreValue> values) {
         throw unsupported();
     }
 
-    @Override @Nonnull
+    @Override @Nonnull @Deprecated
     public NodeBuilder set(String name, String value) {
         throw unsupported();
     }
 
-    @Override @Nonnull
+    @Override @Nonnull @Deprecated
     public NodeBuilder set(String name, String... value) {
         throw unsupported();
     }
@@ -110,6 +111,21 @@ public class ReadOnlyBuilder implements 
     }
 
     @Override
+    public NodeBuilder setProperty(PropertyState property) {
+        throw unsupported();
+    }
+
+    @Override
+    public <T> NodeBuilder setProperty(String name, T value) {
+        throw unsupported();
+    }
+
+    @Override
+    public <T> NodeBuilder setProperty(String name, T value, Type<T> type) {
+        throw unsupported();
+    }
+
+    @Override
     public ReadOnlyBuilder getChildBuilder(String name) {
         NodeState child = state.getChildNode(name);
         if (child != null) {



Mime
View raw message