Author: bdelacretaz
Date: Wed Jul 6 14:25:52 2016
New Revision: 1751688
URL: http://svn.apache.org/viewvc?rev=1751688&view=rev
Log:
SLING-5682 - import ordered nodes from JSON array structures, contributed by
Nicolas Peltier, thanks!
Added:
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReader.java
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReaderTest.java
Modified:
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
Modified:
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java?rev=1751688&r1=1751687&r2=1751688&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
(original)
+++
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
Wed Jul 6 14:25:52 2016
@@ -104,7 +104,7 @@ public class JsonReader implements Conte
private static final String NAME = "jcr:name:";
private static final String URI = "jcr:uri:";
- private static final Set<String> ignoredNames = new HashSet<String>();
+ protected static final Set<String> ignoredNames = new HashSet<String>();
static {
ignoredNames.add("jcr:primaryType");
ignoredNames.add("jcr:mixinTypes");
@@ -160,6 +160,36 @@ public class JsonReader implements Conte
}
}
+ protected boolean handleSecurity(String n, Object o, ContentCreator
contentCreator) throws JSONException, RepositoryException{
+ if (SECURITY_PRINCIPLES.equals(n)) {
+ this.createPrincipals(o, contentCreator);
+ } else if (SECURITY_ACL.equals(n)) {
+ this.createAcl(o, contentCreator);
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ protected void writeChildren(JSONObject obj, ContentCreator
contentCreator) throws JSONException, RepositoryException{
+ // add properties and nodes
+ JSONArray names = obj.names();
+ for (int i = 0; names != null && i < names.length(); i++) {
+ final String n = names.getString(i);
+ // skip well known objects
+ if (!ignoredNames.contains(n)) {
+ Object o = obj.get(n);
+ if (!handleSecurity(n, o, contentCreator)) {
+ if (o instanceof JSONObject) {
+ this.createNode(n, (JSONObject) o, contentCreator);
+ } else {
+ this.createProperty(n, o, contentCreator);
+ }
+ }
+ }
+ }
+ }
+
protected void createNode(String name, JSONObject obj, ContentCreator
contentCreator)
throws JSONException, RepositoryException {
Object primaryTypeObj = obj.opt("jcr:primaryType");
@@ -179,25 +209,7 @@ public class JsonReader implements Conte
}
contentCreator.createNode(name, primaryType, mixinTypes);
-
- // add properties and nodes
- JSONArray names = obj.names();
- for (int i = 0; names != null && i < names.length(); i++) {
- final String n = names.getString(i);
- // skip well known objects
- if (!ignoredNames.contains(n)) {
- Object o = obj.get(n);
- if (SECURITY_PRINCIPLES.equals(n)) {
- this.createPrincipals(o, contentCreator);
- } else if (SECURITY_ACL.equals(n)) {
- this.createAcl(o, contentCreator);
- } else if (o instanceof JSONObject) {
- this.createNode(n, (JSONObject) o, contentCreator);
- } else {
- this.createProperty(n, o, contentCreator);
- }
- }
- }
+ writeChildren(obj, contentCreator);
contentCreator.finishNode();
}
@@ -225,7 +237,7 @@ public class JsonReader implements Conte
}
}
- protected int getType(String name, Object object) {
+ private int getType(String name, Object object) {
if (object instanceof Double || object instanceof Float) {
return PropertyType.DOUBLE;
} else if (object instanceof Number) {
@@ -244,7 +256,7 @@ public class JsonReader implements Conte
return PropertyType.UNDEFINED;
}
- protected String getName(String name) {
+ private String getName(String name) {
if (name.startsWith(REFERENCE)) return
name.substring(REFERENCE.length());
if (name.startsWith(PATH)) return name.substring(PATH.length());
if (name.startsWith(NAME)) return name.substring(NAME.length());
@@ -321,7 +333,7 @@ public class JsonReader implements Conte
/**
* Create or update a user or group
*/
- protected void createPrincipal(JSONObject json, ContentCreator
contentCreator)
+ private void createPrincipal(JSONObject json, ContentCreator
contentCreator)
throws JSONException, RepositoryException {
//create a principal
String name = json.getString("name");
@@ -381,7 +393,7 @@ public class JsonReader implements Conte
* }
* </code>
*/
- protected void createAcl(Object obj, ContentCreator contentCreator)
+ private void createAcl(Object obj, ContentCreator contentCreator)
throws JSONException, RepositoryException {
if (obj instanceof JSONObject) {
//single ace
@@ -403,7 +415,7 @@ public class JsonReader implements Conte
/**
* Create or update an access control entry
*/
- protected void createAce(JSONObject ace, ContentCreator contentCreator)
+ private void createAce(JSONObject ace, ContentCreator contentCreator)
throws JSONException, RepositoryException {
String principalID = ace.getString("principal");
Added:
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReader.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReader.java?rev=1751688&view=auto
==============================================================================
---
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReader.java
(added)
+++
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReader.java
Wed Jul 6 14:25:52 2016
@@ -0,0 +1,94 @@
+/*
+ * 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.sling.jcr.contentloader.internal.readers;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.jcr.contentloader.ContentCreator;
+import org.apache.sling.jcr.contentloader.ContentReader;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Specific <code>JsonReader</code>, <code>OrderedJsonReader</code> parse json
document exactly the same,
+ * but does specific look up for SLING:ordered : [{SLING:name: "first",
...},{SLING:name: "second", ...}]
+ * type of structure that will force import of an orderable node with first &
second
+ * children, in that order.
+ * Note that this is the reponsability of the json file to set appropriate
node type / mixins.
+ */
+@Component(inherit = false)
+@Service
+@Properties({
+ @Property(name = ContentReader.PROPERTY_EXTENSIONS, value =
"ordered-json"),
+ @Property(name = ContentReader.PROPERTY_TYPES, value =
"application/json")
+})
+public class OrderedJsonReader extends JsonReader {
+
+ private static final String PN_ORDEREDCHILDREN = "SLING:ordered";
+ private static final String PN_ORDEREDCHILDNAME = "SLING:name";
+
+ @Override
+ protected void writeChildren(JSONObject obj, ContentCreator
contentCreator) throws JSONException, RepositoryException {
+ if (! obj.has(PN_ORDEREDCHILDREN)) {
+ super.writeChildren(obj, contentCreator);
+ } else {
+ JSONArray names = obj.names();
+ for (int i = 0; names != null && i < names.length(); i++) {
+ final String n = names.getString(i);
+ // skip well known objects
+ if (!ignoredNames.contains(n)) {
+ Object o = obj.get(n);
+ if (!handleSecurity(n, o, contentCreator)) {
+ if (n.equals(PN_ORDEREDCHILDREN)) {
+ if (o instanceof JSONArray) {
+ JSONArray children = (JSONArray) o;
+ for (int childIndex = 0; childIndex <
children.length(); childIndex++) {
+ Object oc = children.get(childIndex);
+ if (oc instanceof JSONObject) {
+ JSONObject child = (JSONObject) oc;
+ String childName =
child.optString(PN_ORDEREDCHILDNAME);
+ if (StringUtils.isNotBlank(childName))
{
+ child.remove(PN_ORDEREDCHILDNAME);
+ this.createNode(childName, child,
contentCreator);
+ } else {
+ throw new
JSONException(PN_ORDEREDCHILDREN + " children must have a name whose key is " +
PN_ORDEREDCHILDNAME);
+ }
+ } else {
+ throw new
JSONException(PN_ORDEREDCHILDREN + " array must only have JSONObject items");
+ }
+
+ }
+ } else {
+ throw new JSONException(PN_ORDEREDCHILDREN + "
value must be a JSON array");
+ }
+ }
+ } else {
+ this.createProperty(n, o, contentCreator);
+ }
+ }
+ }
+ }
+ }
+}
Modified:
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java?rev=1751688&r1=1751687&r2=1751688&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
(original)
+++
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
Wed Jul 6 14:25:52 2016
@@ -39,16 +39,20 @@ import org.junit.runner.RunWith;
@RunWith(JMock.class)
public class JsonReaderTest {
- JsonReader jsonReader;
+ protected JsonReader jsonReader;
- Mockery mockery = new JUnit4Mockery();
+ protected Mockery mockery = new JUnit4Mockery();
- ContentCreator creator;
+ protected ContentCreator creator;
- Sequence mySequence;
+ protected Sequence mySequence;
- @org.junit.Before public void setUp() throws Exception {
+ protected void setReader() {
this.jsonReader = new JsonReader();
+ }
+
+ @org.junit.Before public void setUp() throws Exception {
+ setReader();
this.creator = this.mockery.mock(ContentCreator.class);
this.mySequence = this.mockery.sequence("my-sequence");
}
@@ -339,14 +343,14 @@ public class JsonReaderTest {
//---------- internal helper ----------------------------------------------
- private void parse(String json) throws IOException, RepositoryException {
+ protected void parse(String json) throws IOException, RepositoryException {
String charSet = "ISO-8859-1";
json = "#" + charSet + "\r\n" + json;
InputStream ins = new ByteArrayInputStream(json.getBytes(charSet));
this.jsonReader.parse(ins, this.creator);
}
- private JSONArray toJsonArray(String[] array) throws JSONException {
+ protected JSONArray toJsonArray(String[] array) throws JSONException {
return new JSONArray(Arrays.asList(array));
}
}
Added:
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReaderTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReaderTest.java?rev=1751688&view=auto
==============================================================================
---
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReaderTest.java
(added)
+++
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/OrderedJsonReaderTest.java
Wed Jul 6 14:25:52 2016
@@ -0,0 +1,56 @@
+/*
+ * 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.sling.jcr.contentloader.internal.readers;
+
+import org.apache.sling.jcr.contentloader.internal.JsonReaderTest;
+import org.jmock.Expectations;
+import org.jmock.integration.junit4.JMock;
+import org.junit.runner.RunWith;
+
+/**
+ * testing specific ordered json import case:
+ * - should work with all normal json cases,
+ * - should work for specific ordered case
+ */
+@RunWith(JMock.class)
+public class OrderedJsonReaderTest extends JsonReaderTest {
+
+ @Override
+ protected void setReader() {
+ this.jsonReader = new OrderedJsonReader();
+ }
+
+ @org.junit.Test public void testTwoOrderedChildren() throws Exception {
+ String json = "{ " +
+ " 'SLING:ordered' : [" +
+ "{ 'SLING:name': c1}," +
+ "{ 'SLING:name': c2}" +
+ "]" +
+ "}";
+ this.mockery.checking(new Expectations() {{
+ allowing(creator).createNode(null, null, null);
inSequence(mySequence);
+ allowing(creator).createNode("c1", null, null);
inSequence(mySequence);
+ allowing(creator).finishNode(); inSequence(mySequence);
+ allowing(creator).createNode("c2", null, null);
inSequence(mySequence);
+ allowing(creator).finishNode(); inSequence(mySequence);
+ allowing(creator).finishNode(); inSequence(mySequence);
+ }});
+ this.parse(json);
+ }
+}