From 49e826c829f7c21b0e5fd99b3b8431239d3e23a3 Mon Sep 17 00:00:00 2001 From: Niek Raaijmakers Date: Tue, 29 Oct 2024 19:32:08 +0100 Subject: [PATCH] Add the option to use multiple parameters in 1 field (#3456) * Add the option to use multiple parameters in 1 field --------- Co-authored-by: Niek Raaijmakers --- CHANGELOG.md | 4 ++ .../NamespaceDecoratedValueMapBuilder.java | 56 +++++-------------- .../include/NamespaceResourceWrapperTest.java | 12 +++- .../impl/include/namespace-wrapper-test.json | 8 +++ 4 files changed, 37 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b62f7a8a82..ba91ec55bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com) ## Unreleased ([details][unreleased changes details]) +### Fixed + +- #3460 - Fixes issue where double parameters were not working for the parameterized include + ### Changed - #3420 - Redirect Map Manager - enable Redirect Map Manager in AEM CS (would require a specific - not public yet - AEM diff --git a/bundle/src/main/java/com/adobe/acs/commons/granite/ui/components/impl/include/NamespaceDecoratedValueMapBuilder.java b/bundle/src/main/java/com/adobe/acs/commons/granite/ui/components/impl/include/NamespaceDecoratedValueMapBuilder.java index 579161c34d..ef1ac7d0b6 100644 --- a/bundle/src/main/java/com/adobe/acs/commons/granite/ui/components/impl/include/NamespaceDecoratedValueMapBuilder.java +++ b/bundle/src/main/java/com/adobe/acs/commons/granite/ui/components/impl/include/NamespaceDecoratedValueMapBuilder.java @@ -47,8 +47,7 @@ public class NamespaceDecoratedValueMapBuilder { private final Map copyMap; private final String[] namespacedProperties; - static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("(\\$\\{\\{([a-zA-Z0-9]+?)(:(.+?))??\\}\\})+?"); - static final Pattern PLACEHOLDER_TYPE_HINTED_PATTERN = Pattern.compile("(.*)\\$\\{\\{(\\(([a-zA-Z]+)\\)){1}([a-zA-Z0-9]+)(:(.+))?\\}\\}(.*)?"); + static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{\\{(?:\\(([a-zA-Z]+)\\))?([a-zA-Z0-9]+)(:(.*?))?\\}\\}"); public NamespaceDecoratedValueMapBuilder(SlingHttpServletRequest request, Resource resource, String[] namespacedProperties) { this.request = request; @@ -129,59 +128,34 @@ private void applyDynamicVariables() { private Object filter(String value, SlingHttpServletRequest request) { - Object filtered = applyTypeHintedPlaceHolders(value, request); - - if(filtered != null){ - return filtered; - } - - return applyPlaceHolders(value, request); - } - - private Object applyTypeHintedPlaceHolders(String value, SlingHttpServletRequest request) { - Matcher matcher = PLACEHOLDER_TYPE_HINTED_PATTERN.matcher(value); - - if (matcher.find()) { - - String prefix = matcher.group(1); - String typeHint = matcher.group(3); - String paramKey = matcher.group(4); - String defaultValue = matcher.group(6); - String suffix = matcher.group(7); - - String requestParamValue = (request.getAttribute(PREFIX + paramKey) != null) ? request.getAttribute(PREFIX + paramKey).toString() : null; - String chosenValue = defaultString(requestParamValue, defaultValue); - String finalValue = defaultIfEmpty(prefix, EMPTY) + chosenValue + defaultIfEmpty(suffix, EMPTY); - - return isNotEmpty(typeHint) ? castTypeHintedValue(typeHint, finalValue) : finalValue; - } - - return null; - } - - private String applyPlaceHolders(String value, SlingHttpServletRequest request) { Matcher matcher = PLACEHOLDER_PATTERN.matcher(value); - StringBuffer buffer = new StringBuffer(); + + // Replace all occurrences + StringBuffer result = new StringBuffer(); while (matcher.find()) { + // Retrieve groups for Typecast, paramKey, and default value + String typeHint = matcher.group(1); String paramKey = matcher.group(2); String defaultValue = matcher.group(4); String requestParamValue = (request.getAttribute(PREFIX + paramKey) != null) ? request.getAttribute(PREFIX + paramKey).toString() : null; String chosenValue = defaultString(requestParamValue, defaultValue); - if(chosenValue == null){ - chosenValue = StringUtils.EMPTY; - } - - matcher.appendReplacement(buffer, chosenValue); + String replacement = isNotEmpty(typeHint) ? castTypeHintedValue(typeHint, chosenValue).toString() : chosenValue; + if(replacement == null){ + replacement = ""; + } + // Append the replacement to the result + matcher.appendReplacement(result, replacement); } - matcher.appendTail(buffer); + // Append the remaining text + matcher.appendTail(result); - return buffer.toString(); + return result.toString(); } private Object castTypeHintedValue(String typeHint, String chosenValue) { diff --git a/bundle/src/test/java/com/adobe/acs/commons/granite/ui/components/impl/include/NamespaceResourceWrapperTest.java b/bundle/src/test/java/com/adobe/acs/commons/granite/ui/components/impl/include/NamespaceResourceWrapperTest.java index e4cbce3ae2..94b6eef30f 100644 --- a/bundle/src/test/java/com/adobe/acs/commons/granite/ui/components/impl/include/NamespaceResourceWrapperTest.java +++ b/bundle/src/test/java/com/adobe/acs/commons/granite/ui/components/impl/include/NamespaceResourceWrapperTest.java @@ -74,13 +74,16 @@ public void test() { parameters.put("doubleFieldDefaultValue", 11.34d); parameters.put("hideAField", Boolean.TRUE); parameters.put("fieldLabelText", "Some Text from parameters"); + parameters.put("fieldDescriptionText", "someFieldDescription"); + parameters.put("suffixText", "SuffixTextTest"); setParameters(parameters); systemUnderTest = new NamespaceResourceWrapper(context.currentResource(), expressionResolver, context.request(), properties); - - + Resource someMultiExpressionField = systemUnderTest.getChild("someMultiExpressionField"); + String multiExpressionValue = someMultiExpressionField.getValueMap().get("fieldDescription", ""); + assertEquals("someFieldDescription otherText someFieldDescription evenMoreText SuffixTextTest", multiExpressionValue); Resource someDoubleField = systemUnderTest.getChild("someDoubleField"); Double doubleDefaultValue = someDoubleField.getValueMap().get("defaultValue", Double.class); @@ -119,6 +122,11 @@ public void test_default_values() { Resource regularTextField = systemUnderTest.getChild("someRegularField"); String fieldLabelValue = regularTextField.getValueMap().get("fieldLabel", ""); assertEquals("defaultText", fieldLabelValue); + + Resource someMultiExpressionField = systemUnderTest.getChild("someMultiExpressionField"); + String multiExpressionValue = someMultiExpressionField.getValueMap().get("fieldDescription", ""); + assertEquals("defaultDescription otherText otherDefaultDescription evenMoreText ", multiExpressionValue); + } diff --git a/bundle/src/test/resources/com/adobe/acs/commons/granite/ui/components/impl/include/namespace-wrapper-test.json b/bundle/src/test/resources/com/adobe/acs/commons/granite/ui/components/impl/include/namespace-wrapper-test.json index 43502b7490..a4c963c928 100644 --- a/bundle/src/test/resources/com/adobe/acs/commons/granite/ui/components/impl/include/namespace-wrapper-test.json +++ b/bundle/src/test/resources/com/adobe/acs/commons/granite/ui/components/impl/include/namespace-wrapper-test.json @@ -14,6 +14,14 @@ "sling:resourceType": "granite/ui/components/foundation/container", "items": { "jcr:primaryType": "nt:unstructured", + "someMultiExpressionField": { + "jcr:primaryType": "nt:unstructured", + "name": "./multiExpressionField", + "text": "Some multiExpressionField", + "value": "true", + "sling:resourceType": "granite/ui/components/foundation/form/textfield", + "fieldDescription": "${{(String)fieldDescriptionText:defaultDescription}} otherText ${{(String)fieldDescriptionText:otherDefaultDescription}} evenMoreText ${{suffixText}}" + }, "someDoubleField": { "jcr:primaryType": "nt:unstructured", "name": "./doubleField",