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 c74d4f6a3709d79479fc8a4300f885ce297c7221
Author: Bertrand Delacretaz <[email protected]>
AuthorDate: Wed Aug 26 16:43:46 2020 +0200

    Basic navigation, properties filtering and api/metadata/content/children 
output
---
 dokapi/.gitignore                                  |  2 +
 dokapi/pom.xml                                     | 18 ++++-
 .../sling/dokapi/impl/ChildrenProcessor.java       | 49 +++++++++++++
 .../apache/sling/dokapi/impl/ContentProcessor.java | 34 +++++++++
 .../apache/sling/dokapi/impl/DokapiServlet.java    | 64 +++++++++++++++++
 .../apache/sling/dokapi/impl/JsonProcessor.java    | 24 +++++++
 .../sling/dokapi/impl/MetadataProcessor.java       | 34 +++++++++
 .../main/java/org/apache/sling/dokapi/impl/P.java  | 76 ++++++++++++++++++++
 .../apache/sling/dokapi/impl/PipelineContext.java  | 81 ++++++++++++++++++++++
 9 files changed, 381 insertions(+), 1 deletion(-)

diff --git a/dokapi/.gitignore b/dokapi/.gitignore
new file mode 100644
index 0000000..f87a37c
--- /dev/null
+++ b/dokapi/.gitignore
@@ -0,0 +1,2 @@
+conf/
+launcher/
diff --git a/dokapi/pom.xml b/dokapi/pom.xml
index 232a9fa..c6dcde1 100644
--- a/dokapi/pom.xml
+++ b/dokapi/pom.xml
@@ -82,7 +82,17 @@
           <commandlineArgs>-s src/test/resources/features/feature-sling12.json 
-af src/test/resources/features/feature-dokapi-test.json</commandlineArgs>
         </configuration>
       </plugin>
