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 2018/08/15 15:30:31 UTC

[sling-whiteboard] 02/05: Factor out rendering logic

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 5f482edc494ab713468d2e9873ff9368599004a2
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Wed Aug 15 17:20:41 2018 +0200

    Factor out rendering logic
---
 .../sling/resourceschemas/api/RenderingLogic.java  |  25 +++++
 .../resourceschemas/api/ResourceRenderer.java      |  48 ++++++++++
 .../impl/DefaultRenderingLogic.java                |  75 +++++++++++++++
 .../servlets/DefaultHtmlServlet.java               |  39 ++------
 .../HtmlResourceRenderer.java}                     | 105 ++++++++++++---------
 5 files changed, 216 insertions(+), 76 deletions(-)

diff --git a/resource-schemas/src/main/java/org/apache/sling/resourceschemas/api/RenderingLogic.java b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/api/RenderingLogic.java
new file mode 100644
index 0000000..cc6f09e
--- /dev/null
+++ b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/api/RenderingLogic.java
@@ -0,0 +1,25 @@
+/*
+ * 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.resourceschemas.api;
+
+import java.io.IOException;
+import org.apache.sling.api.resource.Resource;
+
+public interface RenderingLogic {
+    public void render(Resource r, ResourceSchema s, ResourceRenderer rr) throws IOException;
+}
\ No newline at end of file
diff --git a/resource-schemas/src/main/java/org/apache/sling/resourceschemas/api/ResourceRenderer.java b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/api/ResourceRenderer.java
new file mode 100644
index 0000000..3974771
--- /dev/null
+++ b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/api/ResourceRenderer.java
@@ -0,0 +1,48 @@
+/*
+ * 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.resourceschemas.api;
+
+import java.io.IOException;
+import org.apache.sling.api.resource.Resource;
+
+public interface ResourceRenderer {
+    
+    enum NavigationType {
+        PARENT,
+        CHILD,
+        SELF
+    }
+    
+    class NavigationItem {
+        public final NavigationType type;
+        public final Resource resource;
+        public final ResourceSchema schema;
+        
+        public NavigationItem(NavigationType t, Resource r, ResourceSchema s) {
+            type = t;
+            resource = r;
+            schema = s;
+        }
+    }
+    
+    public void renderPrefix(Resource r, ResourceSchema s) throws IOException;
+    public void renderSuffix(Resource r, ResourceSchema s) throws IOException;
+    public void renderContent(Resource r, ResourceSchema s) throws IOException;
+    public void renderNavigationItems(Resource r, NavigationItem ... item) throws IOException;
+    public void renderActions(Resource r, ResourceAction ... action) throws IOException;
+}
\ No newline at end of file
diff --git a/resource-schemas/src/main/java/org/apache/sling/resourceschemas/impl/DefaultRenderingLogic.java b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/impl/DefaultRenderingLogic.java
new file mode 100644
index 0000000..db7d465
--- /dev/null
+++ b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/impl/DefaultRenderingLogic.java
@@ -0,0 +1,75 @@
+/*
+ * 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.resourceschemas.impl;
+
+import org.apache.sling.resourceschemas.api.*;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.resourceschemas.api.ResourceRenderer.NavigationItem;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component(service = RenderingLogic.class,
+    property = {
+            "service.description=Sling Resource Schemas - Default Rendering Logic",
+            "service.vendor=The Apache Software Foundation"
+    })
+public class DefaultRenderingLogic implements RenderingLogic {
+
+    private static NavigationItem [] NI_ARRAY = {};
+    private static ResourceAction [] ACT_ARRAY = {};
+    
+    // TODO: pagination would be better...
+    public static final int MAX_NAV_CHILDREN = 20;
+    
+    @Reference
+    private ResourceSchemaRegistry registry;
+    
+    @Override
+    public void render(Resource r, ResourceSchema s, ResourceRenderer rr) throws IOException {
+        
+        rr.renderPrefix(r, s);
+        
+        final List<NavigationItem> nav = new ArrayList<>();
+        
+        // Navigation
+        if(r.getParent() != null) {
+            final Resource parent = r.getParent();
+            nav.add(new NavigationItem(ResourceRenderer.NavigationType.PARENT, parent, registry.getSchema(parent.getResourceType())));
+        }
+        
+        int availableLinks = MAX_NAV_CHILDREN;
+        final Iterator<Resource> it = r.getResourceResolver().listChildren(r);
+        while(it.hasNext()) {
+            if(availableLinks-- <= 0) {
+                // TODO do something about it
+                break;
+            }
+            final Resource child = it.next();
+            nav.add(new NavigationItem(ResourceRenderer.NavigationType.CHILD, child, registry.getSchema(child.getResourceType())));
+        }
+        
+        rr.renderNavigationItems(r, nav.toArray(NI_ARRAY));
+        rr.renderContent(r, s);
+        rr.renderActions(r, s.getActions().toArray(ACT_ARRAY));
+        rr.renderSuffix(r, s);
+    }
+}
\ No newline at end of file
diff --git a/resource-schemas/src/main/java/org/apache/sling/resourceschemas/servlets/DefaultHtmlServlet.java b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/servlets/DefaultHtmlServlet.java
index 1de08af..a78e46f 100644
--- a/resource-schemas/src/main/java/org/apache/sling/resourceschemas/servlets/DefaultHtmlServlet.java
+++ b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/servlets/DefaultHtmlServlet.java
@@ -18,7 +18,6 @@
 package org.apache.sling.resourceschemas.servlets;
 
 import java.io.IOException;
-import java.io.PrintWriter;
 import javax.servlet.Servlet;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
@@ -26,13 +25,11 @@ import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
-import org.apache.sling.resourceschemas.api.CreateChildAction;
-import org.apache.sling.resourceschemas.api.ResourceAction;
+import org.apache.sling.resourceschemas.api.RenderingLogic;
 import org.apache.sling.resourceschemas.api.ResourceSchema;
-import org.apache.sling.resourceschemas.impl.HtmlGenerator;
+import org.apache.sling.resourceschemas.api.ResourceSchemaRegistry;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
-import org.apache.sling.resourceschemas.api.ResourceSchemaRegistry;
 
 /** SlingServlet that generates the default HTML representations
  *  to allow CRUD operations on resources backed by Sling Resource Schemas
@@ -51,6 +48,9 @@ public class DefaultHtmlServlet extends SlingSafeMethodsServlet {
     @Reference
     private ResourceSchemaRegistry registry;
     
+    @Reference
+    private RenderingLogic renderingLogic;
+    
     @Override
     protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
 
@@ -66,33 +66,8 @@ public class DefaultHtmlServlet extends SlingSafeMethodsServlet {
         
         response.setCharacterEncoding("UTF-8");
         response.setContentType("text/html");
-        
-        final PrintWriter w = response.getWriter();
-        w.println("<html><body><div class='srs-page'>");
-        w.println("<h1>Sling Resource Schemas: generated edit forms<br/>for " + r.getPath() + "</h1><hr/>\n");
-        
-        final HtmlGenerator h = new HtmlGenerator(request, w);
-        h.generateNavigation(r);
-        h.generateEditForm(r, m);
-        w.println();
 
-        if(!m.getActions().isEmpty()) {
-            w.println("<h2>Actions</h2>");
-        }
-        for(ResourceAction a : m.getActions()) {
-            if(a instanceof CreateChildAction) {
-                final CreateChildAction cca = (CreateChildAction)a;
-                final ResourceSchema em = registry.getSchema(cca.getResourceType());
-                if(em == null) {
-                    w.println("<p>WARNING: ResourceSchema not found for resource type " + cca.getResourceType() + "</p>");
-                } else {
-                    h.generateCreateForm(r.getPath(), em);
-                }
-                w.println();
-            }
-        }
-        
-        w.println("\n</div></body></html>\n");
-        w.flush();
+        renderingLogic.render(r, m, new HtmlResourceRenderer(registry, request, response.getWriter()));
+        response.getWriter().flush();
     }
 }
diff --git a/resource-schemas/src/main/java/org/apache/sling/resourceschemas/impl/HtmlGenerator.java b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/servlets/HtmlResourceRenderer.java
similarity index 68%
rename from resource-schemas/src/main/java/org/apache/sling/resourceschemas/impl/HtmlGenerator.java
rename to resource-schemas/src/main/java/org/apache/sling/resourceschemas/servlets/HtmlResourceRenderer.java
index e95e391..4c000e8 100644
--- a/resource-schemas/src/main/java/org/apache/sling/resourceschemas/impl/HtmlGenerator.java
+++ b/resource-schemas/src/main/java/org/apache/sling/resourceschemas/servlets/HtmlResourceRenderer.java
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.sling.resourceschemas.impl;
+package org.apache.sling.resourceschemas.servlets;
 
+import java.io.IOException;
 import java.io.PrintWriter;
-import java.util.Iterator;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ValueMap;
@@ -27,68 +27,85 @@ import org.apache.sling.api.request.ResponseUtil;
 
 
 /** Define a Property of a Resource: name, type, required etc */
