Author: chetanm
Date: Wed Oct 19 15:05:36 2016
New Revision: 1765614

URL: http://svn.apache.org/viewvc?rev=1765614&view=rev
Log:
OAK-1312 -  [bundling] Bundle nodes into a document

Initial implementation of bundling with only write side implemented so far.

Added:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistry.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandler.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRoot.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlor.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/Include.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistryTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandlerTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRootTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlingTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlorTest.java
   (with props)
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/IncludeTest.java
   (with props)
Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java?rev=1765614&r1=1765613&r2=1765614&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java
 Wed Oct 19 15:05:36 2016
@@ -21,9 +21,9 @@ import javax.annotation.Nonnull;
 import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.json.BlobSerializer;
 import org.apache.jackrabbit.oak.json.JsonSerializer;
+import org.apache.jackrabbit.oak.plugins.document.bundlor.BundlingHandler;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
 
@@ -41,23 +41,23 @@ class CommitDiff implements NodeStateDif
 
     private final Commit commit;
 
-    private final String path;
-
     private final JsopBuilder builder;
 
     private final BlobSerializer blobs;
 
+    private final BundlingHandler bundlingHandler;
+
     CommitDiff(@Nonnull DocumentNodeStore store, @Nonnull Commit commit,
                @Nonnull BlobSerializer blobs) {
-        this(checkNotNull(store), checkNotNull(commit), "/",
+        this(checkNotNull(store), checkNotNull(commit), 
store.getBundlingRoot(),
                 new JsopBuilder(), checkNotNull(blobs));
     }
 
-    private CommitDiff(DocumentNodeStore store, Commit commit, String path,
+    private CommitDiff(DocumentNodeStore store, Commit commit, BundlingHandler 
bundlingHandler,
                JsopBuilder builder, BlobSerializer blobs) {
         this.store = store;
         this.commit = commit;
-        this.path = path;
+        this.bundlingHandler = bundlingHandler;
         this.builder = builder;
         this.blobs = blobs;
     }
@@ -76,34 +76,42 @@ class CommitDiff implements NodeStateDif
 
     @Override
     public boolean propertyDeleted(PropertyState before) {
-        commit.updateProperty(path, before.getName(), null);
+        commit.updateProperty(bundlingHandler.getRootBundlePath(), 
bundlingHandler.getPropertyPath(before.getName()), null);
         return true;
     }
 
     @Override
     public boolean childNodeAdded(String name, NodeState after) {
-        String p = PathUtils.concat(path, name);
-        commit.addNode(new DocumentNodeState(store, p,
-                new RevisionVector(commit.getRevision())));
+        BundlingHandler child = bundlingHandler.childHandler(name, after);
+        if (child.isBundlingRoot()) {
+            //TODO Seed in the bundling pattern
+            //TODO Handle case for leaf node optimization
+            commit.addNode(new DocumentNodeState(store, 
child.getRootBundlePath(),
+                    new RevisionVector(commit.getRevision())));
+        }
         return after.compareAgainstBaseState(EMPTY_NODE,
-                new CommitDiff(store, commit, p, builder, blobs));
+                new CommitDiff(store, commit, child, builder, blobs));
     }
 
     @Override
     public boolean childNodeChanged(String name,
                                     NodeState before,
                                     NodeState after) {
-        String p = PathUtils.concat(path, name);
+        //TODO [bundling] Handle change of primaryType
+        BundlingHandler child = bundlingHandler.childHandler(name, after);
         return after.compareAgainstBaseState(before,
-                new CommitDiff(store, commit, p, builder, blobs));
+                new CommitDiff(store, commit, child, builder, blobs));
     }
 
     @Override
     public boolean childNodeDeleted(String name, NodeState before) {
-        String p = PathUtils.concat(path, name);
-        commit.removeNode(p, before);
+        BundlingHandler child = bundlingHandler.childHandler(name, before);
+        if (child.isBundlingRoot()) {
+            //TODO [bundling] Handle delete
+            commit.removeNode(child.getRootBundlePath(), before);
+        }
         return MISSING_NODE.compareAgainstBaseState(before,
-                new CommitDiff(store, commit, p, builder, blobs));
+                new CommitDiff(store, commit, child, builder, blobs));
     }
 
     //----------------------------< internal 
