You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by md...@apache.org on 2011/11/02 20:08:26 UTC
svn commit: r1196766 - in
/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src:
main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java
test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java
Author: mduerig
Date: Wed Nov 2 19:08:25 2011
New Revision: 1196766
URL: http://svn.apache.org/viewvc?rev=1196766&view=rev
Log:
Microkernel based Jackrabbit prototype (WIP): replace JsopTokenizer with JsopParser
Modified:
jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java
jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java
Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java?rev=1196766&r1=1196765&r2=1196766&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java Wed Nov 2 19:08:25 2011
@@ -20,7 +20,6 @@
package org.apache.jackrabbit.spi2microkernel;
import org.apache.jackrabbit.mk.api.MicroKernel;
-import org.apache.jackrabbit.mk.json.JsopTokenizer;
import org.apache.jackrabbit.mk.util.PathUtils;
import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.EventBundle;
@@ -37,11 +36,17 @@ import org.apache.jackrabbit.spi.commons
import org.apache.jackrabbit.spi.commons.identifier.IdFactoryImpl;
import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
import org.apache.jackrabbit.spi2microkernel.json.FullJsonParser;
+import org.apache.jackrabbit.spi2microkernel.json.JsonHandler;
+import org.apache.jackrabbit.spi2microkernel.json.JsonParser;
+import org.apache.jackrabbit.spi2microkernel.json.JsonTokenizer;
import org.apache.jackrabbit.spi2microkernel.json.JsonValue;
import org.apache.jackrabbit.spi2microkernel.json.JsonValue.JsonArray;
import org.apache.jackrabbit.spi2microkernel.json.JsonValue.JsonObject;
-import org.apache.jackrabbit.spi2microkernel.json.JsonValue.Type;
+import org.apache.jackrabbit.spi2microkernel.json.JsopHandler;
+import org.apache.jackrabbit.spi2microkernel.json.JsopParser;
import org.apache.jackrabbit.spi2microkernel.json.ParseException;
+import org.apache.jackrabbit.spi2microkernel.json.Token;
+import org.apache.jackrabbit.spi2microkernel.json.Token.Type;
import org.apache.jackrabbit.spi2microkernel.json.UnescapingJsonTokenizer;
import org.apache.jackrabbit.spi2microkernel.util.WrappedRepositoryException;
import org.slf4j.Logger;
@@ -125,6 +130,12 @@ public class SubscriptionImpl implements
return IdFactoryImpl.getInstance().createNodeId((String) null, path);
}
+ private static NodeId createParentId(Path path) {
+ return path.denotesRoot()
+ ? null
+ : createNodeId(getParent(path));
+ }
+
private static Path getParent(Path path) {
try {
return path.getAncestor(1);
@@ -145,8 +156,8 @@ public class SubscriptionImpl implements
}
}
- private static Path readPath(JsopTokenizer jsopTokenizer) {
- String path = jsopTokenizer.readString();
+ private static Path getPath(Token token) {
+ String path = token.text();
int index = PathUtils.getNextSlash(path, 1); // slash off workspace name
path = index == -1
? "/"
@@ -335,84 +346,121 @@ public class SubscriptionImpl implements
return new EventBundleImpl(events, isLocal);
}
- private Collection<Event> getEvents(String changes, EventTemplate eventTemplate) {
- Collection<Event> events = new LinkedList<Event>();
- JsopTokenizer jsopTokenizer = new JsopTokenizer(changes);
-
- while (jsopTokenizer.read() != JsopTokenizer.END) {
- int tokenType = jsopTokenizer.getTokenType();
- switch(tokenType) {
- case '+': addItem(jsopTokenizer, eventTemplate, events); break;
- case '-': removeNode(jsopTokenizer, eventTemplate, events); break;
- case '^': setProperty(jsopTokenizer, eventTemplate, events); break;
- case '>': moveNode(jsopTokenizer, eventTemplate, events); break;
- default: // skip
+ private Collection<Event> getEvents(String jsop, final EventTemplate eventTemplate) {
+ final Collection<Event> events = new LinkedList<Event>();
+
+ new JsopParser(new JsopHandler(){
+ @Override
+ public void add(Token path, JsonTokenizer object) {
+ addNode(getPath(path), object, eventTemplate, events);
+ }
+
+ @Override
+ public void add(Token path, Token value) {
+ Path qPath = getPath(path);
+ NodeId parentId = createParentId(qPath);
+ addProperty(qPath, parentId, eventTemplate, events);
+ }
+
+ @Override
+ public void add(Token path, Token[] values) {
+ Path qPath = getPath(path);
+ NodeId parentId = createParentId(qPath);
+ addProperty(qPath, parentId, eventTemplate, events);
+ }
+
+ @Override
+ public void remove(Token path) {
+ removeNode(getPath(path), eventTemplate, events);
}
- }
+
+ @Override
+ public void set(Token path, Token value) {
+ setProperty(getPath(path), eventTemplate, events, value.type() == Type.NULL);
+ }
+
+ @Override
+ public void set(Token path, Token[] values) {
+ setProperty(getPath(path), eventTemplate, events, false);
+ }
+
+ @Override
+ public void reorder(Token path, Token position, Token target) {
+ log.error("Not implemented", new UnsupportedOperationException("Not implemented"));
+ }
+
+ @Override
+ public void move(Token path, Token target) {
+ moveNode(getPath(path), getPath(target), eventTemplate, events);
+ }
+ }).parseJsop(new UnescapingJsonTokenizer(jsop));
return events;
}
- private void addItem(JsopTokenizer jsopTokenizer, EventTemplate eventTemplate, Collection<Event> events) {
- Path path = readPath(jsopTokenizer);
- NodeId parentId = path.denotesRoot()
- ? null
- : createNodeId(getParent(path));
+ private void addNode(final Path path, JsonTokenizer object, final EventTemplate eventTemplate,
+ final Collection<Event> events) {
- addItem(jsopTokenizer, eventTemplate, events, path, parentId);
- }
+ NodeId parentId = createParentId(path);
+ addNode(path, parentId, eventTemplate, events);
- private void addItem(JsopTokenizer jsopTokenizer, EventTemplate eventTemplate, Collection<Event> events,
- Path path, NodeId parentId) {
+ new JsonParser(new JsonHandler(){
+ private Path parentPath = path;
+ @Override
+ public void atom(Token key, Token value) {
+ Name name = Paths.stringToName(key.text());
+ Path path = createPath(parentPath, name);
+ addProperty(path, createNodeId(parentPath), eventTemplate, events);
+ }
+
+ @Override
+ public void object(JsonParser parser, Token key, JsonTokenizer tokenizer) {
+ Name name = Paths.stringToName(key.text());
+ Path path = createPath(parentPath, name);
+ addNode(path, createNodeId(parentPath), eventTemplate, events);
+ parentPath = path;
+ super.object(parser, key, tokenizer);
+ parentPath = getParent(parentPath);
+ }
+
+ @Override
+ public void array(JsonParser parser, Token key, JsonTokenizer tokenizer) {
+ Name name = Paths.stringToName(key.text());
+ Path path = createPath(parentPath, name);
+ addProperty(path, createNodeId(parentPath), eventTemplate, events);
+ new JsonParser(JsonHandler.INSTANCE).parseArray(tokenizer);
+ }
+ }).parseObject(object);
+ }
+
+ private void addNode(Path path, NodeId parentId, EventTemplate eventTemplate, Collection<Event> events) {
EventTemplate addItemEvent = eventTemplate.copy();
addItemEvent.setPath(path);
addItemEvent.setParentId(parentId);
// todo set primaryType, mixinTypes this needs context in the journal in the case of property events
// fixme it seems type based filtering does not respect the type hierarchy (see JCR-2542)
- jsopTokenizer.read(':');
- if (jsopTokenizer.read() == '{') {
- addItemEvent.setType(Event.NODE_ADDED);
- NodeId nodeId = createNodeId(path);
- addItemEvent.setItemId(nodeId);
- events.add(addItemEvent.buildEvent());
- addInnerItems(jsopTokenizer, eventTemplate, events, nodeId);
- }
- else {
- if (jsopTokenizer.getTokenType() == '[') {
- // skip over array
- while(jsopTokenizer.read() != ']') {}
- }
-
- addItemEvent.setType(Event.PROPERTY_ADDED);
- addItemEvent.setItemId(createPropertyId(parentId, path.getName()));
- events.add(addItemEvent.buildEvent());
- }
+ addItemEvent.setType(Event.NODE_ADDED);
+ NodeId nodeId = createNodeId(path);
+ addItemEvent.setItemId(nodeId);
+ events.add(addItemEvent.buildEvent());
}
- private void addInnerItems(JsopTokenizer jsopTokenizer, EventTemplate eventTemplate, Collection<Event> events,
- NodeId parentId) {
-
- int tokenType;
- while ((tokenType = jsopTokenizer.read()) != '}' && tokenType != JsopTokenizer.END) {
- if (tokenType == ',') {
- jsopTokenizer.read();
- }
-
- Name name = Paths.stringToName(jsopTokenizer.getToken());
- Path path = createPath(parentId.getPath(), name);
+ private void addProperty(Path path, NodeId parentId, EventTemplate eventTemplate, Collection<Event> events) {
+ EventTemplate addItemEvent = eventTemplate.copy();
+ addItemEvent.setPath(path);
+ addItemEvent.setParentId(parentId);
+ // todo set primaryType, mixinTypes this needs context in the journal in the case of property events
+ // fixme it seems type based filtering does not respect the type hierarchy (see JCR-2542)
- addItem(jsopTokenizer, eventTemplate, events, path, parentId);
- }
+ addItemEvent.setType(Event.PROPERTY_ADDED);
+ addItemEvent.setItemId(createPropertyId(parentId, path.getName()));
+ events.add(addItemEvent.buildEvent());
}
- private void removeNode(JsopTokenizer jsopTokenizer, EventTemplate eventTemplate, Collection<Event> events) {
- Path path = readPath(jsopTokenizer);
- NodeId parentId = path.denotesRoot()
- ? null
- : createNodeId(getParent(path));
-
+ private void removeNode(Path path, EventTemplate eventTemplate, Collection<Event> events) {
+ NodeId parentId = createParentId(path);
EventTemplate removeNodeEvent = eventTemplate.copy();
removeNodeEvent.setType(Event.NODE_REMOVED);
removeNodeEvent.setPath(path);
@@ -425,10 +473,8 @@ public class SubscriptionImpl implements
// todo consider ways to generate events of (large) sub tree
}
- private void setProperty(JsopTokenizer jsopTokenizer, EventTemplate eventTemplate, Collection<Event> events) {
- Path path = readPath(jsopTokenizer);
- NodeId parentId = createNodeId(getParent(path));
-
+ private void setProperty(Path path, EventTemplate eventTemplate, Collection<Event> events, boolean nullValue) {
+ NodeId parentId = createParentId(path);
EventTemplate setPropertyEvent = eventTemplate.copy();
setPropertyEvent.setPath(path);
setPropertyEvent.setParentId(parentId);
@@ -436,8 +482,7 @@ public class SubscriptionImpl implements
// todo set primaryType, mixinTypes this needs context in the journal
// fixme it seems type based filtering does not respect the type hierarchy (see JCR-2542)
- jsopTokenizer.read(':');
- if (jsopTokenizer.read() == JsopTokenizer.NULL) {
+ if (nullValue) {
setPropertyEvent.setType(Event.PROPERTY_REMOVED);
}
else {
@@ -448,20 +493,16 @@ public class SubscriptionImpl implements
// todo consider ways to generate events of (large) sub tree
}
- private void moveNode(JsopTokenizer jsopTokenizer, EventTemplate eventTemplate, Collection<Event> events) {
+ private void moveNode(Path path, Path target, EventTemplate eventTemplate, Collection<Event> events) {
try {
- Path fromPath = readPath(jsopTokenizer);
- jsopTokenizer.read(':');
- Path toPath = readPath(jsopTokenizer);
-
EventTemplate moveNodeEvent = eventTemplate.copy();
moveNodeEvent.setType(Event.NODE_MOVED);
- moveNodeEvent.setPath(toPath);
- moveNodeEvent.setItemId(createNodeId(toPath));
+ moveNodeEvent.setPath(target);
+ moveNodeEvent.setItemId(createNodeId(target));
Map<Name, QValue> info = new HashMap<Name, QValue>();
- info.put(Paths.stringToName("srcAbsPath"), Values.pathToValue(fromPath));
- info.put(Paths.stringToName("destAbsPath"), Values.pathToValue(toPath));
+ info.put(Paths.stringToName("srcAbsPath"), Values.pathToValue(path));
+ info.put(Paths.stringToName("destAbsPath"), Values.pathToValue(target));
moveNodeEvent.setInfo(info);
events.add(moveNodeEvent.buildEvent());
@@ -488,7 +529,7 @@ public class SubscriptionImpl implements
private long getLong(JsonObject jsonObject, String key) {
JsonValue o = jsonObject.get(key);
- if (o.type() == Type.NUMBER) {
+ if (o.type() == JsonValue.Type.NUMBER) {
return Long.parseLong(o.asAtom().value());
}
else {
Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java?rev=1196766&r1=1196765&r2=1196766&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java Wed Nov 2 19:08:25 2011
@@ -23,12 +23,15 @@ import junit.framework.Assert;
import org.apache.jackrabbit.mk.MicroKernelFactory;
import org.apache.jackrabbit.mk.api.MicroKernel;
import org.apache.jackrabbit.mk.api.MicroKernelException;
-import org.apache.jackrabbit.mk.json.JsopTokenizer;
import org.apache.jackrabbit.spi2microkernel.json.FullJsonParser;
+import org.apache.jackrabbit.spi2microkernel.json.JsonTokenizer;
import org.apache.jackrabbit.spi2microkernel.json.JsonValue;
import org.apache.jackrabbit.spi2microkernel.json.JsonValue.JsonArray;
import org.apache.jackrabbit.spi2microkernel.json.JsonValue.JsonObject;
import org.apache.jackrabbit.spi2microkernel.json.JsonValue.Type;
+import org.apache.jackrabbit.spi2microkernel.json.JsopHandler;
+import org.apache.jackrabbit.spi2microkernel.json.JsopParser;
+import org.apache.jackrabbit.spi2microkernel.json.Token;
import org.apache.jackrabbit.spi2microkernel.json.UnescapingJsonTokenizer;
import org.apache.jackrabbit.spi2microkernel.util.NumberStream;
import org.junit.After;
@@ -41,6 +44,7 @@ import java.io.IOException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
public class MicrokernelTest {
@@ -272,15 +276,16 @@ public class MicrokernelTest {
JsonArray jsonArray = FullJsonParser.parseArray(new UnescapingJsonTokenizer(journal));
JsonObject jsonObject = jsonArray.get(0).asObject();
- String changes = jsonObject.get("changes").asAtom().value();
+ String jsop = jsonObject.get("changes").asAtom().value();
- JsopTokenizer tokenizer = new JsopTokenizer(changes);
- tokenizer.read('+');
- assertEquals("/node", tokenizer.readString());
- tokenizer.read(':');
- tokenizer.read('{');
- tokenizer.read('}');
- tokenizer.read(JsopTokenizer.END);
+ new JsopParser(new FailingJsopHandler(){
+ @Override
+ public void add(Token path, JsonTokenizer object) {
+ assertEquals("/node", path.text());
+ assertEquals("{", object.read().text());
+ assertEquals("}", object.read().text());
+ }
+ }).parseJsop(new UnescapingJsonTokenizer(jsop));
}
@Test
@@ -300,15 +305,15 @@ public class MicrokernelTest {
JsonArray jsonArray = FullJsonParser.parseArray(new UnescapingJsonTokenizer(journal));
JsonObject jsonObject = jsonArray.get(0).asObject();
- String changes = jsonObject.get("changes").asAtom().value();
+ String jsop = jsonObject.get("changes").asAtom().value();
- JsopTokenizer tokenizer = new JsopTokenizer(changes);
- tokenizer.read('^');
- assertEquals("/node/prop", tokenizer.readString());
- tokenizer.read(':');
- tokenizer.read(JsopTokenizer.NUMBER);
- assertEquals("21", tokenizer.getToken());
- tokenizer.read(JsopTokenizer.END);
+ new JsopParser(new FailingJsopHandler(){
+ @Override
+ public void set(Token path, Token value) {
+ assertEquals("/node/prop", path.text());
+ assertEquals("21", value.text());
+ }
+ }).parseJsop(new UnescapingJsonTokenizer(jsop));
}
@Test
@@ -328,14 +333,47 @@ public class MicrokernelTest {
JsonArray jsonArray = FullJsonParser.parseArray(new UnescapingJsonTokenizer(journal));
JsonObject jsonObject = jsonArray.get(0).asObject();
- String changes = jsonObject.get("changes").asAtom().value();
+ String jsop = jsonObject.get("changes").asAtom().value();
+
+ new JsopParser(new FailingJsopHandler(){
+ @Override
+ public void set(Token path, Token value) {
+ assertEquals("/node/prop", path.text());
+ assertEquals("bar", value.text());
+ }
+ }).parseJsop(new UnescapingJsonTokenizer(jsop));
+ }
+
+ @Test
+ public void journalSetMultiValuedProperty() {
+ MicroKernel mk = getMicroKernel();
+ String init = mk.getHeadRevision();
+
+ String head = mk.commit("/",
+ "+\"node\" : {\"prop\":\"foo\"}",
+ init, "");
+
+ head = mk.commit("/",
+ "^\"node/prop\":[1,2,3,4]",
+ head, "");
+
+ String journal = mk.getJournal(head, head);
+
+ JsonArray jsonArray = FullJsonParser.parseArray(new UnescapingJsonTokenizer(journal));
+ JsonObject jsonObject = jsonArray.get(0).asObject();
+ String jsop = jsonObject.get("changes").asAtom().value();
- JsopTokenizer tokenizer = new JsopTokenizer(changes);
- tokenizer.read('^');
- assertEquals("/node/prop", tokenizer.readString());
- tokenizer.read(':');
- assertEquals("bar", tokenizer.readString());
- tokenizer.read(JsopTokenizer.END);
+ new JsopParser(new FailingJsopHandler(){
+ @Override
+ public void set(Token path, Token[] values) {
+ assertEquals("/node/prop", path.text());
+ assertEquals(4, values.length);
+ assertEquals("1", values[0].text());
+ assertEquals("2", values[1].text());
+ assertEquals("3", values[2].text());
+ assertEquals("4", values[3].text());
+ }
+ }).parseJsop(new UnescapingJsonTokenizer(jsop));
}
@Test
@@ -366,4 +404,47 @@ public class MicrokernelTest {
return microkernel;
}
+ private static class FailingJsopHandler extends JsopHandler {
+
+ @Override
+ public void add(Token path, JsonTokenizer object) {
+ fail();
+ }
+
+ @Override
+ public void add(Token path, Token[] values) {
+ fail();
+ }
+
+ @Override
+ public void add(Token path, Token value) {
+ fail();
+ }
+
+ @Override
+ public void remove(Token path) {
+ fail();
+ }
+
+ @Override
+ public void set(Token path, Token value) {
+ fail();
+ }
+
+ @Override
+ public void set(Token path, Token[] values) {
+ fail();
+ }
+
+ @Override
+ public void reorder(Token path, Token position, Token target) {
+ fail();
+ }
+
+ @Override
+ public void move(Token path, Token target) {
+ fail();
+ }
+ }
+
}