You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:58:58 UTC

[sling-org-apache-sling-resourcemerger] 18/24: SLING-2986 : Fix resource hiding when parent resource contains attribute but child resource is not available. Reduce resource getting to a minimum

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.resourcemerger-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourcemerger.git

commit d3fa422413894cc8cdc2e82fa080b3d0ccef4b31
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Fri Feb 7 13:38:39 2014 +0000

    SLING-2986 : Fix resource hiding when parent resource contains attribute but child resource is not available. Reduce resource getting to a minimum
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/resourcemerger@1565644 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/resourcemerger/impl/MergedResource.java  |  45 +----
 .../impl/MergedResourceProvider.java               | 199 ++++++++++++++++-----
 .../sling/resourcemerger/impl/MergedValueMap.java  |  49 +++--
 .../impl/MergedResourceProviderTest.java           |  31 ++--
 4 files changed, 196 insertions(+), 128 deletions(-)

diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java
index df1da1a..01a223e 100644
--- a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java
+++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java
@@ -48,19 +48,6 @@ public class MergedResource extends AbstractResource {
      * Constructor
      *
      * @param resolver      Resource resolver
-     * @param mergeRootPath Merge root path
-     * @param relativePath  Relative path
-     */
-    MergedResource(final ResourceResolver resolver,
-                   final String mergeRootPath,
-                   final String relativePath) {
-        this(resolver, mergeRootPath, relativePath, null);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param resolver      Resource resolver
      * @param mergeRootPath   Merge root path
      * @param relativePath    Relative path
      * @param mappedResources List of physical mapped resources' paths
@@ -68,38 +55,25 @@ public class MergedResource extends AbstractResource {
     MergedResource(final ResourceResolver resolver,
                    final String mergeRootPath,
                    final String relativePath,
-                   final List<String> mappedResources) {
+                   final List<Resource> mappedResources,
+                   final List<ValueMap> valueMaps) {
         this.resolver = resolver;
         this.path = (relativePath.length() == 0 ? mergeRootPath : mergeRootPath + "/" + relativePath);
         this.relativePath = (relativePath.length() == 0 ? "/" : relativePath);
         if ( mappedResources != null ) {
-            this.mappedResources.addAll(mappedResources);
+            for(final Resource rsrc : mappedResources) {
+                this.mappedResources.add(rsrc.getPath());
+            }
         }
-        this.resourceType = this.adaptTo(ValueMap.class).get(ResourceResolver.PROPERTY_RESOURCE_TYPE, this.relativePath);
+        this.properties = new MergedValueMap(valueMaps);
+        this.resourceType = this.properties.get(ResourceResolver.PROPERTY_RESOURCE_TYPE, this.relativePath);
         metadata.put("sling.mergedResource", true);
-        metadata.put("sling.mappedResources", mappedResources.toArray(new String[mappedResources.size()]));
-    }
-
-
-    // ---- MergedResource interface ------------------------------------------
-
-    public String getRelativePath() {
-        return relativePath;
+        metadata.put("sling.mappedResources", this.mappedResources.toArray(new String[this.mappedResources.size()]));
     }
 
     /**
      * {@inheritDoc}
      */
-    public Iterable<String> getMappedResources() {
-        return mappedResources;
-    }
-
-
-    // ---- Resource interface ------------------------------------------------
-
-    /**
-     * {@inheritDoc}
-     */
     public String getPath() {
         return this.path;
     }
@@ -141,9 +115,6 @@ public class MergedResource extends AbstractResource {
     @SuppressWarnings("unchecked")
     public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
         if (type == ValueMap.class) {
-            if ( this.properties == null ) {
-                this.properties = new MergedValueMap(this);
-            }
             return (AdapterType) this.properties;
         }
 
diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java
index a152c2f..ad787a7 100644
--- a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java
+++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java
@@ -56,46 +56,100 @@ public class MergedResourceProvider implements ResourceProvider {
         final String relativePath = getRelativePath(path);
 
         if ( relativePath != null ) {
-            final List<String> mappedResources = new ArrayList<String>();
-            // Loop over provided base paths
-            for (final String basePath : resolver.getSearchPath()) {
+            final ResourceHolder holder = new ResourceHolder(ResourceUtil.getName(path));
+
+            // Loop over provided base paths, start with least import
+            final String[] searchPaths = resolver.getSearchPath();
+            for(int i=searchPaths.length-1; i >= 0; i--) {
+                final String basePath = searchPaths[i];
+
                 // Try to get the corresponding physical resource for this base path
-                final Resource baseRes = resolver.getResource(basePath + "/" + relativePath);
-                if (baseRes != null) {
-                    // check if resource is hidden
+                final String fullPath = basePath + "/" + relativePath;
+
+                // check parent for hiding
+                final Resource parent = resolver.getResource(ResourceUtil.getParent(fullPath));
+                if ( parent != null ) {
                     boolean hidden = false;
-                    final ValueMap props = ResourceUtil.getValueMap(baseRes);
-                    if ( props.get(MergedResourceConstants.PN_HIDE_RESOURCE, Boolean.FALSE) ) {
-                        hidden = true;
-                    }
-                    if ( !hidden ) {
-                        // check parent
-                        final ValueMap parentProps = ResourceUtil.getValueMap(baseRes.getParent());
-                        final String[] childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class);
-                        if ( childrenToHideArray != null ) {
-                            for(final String name : childrenToHideArray ) {
-                                if ( name.equals(baseRes.getName()) || name.equals("*") ) {
-                                    hidden = true;
-                                    break;
-                                }
+                    final ValueMap parentProps = ResourceUtil.getValueMap(parent);
+                    final String[] childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class);
+                    if ( childrenToHideArray != null ) {
+                        for(final String name : childrenToHideArray ) {
+                            if ( name.equals(holder.name) || name.equals("*") ) {
+                                hidden = true;
+                                break;
                             }
                         }
                     }
-                    if ( !hidden ) {
-                        // Physical resource exists, add it to the list of mapped resources
-                        mappedResources.add(0, baseRes.getPath());
+                    if ( hidden ) {
+                        holder.resources.clear();
                     } else {
-                        mappedResources.clear();
+                        final Resource baseRes = resolver.getResource(fullPath);
+                        if (baseRes != null) {
+                            holder.resources.add(baseRes);
+                        }
                     }
                 }
             }
+            return createMergedResource(resolver, relativePath, holder);
+        }
+
+        return null;
+    }
+
+    private static final class ResourceHolder {
+        public final String name;
+        public final List<Resource> resources = new ArrayList<Resource>();
+        public final List<ValueMap> valueMaps = new ArrayList<ValueMap>();
+
+        public ResourceHolder(final String n) {
+            this.name = n;
+        }
+    }
 
-            if (!mappedResources.isEmpty()) {
-                // Create a new merged resource based on the list of mapped physical resources
-                return new MergedResource(resolver, mergeRootPath, relativePath, mappedResources);
+    /**
+     * Create the merged resource based on the provided resources
+     */
+    private Resource createMergedResource(final ResourceResolver resolver,
+            final String relativePath,
+            final ResourceHolder holder) {
+        int index = 0;
+        while ( index < holder.resources.size() ) {
+            final Resource baseRes = holder.resources.get(index);
+            // check if resource is hidden
+            boolean hidden = false;
+            final ValueMap props = ResourceUtil.getValueMap(baseRes);
+            holder.valueMaps.add(props);
+            if ( props.get(MergedResourceConstants.PN_HIDE_RESOURCE, Boolean.FALSE) ) {
+                hidden = true;
+            }
+            if ( !hidden ) {
+                // check parent
+                final ValueMap parentProps = ResourceUtil.getValueMap(baseRes.getParent());
+                final String[] childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class);
+                if ( childrenToHideArray != null ) {
+                    for(final String name : childrenToHideArray ) {
+                        if ( name.equals(baseRes.getName()) || name.equals("*") ) {
+                            hidden = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            if ( hidden ) {
+                // clear everything up to now
+                for(int i=0;i<=index;i++) {
+                    holder.resources.remove(0);
+                }
+                holder.valueMaps.clear();
+                index = -1; // start at zero
             }
+            index++;
         }
 
+        if (!holder.resources.isEmpty()) {
+            // create a new merged resource based on the list of mapped physical resources
+            return new MergedResource(resolver, mergeRootPath, relativePath, holder.resources, holder.valueMaps);
+        }
         return null;
     }
 
@@ -108,35 +162,82 @@ public class MergedResourceProvider implements ResourceProvider {
         final String relativePath = getRelativePath(resource.getPath());
 
         if ( relativePath != null ) {
-            final List<String> names = new ArrayList<String>();
-            // Loop over provided base paths
-            for (final String basePath : resolver.getSearchPath()) {
-                final Resource baseResource = resolver.getResource(basePath + "/" + relativePath);
-                if ( baseResource != null ) {
-                    for(final Resource child : baseResource.getChildren()) {
-                        final String rsrcName = child.getName();
-                        if ( !names.contains(rsrcName) ) {
-                            names.add(rsrcName);
-                        }
-                        // Check if children need reordering
-                        int orderBeforeIndex = -1;
-                        final ValueMap vm = ResourceUtil.getValueMap(child);
-                        final String orderBefore = vm.get(MergedResourceConstants.PN_ORDER_BEFORE, String.class);
-                        if (orderBefore != null && !orderBefore.equals(rsrcName)) {
-                            // search entry
-                            orderBeforeIndex = names.indexOf(orderBefore);
+            final List<ResourceHolder> candidates = new ArrayList<ResourceHolder>();
+
+            // Loop over provided base paths, start with least import
+            final String[] searchPaths = resolver.getSearchPath();
+            for(int i=searchPaths.length-1; i >= 0; i--) {
+                final String basePath = searchPaths[i];
+                final Resource parentResource = resolver.getResource(basePath + "/" + relativePath);
+                if ( parentResource != null ) {
+                    final ValueMap parentProps = ResourceUtil.getValueMap(parentResource);
+                    List<String> childrenToHide = new ArrayList<String>();
+                    boolean hideAll = false;
+                    final String[] childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class);
+                    if ( childrenToHideArray != null ) {
+                        for(final String name : childrenToHideArray ) {
+                            if ( name.equals("*") ) {
+                                hideAll = true;
+                            } else {
+                                childrenToHide.add(name);
+                            }
                         }
+                    }
+                    if ( hideAll ) {
+                        candidates.clear();
+                    } else {
+                        for(final Resource child : parentResource.getChildren()) {
+                            final String rsrcName = child.getName();
+                            ResourceHolder holder = null;
+                            for(final ResourceHolder current : candidates) {
+                                if ( current.name.equals(rsrcName) ) {
+                                    holder = current;
+                                    break;
+                                }
+                            }
+                            if ( holder == null ) {
+                                holder = new ResourceHolder(rsrcName);
+                                candidates.add(holder);
+                            }
+                            holder.resources.add(child);
+
+                            // Check if children need reordering
+                            int orderBeforeIndex = -1;
+                            final ValueMap vm = ResourceUtil.getValueMap(child);
+                            final String orderBefore = vm.get(MergedResourceConstants.PN_ORDER_BEFORE, String.class);
+                            if (orderBefore != null && !orderBefore.equals(rsrcName)) {
+                                // search entry
+                                int index = 0;
+                                while (index < candidates.size()) {
+                                    final ResourceHolder current = candidates.get(index);
+                                    if ( current.name.equals(orderBefore) ) {
+                                        orderBeforeIndex = index;
+                                        break;
+                                    }
+                                    index++;
+                                }
+                            }
 
-                        if (orderBeforeIndex > -1) {
-                            names.add(orderBeforeIndex, rsrcName);
-                            names.remove(names.size() - 1);
+                            if (orderBeforeIndex > -1) {
+                                candidates.add(orderBeforeIndex, holder);
+                                candidates.remove(candidates.size() - 1);
+                            }
+                        }
+                        if ( childrenToHide.size() > 0 ) {
+                            final Iterator<ResourceHolder> iter = candidates.iterator();
+                            while ( iter.hasNext() ) {
+                                final ResourceHolder holder = iter.next();
+                                if ( childrenToHide.contains(holder.name) ) {
+                                    iter.remove();
+                                }
+                            }
                         }
                     }
                 }
             }
             final List<Resource> children = new ArrayList<Resource>();
-            for(final String name : names) {
-                final Resource mergedResource = this.getResource(resolver, resource.getPath() + "/" + name);
+            for(final ResourceHolder holder : candidates) {
+                final Resource mergedResource = this.createMergedResource(resolver, relativePath + '/' + holder.name, holder);
                 if ( mergedResource != null ) {
                     children.add(mergedResource);
                 }
diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java b/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java
index 3a888fa..4bb186d 100644
--- a/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java
+++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java
@@ -20,10 +20,9 @@ package org.apache.sling.resourcemerger.impl;
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.wrappers.ValueMapDecorator;
 
@@ -50,34 +49,30 @@ public class MergedValueMap extends ValueMapDecorator {
      *
      * @param resource The merged resource to get properties from
      */
-    public MergedValueMap(final MergedResource resource) {
+    public MergedValueMap(final List<ValueMap> valueMaps) {
         super(new HashMap<String, Object>());
-        // Iterate over physical resources
-        for (final String r : resource.getMappedResources()) {
-            final Resource rsrc = resource.getResourceResolver().getResource(r);
-            if ( rsrc != null ) {
-                final ValueMap vm = ResourceUtil.getValueMap(rsrc);
-                if (this.isEmpty()) {
-                    // Add all properties
-                    this.putAll(vm);
-                } else {
-                    // Get properties to add or override
-                    for (final String key : vm.keySet()) {
-                        if (!isExcludedProperty(key)) {
-                            this.put(key, vm.get(key));
-                        }
+        // Iterate over value maps
+        for (final ValueMap vm : valueMaps) {
+            if (this.isEmpty()) {
+                // Add all properties
+                this.putAll(vm);
+            } else {
+                // Get properties to add or override
+                for (final String key : vm.keySet()) {
+                    if (!isExcludedProperty(key)) {
+                        this.put(key, vm.get(key));
                     }
+                }
 
-                    // Get properties to hide
-                    final String[] propertiesToHide = vm.get(MergedResourceConstants.PN_HIDE_PROPERTIES, String[].class);
-                    if ( propertiesToHide != null ) {
-                        for (final String propName : propertiesToHide) {
-                            if (propName.equals("*")) {
-                                this.clear();
-                                break;
-                            } else {
-                                this.remove(propName);
-                            }
+                // Get properties to hide
+                final String[] propertiesToHide = vm.get(MergedResourceConstants.PN_HIDE_PROPERTIES, String[].class);
+                if ( propertiesToHide != null ) {
+                    for (final String propName : propertiesToHide) {
+                        if (propName.equals("*")) {
+                            this.clear();
+                            break;
+                        } else {
+                            this.remove(propName);
                         }
                     }
                 }
diff --git a/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java b/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java
index e6d703f..08bbab2 100644
--- a/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java
+++ b/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java
@@ -45,25 +45,26 @@ public class MergedResourceProviderTest {
         final ResourceResolverFactory factory = new MockResourceResolverFactory();
         this.resolver = factory.getAdministrativeResourceResolver(null);
         MockHelper.create(this.resolver).resource("/apps")
-                                          .resource("a")
+                                          .resource("a").p(MergedResourceConstants.PN_HIDE_CHILDREN, new String[] {"Z", "x", "y"})
                                             .resource("1").p("a", "1").p("b", "2")
-                                            .resource("./2").p(ResourceResolver.PROPERTY_RESOURCE_TYPE, "apps")
-                                            .resource("./3").p("e", "2")
-                                                            .p(MergedResourceConstants.PN_HIDE_PROPERTIES, "*")
-                                                            .p("b", "x")
-                                                            .p("d", "1")
-                                            .resource("./4").p("e", "2")
-                                                            .p(MergedResourceConstants.PN_HIDE_PROPERTIES, new String[] {"a", "c"})
-                                                            .p("b", "x")
-                                                            .p("d", "1")
-                                            .resource("./X")
+                                            .resource(".2").p(ResourceResolver.PROPERTY_RESOURCE_TYPE, "apps")
+                                            .resource(".3").p("e", "2")
+                                                           .p(MergedResourceConstants.PN_HIDE_PROPERTIES, "*")
+                                                           .p("b", "x")
+                                                           .p("d", "1")
+                                            .resource(".4").p("e", "2")
+                                                           .p(MergedResourceConstants.PN_HIDE_PROPERTIES, new String[] {"a", "c"})
+                                                           .p("b", "x")
+                                                           .p("d", "1")
+                                            .resource(".X")
                                         .resource("/libs")
                                           .resource("a")
                                             .resource("1").p("a", "5").p("c", "2")
-                                            .resource("./2").p(ResourceResolver.PROPERTY_RESOURCE_TYPE, "libs")
-                                            .resource("./3").p("a", "1").p("b", "2").p("c", "3")
-                                            .resource("./4").p("a", "1").p("b", "2").p("c", "3")
-                                            .resource("./Y")
+                                            .resource(".2").p(ResourceResolver.PROPERTY_RESOURCE_TYPE, "libs")
+                                            .resource(".3").p("a", "1").p("b", "2").p("c", "3")
+                                            .resource(".4").p("a", "1").p("b", "2").p("c", "3")
+                                            .resource(".Y")
+                                            .resource(".Z")
                                         .commit();
 
         this.provider = new MergedResourceProvider("/merged");

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.