You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2020/09/03 13:58:23 UTC

[sling-whiteboard] branch master updated (50a4e24 -> 819c093)

This is an automated email from the ASF dual-hosted git repository.

bdelacretaz pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git.


    from 50a4e24  Make space for a different prototype
     new cc8bd9e  Rough, hardcoded experiment with more complex content structures
     new 819c093  Change to ResourceConverter

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../hardcodedfirstshot/ContentProcessor.java       |  32 +++--
 .../HardcodedFirstShotServlet.java                 |   2 -
 .../remotecontentapi/hardcodedfirstshot/P.java     |  36 +++---
 .../hardcodedfirstshot/PipelineContext.java        |  15 ++-
 .../resourceconverter/ResourceConverter.java       | 140 +++++++++++++++++++++
 5 files changed, 196 insertions(+), 29 deletions(-)
 create mode 100644 remote-content-api/src/main/java/org/apache/sling/remotecontentapi/resourceconverter/ResourceConverter.java


[sling-whiteboard] 01/02: Rough, hardcoded experiment with more complex content structures

Posted by bd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bdelacretaz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git

commit cc8bd9e133b9456143490e5e9367fb635c31d13c
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Thu Sep 3 13:34:40 2020 +0200

    Rough, hardcoded experiment with more complex content structures
---
 .../hardcodedfirstshot/ContentProcessor.java       | 82 ++++++++++++++++++++--
 .../hardcodedfirstshot/PipelineContext.java        | 13 +++-
 2 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/ContentProcessor.java b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/ContentProcessor.java
index 92fc063..b145517 100644
--- a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/ContentProcessor.java
+++ b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/ContentProcessor.java
@@ -19,16 +19,90 @@
 
 package org.apache.sling.remotecontentapi.hardcodedfirstshot;
 