-public class HtmlGenerator {
+class HtmlResourceRenderer implements ResourceRenderer {
 
-    private final PrintWriter w;
     private final SlingHttpServletRequest request;
+    private final PrintWriter w;
+    private final ResourceSchemaRegistry registry;
     
-    // TODO: pagination would be better...
-    public static final int MAX_NAV_CHILDREN = 20;
-    
-    public HtmlGenerator(SlingHttpServletRequest request, PrintWriter pw) {
+    HtmlResourceRenderer(ResourceSchemaRegistry rsr, SlingHttpServletRequest request, PrintWriter writer) {
         this.request = request;
-        this.w = pw;
+        this.w = writer;
+        this.registry = rsr;
+    }
+ 
+    @Override
+    public void renderPrefix(Resource r, ResourceSchema s) throws IOException {
+        w.println("<html><body><div class='srs-page'>");
+        w.println("<h1>Sling Resource Schemas: generated edit forms<br/>for " + r.getPath() + "</h1><hr/>\n");
     }
     
-    public String addSelectorsAndExtension(SlingHttpServletRequest request, String path) {
-        final StringBuilder sb = new StringBuilder(path);
-        for(String selector : request.getRequestPathInfo().getSelectors()) {
-            sb.append(".").append(selector);
-        }
-        final String ext = request.getRequestPathInfo().getExtension();
-        if(ext != null && ext.length() > 0) {
-            sb.append(".").append(ext);
+    @Override
+    public void renderSuffix(Resource r, ResourceSchema s) throws IOException {
+        w.println("\n</div></body></html>\n");
+    }
+    
+    public void renderContent(Resource r, ResourceSchema s) throws IOException {
+        if(s.getProperties().isEmpty()) {
+            return;
         }
-        return sb.toString();
+        form(
+            s, 
+            r.adaptTo(ValueMap.class), 
+            "Edit the current Resource",
+            r.getPath() + " (" + s.getDescription() + ")",
+            "srs-edit-form",
+            "", 
+            addSelectorsAndExtension(request, r.getPath()),
+            null);
     }
     
-    public void generateNavigation(Resource r) {
+    public void renderNavigationItems(Resource r, NavigationItem ... items) throws IOException {
         w.println("<div class='srs-navigation'><h2>Navigation</h2>");
         w.println("<ul>");
         
-        if(r.getParent() != null) {
-            link("li", ".. (parent Resource)", addSelectorsAndExtension(request, r.getParent().getPath()));
+        for(NavigationItem i : items) {
+            final String prefix = i.type == NavigationType.PARENT ? "^" : "-";
+            link("ul", prefix + " " + i.resource.getName(), addSelectorsAndExtension(request, i.resource.getPath()));
+        }
+        
+        w.println("</ul></div>");
+    }
+    
+    public void renderActions(Resource r, ResourceAction ... actions) throws IOException {
+        
+        if(actions.length == 0) {
+            w.println("<h2>No Actions available here</h2>");
+        } else {
+            w.println("<h2>Actions</h2>");
         }
         
-        int availableLinks = MAX_NAV_CHILDREN;
-        final Iterator<Resource> it = r.getResourceResolver().listChildren(r);
-        while(it.hasNext()) {
-            if(availableLinks-- <= 0) {
-                w.println("<li><em>Stopping at " + MAX_NAV_CHILDREN + " links</em></li>");
-                break;
+        for(ResourceAction act : actions) {
+            if(act instanceof CreateChildAction) {
+                final CreateChildAction cca = (CreateChildAction)act;
+                generateCreateForm(r.getPath(), registry.getSchema(cca.getResourceType()));
             }
-            final Resource child = it.next();
-            link("li", child.getName(), addSelectorsAndExtension(request, child.getPath()));
         }
-        w.println("</ul></div>");
     }
     
-    public void generateEditForm(Resource r, ResourceSchema m) {
-        if(m.getProperties().isEmpty()) {
-            return;
+    private String addSelectorsAndExtension(SlingHttpServletRequest request, String path) {
+        final StringBuilder sb = new StringBuilder(path);
+        for(String selector : request.getRequestPathInfo().getSelectors()) {
+            sb.append(".").append(selector);
         }
-        form(
-            m, 
-            r.adaptTo(ValueMap.class), 
-            "Edit the current Resource",
-            r.getPath() + " (" + m.getDescription() + ")",
-            "srs-edit-form",
-            "", 
-            addSelectorsAndExtension(request, r.getPath()),
-            null);
+        final String ext = request.getRequestPathInfo().getExtension();
+        if(ext != null && ext.length() > 0) {
+            sb.append(".").append(ext);
+        }
+        return sb.toString();
     }
     
-    public void generateCreateForm(String parentPath, ResourceSchema m) {
+    private void generateCreateForm(String parentPath, ResourceSchema m) {
         form(
             m, 
             null,
@@ -100,7 +117,7 @@ public class HtmlGenerator {
             ResourceSchemasConstants.SRS_FORM_MARKER_PARAMETER);
     }
     
-     public void form(ResourceSchema m, ValueMap vm, String title, String subtitle, String cssClass, String actionPath, String redirectPath, String formMarkerFieldName) {
+    private void form(ResourceSchema m, ValueMap vm, String title, String subtitle, String cssClass, String actionPath, String redirectPath, String formMarkerFieldName) {
         // TODO should use templates
         // TODO escape values
         w.println("<br/>");