-    </plugins>
+      <plugin>
+        <groupId>org.apache.rat</groupId>
+        <artifactId>apache-rat-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>launcher/**</exclude>
+            <exclude>conf/**</exclude>
+        </excludes>
+      </configuration>
+    </plugin>
+</plugins>
   </build>
 
   <dependencies>
@@ -119,6 +129,12 @@
       <version>0.0.2</version>
       <scope>runtime</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.commons.johnzon</artifactId>
+      <version>1.2.2</version>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 
 </project>
diff --git 
a/dokapi/src/main/java/org/apache/sling/dokapi/impl/ChildrenProcessor.java 
b/dokapi/src/main/java/org/apache/sling/dokapi/impl/ChildrenProcessor.java
new file mode 100644
index 0000000..7ba1fa7
--- /dev/null
+++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/ChildrenProcessor.java
@@ -0,0 +1,49 @@
+/*
+ * 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.dokapi.impl;
+
+import javax.json.Json;
+import javax.json.JsonObjectBuilder;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+
+class ChildrenProcessor implements JsonProcessor {
+    @Override
+    public void process(PipelineContext pc) {
+        if(pc.resource.hasChildren()) {
+            for(Resource child: pc.resource.getChildren()) {
+                if(P.ignoreResource(child.getName())) {
+                    continue;
+                }
+                final JsonObjectBuilder childBuilder = 
Json.createObjectBuilder();
+                final ValueMap vm = child.adaptTo(ValueMap.class);
+                if(vm != null) {
+                    childBuilder.add("_path", child.getPath());
+                    childBuilder.add("_url", pc.pathToUrl(child.getPath()));
+                    P.maybeAdd(childBuilder, "sling:resourceType", 
"_resourceType", vm);
+                    P.maybeAddOneOf(childBuilder, "title", vm, P.TITLE_PROPS);
+                    P.maybeAddOneOf(childBuilder, "name", vm, P.NAME_PROPS);
+                }
+                pc.children.add(child.getName(), childBuilder.build());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/dokapi/src/main/java/org/apache/sling/dokapi/impl/ContentProcessor.java 
b/dokapi/src/main/java/org/apache/sling/dokapi/impl/ContentProcessor.java
new file mode 100644
index 0000000..0f4c9f4
--- /dev/null
+++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/ContentProcessor.java
@@ -0,0 +1,34 @@
+/*
+ * 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.dokapi.impl;
+
+import org.apache.sling.api.resource.ValueMap;
+
+class ContentProcessor implements JsonProcessor {
+    @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);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/dokapi/src/main/java/org/apache/sling/dokapi/impl/DokapiServlet.java 
b/dokapi/src/main/java/org/apache/sling/dokapi/impl/DokapiServlet.java
new file mode 100644
index 0000000..346b7b9
--- /dev/null
+++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/DokapiServlet.java
@@ -0,0 +1,64 @@
+/*
+ * 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.dokapi.impl;
+
+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;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.osgi.service.component.annotations.Component;
+
+/** Main Dokapi servlet */
+@Component(service = Servlet.class,
+    name="org.apache.sling.servlets.get.DefaultGetServlet",
+    property = {
+            "service.description=Sling Dokapi Servlet",
+            "service.vendor=The Apache Software Foundation",
+
+            "sling.servlet.resourceTypes=sling/servlet/default",
+            "sling.servlet.prefix:Integer=-1",
+
+            "sling.servlet.methods=GET",
+            "sling.servlet.methods=HEAD",
+            "sling.servlet.selectors=dkp",
+            "sling.servlet.extension=json",
+    })
+public class DokapiServlet extends SlingSafeMethodsServlet {
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public void doGet(SlingHttpServletRequest request, 
SlingHttpServletResponse response) throws IOException {
+        final PipelineContext pc = new PipelineContext(request);
+        new MetadataProcessor().process(pc);
+        new ChildrenProcessor().process(pc);
+        new ContentProcessor().process(pc);
+        final JsonObject json = pc.build();
+
+        response.setCharacterEncoding("UTF-8");
+        response.setContentType("application/json");
+        response.getWriter().write(json.toString());
+    }
+}
\ No newline at end of file
diff --git 
a/dokapi/src/main/java/org/apache/sling/dokapi/impl/JsonProcessor.java 
b/dokapi/src/main/java/org/apache/sling/dokapi/impl/JsonProcessor.java
new file mode 100644
index 0000000..228b974
--- /dev/null
+++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/JsonProcessor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.dokapi.impl;
+
+public interface JsonProcessor {
+    void process(PipelineContext pc);
+}
\ No newline at end of file
diff --git 
a/dokapi/src/main/java/org/apache/sling/dokapi/impl/MetadataProcessor.java 
b/dokapi/src/main/java/org/apache/sling/dokapi/impl/MetadataProcessor.java
new file mode 100644
index 0000000..9ed90f4
--- /dev/null
+++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/MetadataProcessor.java
@@ -0,0 +1,34 @@
+/*
+ * 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.dokapi.impl;
+
+import org.apache.sling.api.resource.ValueMap;
+
+class MetadataProcessor implements JsonProcessor {
+    @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.metadata, key, P.convertName(key), vm);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/dokapi/src/main/java/org/apache/sling/dokapi/impl/P.java 
b/dokapi/src/main/java/org/apache/sling/dokapi/impl/P.java
new file mode 100644
index 0000000..1f5bce6
--- /dev/null
+++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/P.java
@@ -0,0 +1,76 @@
+/*
+ * 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.dokapi.impl;
+
+import javax.json.Json;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObjectBuilder;
+
+import org.apache.sling.api.resource.ValueMap;
+
+class P {
+    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) {
+        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());
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    static void maybeAddOneOf(JsonObjectBuilder b, String propName, ValueMap 
vm, String [] props) {
+        for(String prop : NAME_PROPS) {
+            if(maybeAdd(b, prop, propName, vm)) {
+                break;
+            }
+        }
+    }
+
+    static boolean ignoreProperty(String key) {
+        return key.startsWith("jcr:");
+    }
+
+    static boolean ignoreResource(String name) {
+        return name.startsWith("rep:");
+    }
+
+    static String convertName(String in) {
+        return in.replace("sling:", "_");
+    }
+
+    static boolean isMetadata(String propName) {
+        return propName.startsWith("sling:");
+    }
+}
\ No newline at end of file
diff --git 
a/dokapi/src/main/java/org/apache/sling/dokapi/impl/PipelineContext.java 
b/dokapi/src/main/java/org/apache/sling/dokapi/impl/PipelineContext.java
new file mode 100644
index 0000000..06e6d8e
--- /dev/null
+++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/PipelineContext.java
@@ -0,0 +1,81 @@
+/*
+ * 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.dokapi.impl;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+
+public class PipelineContext {
+    private final SlingHttpServletRequest request;
+    public final Resource resource;
+    public final JsonObjectBuilder api;
+    public final JsonObjectBuilder metadata;
+    public final JsonObjectBuilder children;
+    public final JsonObjectBuilder content;
+
+    PipelineContext(SlingHttpServletRequest request) {
+        this.request = request;
+        resource = request.getResource();
+
+        // TODO should create these on demand
+        api = Json.createObjectBuilder();
+        metadata = Json.createObjectBuilder();
+        children = Json.createObjectBuilder();
+        content = Json.createObjectBuilder();
+
+        api.add("_url", pathToUrl(resource.getPath()));
+        if(resource.getParent() != null) {
+            api.add("_parentUrl", pathToUrl(resource.getParent().getPath()));
+        }
+        api.add("_id", resource.getPath());
+    }
+
+    private void maybeAdd(JsonObjectBuilder target, String key, 
JsonObjectBuilder src) {
+        final JsonObject jo = src.build();
+        if(!jo.isEmpty()) {
+            target.add(key, jo);
+        }
+    }
+
+    JsonObject build() {
+        final JsonObjectBuilder b = Json.createObjectBuilder();
+        maybeAdd(b, "api", api);
+        maybeAdd(b, "metadata", metadata);
+        maybeAdd(b, "content", content);
+        maybeAdd(b, "children", children);
+        return b.build();
+    }
+
+    String pathToUrl(String path) {
+        return String.format(
+            "%s://%s:%d%s.%s.%s",
+            request.getScheme(),
+            request.getServerName(),
+            request.getServerPort(),
+            path,
+            request.getRequestPathInfo().getSelectorString(),
+            request.getRequestPathInfo().getExtension()
+        );
+    }
+}
\ No newline at end of file

Reply via email to