You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2011/12/22 11:02:40 UTC
svn commit: r1222143 - in /jackrabbit/sandbox/microkernel/src:
main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
test/java/org/apache/jackrabbit/mk/MoveNodeTest.java
Author: thomasm
Date: Thu Dec 22 10:02:40 2011
New Revision: 1222143
URL: http://svn.apache.org/viewvc?rev=1222143&view=rev
Log:
Copy node.
Added:
jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java
Modified:
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java?rev=1222143&r1=1222142&r2=1222143&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java Thu Dec 22 10:02:40 2011
@@ -249,7 +249,7 @@ public class MemoryKernelImpl extends Wr
}
diff.newline();
break;
- case '>':
+ case '>': {
t.read(':');
diff.tag('>').key(path);
String name = PathUtils.getName(from);
@@ -315,6 +315,22 @@ public class MemoryKernelImpl extends Wr
data = data.cloneAndRemoveChildNode(from, rev);
}
break;
+ }
+ case '*': {
+ // TODO is it really required?
+ // TODO possibly support target position notation
+ // TODO support copy in wrappers, index,...
+ t.read(':');
+ String target = t.readString();
+ diff.tag('*').key(path).value(target);
+ if (!PathUtils.isAbsolute(target)) {
+ target = PathUtils.concat(rootPath, target);
+ }
+ NodeImpl node = data.getNode(from);
+ String to = PathUtils.relativize("/", target);
+ data = data.cloneAndAddChildNode(to, false, null, node, rev);
+ break;
+ }
default:
throw ExceptionFactory.get("token: " + (char) t.getTokenType());
}
Added: jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java?rev=1222143&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java (added)
+++ jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java Thu Dec 22 10:02:40 2011
@@ -0,0 +1,355 @@
+/*
+ * 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.mk;
+
+import static org.junit.Assert.fail;
+import junit.framework.Assert;
+import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.mk.json.JsopTokenizer;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * Test moving nodes.
+ */
+@RunWith(Parameterized.class)
+public class MoveNodeTest extends MultiMkTestBase {
+
+ private String head;
+ private String journalRevision;
+
+ public MoveNodeTest(String url) {
+ super(url);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ head = mk.getHeadRevision();
+ commit("/", "+ \"test\": {\"a\":{}, \"b\":{}, \"c\":{}}");
+ commit("/", "+ \"test2\": {}");
+ getJournal();
+ }
+
+ @Test
+ public void addProperty() {
+ if (!isMemoryKernel(mk)) {
+ return;
+ }
+
+ // add a property /test/c
+ commit("/", "+ \"test/c\": 123");
+ Assert.assertEquals("{c:123,a,b,c}", getNode("/test"));
+ assertJournal("+\"/test/c\":123");
+
+ // duplicate add property should fail
+ try {
+ commit("/", "+ \"test/c\": 123");
+ Assert.fail();
+ } catch (MicroKernelException e) {
+ // expected
+ }
+ Assert.assertEquals("{c:123,a,b,c}", getNode("/test"));
+ }
+
+ @Test
+ public void order() {
+ Assert.assertEquals("{a,b,c}", getNode("/test"));
+ }
+
+ @Test
+ public void rename() {
+ if (!isMemoryKernel(mk)) {
+ return;
+ }
+
+ // rename /test/b
+ commit("/", "> \"test/b\": \"test/b1\"");
+ Assert.assertEquals("{a,b1,c}", getNode("/test"));
+ assertJournal(">\"/test/b\":\"/test/b1\"");
+
+ // and back
+ commit("/", "> \"test/b1\": \"test/b\"");
+ Assert.assertEquals("{a,b,c}", getNode("/test"));
+ assertJournal(">\"/test/b1\":\"/test/b\"");
+ }
+
+ @Test
+ public void reorderBefore() {
+ if (!isMemoryKernel(mk)) {
+ return;
+ }
+
+ // order c before b
+ commit("/", "> \"test/c\": {\"before\": \"test/b\"}");
+ Assert.assertEquals("{a,c,b}", getNode("/test"));
+ assertJournal(">\"/test/c\":{\"before\":\"/test/b\"}");
+
+ // and now b before a
+ commit("/", "> \"test/b\": {\"before\": \"test/a\"}");
+ Assert.assertEquals("{b,a,c}", getNode("/test"));
+ assertJournal(">\"/test/b\":{\"before\":\"/test/a\"}");
+ }
+
+ @Test
+ public void reorderAfter() {
+ if (!isMemoryKernel(mk)) {
+ return;
+ }
+
+ // order a after b
+ commit("/", "> \"test/a\": {\"after\": \"test/b\"}");
+ Assert.assertEquals("{b,a,c}", getNode("/test"));
+ assertJournal(">\"/test/a\":{\"after\":\"/test/b\"}");
+
+ // and now a after c
+ commit("/", "> \"test/a\": {\"after\": \"test/c\"}");
+ Assert.assertEquals("{b,c,a}", getNode("/test"));
+ assertJournal(">\"/test/a\":{\"after\":\"/test/c\"}");
+
+ // and now a after a (a no-op)
+ commit("/", "> \"test/a\": {\"after\": \"test/a\"}");
+ Assert.assertEquals("{b,c,a}", getNode("/test"));
+ assertJournal(">\"/test/a\":{\"after\":\"/test/a\"}");
+ }
+
+ @Test
+ public void moveFirst() {
+ if (!isMemoryKernel(mk)) {
+ return;
+ }
+
+ // move /test/a to /test2/a (rename is not supported in this way)
+ commit("/", "> \"test/a\": {\"first\": \"test2\"}");
+ Assert.assertEquals("{b,c}", getNode("/test"));
+ Assert.assertEquals("{a}", getNode("/test2"));
+ assertJournal(">\"/test/a\":{\"first\":\"/test2\"}");
+
+ // move /test/c to /test2
+ commit("/", "> \"test/c\": {\"first\": \"test2\"}");
+ Assert.assertEquals("{b}", getNode("/test"));
+ Assert.assertEquals("{c,a}", getNode("/test2"));
+ assertJournal(">\"/test/c\":{\"first\":\"/test2\"}");
+ }
+
+ @Test
+ public void moveCombinedWithSet() {
+ if (!isMemoryKernel(mk)) {
+ return;
+ }
+
+ // move /test/b to /test_b
+ commit("/", "> \"test/b\": \"test_b\"");
+ Assert.assertEquals("{a,c}", getNode("/test"));
+ Assert.assertEquals("{}", getNode("/test_b"));
+ assertJournal(">\"/test/b\":\"/test_b\"");
+
+ // move /test/a to /test_a, combined with adding a property
+ commit("/", "> \"test/a\": \"test_a\" ^ \"test_a/x\": 1");
+ Assert.assertEquals("{c}", getNode("/test"));
+ Assert.assertEquals("{x:1}", getNode("/test_a"));
+ assertJournal(
+ ">\"/test/a\":\"/test_a\"\n"+
+ "+\"/test_a/x\":1");
+ }
+
+ @Test
+ public void moveBefore() {
+ if (!isMemoryKernel(mk)) {
+ return;
+ }
+
+ // move /test/b to /test2/b, before any other nodes in /test2
+ commit("/", "> \"test/b\": {\"first\": \"test2\"}");
+ Assert.assertEquals("{a,c}", getNode("/test"));
+ Assert.assertEquals("{b}", getNode("/test2"));
+ assertJournal(">\"/test/b\":{\"first\":\"/test2\"}");
+
+ // move /test/c to /test2, before b
+ commit("/", "> \"test/c\": {\"before\": \"test2/b\"}");
+ Assert.assertEquals("{a}", getNode("/test"));
+ Assert.assertEquals("{c,b}", getNode("/test2"));
+ assertJournal(">\"/test/c\":{\"before\":\"/test2/b\"}");
+ }
+
+ @Test
+ public void moveAfter() {
+ if (!isMemoryKernel(mk)) {
+ return;
+ }
+
+ // move /test/c to /test2
+ commit("/", "> \"test/c\": \"test2/c\"");
+ Assert.assertEquals("{a,b}", getNode("/test"));
+ Assert.assertEquals("{c}", getNode("/test2"));
+ assertJournal(">\"/test/c\":\"/test2/c\"");
+
+ // move /test/a to /test2, after c
+ commit("/", "> \"test/a\": {\"after\": \"test2/c\"}");
+ Assert.assertEquals("{b}", getNode("/test"));
+ Assert.assertEquals("{c,a}", getNode("/test2"));
+ assertJournal(">\"/test/a\":{\"after\":\"/test2/c\"}");
+
+ // move /test/b to /test2, after c
+ commit("/", "> \"test/b\": {\"after\": \"test2/c\"}");
+ Assert.assertEquals("{}", getNode("/test"));
+ Assert.assertEquals("{c,b,a}", getNode("/test2"));
+ assertJournal(">\"/test/b\":{\"after\":\"/test2/c\"}");
+ }
+
+ @Test
+ public void moveLast() {
+ if (!isMemoryKernel(mk)) {
+ return;
+ }
+
+ // move /test/a to /test2, as last
+ commit("/", "> \"test/b\": {\"last\": \"test2\"}");
+ Assert.assertEquals("{a,c}", getNode("/test"));
+ Assert.assertEquals("{b}", getNode("/test2"));
+ assertJournal(">\"/test/b\":{\"last\":\"/test2\"}");
+
+ // move /test/c to /test2, as last
+ commit("/", "> \"test/c\": {\"last\": \"test2\"}");
+ Assert.assertEquals("{a}", getNode("/test"));
+ Assert.assertEquals("{b,c}", getNode("/test2"));
+ assertJournal(">\"/test/c\":{\"last\":\"/test2\"}");
+ }
+
+ @Test
+ public void copy() {
+ // copy /test to /test2/copy
+ commit("/", "* \"test\": \"/test2/copy\"");
+ Assert.assertEquals("{a,b,c}", getNode("/test"));
+ Assert.assertEquals("{copy:{a,b,c}}", getNode("/test2"));
+
+ if (isMemoryKernel(mk)) {
+ assertJournal("*\"/test\":\"/test2/copy\"");
+ } else {
+ assertJournal("+\"/test2/copy\":{\"a\":{},\"b\":{},\"c\":{}}");
+ }
+ }
+
+ @Test
+ public void move() {
+ // move /test/b to /test2
+ commit("/", "> \"test/b\": \"/test2/b\"");
+ Assert.assertEquals("{a,c}", getNode("/test"));
+ Assert.assertEquals("{b}", getNode("/test2"));
+ assertJournal(">\"/test/b\":\"/test2/b\"");
+
+ // move /test/a to /test2
+ commit("/", "> \"test/a\": \"test2/a1\"");
+ Assert.assertEquals("{c}", getNode("/test"));
+ Assert.assertEquals("{b,a1}", getNode("/test2"));
+ assertJournal(">\"/test/a\":\"/test2/a1\"");
+
+ // move /test/c to /test2
+ commit("/", "> \"test/c\": \"test2/c\"");
+ Assert.assertEquals("{}", getNode("/test"));
+ Assert.assertEquals("{b,a1,c}", getNode("/test2"));
+ assertJournal(">\"/test/c\":\"/test2/c\"");
+ }
+
+ @Test
+ public void moveTryOverwriteExisting() {
+ // move /test/b to /test2
+ commit("/", "> \"test/b\": \"/test2/b\"");
+
+ try {
+ // try to move /test/a to /test2/b
+ commit("/", "> \"test/a\": \"/test2/b\"");
+ fail();
+ } catch (Exception e) {
+ // expected
+ }
+ }
+
+ private void commit(String root, String diff) {
+ head = mk.commit(root, diff, head, null);
+ }
+
+ private String getNode(String node) {
+ String s = mk.getNodes(node, mk.getHeadRevision());
+ s = s.replaceAll("\"", "").replaceAll(":childNodeCount:.", "");
+ s = s.replaceAll("\\{\\,", "\\{").replaceAll("\\,\\}", "\\}");
+ s = s.replaceAll("\\:\\{\\}", "");
+ s = s.replaceAll(",,", ",");
+ return s;
+ }
+
+ private void assertJournal(String expectedJournal) {
+ Assert.assertEquals(expectedJournal, getJournal());
+ }
+
+ private String getJournal() {
+ if (journalRevision == null) {
+ String revs = mk.getRevisions(0, 1);
+ JsopTokenizer t = new JsopTokenizer(revs);
+ t.read('[');
+ do {
+ t.read('{');
+ Assert.assertEquals("id", t.readString());
+ t.read(':');
+ journalRevision = t.readString();
+ t.read(',');
+ Assert.assertEquals("ts", t.readString());
+ t.read(':');
+ t.read(JsopTokenizer.NUMBER);
+ t.read('}');
+ } while (t.matches(','));
+ }
+ String head = mk.getHeadRevision();
+ String journal = mk.getJournal(journalRevision, head);
+ JsopTokenizer t = new JsopTokenizer(journal);
+ StringBuilder buff = new StringBuilder();
+ t.read('[');
+ boolean isNew = false;
+ do {
+ t.read('{');
+ Assert.assertEquals("id", t.readString());
+ t.read(':');
+ t.readString();
+ t.read(',');
+ Assert.assertEquals("ts", t.readString());
+ t.read(':');
+ t.read(JsopTokenizer.NUMBER);
+ t.read(',');
+ Assert.assertEquals("msg", t.readString());
+ t.read(':');
+ t.read();
+ t.read(',');
+ Assert.assertEquals("changes", t.readString());
+ t.read(':');
+ String changes = t.readString().trim();
+ if (isNew) {
+ if (buff.length() > 0) {
+ buff.append('\n');
+ }
+ buff.append(changes);
+ }
+ // the first revision isn't new, all others are
+ isNew = true;
+ t.read('}');
+ } while (t.matches(','));
+ journalRevision = head;
+ return buff.toString();
+ }
+
+}
\ No newline at end of file