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:25 UTC

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

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