>----------------------------------
@@ -112,10 +120,11 @@ class CommitDiff implements NodeStateDif
         builder.resetWriter();
         JsonSerializer serializer = new JsonSerializer(builder, blobs);
         serializer.serialize(property);
-        commit.updateProperty(path, property.getName(), serializer.toString());
+        commit.updateProperty(bundlingHandler.getRootBundlePath(), 
bundlingHandler.getPropertyPath(property.getName()),
+                 serializer.toString());
         if ((property.getType() == Type.BINARY)
                 || (property.getType() == Type.BINARIES)) {
-            this.commit.markNodeHavingBinary(this.path);
+            
this.commit.markNodeHavingBinary(bundlingHandler.getRootBundlePath());
         }
     }
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1765614&r1=1765613&r2=1765614&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
 Wed Oct 19 15:05:36 2016
@@ -85,6 +85,8 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector;
 import org.apache.jackrabbit.oak.plugins.blob.ReferencedBlob;
 import org.apache.jackrabbit.oak.plugins.document.Branch.BranchCommit;
+import org.apache.jackrabbit.oak.plugins.document.bundlor.BundledTypesRegistry;
+import org.apache.jackrabbit.oak.plugins.document.bundlor.BundlingHandler;
 import 
org.apache.jackrabbit.oak.plugins.document.persistentCache.PersistentCache;
 import 
org.apache.jackrabbit.oak.plugins.document.persistentCache.broadcast.DynamicBroadcastConfig;
 import 
org.apache.jackrabbit.oak.plugins.document.util.ReadOnlyDocumentStoreWrapperFactory;
@@ -112,6 +114,7 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.apache.jackrabbit.oak.stats.Clock;
 import org.apache.jackrabbit.oak.stats.StatisticsProvider;
@@ -1107,6 +1110,12 @@ public final class DocumentNodeStore
         return result;
     }
 
