You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by np...@apache.org on 2018/11/23 10:15:37 UTC
[sling-org-apache-sling-pipes] branch master updated: SLING-8130
conditionnal node writes
This is an automated email from the ASF dual-hosted git repository.
npeltier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-pipes.git
The following commit(s) were added to refs/heads/master by this push:
new d21fbcb SLING-8130 conditionnal node writes
d21fbcb is described below
commit d21fbcbfb1eeea6252f61fb003bf5fdb4955aa44
Author: Nicolas Peltier <pe...@gmail.com>
AuthorDate: Fri Nov 23 11:14:51 2018 +0100
SLING-8130 conditionnal node writes
introducing the syntax that can be persisted in a write tree configuration
---
.../java/org/apache/sling/pipes/PipeBindings.java | 40 ++++++++++++++++------
.../java/org/apache/sling/pipes/PipeBuilder.java | 4 +--
.../org/apache/sling/pipes/internal/WritePipe.java | 16 +++++----
.../apache/sling/pipes/internal/WritePipeTest.java | 30 ++++++++++++++++
src/test/resources/write.json | 11 ++++++
5 files changed, 82 insertions(+), 19 deletions(-)
diff --git a/src/main/java/org/apache/sling/pipes/PipeBindings.java b/src/main/java/org/apache/sling/pipes/PipeBindings.java
index 850c3a7..bba4728 100644
--- a/src/main/java/org/apache/sling/pipes/PipeBindings.java
+++ b/src/main/java/org/apache/sling/pipes/PipeBindings.java
@@ -17,9 +17,9 @@
package org.apache.sling.pipes;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -71,8 +71,11 @@ public class PipeBindings {
* add ${name.pipeName} binding allowing to retrieve pipeName's current resource name
*/
public static final String NAME_BINDING = "name";
-
- private static final Pattern INJECTED_SCRIPT = Pattern.compile("\\$\\{(([^\\{^\\}]*(\\{[0-9,]+\\})?)*)\\}");
+
+ private static final String INJECTED_SCRIPT_REGEXP = "\\$\\{(([^\\{^\\}]*(\\{[0-9,]+\\})?)*)\\}";
+ private static final Pattern INJECTED_SCRIPT = Pattern.compile(INJECTED_SCRIPT_REGEXP);
+ protected static final String IF_PREFIX = "$if";
+ protected static final Pattern CONDITIONAL_STRING = Pattern.compile("^\\" + IF_PREFIX + INJECTED_SCRIPT_REGEXP);
ScriptEngine engine;
@@ -197,14 +200,6 @@ public class PipeBindings {
}
/**
- * copy bindings
- * @param original original bindings to copy
- */
- public void copyBindings(PipeBindings original){
- getBindings().putAll(original.getBindings());
- }
-
- /**
* evaluate a given expression
* @param expr ecma like expression
* @return object that is the result of the expression
@@ -255,6 +250,29 @@ public class PipeBindings {
}
/**
+ * Return expression, instantiated expression or null if the expression is conditional and evaluation is falsy
+ * @param conditionalExpression can be static, or dynamic, can be conditional in which case it must be of following
+ * format <code>$if${condition}someString</code>. someString will be returned if condition is true, otherwise null
+ * @return instantiated expression or null if expression is conditional (see above) and condition is falsy
+ * @throws ScriptException in case one of the evaluation went wrong
+ */
+ public String conditionalString(String conditionalExpression) throws ScriptException {
+ Matcher matcher = CONDITIONAL_STRING.matcher(conditionalExpression);
+ if (matcher.find()){
+ Object output = evaluate(StringUtils.substringAfter(matcher.group(0), IF_PREFIX));
+ if (output != null){
+ String s = output.toString().toLowerCase().trim();
+ if(StringUtils.isNotEmpty(s) && !"false".equals(s) && !"undefined".equals(s)){
+ return instantiateExpression(conditionalExpression.substring(matcher.group(0).length()));
+ }
+ }
+ } else {
+ return instantiateExpression(conditionalExpression);
+ }
+ return null;
+ }
+
+ /**
* Expression is a function of variables from execution context, that
* we implement here as a String
* @param expr ecma like expression
diff --git a/src/main/java/org/apache/sling/pipes/PipeBuilder.java b/src/main/java/org/apache/sling/pipes/PipeBuilder.java
index 3388c4c..8607bef 100644
--- a/src/main/java/org/apache/sling/pipes/PipeBuilder.java
+++ b/src/main/java/org/apache/sling/pipes/PipeBuilder.java
@@ -246,11 +246,11 @@ public interface PipeBuilder {
PipeBuilder not(String expr);
/**
- * attach a multi value property pipe to the current context
+ * attach a MULTI value property pipe to the current context
* @return updated instance of PipeBuilder
*/
@PipeExecutor(command = "mp", resourceType = MultiPropertyPipe.RESOURCE_TYPE, pipeClass = MultiPropertyPipe.class,
- description = "read multi property, and output each value in the bindings")
+ description = "read MULTI property, and output each value in the bindings")
PipeBuilder mp();
/**
diff --git a/src/main/java/org/apache/sling/pipes/internal/WritePipe.java b/src/main/java/org/apache/sling/pipes/internal/WritePipe.java
index 9793930..5f2bcbe 100644
--- a/src/main/java/org/apache/sling/pipes/internal/WritePipe.java
+++ b/src/main/java/org/apache/sling/pipes/internal/WritePipe.java
@@ -46,10 +46,12 @@ import java.util.regex.Pattern;
public class WritePipe extends BasePipe {
private static final Logger logger = LoggerFactory.getLogger(WritePipe.class);
public static final String RESOURCE_TYPE = RT_PREFIX + "write";
+ protected static final Pattern ADD_PATCH = Pattern.compile("\\+\\[(.*)\\]");
+ protected static final Pattern MULTI = Pattern.compile("\\[(.*)\\]");
+
Node confTree;
private List<Resource> propertiesToRemove;
- Pattern addPatch = Pattern.compile("\\+\\[(.*)\\]");
- Pattern multi = Pattern.compile("\\[(.*)\\]");
+
/**
* public constructor
@@ -88,7 +90,7 @@ public class WritePipe extends BasePipe {
if (value != null && value instanceof String) {
//in that case we treat special case like MV or patches
String sValue = (String)value;
- Matcher patch = addPatch.matcher(sValue);
+ Matcher patch = ADD_PATCH.matcher(sValue);
if (patch.matches()) {
String newValue = patch.group(1);
String[] actualValues = resource.adaptTo(ValueMap.class).get(key, String[].class);
@@ -98,7 +100,7 @@ public class WritePipe extends BasePipe {
}
return newValues.toArray(new String[newValues.size()]);
}
- Matcher multiMatcher = multi.matcher(sValue);
+ Matcher multiMatcher = MULTI.matcher(sValue);
if (multiMatcher.matches()) {
return multiMatcher.group(1).split(",");
}
@@ -194,8 +196,10 @@ public class WritePipe extends BasePipe {
while (childrenConf.hasNext()){
Node childConf = childrenConf.nextNode();
String name = childConf.getName();
- name = bindings.instantiateExpression(name);
- if (!isDryRun()){
+ name = bindings.conditionalString(name);
+ if (name == null){
+ logger.debug("name has been instantiated as null, not writing that tree");
+ } else if (!isDryRun()){
Node childTarget = targetNode.hasNode(name) ? targetNode.getNode(name) : targetNode.addNode(name, childConf.getPrimaryNodeType().getName());
logger.debug("writing tree {}", childTarget.getPath());
writeTree(childConf, resolver.getResource(childTarget.getPath()));
diff --git a/src/test/java/org/apache/sling/pipes/internal/WritePipeTest.java b/src/test/java/org/apache/sling/pipes/internal/WritePipeTest.java
index 45bbf1d..e1bce7b 100644
--- a/src/test/java/org/apache/sling/pipes/internal/WritePipeTest.java
+++ b/src/test/java/org/apache/sling/pipes/internal/WritePipeTest.java
@@ -29,6 +29,7 @@ import org.junit.Test;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
@@ -37,6 +38,7 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
@@ -159,4 +161,32 @@ public class WritePipeTest extends AbstractPipeTest {
context.resourceResolver().commit();
assertNotNull("there should be a node created", context.resourceResolver().getResource(PATH_APPLE + "/testExpression"));
}
+
+
+ protected void testIfNode(Object bindingValue, boolean nodeExpected) throws PersistenceException, RepositoryException {
+ String expectedPath = PATH_APPLE + "/isTrue";
+ Pipe pipe = getPipe(PATH_PIPE + "/ifNode");
+ pipe.getBindings().addBinding("addedTest", bindingValue);
+ pipe.getOutput().next();
+ context.resourceResolver().commit();
+ Resource resource = context.resourceResolver().getResource(expectedPath);
+ if (nodeExpected){
+ assertNotNull("there should be isTrue node for test binding " + bindingValue, resource);
+ } else {
+ assertNull("there should be no isTrue node created for test binding " + bindingValue, resource);
+ }
+ if (resource != null){
+ resource.adaptTo(Node.class).remove();
+ }
+ }
+
+ @Test
+ public void testIfNode() throws PersistenceException, RepositoryException {
+ testIfNode(null, false);
+ testIfNode("undefined", false);
+ testIfNode("false", false);
+ testIfNode(false, false);
+ testIfNode("some random string", true);
+ testIfNode(true, true);
+ }
}
diff --git a/src/test/resources/write.json b/src/test/resources/write.json
index 0cd2dc4..0b7d20b 100644
--- a/src/test/resources/write.json
+++ b/src/test/resources/write.json
@@ -101,5 +101,16 @@
"jcr:primaryType":"nt:unstructured"
}
}
+ },
+ "ifNode":{
+ "jcr:primaryType":"nt:unstructured",
+ "sling:resourceType":"slingPipes/write",
+ "path":"/content/fruits/apple",
+ "conf": {
+ "jcr:primaryType":"nt:unstructured",
+ "$if${addedTest}isTrue": {
+ "jcr:primaryType":"nt:unstructured"
+ }
+ }
}
}
\ No newline at end of file