+import javax.json.Json;
+import javax.json.JsonObjectBuilder;
+
+import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ValueMap;
 
 class ContentProcessor implements JsonProcessor {
+    private static final int MAX_RECURSION = 99;
+    private static final String JCR_CONTENT = "jcr:content";
+
     @Override
     public void process(PipelineContext pc) {
-        final ValueMap vm = pc.resource.adaptTo(ValueMap.class);
-        for(String key : vm.keySet()) {
-            if(!P.ignoreProperty(key) && !P.isMetadata(key)) {
-                P.maybeAdd(pc.content, key, P.convertName(key), vm);
+        processResource(pc, pc.content, pc.resource, true, MAX_RECURSION);
+    }
+
+    private boolean isNodeType(ValueMap vm, String nodeType) {
+        return vm == null ? false : nodeType.equals(vm.get("jcr:primaryType", String.class));
+    }
+
+    private boolean ignoreResource(Resource r) {
+        final String name = r.getName();
+        if(name.startsWith("cq:")) {
+            return !name.equals("cq:tags");
+        }
+        final ValueMap vm = r.adaptTo(ValueMap.class);
+        if(isNodeType(vm, "cq:Page")) {
+                return true;
+        }
+        return false;
+    }
+
+    private String convertPropertyName(String name) {
+        if(!name.contains(":")) {
+            return name;
+        } else if(name.equals("jcr:title")) {
+            return "title";
+        } else if(name.equals("jcr:description")) {
+            return "description";
+        } else if(name.equals("sling:resourceType")) {
+            return "_resourceType";
+        } else {
+            return null;
+        }
+    }
+
+    private void processResource(PipelineContext pc, JsonObjectBuilder json, Resource r, boolean contentRootMode, int maxRecursion) {
+        if(maxRecursion <= 0) {
+            return;
+        }
+        final ValueMap vm = r.adaptTo(ValueMap.class);
+
+        if(isNodeType(vm, "nt:file")) {
+            json.add("url", pc.pathToUrlNoJsonExtension(r.getPath()));
+            return;
+        }
+        
+        if(vm != null) {
+            for(String key : vm.keySet()) {
+                final String newName = convertPropertyName(key);
+                if(newName != null) {
+                    P.maybeAdd(json, key, newName, vm);
+                }
             }
         }
+
+        if(contentRootMode) {
+            final Resource content = r.getChild(JCR_CONTENT);
+            if(content != null) {
+                json.addAll(visitContentResource(pc, content, maxRecursion - 1));
+            }
+        } else if(r.hasChildren()) {
+            final JsonObjectBuilder b = Json.createObjectBuilder();
+            for(Resource child : r.getChildren()) {
+                if(!ignoreResource(child)) {
+                    b.add(child.getName(), visitContentResource(pc, child, maxRecursion - 1));
+                }
+            }
+            json.addAll(b);
+        }
+    }
+
+    private JsonObjectBuilder visitContentResource(PipelineContext pc, Resource r, int maxRecursion) {
+        final JsonObjectBuilder b = Json.createObjectBuilder();
+        processResource(pc, b, r, false, maxRecursion - 1);
+        return b;
     }
 }
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/PipelineContext.java b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/PipelineContext.java
index 8d2893b..7ae342d 100644
--- a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/PipelineContext.java
+++ b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/PipelineContext.java
@@ -66,13 +66,20 @@ public class PipelineContext {
         return b.build();
     }
 
-    String pathToUrl(String path) {
+    String pathToUrlNoJsonExtension(String path) {
         return String.format(
-            "%s://%s:%d%s.%s.%s",
+            "%s://%s:%d%s",
             request.getScheme(),
             request.getServerName(),
             request.getServerPort(),
-            path,
+            path
+        );
+    }
+
+    String pathToUrl(String path) {
+        return String.format(
+            "%s.%s.%s",
+            pathToUrlNoJsonExtension(path),
             request.getRequestPathInfo().getSelectorString(),
             request.getRequestPathInfo().getExtension()
         );


[sling-whiteboard] 02/02: Change to ResourceConverter

Posted by bd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bdelacretaz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git

commit 819c093aba5d31b5706b8b9ddafe77c536940825
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Thu Sep 3 15:58:08 2020 +0200

    Change to ResourceConverter
---
 .../hardcodedfirstshot/ContentProcessor.java       |  90 +++----------
 .../HardcodedFirstShotServlet.java                 |   2 -
 .../remotecontentapi/hardcodedfirstshot/P.java     |  36 +++---
 .../hardcodedfirstshot/PipelineContext.java        |   2 +-
 .../resourceconverter/ResourceConverter.java       | 140 +++++++++++++++++++++
 5 files changed, 178 insertions(+), 92 deletions(-)

diff --git a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/ContentProcessor.java b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/ContentProcessor.java
index b145517..31b2761 100644
--- a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/ContentProcessor.java
+++ b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/ContentProcessor.java
@@ -19,90 +19,34 @@
 
 package org.apache.sling.remotecontentapi.hardcodedfirstshot;
 
-import javax.json.Json;
-import javax.json.JsonObjectBuilder;
-
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.remotecontentapi.resourceconverter.ResourceConverter;
 
 class ContentProcessor implements JsonProcessor {
-    private static final int MAX_RECURSION = 99;
-    private static final String JCR_CONTENT = "jcr:content";
-
-    @Override
-    public void process(PipelineContext pc) {
-        processResource(pc, pc.content, pc.resource, true, MAX_RECURSION);
-    }
+    static class ConverterContext implements ResourceConverter.Context {
+        private final PipelineContext pc;
 
-    private boolean isNodeType(ValueMap vm, String nodeType) {
-        return vm == null ? false : nodeType.equals(vm.get("jcr:primaryType", String.class));
-    }
-
-    private boolean ignoreResource(Resource r) {
-        final String name = r.getName();
-        if(name.startsWith("cq:")) {
-            return !name.equals("cq:tags");
-        }
-        final ValueMap vm = r.adaptTo(ValueMap.class);
-        if(isNodeType(vm, "cq:Page")) {
-                return true;
+        ConverterContext(PipelineContext pc) {
+            this.pc = pc;
         }
-        return false;
-    }
 
-    private String convertPropertyName(String name) {
-        if(!name.contains(":")) {
-            return name;
-        } else if(name.equals("jcr:title")) {
-            return "title";
-        } else if(name.equals("jcr:description")) {
-            return "description";
-        } else if(name.equals("sling:resourceType")) {
-            return "_resourceType";
-        } else {
-            return null;
-        }
-    }
-
-    private void processResource(PipelineContext pc, JsonObjectBuilder json, Resource r, boolean contentRootMode, int maxRecursion) {
-        if(maxRecursion <= 0) {
-            return;
-        }
-        final ValueMap vm = r.adaptTo(ValueMap.class);
-
-        if(isNodeType(vm, "nt:file")) {
-            json.add("url", pc.pathToUrlNoJsonExtension(r.getPath()));
-            return;
-        }
-        
-        if(vm != null) {
-            for(String key : vm.keySet()) {
-                final String newName = convertPropertyName(key);
-                if(newName != null) {
-                    P.maybeAdd(json, key, newName, vm);
-                }
+        @Override
+        public String getUrlForPath(String path, boolean includeApiSelectorsAndExtension) {
+            if(includeApiSelectorsAndExtension) {
+                return pc.pathToUrl(path);
+            } else {
+                return pc.pathToUrlNoJsonExtension(path);
             }
         }
 
-        if(contentRootMode) {
-            final Resource content = r.getChild(JCR_CONTENT);
-            if(content != null) {
-                json.addAll(visitContentResource(pc, content, maxRecursion - 1));
-            }
-        } else if(r.hasChildren()) {
-            final JsonObjectBuilder b = Json.createObjectBuilder();
-            for(Resource child : r.getChildren()) {
-                if(!ignoreResource(child)) {
-                    b.add(child.getName(), visitContentResource(pc, child, maxRecursion - 1));
-                }
-            }
-            json.addAll(b);
+        @Override
+        public String getRelativePath(Resource r) {
+            return r.getPath().substring(pc.resource.getPath().length());
         }
     }
 
-    private JsonObjectBuilder visitContentResource(PipelineContext pc, Resource r, int maxRecursion) {
-        final JsonObjectBuilder b = Json.createObjectBuilder();
-        processResource(pc, b, r, false, maxRecursion - 1);
-        return b;
+    @Override
+    public void process(PipelineContext pc) {
+        pc.content.addAll(new ResourceConverter(pc.resource, new ConverterContext(pc)).getJson());
     }
 }
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/HardcodedFirstShotServlet.java b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/HardcodedFirstShotServlet.java
index ce48ef7..5cec04d 100644
--- a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/HardcodedFirstShotServlet.java
+++ b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/HardcodedFirstShotServlet.java
@@ -21,9 +21,7 @@ package org.apache.sling.remotecontentapi.hardcodedfirstshot;
 
 import java.io.IOException;
 
-import javax.json.Json;
 import javax.json.JsonObject;
-import javax.json.JsonObjectBuilder;
 import javax.servlet.Servlet;
 
 import org.apache.sling.api.SlingHttpServletRequest;
diff --git a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/P.java b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/P.java
index 168833f..1c1b2ad 100644
--- a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/P.java
+++ b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/P.java
@@ -25,33 +25,37 @@ import javax.json.JsonObjectBuilder;
 
 import org.apache.sling.api.resource.ValueMap;
 
-class P {
+public class P {
     static final String [] IGNORE_RESOURCE_PREIX = { "jcr:", "rep:", "oak:" };
     static final String [] TITLE_PROPS = { "jcr:title", "title" };
     static final String [] NAME_PROPS = { "jcr:name", "name" };
     static final String [] TEXT_PROPS = { "jcr:text", "text" };
     static final String [] DESCRIPTION_PROPS = { "jcr:description", "description" };
 
-    static boolean maybeAdd(JsonObjectBuilder b, String propName, String jsonName, ValueMap vm) {
+    public static boolean maybeAdd(JsonObjectBuilder b, String propName, String jsonName, ValueMap vm) {
         if(vm.containsKey(propName)) {
             final Object value = vm.get(propName);
             if(value != null) {
-                if(value instanceof Object[]) {
-                    final JsonArrayBuilder a = Json.createArrayBuilder();
-                    for(Object o : (Object[])value) {
-                        a.add(o.toString());
-                    }
-                    b.add(jsonName, a.build());
-                } else {
-                    b.add(jsonName, value.toString());
-                }
+                addValue(b, jsonName, value);
             }
             return true;
         }
         return false;
     }
 
-    static void maybeAddOneOf(JsonObjectBuilder b, String propName, ValueMap vm, String [] props) {
+    public static void addValue(JsonObjectBuilder json, String key, Object value) {
+        if(value instanceof Object[]) {
+            final JsonArrayBuilder a = Json.createArrayBuilder();
+            for(Object o : (Object[])value) {
+                a.add(o.toString());
+            }
+            json.add(key, a.build());
+        } else {
+            json.add(key, value.toString());
+        }
+    }
+
+    public static void maybeAddOneOf(JsonObjectBuilder b, String propName, ValueMap vm, String [] props) {
         for(String prop : props) {
             if(maybeAdd(b, prop, propName, vm)) {
                 break;
@@ -59,11 +63,11 @@ class P {
         }
     }
 
-    static boolean ignoreProperty(String key) {
+    public static boolean ignoreProperty(String key) {
         return key.startsWith("jcr:");
     }
 
-    static boolean ignoreResource(String name) {
+    public static boolean ignoreResource(String name) {
         for(String prefix : IGNORE_RESOURCE_PREIX) {
             if(name.startsWith(prefix)) {
                 return true;
@@ -72,11 +76,11 @@ class P {
         return false;
     }
 
-    static String convertName(String in) {
+    public static String convertName(String in) {
         return in.replace("sling:", "_");
     }
 
-    static boolean isMetadata(String propName) {
+    public static boolean isMetadata(String propName) {
         return propName.startsWith("sling:");
     }
 }
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/PipelineContext.java b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/PipelineContext.java
index 7ae342d..ada2197 100644
--- a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/PipelineContext.java
+++ b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/hardcodedfirstshot/PipelineContext.java
@@ -61,8 +61,8 @@ public class PipelineContext {
         final JsonObjectBuilder b = Json.createObjectBuilder();
         maybeAdd(b, "navigation", navigation);
         maybeAdd(b, "metadata", metadata);
-        maybeAdd(b, "content", content);
         maybeAdd(b, "children", children);
+        maybeAdd(b, "content", content);
         return b.build();
     }
 
diff --git a/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/resourceconverter/ResourceConverter.java b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/resourceconverter/ResourceConverter.java
new file mode 100644
index 0000000..466cb33
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/remotecontentapi/resourceconverter/ResourceConverter.java
@@ -0,0 +1,140 @@
+/*
+ * 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.remotecontentapi.resourceconverter;
+
+import java.util.Map;
+
+import javax.json.Json;
+import javax.json.JsonObjectBuilder;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.remotecontentapi.hardcodedfirstshot.P;
+
+public class ResourceConverter {
+    public static interface Context {
+        /** Return the full URL to access the given path */
+        String getUrlForPath(String path, boolean includeApiSelectorsAndExtension);
+
+        /** Return r's path relative to the Resource being rendered */
+        String getRelativePath(Resource r);
+    }
+
+    private final Context context;
+    private final Resource resource;
+
+    static interface ResourceProcessor {
+        void process(JsonObjectBuilder json, Resource r);
+    }
+
+    static interface PropertyProcessor {
+        void process(JsonObjectBuilder json, String key, Object value);
+    }
+
+    static class DefaultResourceProcessor implements ResourceProcessor {
+        private final Resource contentRoot;
+        private final Context context;
+
+        DefaultResourceProcessor(Context context, Resource contentRoot) {
+            this.contentRoot = contentRoot;
+            this.context = context;
+        }
+
+        public void process(JsonObjectBuilder json, Resource r) {
+            final JsonObjectBuilder b = Json.createObjectBuilder();
+            final ValueMap vm = r.adaptTo(ValueMap.class);
+            if(vm != null) {
+                final PropertyProcessor pp = new DefaultPropertyProcessor();
+                for(Map.Entry<String, Object> entry : vm.entrySet()) {
+                    pp.process(json, entry.getKey(), entry.getValue());
+                }
+            }
+
+            // Special treatment for nt:file nodes
+            if(isNodeType(vm, "nt:file")) {
+                json.add("url", context.getUrlForPath(r.getPath(), false));
+                return;
+            }
+    
+            if(r.getPath().equals(contentRoot.getPath())) {
+                // At the root, recurse only in the jcr:content child
+                final Resource content = r.getChild("jcr:content");
+                if(content != null) {
+                    process(b, content);
+                }
+            } else if(r.hasChildren()) {
+                for(Resource child : r.getChildren()) {
+                    process(b, child);
+                }
+            }
+
+            if(r.getName().equals("jcr:content")) {
+                json.add("_components", b.build());
+            } else if(vm!=null && vm.containsKey("sling:resourceType")) {
+                final JsonObjectBuilder comp = Json.createObjectBuilder();
+                comp.add("_name", r.getName());
+                comp.addAll(b);
+                json.add("_component", comp);
+            } else {
+                json.add(r.getName(), b.build());
+            }
+        }
+    }
+
+    private static boolean isNodeType(ValueMap vm, String nodeType) {
+        return vm == null ? false : nodeType.equals(vm.get("jcr:primaryType", String.class));
+    }
+
+    static class DefaultPropertyProcessor implements PropertyProcessor {
+        public void process(JsonObjectBuilder json, String key, Object value) {
+            if(value != null) {
+                final String newName = processName(key);
+                if(newName != null) {
+                    P.addValue(json, newName, value);
+                }
+            }
+        }
+
+        private String processName(String propertyName) {
+            if(!propertyName.contains(":")) {
+                return propertyName;
+            } else if(propertyName.equals("jcr:title")) {
+                return "title";
+            } else if(propertyName.equals("jcr:description")) {
+                return "description";
+            } else if(propertyName.equals("sling:resourceType")) {
+                return "_resourceType";
+            } else {
+                return null;
+            }
+        }
+    }
+
+    public ResourceConverter(Resource r, Context ctx) {
+        context = ctx;
+        resource = r;
+    }
+
+    public JsonObjectBuilder getJson() {
+        final JsonObjectBuilder b = Json.createObjectBuilder();
+        new DefaultResourceProcessor(context, resource).process(b, resource);
+        return b;
+    }
+}
\ No newline at end of file