+    public BundlingHandler getBundlingRoot() {
+        //TODO Move this to observor based
+        NodeState registryState = NodeStateUtils.getNode(getRoot(), 
"/jcr:system/documentstore/bundlor");
+        return new BundlingHandler(BundledTypesRegistry.from(registryState));
+    }
+
     /**
      * Apply the changes of a node to the cache.
      *

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistry.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistry.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistry.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistry.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,148 @@
+/*
+ * 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.document.bundlor;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.CheckForNull;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static 
org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
+
+public class BundledTypesRegistry {
+    private final Map<String, DocumentBundlor> bundlors;
+
+    public BundledTypesRegistry(Map<String, DocumentBundlor> bundlors) {
+        this.bundlors = ImmutableMap.copyOf(bundlors);
+    }
+
+    public static BundledTypesRegistry from(NodeState configParentState){
+        Map<String, DocumentBundlor> bundlors = Maps.newHashMap();
+        for (ChildNodeEntry e : configParentState.getChildNodeEntries()){
+            bundlors.put(e.getName(), DocumentBundlor.from(e.getNodeState()));
+        }
+        return new BundledTypesRegistry(bundlors);
+    }
+
+    @CheckForNull
+    public DocumentBundlor getBundlor(NodeState state) {
+        //Prefer mixin (as they are more specific) over primaryType
+        for (String mixin : getMixinNames(state)){
+            DocumentBundlor bundlor = bundlors.get(mixin);
+            if (bundlor != null){
+                return bundlor;
+            }
+        }
+        return bundlors.get(getPrimaryTypeName(state));
+    }
+
+    private static String getPrimaryTypeName(NodeState nodeState) {
+        PropertyState ps = nodeState.getProperty(JcrConstants.JCR_PRIMARYTYPE);
+        return (ps == null) ? JcrConstants.NT_BASE : ps.getValue(Type.NAME);
+    }
+
+    private static Iterable<String> getMixinNames(NodeState nodeState) {
+        PropertyState ps = nodeState.getProperty(JcrConstants.JCR_MIXINTYPES);
+        return (ps == null) ? Collections.<String>emptyList() : 
ps.getValue(Type.NAMES);
+    }
+
+    //~--------------------------------------------< Builder >
+
+    public static BundledTypesRegistryBuilder builder(){
+        return new BundledTypesRegistryBuilder(EMPTY_NODE.builder());
+    }
+
+    public static class BundledTypesRegistryBuilder {
+        private final NodeBuilder builder;
+
+        public BundledTypesRegistryBuilder(NodeBuilder builder) {
+            this.builder = builder;
+        }
+
+        public TypeBuilder forType(String typeName){
+            return new TypeBuilder(this, builder.child(typeName));
+        }
+
+        public TypeBuilder forType(String typeName, String ... includes){
+            TypeBuilder typeBuilder = forType(typeName);
+            for (String include : includes){
+                typeBuilder.include(include);
+            }
+            return typeBuilder;
+        }
+
+        public BundledTypesRegistry buildRegistry() {
+            return BundledTypesRegistry.from(builder.getNodeState());
+        }
+
+        public NodeState build(){
+            return builder.getNodeState();
+        }
+
+        public static class TypeBuilder {
+            private final BundledTypesRegistryBuilder parent;
+            private final NodeBuilder typeBuilder;
+            private final Set<String> patterns = Sets.newHashSet();
+
+            private TypeBuilder(BundledTypesRegistryBuilder parent, 
NodeBuilder typeBuilder) {
+                this.parent = parent;
+                this.typeBuilder = typeBuilder;
+            }
+
+            public TypeBuilder include(String pattern){
+                patterns.add(pattern);
+                return this;
+            }
+
+            public BundledTypesRegistry buildRegistry(){
+                setupPatternProp();
+                return parent.buildRegistry();
+            }
+
+            public BundledTypesRegistryBuilder registry(){
+                setupPatternProp();
+                return parent;
+            }
+
+            public NodeState build(){
+                setupPatternProp();
+                return parent.build();
+            }
+
+            private void setupPatternProp() {
+                
typeBuilder.setProperty(createProperty(DocumentBundlor.PROP_PATTERN, patterns, 
STRINGS));
+            }
+        }
+    }
+
+}

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

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandler.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandler.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandler.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandler.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,66 @@
+/*
+ * 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.document.bundlor;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import static org.apache.jackrabbit.oak.commons.PathUtils.ROOT_PATH;
+
+public class BundlingHandler {
+    private final BundledTypesRegistry registry;
+    private final String path;
+    private final BundlingRoot root;
+
+    public BundlingHandler(BundledTypesRegistry registry) {
+        this(registry, new BundlingRoot(), ROOT_PATH);
+    }
+
+    private BundlingHandler(BundledTypesRegistry registry, BundlingRoot root, 
String path) {
+        this.registry = registry;
+        this.path = path;
+        this.root = root;
+    }
+
+    public String getPropertyPath(String propertyName) {
+        return root.getPropertyPath(path, propertyName);
+    }
+
+    public String getRootBundlePath() {
+        return root.bundlingEnabled() ? root.getPath() : path;
+    }
+
+    public BundlingHandler childHandler(String name, NodeState state) {
+        String childPath = PathUtils.concat(path, name);
+        if (root.isBundled(childPath)) {
+            return new BundlingHandler(registry, root, childPath);
+        }
+
+        //TODO For only add we should lookup (fully new add) we should lookup 
new bundlor
+        //For update and delete we should always rely on existing bundlor 
config
+        //TODO Check for pattern from state first
+        DocumentBundlor bundlor = registry.getBundlor(state);
+        return new BundlingHandler(registry, new BundlingRoot(childPath, 
bundlor), childPath);
+    }
+
+    public boolean isBundlingRoot() {
+        return root.getPath().equals(path);
+    }
+}

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

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRoot.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRoot.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRoot.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRoot.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,64 @@
+/*
+ * 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.document.bundlor;
+
+import javax.annotation.Nullable;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
+
+import static org.apache.jackrabbit.oak.commons.PathUtils.ROOT_PATH;
+
+class BundlingRoot {
+    private final String rootPath;
+    private final DocumentBundlor documentBundlor;
+
+    public BundlingRoot() {
+        this(ROOT_PATH, null);
+    }
+
+    public BundlingRoot(String rootPath, @Nullable DocumentBundlor 
documentBundlor) {
+        this.rootPath = rootPath;
+        this.documentBundlor = documentBundlor;
+    }
+
+    public boolean bundlingEnabled(){
+        return documentBundlor != null;
+    }
+
+    public String getPropertyPath(String path, String propertyName) {
+        if (isBundled(path)){
+            return PathUtils.concat(relativePath(path), propertyName);
+        }
+        //TODO Assert that in non bundling case path is of depth 1
+        return propertyName;
+    }
+
+    public boolean isBundled(String childPath) {
+        return bundlingEnabled() && 
documentBundlor.isBundled(relativePath(childPath));
+    }
+
+    public String getPath() {
+        return rootPath;
+    }
+
+    private String relativePath(String nodePath){
+        return PathUtils.relativize(rootPath, nodePath);
+    }
+}

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

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlor.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlor.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlor.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlor.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,65 @@
+/*
+ * 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.document.bundlor;
+
+import java.util.List;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+public class DocumentBundlor {
+    public static final String PROP_PATTERN = "pattern";
+    private final List<Include> includes;
+
+    public DocumentBundlor(List<Include> includes) {
+        //TODO Have assertion for that all intermediate paths are included
+        this.includes = ImmutableList.copyOf(includes);
+    }
+
+    public static DocumentBundlor from(NodeState nodeState){
+        Preconditions.checkArgument(nodeState.hasProperty(PROP_PATTERN), 
"NodeStated [%s] does not have required " +
+                "property [%s]", nodeState, PROP_PATTERN);
+       return DocumentBundlor.from(nodeState.getStrings(PROP_PATTERN));
+    }
+
+    public static DocumentBundlor from(Iterable<String> includeStrings){
+        List<Include> includes = Lists.newArrayList();
+        for (String i : includeStrings){
+            includes.add(new Include(i));
+        }
+        return new DocumentBundlor(includes);
+    }
+
+    public boolean isBundled(String relativePath) {
+        for (Include include : includes){
+            if (include.match(relativePath)){
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return includes.toString();
+    }
+}

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

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/Include.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/Include.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/Include.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/Include.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,105 @@
+/*
+ * 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.document.bundlor;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+
+/**
+ * Include represents a single path pattern which captures the path which
+ * needs to be included in bundling. Path patterns can be like below.
+ * <ul>
+ *     <li>* - Match any immediate child</li>
+ *     <li>*\/* - Match child with any name upto 2 levels of depth</li>
+ *     <li>jcr:content - Match immediate child with name jcr:content</li>
+ *     <li>jcr:content\/*;all - Match jcr:content and all its child</li>
+ * </ul>
+ *
+ * The last path element can specify a directive. Supported directive
+ * <ul>
+ *     <li>all - Include all nodes under given path</li>
+ * </ul>
+ */
+public class Include {
+    enum Directive {ALL, NONE}
+    private final String[] elements;
+    private final Directive directive;
+
+    public Include(String pattern){
+        List<String> pathElements = 
ImmutableList.copyOf(PathUtils.elements(pattern));
+        List<String> elementList = 
Lists.newArrayListWithCapacity(pathElements.size());
+        Directive directive = Directive.NONE;
+        for (int i = 0; i < pathElements.size(); i++) {
+            String e = pathElements.get(i);
+            int indexOfColon = e.indexOf(";");
+            if (indexOfColon > 0){
+                directive = Directive.valueOf(e.substring(indexOfColon + 
1).toUpperCase());
+                e = e.substring(0, indexOfColon);
+            }
+            elementList.add(e);
+
+            if (directive != Directive.NONE && i < pathElements.size() - 1){
+                throw new IllegalArgumentException("Directive can only be 
specified for last path segment ["+pattern+"]");
+            }
+        }
+
+        this.elements = elementList.toArray(new String[0]);
+        this.directive = directive;
+    }
+
+    public boolean match(String relativePath) {
+        int targetDepth = 0;
+        for (String e : PathUtils.elements(relativePath)){
+            if (targetDepth == elements.length){
+                //TODO exception when leaf but have extra elements
+                if (directive == Directive.ALL){
+                    return true;
+                }
+                return false;
+            }
+
+            String pe = elements[targetDepth++];
+            if ("*".equals(pe) || pe.equals(e)){
+                continue;
+            }
+
+            return false;
+        }
+
+        //Number of elements in target < pattern then match not possible
+        if (targetDepth < elements.length){
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(%s)", Arrays.toString(elements), directive);
+    }
+
+    Directive getDirective() {
+        return directive;
+    }
+}

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

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistryTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistryTest.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistryTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledTypesRegistryTest.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,95 @@
+/*
+ * 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.document.bundlor;
+
+import java.util.Collections;
+
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.junit.Test;
+
+import static java.util.Arrays.asList;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static 
org.apache.jackrabbit.oak.plugins.document.bundlor.DocumentBundlor.PROP_PATTERN;
+import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static 
org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
+import static org.junit.Assert.*;
+
+public class BundledTypesRegistryTest {
+
+    private NodeBuilder builder = EMPTY_NODE.builder();
+
+    @Test
+    public void basicSetup() throws Exception{
+        builder.child("nt:file").setProperty(createProperty(PROP_PATTERN, 
asList("jcr:content"), STRINGS));
+        BundledTypesRegistry registry = 
BundledTypesRegistry.from(builder.getNodeState());
+
+        assertNull(registry.getBundlor(EMPTY_NODE));
+        assertNotNull(registry.getBundlor(newNode("nt:file", false)));
+        assertNull(registry.getBundlor(newNode("nt:resource", false)));
+
+        DocumentBundlor bundlor = registry.getBundlor(newNode("nt:file", 
false));
+        assertTrue(bundlor.isBundled("jcr:content"));
+        assertFalse(bundlor.isBundled("foo"));
+    }
+
+    @Test
+    public void mixin() throws Exception{
+        builder.child("mix:foo").setProperty(createProperty(PROP_PATTERN, 
asList("jcr:content"), STRINGS));
+        BundledTypesRegistry registry = 
BundledTypesRegistry.from(builder.getNodeState());
+        assertNotNull(registry.getBundlor(newNode("mix:foo", true)));
+    }
+
+    @Test
+    public void mixinOverPrimaryType() throws Exception{
+        builder.child("mix:foo").setProperty(createProperty(PROP_PATTERN, 
asList("foo"), STRINGS));
+        builder.child("nt:file").setProperty(createProperty(PROP_PATTERN, 
asList("jcr:content"), STRINGS));
+        BundledTypesRegistry registry = 
BundledTypesRegistry.from(builder.getNodeState());
+
+        NodeBuilder b2 = EMPTY_NODE.builder();
+        setType("nt:file", false, b2);
+        setType("mix:foo", true, b2);
+
+        DocumentBundlor bundlor = registry.getBundlor(b2.getNodeState());
+
+        //Pattern based on mixin would be applicable
+        assertTrue(bundlor.isBundled("foo"));
+        assertFalse(bundlor.isBundled("jcr:content"));
+    }
+
+    private static NodeState newNode(String typeName, boolean mixin){
+        NodeBuilder builder = EMPTY_NODE.builder();
+        setType(typeName, mixin, builder);
+        return builder.getNodeState();
+    }
+
+    private static void setType(String typeName, boolean mixin, NodeBuilder 
builder) {
+        if (mixin) {
+            builder.setProperty(JCR_MIXINTYPES, 
Collections.singleton(typeName), Type.NAMES);
+        } else {
+            builder.setProperty(JCR_PRIMARYTYPE, typeName);
+        }
+    }
+
+
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandlerTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandlerTest.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandlerTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandlerTest.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,115 @@
+/*
+ * 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.document.bundlor;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.junit.Test;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class BundlingHandlerTest {
+
+    private NodeBuilder builder = EMPTY_NODE.builder();
+
+    @Test
+    public void defaultSetup() throws Exception {
+        BundlingHandler handler = new 
BundlingHandler(BundledTypesRegistry.from(EMPTY_NODE));
+        childBuilder(builder, "/x/y/z");
+        NodeState state = builder.getNodeState();
+
+        assertEquals("/", handler.getRootBundlePath());
+        assertTrue(handler.isBundlingRoot());
+        assertEquals("foo", handler.getPropertyPath("foo"));
+
+        BundlingHandler xh = childHandler(handler, state, "/x");
+        assertEquals("/x", xh.getRootBundlePath());
+        assertTrue(xh.isBundlingRoot());
+        assertEquals("foo", xh.getPropertyPath("foo"));
+
+        BundlingHandler xz = childHandler(handler, state, "/x/y/z");
+        assertEquals("/x/y/z", xz.getRootBundlePath());
+        assertTrue(xz.isBundlingRoot());
+        assertEquals("foo", xz.getPropertyPath("foo"));
+    }
+
+    @Test
+    public void ntFileBundled() throws Exception {
+        BundledTypesRegistry registry = 
BundledTypesRegistry.builder().forType("nt:file", 
"jcr:content").buildRegistry();
+
+        childBuilder(builder, 
"sunrise.jpg/jcr:content").setProperty("jcr:data", "foo");
+        childBuilder(builder, 
"sunrise.jpg/jcr:content/bar").setProperty("jcr:data", "foo");
+        type(childBuilder(builder, "sunrise.jpg"), "nt:file");
+        childBuilder(builder, "/sunrise.jpg/metadata").setProperty("name", 
"foo");
+
+        NodeState state = builder.getNodeState();
+        BundlingHandler handler = new BundlingHandler(registry);
+
+        BundlingHandler fileHandler = childHandler(handler, state, 
"/sunrise.jpg");
+        assertEquals("/sunrise.jpg", fileHandler.getRootBundlePath());
+        assertTrue(fileHandler.isBundlingRoot());
+        assertEquals("foo", fileHandler.getPropertyPath("foo"));
+
+        BundlingHandler jcrContentHandler = childHandler(handler, state, 
"/sunrise.jpg/jcr:content");
+        assertEquals("/sunrise.jpg", jcrContentHandler.getRootBundlePath());
+        assertFalse(jcrContentHandler.isBundlingRoot());
+        assertEquals("jcr:content/foo", 
jcrContentHandler.getPropertyPath("foo"));
+
+        BundlingHandler metadataHandler = childHandler(handler, state, 
"/sunrise.jpg/metadata");
+        assertEquals("/sunrise.jpg/metadata", 
metadataHandler.getRootBundlePath());
+        assertTrue(metadataHandler.isBundlingRoot());
+        assertEquals("foo", metadataHandler.getPropertyPath("foo"));
+
+        // /sunrise.jpg/jcr:content/bar should have bundle root reset
+        BundlingHandler barHandler = childHandler(handler, state, 
"/sunrise.jpg/jcr:content/bar");
+        assertEquals("/sunrise.jpg/jcr:content/bar", 
barHandler.getRootBundlePath());
+        assertTrue(barHandler.isBundlingRoot());
+        assertEquals("foo", barHandler.getPropertyPath("foo"));
+    }
+
+    private BundlingHandler childHandler(BundlingHandler parent, NodeState 
parentState, String childPath) {
+        BundlingHandler result = parent;
+        NodeState state = parentState;
+        for (String name : PathUtils.elements(checkNotNull(childPath))) {
+            state = state.getChildNode(name);
+            result = result.childHandler(name, state);
+        }
+        return result;
+    }
+
+    private NodeBuilder childBuilder(NodeBuilder parent, String childPath) {
+        NodeBuilder result = parent;
+        for (String name : PathUtils.elements(checkNotNull(childPath))) {
+            result = result.child(name);
+        }
+        return result;
+    }
+
+    private NodeBuilder type(NodeBuilder builder, String typeName) {
+        builder.setProperty(JCR_PRIMARYTYPE, typeName);
+        return builder;
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRootTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRootTest.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRootTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingRootTest.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,68 @@
+/*
+ * 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.document.bundlor;
+
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.junit.Test;
+
+import static java.util.Arrays.asList;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static 
org.apache.jackrabbit.oak.plugins.document.bundlor.DocumentBundlor.PROP_PATTERN;
+import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static 
org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
+import static org.junit.Assert.*;
+
+public class BundlingRootTest {
+    private NodeBuilder builder = EMPTY_NODE.builder();
+
+    @Test
+    public void defaultSetup() throws Exception{
+        BundlingRoot root = new BundlingRoot();
+        assertFalse(root.bundlingEnabled());
+        assertEquals("foo", root.getPropertyPath("/x/y", "foo"));
+        assertFalse(root.isBundled("x/y"));
+    }
+
+    @Test
+    public void rootWithoutBundlor() throws Exception{
+        BundlingRoot root = new BundlingRoot("/x/y", null);
+
+        assertFalse(root.bundlingEnabled());
+        assertEquals("foo", root.getPropertyPath("/x/y", "foo"));
+        assertFalse(root.isBundled("x/y"));
+        assertEquals("/x/y", root.getPath());
+    }
+
+    @Test
+    public void rootWithBundlor() throws Exception{
+        builder.setProperty(createProperty(PROP_PATTERN, asList("x", "x/y", 
"z/*;all", "z"), STRINGS));
+        DocumentBundlor bundlor = DocumentBundlor.from(builder.getNodeState());
+
+        BundlingRoot root = new BundlingRoot("/m/n", bundlor);
+        assertTrue(root.bundlingEnabled());
+        assertEquals("x/foo", root.getPropertyPath("/m/n/x", "foo"));
+        assertEquals("x/y/foo", root.getPropertyPath("/m/n/x/y", "foo"));
+        assertEquals("z/q/r/foo", root.getPropertyPath("/m/n/z/q/r", "foo"));
+
+        assertEquals("foo", root.getPropertyPath("/m/n/k", "foo"));
+        assertEquals("foo", root.getPropertyPath("/m/n/k/r", "foo"));
+    }
+
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlingTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlingTest.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlingTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlingTest.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,82 @@
+/*
+ * 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.document.bundlor;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.plugins.document.Collection;
+import org.apache.jackrabbit.oak.plugins.document.DocumentMKBuilderProvider;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.CompositeHook;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.state.EqualsDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static org.junit.Assert.assertTrue;
+
+public class DocumentBundlingTest {
+    @Rule
+    public DocumentMKBuilderProvider builderProvider = new 
DocumentMKBuilderProvider();
+    private DocumentNodeStore store;
+
+    @Before
+    public void setUpBundlor() throws CommitFailedException {
+        store = builderProvider.newBuilder().getNodeStore();
+        NodeState registryState = BundledTypesRegistry.builder()
+                .forType("nt:file", "jcr:content")
+                .registry()
+                .forType("app:Asset", "jcr:content", "jcr:content/metadata")
+                .build();
+
+        NodeBuilder builder = store.getRoot().builder();
+        
builder.child("jcr:system").child("documentstore").setChildNode("bundlor", 
registryState);
+        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+    }
+
+    @Ignore("Read part not yet implemented")
+    @Test
+    public void saveAndReadNtFile() throws Exception{
+        NodeBuilder builder = store.getRoot().builder();
+        NodeBuilder fileNode = newNode("nt:file");
+        fileNode.child("jcr:content").setProperty("jcr:data", "foo");
+        builder.child("test").setChildNode("book.jpg", 
fileNode.getNodeState());
+
+        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+        System.out.println(store.getDocumentStore().find(Collection.NODES, 
"2:/test/book.jpg").asString());
+
+        NodeState root = store.getRoot();
+        NodeState fileNodeState = root.getChildNode("test");
+        assertTrue(EqualsDiff.equals(fileNode.getNodeState(), fileNodeState));
+    }
+
+    private static NodeBuilder newNode(String typeName){
+        NodeBuilder builder = EMPTY_NODE.builder();
+        builder.setProperty(JCR_PRIMARYTYPE, typeName);
+        return builder;
+    }
+}

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

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlorTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlorTest.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlorTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlorTest.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,53 @@
+/*
+ * 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.document.bundlor;
+
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.junit.Test;
+
+import static java.util.Arrays.asList;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static 
org.apache.jackrabbit.oak.plugins.document.bundlor.DocumentBundlor.PROP_PATTERN;
+import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static 
org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class DocumentBundlorTest {
+
+    private NodeBuilder builder = EMPTY_NODE.builder();
+
+    @Test
+    public void basicSetup() throws Exception{
+        builder.setProperty(createProperty(PROP_PATTERN, asList("x", "x/y"), 
STRINGS));
+        DocumentBundlor bundlor = DocumentBundlor.from(builder.getNodeState());
+
+        assertTrue(bundlor.isBundled("x"));
+        assertTrue(bundlor.isBundled("x/y"));
+        assertFalse(bundlor.isBundled("x/y/z"));
+        assertFalse(bundlor.isBundled("z"));
+    }
+    
+    @Test(expected = IllegalArgumentException.class)
+    public void invalid() throws Exception{
+        DocumentBundlor.from(builder.getNodeState());
+    }
+
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/IncludeTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/IncludeTest.java?rev=1765614&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/IncludeTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/IncludeTest.java
 Wed Oct 19 15:05:36 2016
@@ -0,0 +1,74 @@
+/*
+ * 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.document.bundlor;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class IncludeTest {
+
+    @Test
+    public void simpleWildcard() throws Exception{
+        Include i = new Include("*");
+        assertTrue(i.match("x"));
+        assertTrue(i.match("/x"));
+        assertFalse(i.match("/x/y"));
+    }
+
+    @Test
+    public void exactName() throws Exception{
+        assertTrue(new Include("x").match("x"));
+        assertFalse(new Include("x").match("y"));
+
+        assertFalse(new Include("x/y").match("x"));
+        assertTrue(new Include("x/y").match("x/y"));
+    }
+
+    @Test
+    public void directive() throws Exception{
+        Include i0 = new Include("x/*");
+        assertEquals(Include.Directive.NONE, i0.getDirective());
+
+        Include i = new Include("x/*;all");
+        assertEquals(Include.Directive.ALL, i.getDirective());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidDirective() throws Exception{
+        new Include("x/y;all/z");
+    }
+
+    @Test
+    public void directiveAll() throws Exception{
+        Include i = new Include("x/*;all");
+        assertTrue(i.match("x/y"));
+        assertTrue(i.match("x/y/z"));
+        assertTrue(i.match("x/y/z/x"));
+
+        Include i2 = new Include("x/y;all");
+        assertTrue(i2.match("x/y"));
+        assertTrue(i2.match("x/y/z"));
+        assertTrue(i2.match("x/y/z/x"));
+    }
+
+}
\ No newline at end of file

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


Reply via email to