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