SLING-7792 - Resource Resolver should return more than one resolved path if available

Add a new ResourceMapper class that exposes more fine-grained information about the
resolution mappings.
diff --git a/src/main/java/org/apache/sling/api/resource/ResourceResolver.java b/src/main/java/org/apache/sling/api/resource/ResourceResolver.java
index 2899ea0..0cc9ba7 100644
--- a/src/main/java/org/apache/sling/api/resource/ResourceResolver.java
+++ b/src/main/java/org/apache/sling/api/resource/ResourceResolver.java
@@ -27,6 +27,7 @@
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.sling.api.adapter.Adaptable;
+import org.apache.sling.api.resource.mapping.ResourceMapper;
 import org.osgi.annotation.versioning.ProviderType;
 
 /**
@@ -257,54 +258,16 @@
     @NotNull Resource resolve(@NotNull HttpServletRequest request);
 
     /**
-     * Returns a path mapped from the (resource) path applying the reverse
-     * mapping used by the {@link #resolve(String)} such that when the path is
-     * given to the {@link #resolve(String)} method the same resource is
-     * returned.
-     * <p>
-     * Note, that technically the <code>resourcePath</code> need not refer to an
-     * existing resource. This method just applies the mappings and returns the
-     * resulting string. If the <code>resourcePath</code> does not address an
-     * existing resource roundtripping may of course not work and calling
-     * {@link #resolve(String)} with the path returned may return
-     * <code>null</code>.
-     * <p>
-     * This method is intended as the reverse operation of the
-     * {@link #resolve(String)} method.
-     *
-     * @param resourcePath The path for which to return a mapped path.
-     * @return The mapped path.
-     * @throws IllegalStateException if this resource resolver has already been
-     *             {@link #close() closed}.
+     * Returns a path mapped from the (resource) path
+     * 
+     * @see {@link ResourceMapper#getMapping(String, HttpServletRequest)}
      */
     @NotNull String map(@NotNull String resourcePath);
 
     /**
-     * Returns an URL mapped from the (resource) path applying the reverse
-     * mapping used by the {@link #resolve(HttpServletRequest, String)} such
-     * that when the path is given to the
-     * {@link #resolve(HttpServletRequest, String)} method the same resource is
-     * returned.
-     * <p>
-     * Note, that technically the <code>resourcePath</code> need not refer to an
-     * existing resource. This method just applies the mappings and returns the
-     * resulting string. If the <code>resourcePath</code> does not address an
-     * existing resource roundtripping may of course not work and calling
-     * {@link #resolve(HttpServletRequest, String)} with the path returned may
-     * return <code>null</code>.
-     * <p>
-     * This method is intended as the reverse operation of the
-     * {@link #resolve(HttpServletRequest, String)} method. As such the URL
-     * returned is expected to be an absolute URL including scheme, host, any
-     * servlet context path and the actual path used to resolve the resource.
-     *
-     * @param request The http servlet request object which may be used to apply
-     *            more mapping functionality.
-     * @param resourcePath The path for which to return a mapped path.
-     * @return The mapped URL.
-     * @throws IllegalStateException if this resource resolver has already been
-     *             {@link #close() closed}.
-     * @since 2.0.4 (Sling API Bundle 2.0.4)
+     * Returns an URL mapped from the (resource) path
+     * 
+     * @see {@link ResourceMapper#getMapping(String, HttpServletRequest)}
      */
     @Nullable String map(@NotNull HttpServletRequest request, @NotNull String resourcePath);
 
