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