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/10/10 17:15:16 UTC

svn commit: r1396640 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/api/ main/java/org/apache/jackrabbit/oak/plugins/memory/ main/java/org/apache/jackrabbit/oak/security/user/ main/java/org/apache/jackrabbit/oak/spi/state/...

Author: mduerig
Date: Wed Oct 10 15:15:15 2012
New Revision: 1396640

URL: http://svn.apache.org/viewvc?rev=1396640&view=rev
Log:
OAK-350: Unify PropertyState and CoreValue
- Add property builder

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilder.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/PropertyBuilder.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilderTest.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.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/security/user/MembershipProviderImpl.java

Modified: 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=1396640&r1=1396639&r2=1396640&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Type.java Wed Oct 10 15:15:15 2012
@@ -24,6 +24,8 @@ import javax.jcr.PropertyType;
 
 import com.google.common.base.Objects;
 
+import static com.google.common.base.Preconditions.checkState;
+
 /**
  * Instances of this class map Java types to {@link PropertyType property types}.
  * Passing an instance of this class to {@link PropertyState#getValue(Type)} determines
@@ -163,12 +165,20 @@ public final class Type<T> {
      * @throws IllegalStateException if {@code isArray} is false.
      */
     public Type<?> getBaseType() {
-        if (!isArray()) {
-            throw new IllegalStateException("Not an array: " + this);
-        }
+        checkState(isArray(), "Not an array: " + this);
         return fromTag(tag, false);
     }
 
