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 2021/05/06 13:40:44 UTC
[sling-whiteboard] branch master updated: Use a class for
Annotations
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 f46c41f Use a class for Annotations
f46c41f is described below
commit f46c41f8d6784ff983665fc43de9d9775a91fb3d
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Thu May 6 15:39:27 2021 +0200
Use a class for Annotations
---
.../documentmapper/api/AnnotationNames.java | 35 ------
.../documentmapper/api/Annotations.java | 127 +++++++++++++++++++++
...ationRegistry.java => AnnotationsRegistry.java} | 5 +-
.../sling/remotecontent/documentmapper/impl/A.java | 34 ------
.../documentmapper/impl/ContentDocumentMapper.java | 33 +++---
.../impl/ContentPropertiesSelector.java | 47 --------
.../documentmapper/impl/PropertiesMapper.java | 5 +-
...istryImpl.java => AnnotationsRegistryImpl.java} | 53 +++++----
8 files changed, 174 insertions(+), 165 deletions(-)
diff --git a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/AnnotationNames.java b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/AnnotationNames.java
deleted file mode 100644
index d4ed5ae..0000000
--- a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/AnnotationNames.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.remotecontent.documentmapper.api;
-
-import org.osgi.annotation.versioning.ProviderType;
-
-@ProviderType
-public interface AnnotationNames {
- String SLING_PREFIX = "sling:";
- String NAVIGABLE = SLING_PREFIX + "isNavigable";
- String DOCUMENT_ROOT = SLING_PREFIX + "documentRoot";
- String VISIT_CONTENT = SLING_PREFIX + "visitContent";
- String VISIT_CONTENT_RESOURCE_NAME_PATTERN = SLING_PREFIX + "visitContentResourceNamePattern";
- String CONTENT_INCLUDE_PROPERTY_REGEXP = SLING_PREFIX + "includePropertyRegexp";
- String CONTENT_EXCLUDE_PROPERTY_REGEXP = SLING_PREFIX + "excludePropertyRegexp";
- String NAVIGATION_PROPERTIES_LIST = SLING_PREFIX + "navigationPropertiesList";
- String DEREFERENCE_BY_PATH = SLING_PREFIX + "dereferenceByPath";
-}
\ No newline at end of file
diff --git a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/Annotations.java b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/Annotations.java
new file mode 100644
index 0000000..c460ac8
--- /dev/null
+++ b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/Annotations.java
@@ -0,0 +1,127 @@
+/*
+ * 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.remotecontent.documentmapper.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/** Document mapping annotations for a given Resource Type */
+@ProviderType
+public class Annotations {
+ public final String resourceType;
+ private boolean navigable;
+ private boolean visitContent;
+ private boolean documentRoot;
+ private Pattern visitContentResourceNamePattern;
+ private Pattern includePropertyPattern;
+ private Pattern excludePropertyPattern;
+ private List<String> dereferenceByPathProperties;
+
+ private Annotations(String resourceType) {
+ this.resourceType = resourceType;
+ }
+
+ // TODO equals + hashcode
+
+ public String getResourceType() {
+ return resourceType;
+ }
+
+ public boolean isNavigable() {
+ return navigable;
+ }
+ public boolean isDocumentRoot() {
+ return documentRoot;
+ }
+
+ public boolean visitContent() {
+ return visitContent;
+ }
+
+ public boolean visitChildResource(String resourceName) {
+ return visitContentResourceNamePattern == null ? true : visitContentResourceNamePattern.matcher(resourceName).matches();
+ }
+
+ public boolean includeProperty(String name) {
+ // include has priority over exclude
+ boolean result = includePropertyPattern == null ? true : includePropertyPattern.matcher(name).matches();
+ if(!result) {
+ result = excludePropertyPattern == null ? true : !excludePropertyPattern.matcher(name).matches();
+ }
+ return result;
+ }
+
+ public Collection<String> dereferenceByPathPropertyNames() {
+ if(dereferenceByPathProperties != null) {
+ return dereferenceByPathProperties;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ public static Builder forResourceType(String resourceType) {
+ return new Builder(resourceType);
+ }
+
+ public static class Builder {
+ private final Annotations target;
+ Builder(String resourceType) {
+ target = new Annotations(resourceType);
+ }
+
+ public Builder withNavigable(boolean b) {
+ target.navigable = b;
+ return this;
+ }
+
+ public Builder withDocumentRoot(boolean b) {
+ target.documentRoot = b;
+ return this;
+ }
+
+ public Builder withVisitContent(boolean b) {
+ target.visitContent = b;
+ return this;
+ }
+
+ public Builder withVisitContentChildResourceNamePattern(String p) {
+ target.visitContentResourceNamePattern = Pattern.compile(p);
+ return this;
+ }
+
+ public Builder withIncludePropertyPattern(String p) {
+ target.includePropertyPattern = Pattern.compile(p);
+ return this;
+ }
+
+ public Builder withExcludePropertyPattern(String p) {
+ target.excludePropertyPattern = Pattern.compile(p);
+ return this;
+ }
+
+ public Annotations build() {
+ return target;
+ }
+ }
+}
\ No newline at end of file
diff --git a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/AnnotationRegistry.java b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/AnnotationsRegistry.java
similarity index 83%
rename from remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/AnnotationRegistry.java
rename to remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/AnnotationsRegistry.java
index c670629..543411f 100644
--- a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/AnnotationRegistry.java
+++ b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/api/AnnotationsRegistry.java
@@ -22,7 +22,6 @@ package org.apache.sling.remotecontent.documentmapper.api;
import org.osgi.annotation.versioning.ProviderType;
@ProviderType
-public interface AnnotationRegistry {
- String getAnnotation(String resourceType, String annotationName);
- boolean hasAnnotation(String resourceType, String annotationName);
+public interface AnnotationsRegistry {
+ Annotations getAnnotations(String resourceType);
}
\ No newline at end of file
diff --git a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/A.java b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/A.java
deleted file mode 100644
index b8239ae..0000000
--- a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/A.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.remotecontent.documentmapper.impl;
-
-import java.util.regex.Pattern;
-
-import org.apache.sling.remotecontent.documentmapper.api.AnnotationRegistry;
-
-/** Annotation utilities
- * TODO should not be needed if we tweak the type system APIs just the right way
- */
-class A {
- static Pattern getAnnotationPattern(AnnotationRegistry registry, String resourceType, String name) {
- final String str = registry.getAnnotation(resourceType, name);
- return str == null ? null : Pattern.compile(str);
- }
-}
\ No newline at end of file
diff --git a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/ContentDocumentMapper.java b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/ContentDocumentMapper.java
index b84c03c..47b95be 100644
--- a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/ContentDocumentMapper.java
+++ b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/ContentDocumentMapper.java
@@ -21,7 +21,8 @@ package org.apache.sling.remotecontent.documentmapper.impl;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.remotecontent.documentmapper.api.AnnotationRegistry;
+import org.apache.sling.remotecontent.documentmapper.api.Annotations;
+import org.apache.sling.remotecontent.documentmapper.api.AnnotationsRegistry;
import org.apache.sling.remotecontent.documentmapper.api.DocumentMapper;
import org.apache.sling.remotecontent.documentmapper.api.MappingTarget;
import org.jetbrains.annotations.NotNull;
@@ -30,12 +31,6 @@ import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static org.apache.sling.remotecontent.documentmapper.api.AnnotationNames.VISIT_CONTENT;
-import static org.apache.sling.remotecontent.documentmapper.api.AnnotationNames.DOCUMENT_ROOT;
-import static org.apache.sling.remotecontent.documentmapper.api.AnnotationNames.VISIT_CONTENT_RESOURCE_NAME_PATTERN;
-
-import static org.apache.sling.remotecontent.documentmapper.api.AnnotationNames.DEREFERENCE_BY_PATH;
-
@Component(service = DocumentMapper.class, property = { DocumentMapper.ROLE + "=content" })
public class ContentDocumentMapper implements DocumentMapper {
@@ -43,26 +38,25 @@ public class ContentDocumentMapper implements DocumentMapper {
private final Logger log = LoggerFactory.getLogger(getClass());
@Reference
- private AnnotationRegistry annotations;
+ private AnnotationsRegistry annotationsRegistry;
@Override
public void map(@NotNull Resource r, @NotNull MappingTarget.TargetNode dest, UrlBuilder urlb) {
final String resourceType = r.getResourceType();
- final ContentPropertiesSelector hints = new ContentPropertiesSelector(annotations, resourceType);
+ final Annotations annot = annotationsRegistry.getAnnotations(resourceType);
dest.addValue("path", r.getPath());
- mapResource(r, dest, urlb, resourceType, hints, annotations.hasAnnotation(resourceType, DOCUMENT_ROOT));
+ mapResource(r, dest, urlb, resourceType, annot, annot.isDocumentRoot());
}
private void mapResource(@NotNull Resource r, @NotNull MappingTarget.TargetNode dest,
- UrlBuilder urlb, String parentResourceType, ContentPropertiesSelector selector, boolean recurse) {
+ UrlBuilder urlb, String parentResourceType, Annotations annot, boolean recurse) {
log.debug("Mapping Resource {} as {}", r.getPath(), r.getResourceType());
- propertiesMapper.mapProperties(dest, r, selector);
+ propertiesMapper.mapProperties(dest, r, annot);
// Dereference by path if specified
// TODO detect cycles which might lead to infinite loops
- final String derefPathPropertyName = annotations.getAnnotation(parentResourceType, DEREFERENCE_BY_PATH);
- if(derefPathPropertyName != null) {
+ annot.dereferenceByPathPropertyNames().forEach(derefPathPropertyName -> {
log.debug("Dereferencing {} on {}", r.getPath(), derefPathPropertyName);
final ValueMap vm = r.adaptTo(ValueMap.class);
final String derefPath = vm == null ? null : vm.get(derefPathPropertyName, String.class);
@@ -70,23 +64,22 @@ public class ContentDocumentMapper implements DocumentMapper {
final Resource dereferenced = r.getResourceResolver().getResource(derefPath);
if(dereferenced != null) {
final MappingTarget.TargetNode derefNode = dest.addChild("dereferenced_by_" + derefPathPropertyName);
- mapResource(dereferenced, derefNode, urlb, parentResourceType, selector, recurse);
+ mapResource(dereferenced, derefNode, urlb, parentResourceType, annot, recurse);
}
}
- }
+ });
// TODO detect too much recursion?
if(recurse) {
log.debug("Recursing into {}", r.getPath());
- final String namePattern = annotations.getAnnotation(parentResourceType, VISIT_CONTENT_RESOURCE_NAME_PATTERN);
for(Resource child : r.getChildren()) {
- if(namePattern != null && !child.getName().equals(namePattern)) {
+ if(!annot.visitChildResource(child.getName())) {
continue;
}
final String childResourceType = child.getResourceType();
- if(annotations.hasAnnotation(childResourceType, VISIT_CONTENT)) {
+ if(annotationsRegistry.getAnnotations(childResourceType).visitContent()) {
final MappingTarget.TargetNode childDest = dest.addChild(child.getName());
- mapResource(child, childDest, urlb, childResourceType, selector, true);
+ mapResource(child, childDest, urlb, childResourceType, annot, true);
}
}
} else if(log.isDebugEnabled()) {
diff --git a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/ContentPropertiesSelector.java b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/ContentPropertiesSelector.java
deleted file mode 100644
index afd6e7c..0000000
--- a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/ContentPropertiesSelector.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.remotecontent.documentmapper.impl;
-
-import java.util.regex.Pattern;
-
-import org.apache.sling.remotecontent.documentmapper.api.AnnotationRegistry;
-
-import static org.apache.sling.remotecontent.documentmapper.api.AnnotationNames.CONTENT_EXCLUDE_PROPERTY_REGEXP;
-import static org.apache.sling.remotecontent.documentmapper.api.AnnotationNames.CONTENT_INCLUDE_PROPERTY_REGEXP;
-
-class ContentPropertiesSelector implements PropertiesSelector {
- private final Pattern includeProperty;
- private final Pattern excludeProperty;
-
- ContentPropertiesSelector(AnnotationRegistry registry, String resourceType) {
- includeProperty = A.getAnnotationPattern(registry, resourceType, CONTENT_INCLUDE_PROPERTY_REGEXP);
- excludeProperty = A.getAnnotationPattern(registry, resourceType, CONTENT_EXCLUDE_PROPERTY_REGEXP);
- }
-
- @Override
- public boolean renderProperty(String name) {
- if(includeProperty != null && includeProperty.matcher(name).matches()) {
- return true;
- } else if(excludeProperty != null && excludeProperty.matcher(name).matches()) {
- return false;
- }
- return true;
- }
-}
\ No newline at end of file
diff --git a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/PropertiesMapper.java b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/PropertiesMapper.java
index fbfd591..1190e6a 100644
--- a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/PropertiesMapper.java
+++ b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/documentmapper/impl/PropertiesMapper.java
@@ -24,14 +24,15 @@ import java.util.Map;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.remotecontent.documentmapper.api.Annotations;
import org.apache.sling.remotecontent.documentmapper.api.MappingTarget;
class PropertiesMapper {
- void mapProperties(MappingTarget.TargetNode dest, Resource r, PropertiesSelector selector) {
+ void mapProperties(MappingTarget.TargetNode dest, Resource r, Annotations annot) {
final ValueMap vm = r.adaptTo(ValueMap.class);
if(vm != null) {
for(Map.Entry<String, Object> e : vm.entrySet()) {
- if(!selector.renderProperty(e.getKey())) {
+ if(!annot.includeProperty(e.getKey())) {
continue;
}
final Object value = e.getValue();
diff --git a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/samples/graphql/annotations/AnnotationRegistryImpl.java b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/samples/graphql/annotations/AnnotationsRegistryImpl.java
similarity index 71%
rename from remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/samples/graphql/annotations/AnnotationRegistryImpl.java
rename to remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/samples/graphql/annotations/AnnotationsRegistryImpl.java
index e28b1e2..5b10de4 100644
--- a/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/samples/graphql/annotations/AnnotationRegistryImpl.java
+++ b/remote-content-api/sample-graphql-api/src/main/java/org/apache/sling/remotecontent/samples/graphql/annotations/AnnotationsRegistryImpl.java
@@ -22,36 +22,44 @@ package org.apache.sling.remotecontent.samples.graphql.annotations;
import java.util.HashMap;
import java.util.Map;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.remotecontent.documentmapper.api.AnnotationRegistry;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.apache.sling.remotecontent.documentmapper.api.Annotations;
+import org.apache.sling.remotecontent.documentmapper.api.AnnotationsRegistry;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
-import static org.apache.sling.remotecontent.documentmapper.api.AnnotationNames.*;
-
/** Temporary hardcoded type system for this prototype, until we
* have the actual type system
* NOTE that this is DUPLICATED from the http sample API module, we'll
* need to refactor!
*/
-@Component(service=AnnotationRegistry.class)
-public class AnnotationRegistryImpl implements AnnotationRegistry {
+@Component(service=AnnotationsRegistry.class)
+public class AnnotationsRegistryImpl implements AnnotationsRegistry {
+
+ private static final Map<String, Annotations> annotations = new HashMap<>();
+ private static final Annotations DEFAULT_ANNOTATIONS;
- private static final String SLING_DEFAULT_RESOURCE_TYPE = "sling/servlet/default";
- private static final Map<String, String> annotations = new HashMap<>();
+ static {
+ DEFAULT_ANNOTATIONS = Annotations.forResourceType("sling/servlet/default")
+ .withVisitContent(true)
+ .build();
+ }
// TODO in many cases we're just interested in the presence of an annotation, but
// not its value - refine this in the type system
- private static final String TRUE = "true";
@Activate
public void activate() {
- // Although these definitions are in Java code for this early prototype, the
- // plan is to move to a mini-language (DSL) to avoid having to use Java
- // code for what is actually just declarative statements.
+ add(
+ Annotations.forResourceType("cg:page")
+ .withDocumentRoot(true)
+ .withNavigable(true)
+ .withVisitContent(true)
+ .withVisitContentChildResourceNamePattern("jcr:content")
+ .withIncludePropertyPattern("sling:ResourceType|cq:tags")
+ .withExcludePropertyPattern("jcr:.*|cq:.*")
+ );
+ /*
add(
Builder.forResourceType("cq:Page")
.withAnnotation(DOCUMENT_ROOT, TRUE)
@@ -97,20 +105,17 @@ public class AnnotationRegistryImpl implements AnnotationRegistry {
Builder.forResourceType("samples/article")
.withAnnotation(NAVIGABLE, TRUE)
);
+ */
}
- private void add(Builder b) {
- b.getAnnotations().forEach(a -> annotations.put(a.getKey(), a.getValue()));
+ private void add(Annotations.Builder b) {
+ final Annotations a = b.build();
+ annotations.put(a.getResourceType(), a);
}
@Override
- public String getAnnotation(String resourceType, String annotationName) {
- return annotations.get(AnnotationImpl.makeKey(resourceType, annotationName));
+ public Annotations getAnnotations(String resourceType) {
+ Annotations result = annotations.get(resourceType);
+ return result == null ? DEFAULT_ANNOTATIONS : result;
}
-
- @Override
- public boolean hasAnnotation(String resourceType, String annotationName) {
- return annotations.containsKey(AnnotationImpl.makeKey(resourceType, annotationName));
- }
-
}
\ No newline at end of file