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/11/18 16:30:32 UTC
[sling-whiteboard] branch master updated: Switch to ContentMapper
implementation (with the Java classes this time)
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
The following commit(s) were added to refs/heads/master by this push:
new 9b69bbd Switch to ContentMapper implementation (with the Java classes this time)
9b69bbd is described below
commit 9b69bbd032e88e43379472e2f2ef2d53a3e229e4
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Wed Nov 18 17:21:24 2020 +0100
Switch to ContentMapper implementation (with the Java classes this time)
---
.../apache/sling/contentmapper/ContentMapper.java | 37 ++++++++++
.../apache/sling/contentmapper/MappingTarget.java | 40 +++++++++++
.../sling/contentmapper/impl/ApiContentMapper.java | 46 ++++++++++++
.../contentmapper/impl/ContentContentMapper.java | 57 +++++++++++++++
.../contentmapper/impl/JsonMappingTarget.java | 34 +++++++++
.../sling/contentmapper/impl/JsonTargetNode.java | 84 ++++++++++++++++++++++
.../impl/NavigationContentMapper.java | 51 +++++++++++++
.../org/apache/sling/testservlet/TestServlet.java | 63 ++++++++++++++++
.../org/apache/sling/testservlet/UrlBuilder.java | 51 +++++++++++++
9 files changed, 463 insertions(+)
diff --git a/remote-content-api/src/main/java/org/apache/sling/contentmapper/ContentMapper.java b/remote-content-api/src/main/java/org/apache/sling/contentmapper/ContentMapper.java
new file mode 100644
index 0000000..fd2eb14
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/contentmapper/ContentMapper.java
@@ -0,0 +1,37 @@
+/*
+ * 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.contentmapper;
+
+import org.apache.sling.api.resource.Resource;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Maps Sling {@link Resource} to a {@link MappingTarget.TargetNode}
+ */
+public interface ContentMapper {
+
+ String ROLE = "sling.content.mapper.role";
+
+ interface UrlBuilder {
+ String pathToUrl(String path);
+ }
+
+ void map(@NotNull Resource r, @NotNull MappingTarget.TargetNode destination, UrlBuilder urlb);
+}
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/contentmapper/MappingTarget.java b/remote-content-api/src/main/java/org/apache/sling/contentmapper/MappingTarget.java
new file mode 100644
index 0000000..33b0e2a
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/contentmapper/MappingTarget.java
@@ -0,0 +1,40 @@
+/*
+ * 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.contentmapper;
+
+import org.apache.sling.api.adapter.Adaptable;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A target for content mapping, usually implemented by a Map of Maps, a JSON
+ * document tree, etc.
+ */
+public interface MappingTarget {
+ String TARGET_TYPE = "sling.mapping.target.type";
+
+ interface TargetNode extends Adaptable {
+ TargetNode addChild(String name);
+ TargetNode addValue(String name, Object value);
+ TargetNode addValue(String name, Object [] value);
+ void close();
+ }
+
+ @NotNull TargetNode newTargetNode();
+}
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/ApiContentMapper.java b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/ApiContentMapper.java
new file mode 100644
index 0000000..7d5308f
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/ApiContentMapper.java
@@ -0,0 +1,46 @@
+/*
+ * 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.contentmapper.impl;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.contentmapper.ContentMapper;
+import org.apache.sling.contentmapper.MappingTarget;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component(service = ContentMapper.class, property = { ContentMapper.ROLE + "=api" })
+public class ApiContentMapper implements ContentMapper {
+
+ @Reference(target="(" + ContentMapper.ROLE + "=navigation)")
+ private ContentMapper navMapper;
+
+ @Reference(target="(" + ContentMapper.ROLE + "=content)")
+ private ContentMapper contentMapper;
+
+ @Override
+ public void map(@NotNull Resource r, @NotNull MappingTarget.TargetNode dest, UrlBuilder urlb) {
+ final MappingTarget.TargetNode n = dest.addChild("navigation");
+ navMapper.map(r, n, urlb);
+
+ final MappingTarget.TargetNode c = dest.addChild("content");
+ contentMapper.map(r, c, urlb);
+ }
+}
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/ContentContentMapper.java b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/ContentContentMapper.java
new file mode 100644
index 0000000..d1f83e0
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/ContentContentMapper.java
@@ -0,0 +1,57 @@
+/*
+ * 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.contentmapper.impl;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.contentmapper.ContentMapper;
+import org.apache.sling.contentmapper.MappingTarget;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Component;
+
+@Component(service = ContentMapper.class, property = { ContentMapper.ROLE + "=content" })
+public class ContentContentMapper implements ContentMapper {
+
+ @Override
+ public void map(@NotNull Resource r, @NotNull MappingTarget.TargetNode dest, UrlBuilder urlb) {
+ dest
+ .addValue("source", getClass().getName())
+ .addValue("path", r.getPath())
+ ;
+ addValues(dest, r);
+ }
+
+ private static void addValues(MappingTarget.TargetNode dest, Resource r) {
+ final ValueMap vm = r.adaptTo(ValueMap.class);
+ if(vm != null) {
+ for(Map.Entry<String, Object> e : vm.entrySet()) {
+ final Object value = e.getValue();
+ if(value instanceof Object[]) {
+ dest.addValue(e.getKey(), Arrays.asList((Object[])value));
+ } else {
+ dest.addValue(e.getKey(), String.valueOf(value));
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/JsonMappingTarget.java b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/JsonMappingTarget.java
new file mode 100644
index 0000000..b85fdfb
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/JsonMappingTarget.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.contentmapper.impl;
+
+import org.apache.sling.contentmapper.MappingTarget;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Component;
+
+/** MappingTarget that outputs to a JSON document */
+@Component(service = MappingTarget.class, property = { MappingTarget.TARGET_TYPE + "=json" })
+public class JsonMappingTarget implements MappingTarget {
+
+ @Override
+ public @NotNull TargetNode newTargetNode() {
+ return new JsonTargetNode("ROOT_THIS_NAME_SHOULD_NOT_APPEAR_IN_OUTPUT");
+ }
+}
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/JsonTargetNode.java b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/JsonTargetNode.java
new file mode 100644
index 0000000..1d51c0c
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/JsonTargetNode.java
@@ -0,0 +1,84 @@
+/*
+ * 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.contentmapper.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.json.Json;
+import javax.json.JsonObjectBuilder;
+
+import org.apache.sling.contentmapper.MappingTarget;
+import org.apache.sling.contentmapper.MappingTarget.TargetNode;
+
+/** A TargetNode that outputs to a JSON document */
+public class JsonTargetNode implements MappingTarget.TargetNode {
+
+ private final String name;
+ private final JsonObjectBuilder builder;
+ private List<JsonTargetNode> children;
+
+ JsonTargetNode(String name) {
+ this.name = name;
+ this.builder = Json.createObjectBuilder();
+ }
+
+ @Override
+ public TargetNode addChild(String name) {
+ if(children == null) {
+ children = new ArrayList<>();
+ }
+ final JsonTargetNode child = new JsonTargetNode(name);
+ children.add(child);
+ return child;
+ }
+
+ @Override
+ public TargetNode addValue(String name, Object value) {
+ builder.add(name, String.valueOf(value));
+ return this;
+ }
+
+ @Override
+ public TargetNode addValue(String name, Object[] value) {
+ builder.add(name, String.valueOf(Arrays.asList(value)));
+ return this;
+ }
+
+ @Override
+ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+ if(type.equals(String.class)) {
+ close();
+ return (AdapterType)builder.build().toString();
+ }
+ throw new IllegalArgumentException("For now, can only adapt to a String");
+ }
+
+ @Override
+ public void close() {
+ if(children != null) {
+ children.stream().forEach(c -> {
+ c.close();
+ builder.add(c.name, c.builder);
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/NavigationContentMapper.java b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/NavigationContentMapper.java
new file mode 100644
index 0000000..22aa79a
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/contentmapper/impl/NavigationContentMapper.java
@@ -0,0 +1,51 @@
+/*
+ * 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.contentmapper.impl;
+
+import java.util.Map;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.contentmapper.ContentMapper;
+import org.apache.sling.contentmapper.MappingTarget;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Component;
+
+@Component(service = ContentMapper.class, property = { ContentMapper.ROLE + "=navigation" })
+public class NavigationContentMapper implements ContentMapper {
+
+ @Override
+ public void map(@NotNull Resource r, @NotNull MappingTarget.TargetNode dest, UrlBuilder urlb) {
+ dest.addValue("self", urlb.pathToUrl(r.getPath()));
+
+ final Resource parent = r.getParent();
+ if(parent != null) {
+ dest.addValue("parent", urlb.pathToUrl(parent.getPath()));
+ }
+
+ final MappingTarget.TargetNode children = dest.addChild("children");
+ for(Resource child : r.getChildren()) {
+ children
+ .addChild(child.getName())
+ .addValue("url", urlb.pathToUrl(child.getPath()))
+ .addValue("path", child.getPath())
+ ;
+ }
+ }
+}
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/testservlet/TestServlet.java b/remote-content-api/src/main/java/org/apache/sling/testservlet/TestServlet.java
new file mode 100644
index 0000000..0462669
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/testservlet/TestServlet.java
@@ -0,0 +1,63 @@
+/*
+ * 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.testservlet;
+
+import java.io.IOException;
+
+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.apache.sling.contentmapper.ContentMapper;
+import org.apache.sling.contentmapper.MappingTarget;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/** Render the current Resource to JSON */
+@Component(service = Servlet.class,
+ property = {
+ "sling.servlet.resourceTypes=sling/servlet/default",
+ "sling.servlet.prefix:Integer=-1",
+
+ "sling.servlet.methods=GET",
+ "sling.servlet.methods=HEAD",
+ "sling.servlet.selectors=s:ts",
+ "sling.servlet.extension=json",
+ })
+public class TestServlet extends SlingSafeMethodsServlet {
+ private static final long serialVersionUID = 1L;
+
+ @Reference(target="(" + MappingTarget.TARGET_TYPE + "=json)")
+ private transient MappingTarget mappingTarget;
+
+ @Reference(target="(" + ContentMapper.ROLE + "=api)")
+ private transient ContentMapper contentMapper;
+
+ @Override
+ public void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
+
+ MappingTarget.TargetNode target = mappingTarget.newTargetNode();
+ contentMapper.map(request.getResource(), target, new UrlBuilder(request));
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application/json");
+ response.getWriter().write(target.adaptTo(String.class));
+ }
+}
\ No newline at end of file
diff --git a/remote-content-api/src/main/java/org/apache/sling/testservlet/UrlBuilder.java b/remote-content-api/src/main/java/org/apache/sling/testservlet/UrlBuilder.java
new file mode 100644
index 0000000..43cd0ae
--- /dev/null
+++ b/remote-content-api/src/main/java/org/apache/sling/testservlet/UrlBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * 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.testservlet;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.contentmapper.ContentMapper;
+
+class UrlBuilder implements ContentMapper.UrlBuilder {
+ private SlingHttpServletRequest request;
+
+ UrlBuilder(SlingHttpServletRequest request) {
+ this.request = request;
+ }
+
+ public String pathToUrlNoExtension(String path) {
+ return String.format(
+ "%s://%s:%d%s",
+ request.getScheme(),
+ request.getServerName(),
+ request.getServerPort(),
+ path
+ );
+ }
+
+ @Override
+ public String pathToUrl(String path) {
+ return String.format(
+ "%s.%s.%s",
+ pathToUrlNoExtension(path),
+ request.getRequestPathInfo().getSelectorString(),
+ request.getRequestPathInfo().getExtension()
+ );
+ }
+}
\ No newline at end of file