+    /**
+     * Determine the array type which has this type as base type
+     * @return  array type with this type as base type
+     * @throws IllegalStateException if {@code isArray} is true.
+     */
+    public Type<?> getArrayType() {
+        checkState(!isArray(), "Not a simply type: " + this);
+        return fromTag(tag, true);
+    }
+
     @Override
     public String toString() {
         return isArray()

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=1396640&r1=1396639&r2=1396640&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 Wed Oct 10 15:15:15 2012
@@ -23,6 +23,7 @@ import java.util.Collections;
 import javax.annotation.Nonnull;
 import javax.jcr.PropertyType;
 
+import com.google.common.collect.Iterables;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 
@@ -110,7 +111,8 @@ abstract class EmptyPropertyState implem
                 return getValue(BINARIES).equals(that.getValue(BINARIES));
             }
             else {
-                return getValue(STRINGS).equals(that.getValue(STRINGS));
+                return Iterables.elementsEqual(
+                        getValue(STRINGS), that.getValue(STRINGS));
             }
         }
         else {

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilder.java?rev=1396640&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilder.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilder.java Wed Oct 10 15:15:15 2012
@@ -0,0 +1,221 @@
+/*
+ * 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.plugins.memory;
+
+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.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.PropertyBuilder;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+public class MemoryPropertyBuilder<T> implements PropertyBuilder<T> {
+    private final Type<T> type;
+
+    private String name;
+    private List<T> values = Lists.newArrayList();
+
+    public MemoryPropertyBuilder(Type<T> type) {
+        this.type = type;
+    }
+
+    public static <T> PropertyBuilder<T> create(Type<T> type) {
+        checkArgument(!type.isArray(), "type must not be array");
+        return new MemoryPropertyBuilder<T>(type);
+    }
+
+    public static <T> PropertyBuilder<T> create(Type<T> type, PropertyState property) {
+        checkArgument(!type.isArray(), "type must not be array");
+        return new MemoryPropertyBuilder<T>(type)
+            .assignFrom(property);
+    }
+
+    public static <T> PropertyBuilder<T> create(Type<T> type, String name) {
+        checkArgument(!type.isArray(), "type must not be array");
+        return new MemoryPropertyBuilder<T>(type)
+            .setName(name);
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public T getValue() {
+        return values.isEmpty() ? null : values.get(0);
+    }
+
+    @Nonnull
+    @Override
+    public List<T> getValues() {
+        return Lists.newArrayList(values);
+    }
+
+    @Override
+    public T getValue(int index) {
+        return values.get(index);
+    }
+
+    @Override
+    public boolean hasValue(Object value) {
+        return values.contains(value);
+    }
+
+    @Override
+    public int count() {
+        return values.size();
+    }
+
+    @Override
+    public boolean isArray() {
+        return count() != 1;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return count() == 0;
+    }
+
+    @Nonnull
+    @Override
+    public PropertyState getPropertyState() {
+        return getPropertyState(false);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Nonnull
+    @Override
+    public PropertyState getPropertyState(boolean asArray) {
+        checkState(name != null, "Property has no name");
+        if (values.isEmpty()) {
+            return PropertyStates.emptyProperty(name, type);
+        }
+        else if (isArray() || asArray) {
+            switch (type.tag()) {
+                case PropertyType.STRING:
+                    return PropertyStates.stringProperty(name, (Iterable<String>) values);
+                case PropertyType.BINARY:
+                    return PropertyStates.binaryPropertyFromBlob(name, (Iterable<Blob>) values);
+                case PropertyType.LONG:
+                    return PropertyStates.longProperty(name, (Iterable<Long>) values);
+                case PropertyType.DOUBLE:
+                    return PropertyStates.doubleProperty(name, (Iterable<Double>) values);
+                case PropertyType.BOOLEAN:
+                    return PropertyStates.booleanProperty(name, (Iterable<Boolean>) values);
+                case PropertyType.DECIMAL:
+                    return PropertyStates.decimalProperty(name, (Iterable<BigDecimal>) values);
+                default:
+                    return new GenericsPropertyState(name, (List<String>) Lists.newArrayList(values),
+                            Type.fromTag(type.tag(), true));
+            }
+        }
+        else {
+            T value = values.get(0);
+            switch (type.tag()) {
+                case PropertyType.STRING:
+                    return PropertyStates.stringProperty(name, (String) value);
+                case PropertyType.BINARY:
+                    return PropertyStates.binaryProperty(name, (Blob) value);
+                case PropertyType.LONG:
+                    return PropertyStates.longProperty(name, (Long) value);
+                case PropertyType.DOUBLE:
+                    return PropertyStates.doubleProperty(name, (Double) value);
+                case PropertyType.BOOLEAN:
+                    return PropertyStates.booleanProperty(name, (Boolean) value);
+                case PropertyType.DECIMAL:
+                    return PropertyStates.decimalProperty(name, (BigDecimal) value);
+                default:
+                    return new GenericPropertyState(name, (String) value, type);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Nonnull
+    @Override
+    public PropertyBuilder<T> assignFrom(PropertyState property) {
+        if (property != null) {
+            setName(property.getName());
+            if (property.isArray()) {
+                setValues((Iterable<T>) property.getValue(type.getArrayType()));
+            }
+            else {
+                setValue(property.getValue(type));
+            }
+        }
+        return this;
+    }
+
+    @Nonnull
+    @Override
+    public PropertyBuilder<T> setName(String name) {
+        this.name = name;
+        return this;
+    }
+
+    @Nonnull
+    @Override
+    public PropertyBuilder<T> setValue(T value) {
+        values.clear();
+        values.add(value);
+        return this;
+    }
+
+    @Nonnull
+    @Override
+    public PropertyBuilder<T> addValue(T value) {
+        values.add(value);
+        return this;
+    }
+
+    @Nonnull
+    @Override
+    public PropertyBuilder<T> setValue(T value, int index) {
+        values.set(index, value);
+        return this;
+    }
+
+    @Nonnull
+    @Override
+    public PropertyBuilder<T> setValues(Iterable<T> values) {
+        this.values = Lists.newArrayList(values);
+        return this;
+    }
+
+    @Nonnull
+    @Override
+    public PropertyBuilder<T> removeValue(int index) {
+        values.remove(index);
+        return this;
+    }
+
+    @Nonnull
+    @Override
+    public PropertyBuilder<T> removeValue(Object value) {
+        values.remove(value);
+        return this;
+    }
+}

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

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

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProviderImpl.java?rev=1396640&r1=1396639&r2=1396640&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProviderImpl.java Wed Oct 10 15:15:15 2012
@@ -29,22 +29,23 @@ import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Iterators;
-import com.google.common.collect.Lists;
 import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.plugins.memory.CoreValues;
-import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryPropertyBuilder;
 import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
 import org.apache.jackrabbit.oak.spi.security.user.MembershipProvider;
 import org.apache.jackrabbit.oak.spi.security.user.UserConfig;
+import org.apache.jackrabbit.oak.spi.state.PropertyBuilder;
 import org.apache.jackrabbit.oak.util.NodeUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static org.apache.jackrabbit.oak.api.Type.WEAKREFERENCE;
 
 /**
  * {@code MembershipProvider} implementation storing group membership information
@@ -207,21 +208,17 @@ public class MembershipProviderImpl exte
             // TODO: add implementation
             throw new UnsupportedOperationException("not implemented: addMember with member-node hierarchy");
         } else {
-            List<CoreValue> values;
-            CoreValue toAdd = createCoreValue(newMemberTree);
+            String toAdd = getContentID(newMemberTree);
             PropertyState property = groupTree.getProperty(REP_MEMBERS);
-            if (property != null) {
-                values = CoreValues.getValues(property);
-                if (values.contains(toAdd)) {
-                    return false;
-                } else {
-                    values = Lists.newArrayList(values);
-                    values.add(toAdd);
-                }
+            PropertyBuilder<String> propertyBuilder = property == null
+                ? MemoryPropertyBuilder.create(WEAKREFERENCE, REP_MEMBERS)
+                : MemoryPropertyBuilder.create(WEAKREFERENCE, property);
+            if (propertyBuilder.hasValue(toAdd)) {
+                return false;
             } else {
-                values = Collections.singletonList(toAdd);
+                propertyBuilder.addValue(toAdd);
             }
-            groupTree.setProperty(PropertyStates.createProperty(REP_MEMBERS, values));
+            groupTree.setProperty(propertyBuilder.getPropertyState(true));
         }
         return true;
     }
@@ -235,18 +232,19 @@ public class MembershipProviderImpl exte
                 throw new UnsupportedOperationException("not implemented: remove member from member-node hierarchy");
             }
         } else {
+            String toRemove = getContentID(memberTree);
             PropertyState property = groupTree.getProperty(REP_MEMBERS);
-            if (property != null) {
-                CoreValue toRemove = createCoreValue(memberTree);
-                List<CoreValue> values = CoreValues.getValues(property);
-                if (values.remove(toRemove)) {
-                    if (values.isEmpty()) {
-                        groupTree.removeProperty(REP_MEMBERS);
-                    } else {
-                        groupTree.setProperty(PropertyStates.createProperty(REP_MEMBERS, values));
-                    }
-                    return true;
+            PropertyBuilder<String> propertyBuilder = property == null
+                ? MemoryPropertyBuilder.create(WEAKREFERENCE, REP_MEMBERS)
+                : MemoryPropertyBuilder.create(WEAKREFERENCE, property);
+            if (propertyBuilder.hasValue(toRemove)) {
+                propertyBuilder.removeValue(toRemove);
+                if (propertyBuilder.isEmpty()) {
+                    groupTree.removeProperty(REP_MEMBERS);
+                } else {
+                    groupTree.setProperty(propertyBuilder.getPropertyState(true));
                 }
+                return true;
             }
         }
 
@@ -257,10 +255,6 @@ public class MembershipProviderImpl exte
 
     //-----------------------------------------< private MembershipProvider >---
 
-    private CoreValue createCoreValue(Tree authorizableTree) {
-        return valueFactory.createValue(getContentID(authorizableTree), PropertyType.WEAKREFERENCE);
-    }
-
     private boolean useMemberNode(Tree groupTree) {
         return splitSize >= 4 && !groupTree.hasProperty(REP_MEMBERS);
     }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/PropertyBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/PropertyBuilder.java?rev=1396640&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/PropertyBuilder.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/PropertyBuilder.java Wed Oct 10 15:15:15 2012
@@ -0,0 +1,171 @@
+/*
+ * 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.spi.state;
+
+import java.util.List;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+
+/**
+ * Builder interface for constructing new {@link PropertyState node states}.
+ */
+public interface PropertyBuilder<T> {
+
+    /**
+     * @return The name of the property state
+     */
+    @CheckForNull
+    String getName();
+
+    /**
+     * @return The value of the property state or {@code null} if {@code isEmpty} is {@code true}
+     */
+    @CheckForNull
+    T getValue();
+
+    /**
+     * @return  A list of values of the property state
+     */
+    @Nonnull
+    List<T> getValues();
+
+    /**
+     * @param index
+     * @return  The value of the property state at the given {@code index}.
+     * @throws IndexOutOfBoundsException  if {@code index >= count}
+     */
+    @Nonnull
+    T getValue(int index);
+
+    /**
+     * @param value
+     * @return  {@code true} iff the property state contains {@code value}.
+     */
+    boolean hasValue(Object value);
+
+    /**
+     * @return  The number of values of the property state
+     */
+    int count();
+
+    /**
+     * @return  {@code true} iff {@code count() != 1}
+     */
+    boolean isArray();
+
+    /**
+     * @return  {{@code true}} iff {@code count() == 0}
+     * @return
+     */
+    boolean isEmpty();
+
+    /**
+     * Returns an immutable property state that matches the current state of
+     * the builder. The {@code asArray} flag can be used to coerce a property
+     * state with a single value into a multi valued property state.
+     * Equivalent to {@code getPropertyState(false)}
+     *
+     * @return immutable property state
+     * @throws IllegalStateException  If the name of the property is not set
+     */
+    @Nonnull
+    PropertyState getPropertyState();
+
+    /**
+     * Returns an immutable property state that matches the current state of
+     * the builder. The {@code asArray} flag can be used to coerce a property
+     * state with a single value into a multi valued property state.
+     *
+     * @param asArray  If {@code true} the builder creates a multi valued property state
+     * @return immutable property state
+     * @throws IllegalStateException  If the name of the property is not set
+     */
+    @Nonnull
+    PropertyState getPropertyState(boolean asArray);
+
+    /**
+     * Clone {@code property} to the property state being built. After
+     * this call {@code getPropertyState(property.isArray()).equals(property)} will hold.
+     * @param property  the property to clone
+     * @return  {@code this}
+     */
+    @Nonnull
+    PropertyBuilder<T> assignFrom(PropertyState property);
+
+    /**
+     * Set the name of the property
+     * @param name
+     * @return  {@code this}
+     */
+    @Nonnull
+    PropertyBuilder<T> setName(String name);
+
+    /**
+     * Set the value of the property state clearing all previously set values.
+     * @param value  value to set
+     * @return  {@code this}
+     */
+    @Nonnull
+    PropertyBuilder<T> setValue(T value);
+
+    /**
+     * Add a value to the end of the list of values of the property state.
+     * @param value  value to add
+     * @return  {@code this}
+     */
+    @Nonnull
+    PropertyBuilder<T> addValue(T value);
+
+    /**
+     * Set the value of the property state at the given {@code index}.
+     * @param value  value to set
+     * @param index  index to set the value
+     * @return  {@code this}
+     * @throws IndexOutOfBoundsException  if {@code index >= count}
+     */
+    @Nonnull
+    PropertyBuilder<T> setValue(T value, int index);
+
+    /**
+     * Set the values of the property state clearing all previously set values.
+     * @param values
+     * @return  {@code this}
+     */
+    @Nonnull
+    PropertyBuilder<T> setValues(Iterable<T> values);
+
+    /**
+     * Remove the value at the given {@code index}
+     * @param index
+     * @return  {@code this}
+     * @throws IndexOutOfBoundsException  if {@code index >= count}
+     */
+    @Nonnull
+    PropertyBuilder<T> removeValue(int index);
+
+    /**
+     * Remove the given value from the property state
+     * @param value  value to remove
+     * @return  {@code this}
+     */
+    @Nonnull
+    PropertyBuilder<T> removeValue(Object value);
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/PropertyBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilderTest.java?rev=1396640&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilderTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryPropertyBuilderTest.java Wed Oct 10 15:15:15 2012
@@ -0,0 +1,113 @@
+/*
+ * 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.plugins.memory;
+
+import java.util.Arrays;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.PropertyBuilder;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class MemoryPropertyBuilderTest {
+
+    @Test
+    public void testStringProperty() {
+        PropertyBuilder<String> builder = MemoryPropertyBuilder.create(Type.STRING);
+        builder.setName("foo").setValue("bar");
+        assertEquals(PropertyStates.stringProperty("foo", "bar"),
+                builder.getPropertyState());
+
+        assertEquals(PropertyStates.stringProperty("foo", Arrays.asList("bar")),
+                builder.getPropertyState(true));
+    }
+
+    @Test
+    public void testLongProperty() {
+        PropertyBuilder<Long> builder = MemoryPropertyBuilder.create(Type.LONG);
+        builder.setName("foo").setValue(42L);
+        assertEquals(PropertyStates.longProperty("foo", 42L),
+                builder.getPropertyState());
+
+        assertEquals(PropertyStates.longProperty("foo", Arrays.asList(42L)),
+                builder.getPropertyState(true));
+    }
+
+    @Test
+    public void testStringsProperty() {
+        PropertyBuilder<String> builder = MemoryPropertyBuilder.create(Type.STRING);
+        builder.setName("foo")
+                .addValue("one")
+                .addValue("two");
+        assertEquals(PropertyStates.stringProperty("foo", Arrays.asList("one", "two")),
+                builder.getPropertyState());
+    }
+
+    @Test
+    public void testAssignFromLong() {
+        PropertyState source = PropertyStates.longProperty("foo", 42);
+        PropertyBuilder<String> builder = MemoryPropertyBuilder.create(Type.STRING);
+        builder.assignFrom(source);
+        assertEquals(PropertyStates.stringProperty("foo", "42"),
+                builder.getPropertyState());
+    }
+
+    @Test
+    public void testAssignFromString() {
+        PropertyState source = PropertyStates.stringProperty("foo", "42");
+        PropertyBuilder<Long> builder = MemoryPropertyBuilder.create(Type.LONG);
+        builder.assignFrom(source);
+        assertEquals(PropertyStates.longProperty("foo", 42),
+                builder.getPropertyState());
+    }
+
+    @Test(expected = NumberFormatException.class)
+    public void testAssignFromStringNumberFormatException() {
+        PropertyState source = PropertyStates.stringProperty("foo", "bar");
+        PropertyBuilder<Long> builder = MemoryPropertyBuilder.create(Type.LONG);
+        builder.assignFrom(source);
+    }
+
+    @Test
+    public void testAssignFromLongs() {
+        PropertyState source = PropertyStates.longProperty("foo", Arrays.asList(1L, 2L, 3L));
+        PropertyBuilder<String> builder = MemoryPropertyBuilder.create(Type.STRING);
+        builder.assignFrom(source);
+        assertEquals(PropertyStates.stringProperty("foo", Arrays.asList("1", "2", "3")),
+                builder.getPropertyState());
+    }
+
+    @Test
+    public void testAssignFromStrings() {
+        PropertyState source = PropertyStates.stringProperty("foo", Arrays.asList("1", "2", "3"));
+        PropertyBuilder<Long> builder = MemoryPropertyBuilder.create(Type.LONG);
+        builder.assignFrom(source);
+        assertEquals(PropertyStates.longProperty("foo", Arrays.asList(1L, 2L, 3L)),
+                builder.getPropertyState());
+    }
+
+    @Test
+    public void testAssignInvariant() {
+        PropertyState source = PropertyStates.stringProperty("source", Arrays.asList("1", "2", "3"));
+        PropertyBuilder<String> builder = MemoryPropertyBuilder.create(Type.STRING);
+        builder.assignFrom(source);
+        assertEquals(source, builder.getPropertyState(true));
+    }
+
+}

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

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