Author: chetanm
Date: Wed Oct 19 15:07:30 2016
New Revision: 1765623
URL: http://svn.apache.org/viewvc?rev=1765623&view=rev
Log:
OAK-1312 - [bundling] Bundle nodes into a document
Implement read part of bundling
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlingTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java?rev=1765623&r1=1765622&r2=1765623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
Wed Oct 19 15:07:30 2016
@@ -41,6 +41,9 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.commons.json.JsopWriter;
import org.apache.jackrabbit.oak.json.JsonSerializer;
+import org.apache.jackrabbit.oak.plugins.document.bundlor.BundlorUtils;
+import org.apache.jackrabbit.oak.plugins.document.bundlor.DocumentBundlor;
+import org.apache.jackrabbit.oak.plugins.document.bundlor.Matcher;
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
@@ -81,6 +84,7 @@ public class DocumentNodeState extends A
private final boolean hasChildren;
private final DocumentNodeStore store;
+ private BundlingContext bundlingContext;
private AbstractDocumentNodeState cachedSecondaryState;
@@ -106,13 +110,28 @@ public class DocumentNodeState extends A
boolean hasChildren,
@Nullable RevisionVector lastRevision,
boolean fromExternalChange) {
+ this(store, path, hasChildren, rootRevision, lastRevision,
+ fromExternalChange,
createBundlingContext(checkNotNull(properties)));
+ }
+
+ private DocumentNodeState(@Nonnull DocumentNodeStore store,
+ @Nonnull String path,
+ boolean hasChildren,
+ @Nonnull RevisionVector rootRevision,
+ @Nullable RevisionVector lastRevision,
+ boolean fromExternalChange,
+ BundlingContext bundlingContext) {
this.store = checkNotNull(store);
this.path = checkNotNull(path);
this.rootRevision = checkNotNull(rootRevision);
this.lastRevision = lastRevision;
this.fromExternalChange = fromExternalChange;
- this.hasChildren = hasChildren;
- this.properties = checkNotNull(properties);
+ this.properties = bundlingContext.getProperties();
+ this.bundlingContext = bundlingContext;
+
+ //TODO [bundling] hasChildren optimization
+ this.hasChildren = this.bundlingContext.matcher.isMatch() ||
hasChildren;
+
}
/**
@@ -237,9 +256,12 @@ public class DocumentNodeState extends A
if (!hasChildren) {
return 0;
}
+
+ //TODO [bundling] Optimize if matcher matches all child
+
if (max > DocumentNodeStore.NUM_CHILDREN_CACHE_LIMIT) {
// count all
- return Iterators.size(new ChildNodeEntryIterator());
+ return Iterables.size(getChildNodeEntries());
}
Children c = store.getChildren(this, null, (int) max);
if (c.hasMore) {
@@ -267,10 +289,12 @@ public class DocumentNodeState extends A
return secondaryState.getChildNodeEntries();
}
+ //TODO [bundling] Optimize if matcher matches all child
+
return new Iterable<ChildNodeEntry>() {
@Override
public Iterator<ChildNodeEntry> iterator() {
- return new ChildNodeEntryIterator();
+ return Iterators.concat(getBundledChildren(), new
ChildNodeEntryIterator());
}
};
}
@@ -414,6 +438,16 @@ public class DocumentNodeState extends A
}
return null;
}
+
+ Matcher child = bundlingContext.matcher.next(childNodeName);
+ if (child.isMatch()){
+ if (bundlingContext.hasChildNode(child.getMatchedPath())){
+ return createBundledState(childNodeName, child);
+ } else {
+ return null;
+ }
+ }
+
return store.getNode(PathUtils.concat(getPath(), childNodeName),
lastRevision);
}
@@ -478,6 +512,7 @@ public class DocumentNodeState extends A
if (hasChildren) {
json.key("hasChildren").value(true);
}
+ //TODO [bundling] Handle serialization
if (properties.size() > 0) {
json.key("prop").object();
for (String k : properties.keySet()) {
@@ -668,4 +703,80 @@ public class DocumentNodeState extends A
}
}
+ //~----------------------------------------------< Bundling >
+
+ private AbstractDocumentNodeState createBundledState(String childNodeName,
Matcher child) {
+ return new DocumentNodeState(
+ store,
+ PathUtils.concat(path, childNodeName),
+ true, //TODO Determine child node
+ lastRevision,
+ rootRevision,
+ fromExternalChange,
+ bundlingContext.childContext(child));
+ }
+
+ private Iterator<ChildNodeEntry> getBundledChildren(){
+ return
Iterators.transform(bundlingContext.getBundledChildNodeNames().iterator(),
+ new Function<String, ChildNodeEntry>() {
+ @Override
+ public ChildNodeEntry apply(final String childNodeName) {
+ return new AbstractChildNodeEntry() {
+ @Nonnull
+ @Override
+ public String getName() {
+ return childNodeName;
+ }
+
+ @Nonnull
+ @Override
+ public NodeState getNodeState() {
+ return createBundledState(childNodeName,
bundlingContext.matcher.next(childNodeName));
+ }
+ };
+ }
+ });
+ }
+
+ private static BundlingContext createBundlingContext(Map<String,
PropertyState> properties) {
+ PropertyState bundlorConfig =
properties.get(DocumentBundlor.META_PROP_PATTERN);
+ Matcher matcher = Matcher.NON_MATCHING;
+ if (bundlorConfig != null){
+ matcher = DocumentBundlor.from(bundlorConfig).createMatcher();
+ }
+ return new BundlingContext(matcher, properties);
+ }
+
+ private static class BundlingContext {
+ final Matcher matcher;
+ final Map<String, PropertyState> rootProperties;
+
+ public BundlingContext(Matcher matcher, Map<String, PropertyState>
rootProperties) {
+ this.matcher = matcher;
+ this.rootProperties = rootProperties;
+ }
+
+ public BundlingContext childContext(Matcher childMatcher){
+ return new BundlingContext(childMatcher, rootProperties);
+ }
+
+ public Map<String, PropertyState> getProperties(){
+ if (matcher.isMatch()){
+ return BundlorUtils.getMatchingProperties(rootProperties,
matcher);
+ }
+ return rootProperties;
+ }
+
+ public boolean hasChildNode(String relativePath){
+ String key = PathUtils.concat(relativePath,
DocumentBundlor.META_PROP_NODE);
+ return rootProperties.containsKey(key);
+ }
+
+ public List<String> getBundledChildNodeNames(){
+ if (matcher.isMatch()) {
+ return BundlorUtils.getChildNodeNames(rootProperties.keySet(),
matcher);
+ }
+ return Collections.emptyList();
+ }
+ }
}
Modified:
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=1765623&r1=1765622&r2=1765623&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlingTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/bundlor/DocumentBundlingTest.java
Wed Oct 19 15:07:30 2016
@@ -19,18 +19,20 @@
package org.apache.jackrabbit.oak.plugins.document.bundlor;
+import java.util.Set;
+
+import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
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;
@@ -57,7 +59,6 @@ public class DocumentBundlingTest {
store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
}
- @Ignore("Read part not yet implemented")
@Test
public void saveAndReadNtFile() throws Exception{
NodeBuilder builder = store.getRoot().builder();
@@ -71,7 +72,10 @@ public class DocumentBundlingTest {
NodeState root = store.getRoot();
NodeState fileNodeState = root.getChildNode("test");
- assertTrue(EqualsDiff.equals(fileNode.getNodeState(), fileNodeState));
+ assertTrue(fileNodeState.getChildNode("book.jpg").exists());
+
assertTrue(fileNodeState.getChildNode("book.jpg").getChildNode("jcr:content").exists());
+
+ assertTrue(PartialEqualsDiff.equals(fileNode.getNodeState(),
fileNodeState.getChildNode("book.jpg")));
}
private static NodeBuilder newNode(String typeName){
@@ -79,4 +83,35 @@ public class DocumentBundlingTest {
builder.setProperty(JCR_PRIMARYTYPE, typeName);
return builder;
}
+
+ private static class PartialEqualsDiff extends EqualsDiff {
+ private final Set<String> ignoredProps =
Sets.newHashSet(DocumentBundlor.META_PROP_PATTERN);
+
+ public static boolean equals(NodeState before, NodeState after) {
+ return before.exists() == after.exists()
+ && after.compareAgainstBaseState(before, new
PartialEqualsDiff());
+ }
+
+ @Override
+ public boolean propertyAdded(PropertyState after) {
+ if (ignore(after)) return true;
+ return super.propertyAdded(after);
+ }
+
+ @Override
+ public boolean propertyChanged(PropertyState before, PropertyState
after) {
+ if (ignore(after)) return true;
+ return super.propertyChanged(before, after);
+ }
+
+ @Override
+ public boolean propertyDeleted(PropertyState before) {
+ if (ignore(before)) return true;
+ return super.propertyDeleted(before);
+ }
+
+ private boolean ignore(PropertyState state){
+ return ignoredProps.contains(state.getName());
+ }
+ }
}