Author: radu Date: Mon Feb 16 14:59:12 2015 New Revision: 1660131 URL: http://svn.apache.org/r1660131 Log: SLING-4402 - The selector manipulation options for data-sly-resource should accept string arrays
* implemented support for using string arrays in the options for data-sly-resource Added: sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/includedresource/ sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/includedresource/includedresource.html sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/resource/ sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/resource/resource.html Modified: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json sling/trunk/contrib/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java Modified: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java?rev=1660131&r1=1660130&r2=1660131&view=diff ============================================================================== --- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java (original) +++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java Mon Feb 16 14:59:12 2015 @@ -20,8 +20,11 @@ package org.apache.sling.scripting.sight import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import javax.script.Bindings; import javax.servlet.RequestDispatcher; @@ -76,80 +79,131 @@ public class ResourceRuntimeExtension im private String provideResource(final RenderContext renderContext, Object pathObj, Map<String, Object> options) { Map<String, Object> opts = new HashMap<String, Object>(options); - String path = buildPath(pathObj, opts); - String resourceType = getAndRemoveOption(opts, OPTION_RESOURCE_TYPE); + PathInfo pathInfo = new PathInfo(coerceString(pathObj)); + String path = pathInfo.path; + String finalPath = buildPath(path, opts); + String resourceType = coerceString(getAndRemoveOption(opts, OPTION_RESOURCE_TYPE)); final Bindings bindings = renderContext.getBindings(); - handleSelectors(bindings, path, opts); - String dispatcherOptions = createDispatcherOptions(opts); + Map<String, String> dispatcherOptionsMap = handleSelectors(bindings, pathInfo.selectors, opts); + String dispatcherOptions = createDispatcherOptions(dispatcherOptionsMap); StringWriter writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); - includeResource(bindings, printWriter, path, dispatcherOptions, resourceType); + includeResource(bindings, printWriter, finalPath, dispatcherOptions, resourceType); return writer.toString(); } - private void handleSelectors(final Bindings bindings, String path, Map<String, Object> options) { - String selectors = getAndRemoveOption(options, OPTION_SELECTORS); - if (StringUtils.isNotEmpty(selectors)) { - // handle the selectors option - options.put(OPTION_ADD_SELECTORS, selectors); - options.put(OPTION_REPLACE_SELECTORS, " "); - } else { - if (options.containsKey(OPTION_REMOVE_SELECTORS)) { - String removeSelectors = getAndRemoveOption(options, OPTION_REMOVE_SELECTORS); - if (StringUtils.isEmpty(removeSelectors)) { - options.put(OPTION_REPLACE_SELECTORS, " "); - } else { - String currentSelectors = getSelectorsFromPath(path); - if (StringUtils.isEmpty(currentSelectors)) { - currentSelectors = ((SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST)).getRequestPathInfo() - .getSelectorString(); + private Map<String, String> handleSelectors(Bindings bindings, Set<String> selectors, Map<String, Object> options) { + if (selectors.isEmpty()) { + SlingHttpServletRequest request = (SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST); + selectors.addAll(Arrays.asList(request.getRequestPathInfo().getSelectors())); + } + Map<String, String> dispatcherOptionsMap = new HashMap<String, String>(); + if (options.containsKey(OPTION_SELECTORS)) { + Object selectorsObject = getAndRemoveOption(options, OPTION_SELECTORS); + selectors.clear(); + if (selectorsObject instanceof String) { + String selectorString = (String) selectorsObject; + String[] parts = selectorString.split("\\."); + selectors.addAll(Arrays.asList(parts)); + } else if (selectorsObject instanceof Object[]) { + for (Object s : (Object[]) selectorsObject) { + String selector = coerceString(s); + if (StringUtils.isNotEmpty(selector)) { + selectors.add(selector); } - if (StringUtils.isNotEmpty(currentSelectors)) { - options.put(OPTION_REPLACE_SELECTORS, " "); - String addSelectors = currentSelectors.replace(removeSelectors, "").replaceAll("\\.\\.", "\\."); - if (addSelectors.startsWith(".")) { - addSelectors = addSelectors.substring(1); - } - if (addSelectors.endsWith(".")) { - addSelectors = addSelectors.substring(0, addSelectors.length() - 1); - } - options.put(OPTION_ADD_SELECTORS, addSelectors); + } + } + dispatcherOptionsMap.put(OPTION_ADD_SELECTORS, getSelectorString(selectors)); + dispatcherOptionsMap.put(OPTION_REPLACE_SELECTORS, " "); + } + if (options.containsKey(OPTION_ADD_SELECTORS)) { + Object selectorsObject = getAndRemoveOption(options, OPTION_ADD_SELECTORS); + if (selectorsObject instanceof String) { + String selectorString = (String) selectorsObject; + String[] parts = selectorString.split("\\."); + for (String s : parts) { + selectors.add(s); + } + } else if (selectorsObject instanceof Object[]) { + for (Object s : (Object[]) selectorsObject) { + String selector = coerceString(s); + if (StringUtils.isNotEmpty(selector)) { + selectors.add(selector); } } } + dispatcherOptionsMap.put(OPTION_ADD_SELECTORS, getSelectorString(selectors)); + dispatcherOptionsMap.put(OPTION_REPLACE_SELECTORS, " "); } + if (options.containsKey(OPTION_REMOVE_SELECTORS)) { + Object selectorsObject = getAndRemoveOption(options, OPTION_REMOVE_SELECTORS); + if (selectorsObject instanceof String) { + String selectorString = (String) selectorsObject; + String[] parts = selectorString.split("\\."); + for (String s : parts) { + selectors.remove(s); + } + } else if (selectorsObject instanceof Object[]) { + for (Object s : (Object[]) selectorsObject) { + String selector = coerceString(s); + if (StringUtils.isNotEmpty(selector)) { + selectors.remove(selector); + } + } + } else if (selectorsObject == null) { + selectors.clear(); + } + String selectorString = getSelectorString(selectors); + if (StringUtils.isEmpty(selectorString)) { + dispatcherOptionsMap.put(OPTION_REPLACE_SELECTORS, " "); + } else { + dispatcherOptionsMap.put(OPTION_ADD_SELECTORS, getSelectorString(selectors)); + dispatcherOptionsMap.put(OPTION_REPLACE_SELECTORS, " "); + } + } + return dispatcherOptionsMap; } private String buildPath(Object pathObj, Map<String, Object> options) { - String path = coerceString(pathObj); - String prependPath = getAndRemoveOption(options, OPTION_PREPEND_PATH); - String appendPath = getAndRemoveOption(options, OPTION_APPEND_PATH); - if (StringUtils.isEmpty(path)) { - path = getOption(options, OPTION_PATH); + String prependPath = getOption(OPTION_PREPEND_PATH, options, StringUtils.EMPTY); + if (prependPath == null) { + prependPath = StringUtils.EMPTY; } if (StringUtils.isNotEmpty(prependPath)) { - path = prependPath + "/" + path; + if (!prependPath.startsWith("/")) { + prependPath = "/" + prependPath; + } + if (!prependPath.endsWith("/")) { + prependPath += "/"; + } + } + String path = coerceString(pathObj); + path = getOption(OPTION_PATH, options, StringUtils.isNotEmpty(path) ? path : StringUtils.EMPTY); + String appendPath = getOption(OPTION_APPEND_PATH, options, StringUtils.EMPTY); + if (appendPath == null) { + appendPath = StringUtils.EMPTY; } if (StringUtils.isNotEmpty(appendPath)) { - path = path + "/" + appendPath; + if (!appendPath.startsWith("/")) { + appendPath = "/" + appendPath; + } } - - return path; + return ResourceUtil.normalize(prependPath + path + appendPath); } - private String createDispatcherOptions(Map<String, Object> options) { + private String createDispatcherOptions(Map<String, String> options) { if (options == null || options.isEmpty()) { return null; } StringBuilder buffer = new StringBuilder(); boolean hasPreceding = false; - for (Map.Entry<String, Object> option : options.entrySet()) { + for (Map.Entry<String, String> option : options.entrySet()) { if (hasPreceding) { buffer.append(", "); } String key = option.getKey(); buffer.append(key).append("="); - String strVal = coerceString(option.getValue()); + String strVal = option.getValue(); if (strVal == null) { strVal = ""; } @@ -170,31 +224,15 @@ public class ResourceRuntimeExtension im return (String) options.get(property); } - private String getAndRemoveOption(Map<String, Object> options, String property) { - return (String) options.remove(property); + private String getOption(String option, Map<String, Object> options, String defaultValue) { + if (options.containsKey(option)) { + return (String) options.get(option); + } + return defaultValue; } - private String getSelectorsFromPath(String path) { - String filePath; - if (path.contains("/")) { - filePath = path.substring(path.lastIndexOf('/') + 1, path.length()); - } else { - filePath = path; - } - String[] parts = filePath.split("\\."); - if (parts.length > 2) { - StringBuilder sb = new StringBuilder(); - for (int i = 1; i < parts.length - 1; i++) { - sb.append(parts[i]); - if (i != parts.length - 2) { - sb.append("."); - } - } - if (sb.length() > 0) { - return sb.toString(); - } - } - return null; + private Object getAndRemoveOption(Map<String, Object> options, String property) { + return options.remove(property); } private void includeResource(final Bindings bindings, PrintWriter out, String script, String dispatcherOptions, String resourceType) { @@ -229,4 +267,50 @@ public class ResourceRuntimeExtension im } return ResourceUtil.normalize(path); } + + private class PathInfo { + private String path; + private Set<String> selectors; + + PathInfo(String path) { + selectors = getSelectorsFromPath(path); + String selectorString = getSelectorString(selectors); + if (StringUtils.isNotEmpty(selectorString)) { + this.path = path.substring(0, path.length() - selectorString.length() - 1); + } else { + this.path = path; + } + } + } + + private Set<String> getSelectorsFromPath(String path) { + Set<String> selectors = new LinkedHashSet<String>(); + if (path != null) { + String processingPath = path; + int lastSlashPos = path.lastIndexOf('/'); + if (lastSlashPos > -1) { + processingPath = path.substring(lastSlashPos + 1, path.length()); + } + int dotPos = processingPath.indexOf('.'); + if (dotPos > -1) { + String selectorString = processingPath.substring(dotPos + 1, processingPath.length()); + String[] selectorParts = selectorString.split("\\."); + selectors.addAll(Arrays.asList(selectorParts)); + } + } + return selectors; + } + + private String getSelectorString(Set<String> selectors) { + StringBuilder sb = new StringBuilder(); + int i = 0; + for (String s : selectors) { + sb.append(s); + if (i < selectors.size() - 1) { + sb.append("."); + i++; + } + } + return sb.toString(); + } } Added: sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/includedresource/includedresource.html URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/includedresource/includedresource.html?rev=1660131&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/includedresource/includedresource.html (added) +++ sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/includedresource/includedresource.html Mon Feb 16 14:59:12 2015 @@ -0,0 +1,20 @@ +<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--> +<span class="path">path: ${resource.path}</span><br> +<span class="selectors">selectors: ${request.requestPathInfo.selectorString}</span> \ No newline at end of file Added: sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/resource/resource.html URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/resource/resource.html?rev=1660131&view=auto ============================================================================== --- sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/resource/resource.html (added) +++ sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/resource/resource.html Mon Feb 16 14:59:12 2015 @@ -0,0 +1,30 @@ +<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--> +<!DOCTYPE html> +<html> +<head> + <title>Sightly data-sly-resource - Sling implementation</title> +</head> +<body> +<div id="selectors" data-sly-resource="${'/sightly/includedresource' @ selectors=['a', 'b']}"></div> +<div id="selectors-remove-c" data-sly-resource="${'/sightly/includedresource.a.b.c' @ selectors=['a', 'b']}"></div> +<div id="removeselectors-remove-b" data-sly-resource="${'/sightly/includedresource.a.b.c' @ removeSelectors=['b']}"></div> +<div id="addselectors" data-sly-resource="${'/sightly/includedresource' @ addSelectors=['a', 'b', 'c']}"></div> +</body> +</html> \ No newline at end of file Modified: sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json?rev=1660131&r1=1660130&r2=1660131&view=diff ============================================================================== --- sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json (original) +++ sling/trunk/contrib/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json Mon Feb 16 14:59:12 2015 @@ -4,5 +4,13 @@ "jcr:primaryType": "nt:unstructured", "sling:resourceType": "/apps/sightly/scripts/use", "jcr:title": "SUCCESS" + }, + "resource": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "/apps/sightly/scripts/resource" + }, + "includedresource": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "/apps/sightly/scripts/includedresource" } } Modified: sling/trunk/contrib/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java?rev=1660131&r1=1660130&r2=1660131&view=diff ============================================================================== --- sling/trunk/contrib/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java (original) +++ sling/trunk/contrib/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java Mon Feb 16 14:59:12 2015 @@ -31,6 +31,7 @@ public class SlingSpecificsSightlyIT { private static Client client; private static String launchpadURL; private static final String SLING_USE = "/sightly/use.html"; + private static final String SLING_RESOURCE = "/sightly/resource.html"; @BeforeClass public static void init() { @@ -55,4 +56,14 @@ public class SlingSpecificsSightlyIT { assertEquals("SUCCESS", HTMLExtractor.innerHTML(url, pageContent, "#reqadapt")); } + @Test + public void testDataSlyResourceArraySelectors() { + String url = launchpadURL + SLING_RESOURCE; + String pageContent = client.getStringContent(url, 200); + assertEquals("selectors: a.b", HTMLExtractor.innerHTML(url, pageContent, "#selectors span.selectors")); + assertEquals("selectors: a.b", HTMLExtractor.innerHTML(url, pageContent, "#selectors-remove-c span.selectors")); + assertEquals("selectors: a.c", HTMLExtractor.innerHTML(url, pageContent, "#removeselectors-remove-b span.selectors")); + assertEquals("selectors: a.b.c", HTMLExtractor.innerHTML(url, pageContent, "#addselectors span.selectors")); + } + }