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);
+    }
+}


Reply via email to