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 ch...@apache.org on 2016/08/31 11:20:57 UTC

svn commit: r1758585 - in /jackrabbit/oak/trunk/oak-lucene/src: main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/ test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/

Author: chetanm
Date: Wed Aug 31 11:20:57 2016
New Revision: 1758585

URL: http://svn.apache.org/viewvc?rev=1758585&view=rev
Log:
OAK-4713 - Builder class to simplify Lucene Index Definition building

Added:
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java   (with props)
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtils.java   (with props)
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java   (with props)
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtilsTest.java   (with props)

Added: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java?rev=1758585&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java Wed Aug 31 11:20:57 2016
@@ -0,0 +1,283 @@
+/*
+ * 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.index.lucene.util;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.Node;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
+import org.apache.jackrabbit.oak.plugins.index.PathFilter;
+import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants;
+import org.apache.jackrabbit.oak.plugins.tree.TreeFactory;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import static java.util.Arrays.asList;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
+import static org.apache.jackrabbit.oak.api.Type.NAME;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+
+public final class IndexDefinitionBuilder {
+    private final NodeBuilder builder = EMPTY_NODE.builder();
+    private final Tree tree = TreeFactory.createTree(builder);
+    private final Map<String, IndexRule> rules = Maps.newHashMap();
+    private final Map<String, AggregateRule> aggRules = Maps.newHashMap();
+    private final Tree indexRule;
+    private Tree aggregatesTree;
+
+    public IndexDefinitionBuilder(){
+        tree.setProperty(LuceneIndexConstants.COMPAT_MODE, 2);
+        tree.setProperty("async", "async");
+        tree.setProperty(IndexConstants.TYPE_PROPERTY_NAME, "lucene");
+        tree.setProperty(JCR_PRIMARYTYPE, "oak:QueryIndexDefinition", NAME);
+        indexRule = createChild(tree, LuceneIndexConstants.INDEX_RULES);
+    }
+
+    public IndexDefinitionBuilder evaluatePathRestrictions(){
+        tree.setProperty(LuceneIndexConstants.EVALUATE_PATH_RESTRICTION, true);
+        return this;
+    }
+
+    public IndexDefinitionBuilder includedPaths(String ... paths){
+        tree.setProperty(PathFilter.PROP_INCLUDED_PATHS, asList(paths), STRINGS);
+        return this;
+    }
+
+    public IndexDefinitionBuilder excludedPaths(String ... paths){
+        tree.setProperty(PathFilter.PROP_EXCLUDED_PATHS, asList(paths), STRINGS);
+        return this;
+    }
+
+    public NodeState build(){
+        return builder.getNodeState();
+    }
+
+    public Tree build(Tree tree){
+        NodeStateCopyUtils.copyToTree(builder.getNodeState(), tree);
+        return tree;
+    }
+
+    public Node build(Node node) throws RepositoryException {
+        NodeStateCopyUtils.copyToNode(builder.getNodeState(), node);
+        return node;
+    }
+
+
+    //~--------------------------------------< IndexRule >
+
+    public IndexRule indexRule(String type){
+        IndexRule rule = rules.get(type);
+        if (rule == null){
+            rule = new IndexRule(createChild(indexRule, type), type);
+            rules.put(type, rule);
+        }
+        return rule;
+    }
+
+    public static class IndexRule {
+        private final Tree indexRule;
+        private final Tree propsTree;
+        private final String ruleName;
+        private final Map<String, PropertyRule> props = Maps.newHashMap();
+        private final Set<String> propNodeNames = Sets.newHashSet();
+
+        private IndexRule(Tree indexRule, String type) {
+            this.indexRule = indexRule;
+            this.propsTree = createChild(indexRule, LuceneIndexConstants.PROP_NODE);
+            this.ruleName = type;
+        }
+
+        public IndexRule indexNodeName(){
+            indexRule.setProperty(LuceneIndexConstants.INDEX_NODE_NAME, true);
+            return this;
+        }
+
+        public PropertyRule property(String name){
+            PropertyRule propRule = props.get(name);
+            if (propRule == null){
+                propRule = new PropertyRule(this, createChild(propsTree, createPropNodeName(name)), name);
+                props.put(name, propRule);
+            }
+            return propRule;
+        }
+
+        private String createPropNodeName(String name) {
+            name = getSafePropName(name);
+            if (name.isEmpty()){
+                name = "prop";
+            }
+            if (propNodeNames.contains(name)){
+                name = name + "_" + propNodeNames.size();
+            }
+            propNodeNames.add(name);
+            return name;
+        }
+
+        public String getRuleName() {
+            return ruleName;
+        }
+    }
+
+    public static class PropertyRule {
+        private final IndexRule indexRule;
+        private final Tree propTree;
+
+        private PropertyRule(IndexRule indexRule, Tree propTree, String name) {
+            this.indexRule = indexRule;
+            this.propTree = propTree;
+            propTree.setProperty(LuceneIndexConstants.PROP_NAME, name);
+        }
+
+        public PropertyRule useInExcerpt(){
+            propTree.setProperty(LuceneIndexConstants.PROP_USE_IN_EXCERPT, true);
+            return this;
+        }
+
+        public PropertyRule analyzed(){
+            propTree.setProperty(LuceneIndexConstants.PROP_ANALYZED, true);
+            return this;
+        }
+
+        public PropertyRule nodeScopeIndex(){
+            propTree.setProperty(LuceneIndexConstants.PROP_NODE_SCOPE_INDEX, true);
+            return this;
+        }
+
+        public PropertyRule ordered(){
+            propTree.setProperty(LuceneIndexConstants.PROP_ORDERED, true);
+            return this;
+        }
+
+        public PropertyRule ordered(String type){
+            //This would throw an IAE if type is invalid
+            PropertyType.valueFromName(type);
+            propTree.setProperty(LuceneIndexConstants.PROP_ORDERED, true);
+            propTree.setProperty(LuceneIndexConstants.PROP_TYPE, type);
+            return this;
+        }
+
+        public PropertyRule propertyIndex(){
+            propTree.setProperty(LuceneIndexConstants.PROP_PROPERTY_INDEX, true);
+            return this;
+        }
+
+        public PropertyRule nullCheckEnabled(){
+            propTree.setProperty(LuceneIndexConstants.PROP_NULL_CHECK_ENABLED, true);
+            return this;
+        }
+
+        public PropertyRule notNullCheckEnabled(){
+            propTree.setProperty(LuceneIndexConstants.PROP_NOT_NULL_CHECK_ENABLED, true);
+            return this;
+        }
+
+        public IndexRule enclosingRule(){
+            return indexRule;
+        }
+    }
+
+    //~--------------------------------------< Aggregates >
+
+    public AggregateRule aggregateRule(String type){
+        if (aggregatesTree == null){
+            aggregatesTree = createChild(tree, LuceneIndexConstants.AGGREGATES);
+        }
+        AggregateRule rule = aggRules.get(type);
+        if (rule == null){
+            rule = new AggregateRule(createChild(aggregatesTree, type));
+            aggRules.put(type, rule);
+        }
+        return rule;
+    }
+
+    public AggregateRule aggregateRule(String primaryType, String ... includes){
+        AggregateRule rule = aggregateRule(primaryType);
+        for (String include : includes){
+            rule.include(include);
+        }
+        return rule;
+    }
+
+    public static class AggregateRule {
+        private final Tree aggregate;
+        private final Map<String, Include> includes = Maps.newHashMap();
+
+        private AggregateRule(Tree aggregate) {
+            this.aggregate = aggregate;
+        }
+
+        public Include include(String includePath) {
+            Include include = includes.get(includePath);
+            if (include == null){
+                include = new Include(createChild(aggregate, "include" + includes.size()));
+                includes.put(includePath, include);
+            }
+            include.path(includePath);
+            return include;
+        }
+
+        public static class Include {
+            private final Tree include;
+
+            private Include(Tree include) {
+                this.include = include;
+            }
+
+            public Include path(String includePath) {
+                include.setProperty(LuceneIndexConstants.AGG_PATH, includePath);
+                return this;
+            }
+
+            public Include relativeNode(){
+                include.setProperty(LuceneIndexConstants.AGG_RELATIVE_NODE, true);
+                return this;
+            }
+        }
+    }
+
+    private static Tree createChild(Tree tree, String name){
+        Tree child = tree.addChild(name);
+        child.setOrderableChildren(true);
+        child.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME);
+        return child;
+    }
+
+    static String getSafePropName(String relativePropName) {
+        String propName = PathUtils.getName(relativePropName);
+        int indexOfColon = propName.indexOf(':');
+        if (indexOfColon > 0){
+            propName = propName.substring(indexOfColon + 1);
+        }
+
+        //Just keep ascii chars
+        propName = propName.replaceAll("\\W", "");
+        return propName;
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtils.java?rev=1758585&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtils.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtils.java Wed Aug 31 11:20:57 2016
@@ -0,0 +1,143 @@
+/*
+ * 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.index.lucene.util;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.tree.TreeFactory;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
+
+final class NodeStateCopyUtils {
+    private static final String OAK_CHILD_ORDER = ":childOrder";
+
+    public static void copyToTree(NodeState state, Tree tree){
+        tree.setOrderableChildren(state.hasProperty(OAK_CHILD_ORDER));
+        copyProps(state, tree);
+
+        Tree src = TreeFactory.createReadOnlyTree(state);
+        for (Tree srcChild : src.getChildren()){
+            String childName = srcChild.getName();
+            Tree child = tree.addChild(childName);
+            copyToTree(state.getChildNode(childName), child);
+        }
+    }
+
+    public static void copyToNode(NodeState state, Node node) throws RepositoryException {
+        copyProps(state, node);
+
+        Tree src = TreeFactory.createReadOnlyTree(state);
+        for (Tree srcChild : src.getChildren()){
+            String childName = srcChild.getName();
+            NodeState childState = state.getChildNode(childName);
+            Node child = node.addNode(childName, primaryType(childState));
+            copyToNode(childState, child);
+        }
+    }
+
+    private static void copyProps(NodeState state, Tree tree) {
+        for (PropertyState ps : state.getProperties()){
+            if (!ps.getName().equals(OAK_CHILD_ORDER)){
+                tree.setProperty(ps);
+            }
+        }
+    }
+
+    private static void copyProps(NodeState state, Node node) throws RepositoryException {
+        ValueFactory vf = node.getSession().getValueFactory();
+        for (PropertyState ps : state.getProperties()){
+            String name = ps.getName();
+            if (name.equals(JcrConstants.JCR_PRIMARYTYPE)
+                    || name.equals(OAK_CHILD_ORDER)){
+                continue;
+            }
+
+            if (name.equals(JcrConstants.JCR_MIXINTYPES)){
+                for (String n : ps.getValue(NAMES)) {
+                    node.addMixin(n);
+                }
+                continue;
+            }
+
+            if (ps.isArray()){
+                Value[] values = new Value[ps.count()];
+                for (int i = 0; i < ps.count(); i++) {
+                    values[i] = createValue(vf, ps, i);
+                }
+                node.setProperty(name, values, ps.getType().tag());
+            } else {
+                node.setProperty(name, createValue(vf, ps, -1), ps.getType().tag());
+            }
+        }
+    }
+
+    private static Value createValue(ValueFactory vf, PropertyState ps, int index) throws RepositoryException {
+        switch(ps.getType().tag()) {
+            case PropertyType.STRING :
+                return vf.createValue(getValue(ps, Type.STRING, index));
+            case PropertyType.BINARY:
+                Blob blob = getValue(ps, Type.BINARY, index);
+                Binary bin = vf.createBinary(blob.getNewStream());
+                return vf.createValue(bin);
+            case PropertyType.LONG:
+                return vf.createValue(getValue(ps, Type.LONG, index));
+            case PropertyType.DOUBLE:
+                return vf.createValue(getValue(ps, Type.DOUBLE, index));
+            case PropertyType.DATE:
+                return vf.createValue(getValue(ps, Type.DATE, index));
+            case PropertyType.BOOLEAN:
+                return vf.createValue(getValue(ps, Type.BOOLEAN, index));
+            case PropertyType.NAME:
+                return vf.createValue(getValue(ps, Type.NAME, index));
+            case PropertyType.PATH:
+                return vf.createValue(getValue(ps, Type.PATH, index));
+            case PropertyType.REFERENCE:
+                return vf.createValue(getValue(ps, Type.REFERENCE, index));
+            case PropertyType.WEAKREFERENCE:
+                return vf.createValue(getValue(ps, Type.WEAKREFERENCE, index));
+            case PropertyType.URI:
+                return vf.createValue(getValue(ps, Type.URI, index));
+            case PropertyType.DECIMAL:
+                return vf.createValue(getValue(ps, Type.DECIMAL, index));
+            default:
+                throw new IllegalStateException("Unsupported type " + ps.getType());
+        }
+    }
+
+    private static <T> T getValue(PropertyState ps, Type<T> type, int index){
+        return index < 0 ? ps.getValue(type) : ps.getValue(type, index);
+    }
+
+    private static String primaryType(NodeState state){
+        return checkNotNull(state.getName(JcrConstants.JCR_PRIMARYTYPE), "jcr:primaryType not defined for %s", state);
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java?rev=1758585&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java Wed Aug 31 11:20:57 2016
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.plugins.index.lucene.util;
+
+import java.util.Iterator;
+
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.index.PathFilter;
+import org.apache.jackrabbit.oak.plugins.tree.TreeFactory;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.junit.After;
+import org.junit.Test;
+
+import static java.util.Arrays.asList;
+import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static org.junit.Assert.*;
+
+public class IndexDefinitionBuilderTest {
+    private IndexDefinitionBuilder builder = new IndexDefinitionBuilder();
+
+    @After
+    public void dumpState(){
+        System.out.println(NodeStateUtils.toString(builder.build()));
+    }
+
+    @Test
+    public void defaultSetup() throws Exception{
+        NodeState state = builder.build();
+        assertEquals(2, state.getLong("compatVersion"));
+        assertEquals("async", state.getString("async"));
+        assertEquals("lucene", state.getString("type"));
+    }
+
+    @Test
+    public void indexRule() throws Exception{
+        builder.includedPaths("/a", "/b");
+        builder.indexRule("nt:base")
+                    .property("foo")
+                        .ordered()
+                .enclosingRule()
+                    .property("bar")
+                        .analyzed()
+                        .propertyIndex()
+                .enclosingRule()
+                    .property("baz")
+                    .propertyIndex();
+
+        NodeState state = builder.build();
+        assertTrue(state.getChildNode("indexRules").exists());
+        assertTrue(state.getChildNode("indexRules").getChildNode("nt:base").exists());
+        assertEquals(asList("/a", "/b"), state.getProperty(PathFilter.PROP_INCLUDED_PATHS).getValue(Type.STRINGS));
+    }
+
+    @Test
+    public void aggregates() throws Exception{
+        builder.aggregateRule("cq:Page").include("jcr:content").relativeNode();
+        builder.aggregateRule("dam:Asset", "*", "*/*");
+
+        NodeState state = builder.build();
+        assertTrue(state.getChildNode("aggregates").exists());
+        assertTrue(state.getChildNode("aggregates").getChildNode("dam:Asset").exists());
+        assertTrue(state.getChildNode("aggregates").getChildNode("cq:Page").exists());
+    }
+
+    @Test
+    public void duplicatePropertyName() throws Exception{
+        builder.indexRule("nt:base")
+                    .property("foo")
+                        .ordered()
+                .enclosingRule()
+                    .property("jcr:content/foo")
+                        .analyzed()
+                        .propertyIndex()
+                .enclosingRule()
+                    .property("metadata/content/foo")
+                        .propertyIndex();
+
+        NodeState state = builder.build();
+        assertTrue(state.getChildNode("indexRules").exists());
+        assertTrue(state.getChildNode("indexRules").getChildNode("nt:base").exists());
+        assertEquals(3, state.getChildNode("indexRules").getChildNode("nt:base")
+                .getChildNode("properties").getChildNodeCount(10));
+    }
+
+    @Test
+    public void ruleOrder() throws Exception{
+        builder.indexRule("nt:unstructured");
+        builder.indexRule("nt:base");
+
+        Tree tree = TreeFactory.createTree(EMPTY_NODE.builder());
+        builder.build(tree);
+
+        //Assert the order
+        Iterator<Tree> children = tree.getChild("indexRules").getChildren().iterator();
+        assertEquals("nt:unstructured", children.next().getName());
+        assertEquals("nt:base", children.next().getName());
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/IndexDefinitionBuilderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtilsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtilsTest.java?rev=1758585&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtilsTest.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtilsTest.java Wed Aug 31 11:20:57 2016
@@ -0,0 +1,179 @@
+/*
+ * 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.index.lucene.util;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Iterator;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.Session;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.jcr.Jcr;
+import org.apache.jackrabbit.oak.plugins.memory.ArrayBasedBlob;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.plugins.tree.TreeFactory;
+import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.util.ISO8601;
+import org.junit.After;
+import org.junit.Test;
+
+import static java.util.Arrays.asList;
+import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NT_OAK_UNSTRUCTURED;
+import static org.junit.Assert.*;
+
+public class NodeStateCopyUtilsTest {
+    private NodeBuilder builder = EMPTY_NODE.builder();
+    private Repository repository;
+
+    @After
+    public void cleanup(){
+        if (repository instanceof JackrabbitRepository) {
+            ((JackrabbitRepository) repository).shutdown();
+        }
+    }
+
+    @Test
+    public void copyUnordered() throws Exception{
+        builder.setProperty("foo", "x");
+        builder.child("a").setProperty("foo", "y");
+        builder.child("b").setProperty("foo", "z");
+        builder.child("a").child("c").setProperty("foo", "acx");
+
+        Tree tree = TreeFactory.createTree(EMPTY_NODE.builder());
+        NodeStateCopyUtils.copyToTree(builder.getNodeState(), tree);
+
+        assertEquals("x", tree.getProperty("foo").getValue(Type.STRING));
+        assertEquals(2, tree.getChildrenCount(100));
+        assertEquals("y", tree.getChild("a").getProperty("foo").getValue(Type.STRING));
+        assertEquals("z", tree.getChild("b").getProperty("foo").getValue(Type.STRING));
+        assertEquals("acx", tree.getChild("a").getChild("c").getProperty("foo").getValue(Type.STRING));
+    }
+
+    @Test
+    public void copyOrdered() throws Exception{
+        NodeBuilder testBuilder = EMPTY_NODE.builder();
+        Tree srcTree = TreeFactory.createTree(testBuilder);
+        srcTree.setOrderableChildren(true);
+        srcTree.setProperty("foo", "x");
+
+        srcTree.addChild("a").setOrderableChildren(true);
+        srcTree.addChild("a").setProperty("foo", "y");
+
+        srcTree.addChild("b").setOrderableChildren(true);
+        srcTree.addChild("b").setProperty("foo", "z");
+
+        Tree tree = TreeFactory.createTree(EMPTY_NODE.builder());
+        NodeStateCopyUtils.copyToTree(testBuilder.getNodeState(), tree);
+
+        assertEquals("x", tree.getProperty("foo").getValue(Type.STRING));
+        assertEquals(2, tree.getChildrenCount(100));
+        assertEquals("y", tree.getChild("a").getProperty("foo").getValue(Type.STRING));
+        assertEquals("z", tree.getChild("b").getProperty("foo").getValue(Type.STRING));
+
+        //Assert the order
+        Iterator<Tree> children = tree.getChildren().iterator();
+        assertEquals("a", children.next().getName());
+        assertEquals("b", children.next().getName());
+    }
+
+    @Test
+    public void copyToJcr() throws Exception{
+        repository = new Jcr().with(new OpenSecurityProvider()).createRepository();
+
+        Tree srcTree = TreeFactory.createTree(builder);
+        srcTree.setOrderableChildren(true);
+        srcTree.setProperty("foo", "x");
+        srcTree.setProperty("foo", "x");
+        srcTree.setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_OAK_UNSTRUCTURED, Type.NAME);
+
+        srcTree.addChild("a").setOrderableChildren(true);
+        srcTree.addChild("a").setProperty("foo", "y");
+        srcTree.addChild("a").setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_OAK_UNSTRUCTURED, Type.NAME);
+
+        srcTree.addChild("b").setOrderableChildren(true);
+        srcTree.addChild("b").setProperty("foo", "z");
+        srcTree.addChild("b").setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_OAK_UNSTRUCTURED, Type.NAME);
+
+        Session session = repository.login(null, null);
+        Node node = session.getRootNode();
+        Node test = node.addNode("test", NT_OAK_UNSTRUCTURED);
+
+        NodeStateCopyUtils.copyToNode(builder.getNodeState(), test);
+        session.save();
+
+        test = session.getNode("/test");
+        assertEquals("y", test.getProperty("a/foo").getString());
+        assertEquals("z", test.getProperty("b/foo").getString());
+    }
+
+    @Test
+    public void copyToJcrVariousProps() throws Exception{
+        repository = new Jcr().with(new OpenSecurityProvider()).createRepository();
+
+        Calendar cal = ISO8601.parse(ISO8601.format(Calendar.getInstance()));
+        Tree srcTree = TreeFactory.createTree(builder);
+        srcTree.setOrderableChildren(true);
+        srcTree.setProperty("fooString", "x");
+        srcTree.setProperty("fooLong", 1L, Type.LONG);
+        srcTree.setProperty("fooPath", "/fooNode", Type.PATH);
+        srcTree.setProperty("fooName", "mix:title", Type.NAME);
+        srcTree.setProperty("fooDouble", 1.0, Type.DOUBLE);
+        srcTree.setProperty("fooDate", ISO8601.format(cal), Type.DATE);
+        srcTree.setProperty("fooBoolean", true, Type.BOOLEAN);
+        srcTree.setProperty("fooStrings", asList("a", "b"), Type.STRINGS);
+        srcTree.setProperty("fooBlob", new ArrayBasedBlob("foo".getBytes()), Type.BINARY);
+        srcTree.setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_OAK_UNSTRUCTURED, Type.NAME);
+
+        srcTree.setProperty(JcrConstants.JCR_MIXINTYPES, asList("mix:mimeType", "mix:title"), Type.NAMES);
+
+        Session session = repository.login(null, null);
+        Node node = session.getRootNode();
+        Node test = node.addNode("test", NT_OAK_UNSTRUCTURED);
+        Node fooNode = node.addNode("fooNode", NT_OAK_UNSTRUCTURED);
+
+        NodeStateCopyUtils.copyToNode(builder.getNodeState(), test);
+        session.save();
+
+        test = session.getNode("/test");
+        assertEquals("x", test.getProperty("fooString").getString());
+        assertEquals("/fooNode", test.getProperty("fooPath").getNode().getPath());
+        assertEquals("mix:title", test.getProperty("fooName").getString());
+        assertEquals(1, test.getProperty("fooLong").getLong());
+
+        assertEquals(cal, test.getProperty("fooDate").getDate());
+        assertEquals("a", test.getProperty("fooStrings").getValues()[0].getString());
+        assertEquals("b", test.getProperty("fooStrings").getValues()[1].getString());
+
+        InputStream is = test.getProperty("fooBlob").getBinary().getStream();
+        String streamVal = IOUtils.toString(is, "UTF-8");
+        assertEquals("foo", streamVal);
+    }
+
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateCopyUtilsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native