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 2021/10/12 20:41:57 UTC
[sling-org-apache-sling-pipes] branch master updated: SLING-10869
introduce binding declarations
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 ed5ef03 SLING-10869 introduce binding declarations
ed5ef03 is described below
commit ed5ef03fb4016bc25804525918891dbb79728f47
Author: Nicolas Peltier <np...@apache.org>
AuthorDate: Tue Oct 12 22:41:38 2021 +0200
SLING-10869 introduce binding declarations
ability to add a binding in a script file (which scope will be the full file) with binding foo = bar (bar being a json or a csv)
---
pom.xml | 2 +
.../sling/pipes/internal/CommandExecutorImpl.java | 53 ++++++++++++++++------
.../pipes/internal/CommandExecutorImplTest.java | 48 ++++++++++++++++----
src/test/resources/declbasedinit.txt | 27 +++++++++++
4 files changed, 108 insertions(+), 22 deletions(-)
diff --git a/pom.xml b/pom.xml
index 9024be5..2a3a250 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,6 +38,8 @@
<sling.java.version>8</sling.java.version>
<org.ops4j.pax.exam.version>4.13.3</org.ops4j.pax.exam.version>
<project.build.outputTimestamp>1</project.build.outputTimestamp>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
</properties>
<scm>
diff --git a/src/main/java/org/apache/sling/pipes/internal/CommandExecutorImpl.java b/src/main/java/org/apache/sling/pipes/internal/CommandExecutorImpl.java
index 29c849d..366a16a 100644
--- a/src/main/java/org/apache/sling/pipes/internal/CommandExecutorImpl.java
+++ b/src/main/java/org/apache/sling/pipes/internal/CommandExecutorImpl.java
@@ -98,6 +98,12 @@ public class CommandExecutorImpl extends AbstractPlumberServlet implements Comma
static final String KEY_NAME = "name";
static final String KEY_PATH = "path";
static final String KEY_EXPR = "expr";
+ static final String DECL_BINDING = "binding";
+ static final String DECL_BINDING_CONTENT = "declcontent";
+ static final Pattern DECL_BINDING_PATTERN = Pattern.compile(DECL_BINDING + WHITE_SPACE_SEPARATOR + "*"
+ + "(?<" + DECL_BINDING + ">[\\w_\\-\\d]+)"
+ + WHITE_SPACE_SEPARATOR + "*=" + WHITE_SPACE_SEPARATOR + "*" +
+ "(?<" + DECL_BINDING_CONTENT + ">.*)");
private static final String HELP_START =
"\n a <pipe token> is <pipe> <expr|conf>? (<options>)?" +
@@ -126,11 +132,23 @@ public class CommandExecutorImpl extends AbstractPlumberServlet implements Comma
help = null;
}
- boolean isCommandCandidate(String line) {
- return StringUtils.isNotBlank(line) && !line.startsWith(COMMENT_PREFIX);
+ boolean isBlankLine(String line) {
+ return StringUtils.isBlank(line) || line.startsWith(COMMENT_PREFIX);
}
- List<String> getCommandList(SlingHttpServletRequest request) throws IOException {
+ boolean isJsonBinding(String line) {
+ return line.indexOf(DECL_BINDING) >= 0;
+ }
+
+ private void handleInputEnd(StringBuilder builder, String currentBinding, List<String> cmds, Map<String, Object> bindings) {
+ if (StringUtils.isBlank(currentBinding) && builder.length() > 0) {
+ cmds.add(builder.toString().trim());
+ } else if (StringUtils.isNoneBlank(currentBinding, builder)) {
+ bindings.put(currentBinding, builder.toString().trim());
+ }
+ }
+
+ List<String> getCommandList(SlingHttpServletRequest request, Map<String, Object> bindings) throws IOException {
List<String> cmds = new ArrayList<>();
if (request.getParameterMap().containsKey(REQ_PARAM_CMD)) {
cmds.add(request.getParameter(REQ_PARAM_CMD));
@@ -140,18 +158,27 @@ public class CommandExecutorImpl extends AbstractPlumberServlet implements Comma
InputStream is = paramFile.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
String line;
- StringBuilder cmdBuilder = new StringBuilder();
+ String currentBinding = null;
+ StringBuilder readerBuilder = new StringBuilder();
while ((line = reader.readLine()) != null) {
- if (isCommandCandidate(line)) {
- cmdBuilder.append(LINE_SEPARATOR + line.trim());
- } else if (cmdBuilder.length() > 0){
- cmds.add(cmdBuilder.toString().trim());
- cmdBuilder = new StringBuilder();
+ if (isBlankLine(line)) {
+ if (readerBuilder.length() > 0) {
+ handleInputEnd(readerBuilder, currentBinding, cmds, bindings);
+ readerBuilder = new StringBuilder();
+ currentBinding = null;
+ }
+ } else if (isJsonBinding(line)) {
+ Matcher matcher = DECL_BINDING_PATTERN.matcher(line);
+ if (matcher.find()) {
+ currentBinding = matcher.group(DECL_BINDING);
+ readerBuilder.append(matcher.group(DECL_BINDING_CONTENT).trim());
+ }
+ } else {
+ //depending on what we are appending, we keep lines return or not
+ readerBuilder.append((StringUtils.isBlank(currentBinding) ? LINE_SEPARATOR : "\n") + line.trim());
}
}
- if (cmdBuilder.length() > 0) {
- cmds.add(cmdBuilder.toString().trim());
- }
+ handleInputEnd(readerBuilder, currentBinding, cmds, bindings);
}
}
return cmds;
@@ -167,7 +194,7 @@ public class CommandExecutorImpl extends AbstractPlumberServlet implements Comma
} else {
ResourceResolver resolver = request.getResourceResolver();
Map<String, Object> bindings = plumber.getBindingsFromRequest(request, true);
- List<String> cmds = getCommandList(request);
+ List<String> cmds = getCommandList(request, bindings);
if (cmds.isEmpty()) {
writer.println("No command to execute!");
}
diff --git a/src/test/java/org/apache/sling/pipes/internal/CommandExecutorImplTest.java b/src/test/java/org/apache/sling/pipes/internal/CommandExecutorImplTest.java
index 753e833..d36c4f2 100644
--- a/src/test/java/org/apache/sling/pipes/internal/CommandExecutorImplTest.java
+++ b/src/test/java/org/apache/sling/pipes/internal/CommandExecutorImplTest.java
@@ -37,8 +37,12 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.regex.Matcher;
import java.util.stream.Collectors;
+import static org.apache.sling.pipes.internal.CommandExecutorImpl.DECL_BINDING;
+import static org.apache.sling.pipes.internal.CommandExecutorImpl.DECL_BINDING_CONTENT;
+import static org.apache.sling.pipes.internal.CommandExecutorImpl.DECL_BINDING_PATTERN;
import static org.apache.sling.pipes.internal.CommandExecutorImpl.PARAMS_SEPARATOR;
import static org.apache.sling.pipes.internal.CommandUtil.keyValuesToArray;
import static org.junit.Assert.assertArrayEquals;
@@ -232,7 +236,7 @@ public class CommandExecutorImplTest extends AbstractPipeTest {
MockSlingHttpServletRequest request = context.request();
request.setParameterMap(params);
request.setMethod("POST");
- List<String> cmdList = commands.getCommandList(context.request());
+ List<String> cmdList = commands.getCommandList(context.request(), new HashMap<>());
assertEquals(5, cmdList.size());
for (int i = 0; i < 3; i ++) {
assertEquals("echo /content | $ /apps/pipes-it/fruit | children nt:unstructured", cmdList.get(i));
@@ -247,12 +251,16 @@ public class CommandExecutorImplTest extends AbstractPipeTest {
return items.toArray(new String[jsonItems.size()]);
}
+ JsonObject executeFile(String fileName) throws IOException, ServletException {
+ Map<String, Object> params = new HashMap<>();
+ params.put(CommandExecutorImpl.REQ_PARAM_FILE, IOUtils.toString(getClass().getResourceAsStream("/" + fileName
+ + ".txt"), "UTF-8"));
+ return testServlet(params);
+ }
+
@Test
public void testChainedCommand() throws IOException, ServletException {
- Map<String, Object> params = new HashMap<>();
- params.put(CommandExecutorImpl.REQ_PARAM_FILE, IOUtils.toString(getClass().getResourceAsStream("/chainedCommand"
- + ".txt"), "UTF-8"));
- JsonObject response = testServlet(params);
+ JsonObject response = executeFile("chainedCommand");
assertEquals(5, response.getJsonNumber("size").intValue());
assertArrayEquals(new String[]{ "/content/fruits/banana/isnota/pea","/content/fruits/banana/isnota/carrot",
"/content/fruits/apple/isnota/pea","/content/fruits/apple/isnota/plum",
@@ -261,12 +269,34 @@ public class CommandExecutorImplTest extends AbstractPipeTest {
@Test
public void testFileCommandServlet() throws IOException, ServletException {
- Map<String, Object> params = new HashMap<>();
- params.put(CommandExecutorImpl.REQ_PARAM_FILE, IOUtils.toString(getClass().getResourceAsStream("/testcommand"
- + ".txt"), "UTF-8"));
- JsonObject response = testServlet(params);
+ JsonObject response = executeFile("testcommand");
assertEquals(5, response.getJsonNumber("size").intValue());
assertArrayEquals(new String[]{"/content/beatles/john", "/content/beatles/paul", "/content/beatles/georges",
"/content/beatles/ringo", "/content/beatles/ringo/jcr:content"}, getItemsArray(response));
}
+
+
+ void assertDeclBinding(String input, String expectedBinding, String expectedContent) {
+ Matcher matcher = DECL_BINDING_PATTERN.matcher(input);
+ assertTrue(input + " should match", matcher.matches());
+ assertEquals("binding should be " + expectedBinding, expectedBinding, matcher.group(DECL_BINDING));
+ assertEquals("content should be " + expectedContent, expectedContent, matcher.group(DECL_BINDING_CONTENT));
+ }
+
+ @Test
+ public void testDeclBindingPattern() {
+ assertDeclBinding("binding blah = {\"foo\":\"bar\"}", "blah", "{\"foo\":\"bar\"}");
+ assertDeclBinding("binding blah={\"foo\":\"bar\"}", "blah", "{\"foo\":\"bar\"}");
+ assertDeclBinding("binding blah = {", "blah", "{");
+ assertDeclBinding("binding csvStart = name,title", "csvStart", "name,title");
+ assertDeclBinding("binding csvStart =", "csvStart", "");
+ }
+
+ @Test
+ public void testDeclaredBindingBasedInit() throws ServletException, IOException {
+ JsonObject response = executeFile("declbasedinit");
+ assertEquals(4, response.getJsonNumber("size").intValue());
+ assertArrayEquals(new String[]{"/content/pages/1/leaves/child1","/content/pages/1/leaves/child2",
+ "/content/pages/2/leaves/child1","/content/pages/2/leaves/child2"}, getItemsArray(response));
+ }
}
\ No newline at end of file
diff --git a/src/test/resources/declbasedinit.txt b/src/test/resources/declbasedinit.txt
new file mode 100644
index 0000000..c346f4a
--- /dev/null
+++ b/src/test/resources/declbasedinit.txt
@@ -0,0 +1,27 @@
+#
+# 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.
+
+binding pages = name,label
+1,first
+2,second
+
+binding leaves = {"child1": {"title":"child one"},
+ "child2": {"title":"child two"}
+}
+
+echo /content
+ | csv ${pages} @ name page | mkdir pages/${page.name} | write title=page.label
+ | json ${leaves} @ name leaf | mkdir leaves/${leaf.key} | write title=leaf.value.title
\ No newline at end of file