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 md...@apache.org on 2012/03/23 00:22:38 UTC

svn commit: r1304130 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/ oak-core/src/main/java/org/apache/jackrabbit/oak/api/ oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/ oak-jcr/src/main/java/org/apache/jackrabbit/oa...

Author: mduerig
Date: Thu Mar 22 23:22:37 2012
New Revision: 1304130

URL: http://svn.apache.org/viewvc?rev=1304130&view=rev
Log:
OAK-33: Values in oak-core (WIP)
initial implementation of Scalar

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/ScalarImpl.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Scalar.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelPropertyState.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/ChangeTree.java

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/ScalarImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/ScalarImpl.java?rev=1304130&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/ScalarImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/ScalarImpl.java Thu Mar 22 23:22:37 2012
@@ -0,0 +1,314 @@
+package org.apache.jackrabbit;
+
+import org.apache.jackrabbit.oak.api.Scalar;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.concurrent.Callable;
+
+public abstract class ScalarImpl implements Scalar {
+    private final int type;
+
+    public static Scalar createNumber(String value) {
+        // todo improve
+        try {
+            return createLong(Long.parseLong(value));
+        }
+        catch (NumberFormatException e) {
+            return createDouble(Double.parseDouble(value));
+        }
+    }
+
+    public static Scalar createBoolean(final boolean value) {
+        return value ? TRUE_SCALAR : FALSE_SCALAR;
+    }
+    
+    public static Scalar createLong(final long value) {
+        return new LongScalar(value);
+    }
+    
+    public static Scalar createDouble(final double value) {
+        return new DoubleScalar(value);
+    }
+    
+    public static Scalar createString(final String value) {
+        if (value == null) {
+            throw new IllegalArgumentException("Value must not be null");
+        }
+        return new StringScalar(value);
+    }
+    
+    public static Scalar createBinary(final String value) {
+        if (value == null) {
+            throw new IllegalArgumentException("Value must not be null");
+        }
+        return new SmallBinaryScalar(value);
+    }
+    
+    public static Scalar createBinary(final Callable<InputStream> valueProvider) {
+        if (valueProvider == null) {
+            throw new IllegalArgumentException("Value must not be null");
+        }
+        return new BinaryScalar(valueProvider);
+    }
+
+    protected ScalarImpl(int type) {
+        this.type = type;
+    }
+
+    @Override
+    public int getType() {
+        return type;   
+    }
+
+    @Override
+    public boolean getBoolean() {
+        return Boolean.valueOf(getString());
+    }
+
+    @Override
+    public long getLong() {
+        return Long.parseLong(getString());
+    }
+
+    @Override
+    public double getDouble() {
+        return Double.parseDouble(getString());
+    }
+
+    @Override
+    public InputStream getInputStream() {
+        try {
+            return new ByteArrayInputStream(getString().getBytes("UTF-8"));
+        }
+        catch (UnsupportedEncodingException e) {
+            // todo handle UnsupportedEncodingException
+            return null;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return getString() + ": " + Scalar.typeNames[type];
+    }
+
+    //------------------------------------------------------------< private >---
+
+    private static final BooleanScalar TRUE_SCALAR = new BooleanScalar(true);
+    private static final BooleanScalar FALSE_SCALAR = new BooleanScalar(false);
+
+    private static final class BooleanScalar extends ScalarImpl {
+        private final boolean value;
+
+        public BooleanScalar(boolean value) {
+            super(Scalar.BOOLEAN);
+            this.value = value;
+        }
+
+        @Override
+        public boolean getBoolean() {
+            return value;
+        }
+
+        @Override
+        public String getString() {
+            return Boolean.toString(value);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (other == null || getClass() != other.getClass()) {
+                return false;
+            }
+
+            return value == ((BooleanScalar) other).value;
+        }
+
+        @Override
+        public int hashCode() {
+            return (value ? 1 : 0);
+        }
+    }
+
+    private static final class LongScalar extends ScalarImpl {
+        private final long value;
+
+        public LongScalar(long value) {
+            super(Scalar.LONG);
+            this.value = value;
+        }
+
+        @Override
+        public long getLong() {
+            return value;
+        }
+
+        @Override
+        public String getString() {
+            return Long.toString(value);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (other == null || getClass() != other.getClass()) {
+                return false;
+            }
+
+            return value == ((LongScalar) other).value;
+        }
+
+        @Override
+        public int hashCode() {
+            return (int) (value ^ (value >>> 32));
+        }
+    }
+
+    private static final class DoubleScalar extends ScalarImpl {
+        private final double value;
+
+        public DoubleScalar(double value) {
+            super(Scalar.DOUBLE);
+            this.value = value;
+        }
+
+        @Override
+        public double getDouble() {
+            return value;
+        }
+
+        @Override
+        public String getString() {
+            return Double.toString(value);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (other == null || getClass() != other.getClass()) {
+                return false;
+            }
+
+            return Double.compare(((DoubleScalar) other).value, value) == 0;
+
+        }
+
+        @Override
+        public int hashCode() {
+            long h = value != 0.0d ? Double.doubleToLongBits(value) : 0L;
+            return (int) (h ^ (h >>> 32));
+        }
+    }
+
+    private static final class StringScalar extends ScalarImpl {
+        private final String value;
+
+        public StringScalar(String value) {
+            super(Scalar.STRING);
+            this.value = value;
+        }
+
+        @Override
+        public String getString() {
+            return value;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            return value.equals(((StringScalar) o).value);
+        }
+
+        @Override
+        public int hashCode() {
+            return value.hashCode();
+        }
+    }
+
+    private static final class SmallBinaryScalar extends ScalarImpl {
+        private final String value;
+
+        public SmallBinaryScalar(String value) {
+            super(Scalar.BINARY);
+            this.value = value;
+        }
+
+        @Override
+        public String getString() {
+            return value;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (other == null || getClass() != other.getClass()) {
+                return false;
+            }
+
+            return value.equals(((SmallBinaryScalar) other).value);
+        }
+
+        @Override
+        public int hashCode() {
+            return value.hashCode();
+        }
+    }
+
+    private static class BinaryScalar extends ScalarImpl {
+        private final Callable<InputStream> valueProvider;
+
+        public BinaryScalar(Callable<InputStream> valueProvider) {
+            super(Scalar.BINARY);
+            this.valueProvider = valueProvider;
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            try {
+                return valueProvider.call();
+            }
+            catch (Exception e) {
+                // todo handle Exception
+                return null;
+            }
+        }
+
+        @Override
+        public String getString() {
+            return ""; // todo implement getString
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (other == null || getClass() != other.getClass()) {
+                return false;
+            }
+
+            return getString().equals(((BinaryScalar) other).getString());
+        }
+
+        @Override
+        public int hashCode() {
+            return getString().hashCode();
+        }
+    }
+}

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Scalar.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Scalar.java?rev=1304130&r1=1304129&r2=1304130&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Scalar.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Scalar.java Thu Mar 22 23:22:37 2012
@@ -22,6 +22,13 @@ import java.io.InputStream;
  * An immutable, typed scalar value.
  */
 public interface Scalar {
+    int BOOLEAN = 0;
+    int LONG = 1;
+    int DOUBLE = 2;
+    int BINARY = 3;
+    int STRING = 4;
+    
+    String[] typeNames = {"boolean", "long", "double", "binary", "string"};
 
     /**
      * Returns the value type.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java?rev=1304130&r1=1304129&r2=1304130&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java Thu Mar 22 23:22:37 2012
@@ -18,6 +18,7 @@
  */
 package org.apache.jackrabbit.oak.kernel;
 
+import org.apache.jackrabbit.ScalarImpl;
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.api.MicroKernelException;
 import org.apache.jackrabbit.mk.json.JsopReader;
@@ -26,6 +27,7 @@ import org.apache.jackrabbit.mk.model.Ab
 import org.apache.jackrabbit.mk.model.ChildNodeEntry;
 import org.apache.jackrabbit.mk.model.NodeState;
 import org.apache.jackrabbit.mk.model.PropertyState;
+import org.apache.jackrabbit.oak.api.Scalar;
 
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -87,16 +89,16 @@ public class KernelNodeState extends Abs
                             kernel, childPath, revision));
                 } else if (reader.matches(JsopTokenizer.NUMBER)) {
                     properties.put(name, new KernelPropertyState(
-                            name, reader.getToken()));
+                            name, ScalarImpl.createNumber(reader.getToken())));
                 } else if (reader.matches(JsopTokenizer.STRING)) {
                     properties.put(name, new KernelPropertyState(
-                            name, '"' + reader.getToken() + '"'));
+                            name, ScalarImpl.createString(reader.getToken())));
                 } else if (reader.matches(JsopTokenizer.TRUE)) {
                     properties.put(name, new KernelPropertyState(
-                            name, "true"));
+                            name, ScalarImpl.createBoolean(true)));
                 } else if (reader.matches(JsopTokenizer.FALSE)) {
                     properties.put(name, new KernelPropertyState(
-                            name, "false"));
+                            name, ScalarImpl.createBoolean(false)));
                 } else if (reader.matches('[')) {
                     properties.put(name, new KernelPropertyState(
                             name, readArray(reader)));
@@ -212,30 +214,23 @@ public class KernelNodeState extends Abs
         }
     }
 