diff --git a/src/main/java/org/apache/sling/api/resource/mapping/ResourceMapper.java b/src/main/java/org/apache/sling/api/resource/mapping/ResourceMapper.java
new file mode 100644
index 0000000..53086d5
--- /dev/null
+++ b/src/main/java/org/apache/sling/api/resource/mapping/ResourceMapper.java
@@ -0,0 +1,136 @@
+/*
+ * 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.api.resource.mapping;
+
+import java.util.Collection;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Allows access to resource mappings
+ * 
+ * <p>This interface superceeds the resource mapping functionality present
+ * in the {@link ResourceResolver}. Although the methods present in that
+ * interface will continue to work, the resource mapper will provide better
+ * APIs to access the resource mappings.</p>
+ * 
+ * <p>Implementations of this class are obtained by adapting a {@link ResourceResolver}
+ * instance. As such, the mappings returned by its methods reflect the repository
+ * permissions of the underyling resolver instance.</p> 
+ */
+@ProviderType
+public interface ResourceMapper {
+    
+    /**
+     * Returns a path mapped from the (resource) path applying the reverse
+     * mapping used by the {@link ResourceResolver#resolve(String)} such that when the path is
+     * given to the {@link ResourceResolver#resolve(String)} method the same resource is
+     * returned.
+     * <p>
+     * Note, that technically the <code>resourcePath</code> need not refer to an
+     * existing resource. This method just applies the mappings and returns the
+     * resulting string. If the <code>resourcePath</code> does not address an
+     * existing resource roundtripping may of course not work and calling
+     * {@link ResourceResolver#resolve(String)} with the path returned may return
+     * <code>null</code>.
+     * <p>
+     * This method is intended as the reverse operation of the
+     * {@link ResourceResolver#resolve(String)} method.
+     *
+     * @param resourcePath The path for which to return a mapped path.
+     * @return The mapped path.
+     * @throws IllegalStateException if the underlying resource resolver has already been
+     *             {@link ResourceResolver#close() closed}.
+     *
+     * @since 1.0.0 (Sling API Bundle 2.19.0)
+     */
+    @NotNull String getMapping(@NotNull String resourcePath);
+
+    /**
+     * Returns an URL mapped from the (resource) path applying the reverse
+     * mapping used by the {@link ResourceResolver#resolve(HttpServletRequest, String)} such
+     * that when the path is given to the
+     * {@link ResourceResolver#resolve(HttpServletRequest, String)} method the same resource is
+     * returned.
+     * <p>
+     * Note, that technically the <code>resourcePath</code> need not refer to an
+     * existing resource. This method just applies the mappings and returns the
+     * resulting string. If the <code>resourcePath</code> does not address an
+     * existing resource roundtripping may of course not work and calling
+     * {@link ResourceResolver#resolve(HttpServletRequest, String)} with the path returned may
+     * return <code>null</code>.
+     * <p>
+     * This method is intended as the reverse operation of the
+     * {@link ResourceResolver#resolve(HttpServletRequest, String)} method. As such the URL
+     * returned is expected to be an absolute URL including scheme, host, any
+     * servlet context path and the actual path used to resolve the resource.
+
+     * @param resourcePath The path for which to return a mapped path.
+     * @param request The http servlet request object which may be used to apply
+     *            more mapping functionality.
+     * @return The mapped URL.
+     * @throws IllegalStateException if the underlying resource resolver has already been
+     *             {@link ResourceResolver#close() closed}.
+     * @since 1.0.0 (Sling API Bundle 2.19.0)
+     */
+    @NotNull String getMapping(@NotNull String resourcePath, @NotNull HttpServletRequest request);
+    
+    /**
+     * Retuns all possible mappings for a given <tt>resourcePath</tt> as paths.
+     * 
+     * <p>
+     * This method differs from the {@link #getMapping(String)} variant
+     * by guaranteeing that all possible mappings are returned for a specified path.
+     * 
+     * <p>
+     * The mappings are not returned in any particular order.
+     * 
+     * @param resourcePath The path for which to return a mapped path.
+     * @return a collection of mapped URLs, in no particular order. May not be null or empty.
+     * @throws IllegalStateException if the underlying resource resolver has already been
+     *             {@link ResourceResolver#close() closed}.
+     * @since 1.0.0 (Sling API Bundle 2.19.0)
+     */
+    Collection<String> getAllMappings(@NotNull String resourcePath);
+
+    /**
+     * Retuns all possible mappings for a given <tt>resourcePath</tt> as URLs.
+     * 
+     * <p>
+     * This method differs from the {@link #getMapping(String, HttpServletRequest)} variant
+     * by guaranteeing that all possible mappings are returned for a specified path.
+     * 
+     * <p>
+     * The mappings are not returned in any particular order.
+     * 
+     * @param resourcePath The path for which to return a mapped path.
+     * @param request The http servlet request object which may be used to apply
+     *            more mapping functionality.
+
+     * @return a collection of mapped URLs, in no particular order. May not be null or empty.
+     * @throws IllegalStateException if the underlying resource resolver has already been
+     *             {@link ResourceResolver#close() closed}.
+     * @since 1.0.0 (Sling API Bundle 2.19.0)
+     */
+    Collection<String> getAllMappings(@NotNull String resourcePath, @NotNull HttpServletRequest request);
+}
diff --git a/src/main/java/org/apache/sling/api/resource/mapping/package-info.java b/src/main/java/org/apache/sling/api/resource/mapping/package-info.java
new file mode 100644
index 0000000..b3f937d
--- /dev/null
+++ b/src/main/java/org/apache/sling/api/resource/mapping/package-info.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.
+ */
+
+@Version("1.0.0")
+package org.apache.sling.api.resource.mapping;
+
+import org.osgi.annotation.versioning.Version;
+