-    private static String readArray(JsopReader reader) {
-        StringBuilder sb = new StringBuilder("[");
-        String sep = "";
+    private static List<Scalar> readArray(JsopReader reader) {
+        List<Scalar> values = new ArrayList<Scalar>();
         while (!reader.matches(']')) {
-            String v;
             if (reader.matches(JsopTokenizer.NUMBER)) {
-                v = reader.getToken();
+                values.add(ScalarImpl.createNumber(reader.getToken()));
             } else if (reader.matches(JsopTokenizer.STRING)) {
-                v = '"' + reader.getToken() + '"';
-            }
-            else if (reader.matches(JsopTokenizer.TRUE)) {
-                v = "true";
+                values.add(ScalarImpl.createString(reader.getToken()));
+            } else if (reader.matches(JsopTokenizer.TRUE)) {
+                values.add(ScalarImpl.createBoolean(true));
             } else if (reader.matches(JsopTokenizer.FALSE)) {
-                v = "false";
+                values.add(ScalarImpl.createBoolean(false));
             } else {
                 throw new IllegalArgumentException("Unexpected token: " + reader.getToken());
             }
-            sb.append(sep);
-            sep = ",";
-            sb.append(v);
             reader.matches(',');
         }
-        sb.append(']');
-        return sb.toString();
+        return values;
     }
 
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelPropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelPropertyState.java?rev=1304130&r1=1304129&r2=1304130&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelPropertyState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelPropertyState.java Thu Mar 22 23:22:37 2012
@@ -19,16 +19,27 @@
 package org.apache.jackrabbit.oak.kernel;
 
 import org.apache.jackrabbit.mk.model.AbstractPropertyState;
+import org.apache.jackrabbit.oak.api.Scalar;
+
+import java.util.Collections;
+import java.util.List;
 
 public class KernelPropertyState extends AbstractPropertyState { // fixme make package private
 
     private final String name;
+    private final Scalar value;
+    private final List<Scalar> values;
 
-    private final String value;
-
-    public KernelPropertyState(String name, String value) {
+    public KernelPropertyState(String name, Scalar value) {
         this.name = name;
         this.value = value;
+        this.values = null;
+    }
+
+    public KernelPropertyState(String name, List<Scalar> values) {
+        this.name = name;
+        this.value = null;
+        this.values = Collections.unmodifiableList(values);
     }
 
     @Override
@@ -38,7 +49,41 @@ public class KernelPropertyState extends
 
     @Override
     public String getEncodedValue() {
-        return value;
+        if (value == null) {
+            String sep = "";
+            StringBuilder sb = new StringBuilder("[");
+            for (Scalar s : values) {
+                sb.append(sep);
+                sep = ",";
+                if (s.getType() == Scalar.STRING) {
+                    sb.append('"' + s.getString() + '"');
+                }
+                else {
+                    sb.append(s.getString());
+                }
+            }
+            sb.append(']');
+            return sb.toString();
+        }
+        else {
+            if (value.getType() == Scalar.STRING) {
+                return '"' + value.getString() + '"';
+            }
+            else {
+                return value.getString();
+            }
+        }
     }
 
+    public boolean isMultiValues() {
+        return value == null;
+    }
+    
+    public Scalar getValue() {
+        return value;
+    }
+    
+    public List<Scalar> getValues() {
+        return values;
+    }
 }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/ChangeTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/ChangeTree.java?rev=1304130&r1=1304129&r2=1304130&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/ChangeTree.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/state/ChangeTree.java Thu Mar 22 23:22:37 2012
@@ -28,7 +28,6 @@ import org.apache.jackrabbit.oak.jcr.uti
 import org.apache.jackrabbit.oak.jcr.util.Iterators;
 import org.apache.jackrabbit.oak.jcr.util.Path;
 import org.apache.jackrabbit.oak.jcr.util.Predicate;
-import org.apache.jackrabbit.oak.kernel.KernelPropertyState;
 
 import javax.jcr.ItemExistsException;
 import javax.jcr.ItemNotFoundException;
@@ -273,7 +272,17 @@ public class ChangeTree {
                     new Function1<Entry<String, JsonValue>, PropertyState>() {
                         @Override
                         public PropertyState apply(final Entry<String, JsonValue> entry) {
-                            return new KernelPropertyState(entry.getKey(), entry.getValue().toJson());
+                            return new PropertyState() {
+                                @Override
+                                public String getName() {
+                                    return entry.getKey();
+                                }
+
+                                @Override
+                                public String getEncodedValue() {
+                                    return entry.getValue().toJson();
+                                }
+                            };
                         }
                     });
         }