You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2023/01/10 08:38:44 UTC

[sling-org-apache-sling-repoinit-parser] branch master updated: SLING-11736 Add "ensure nodes" as replacement of "create path" (#27)

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

kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-repoinit-parser.git


The following commit(s) were added to refs/heads/master by this push:
     new 9d7d66a  SLING-11736 Add "ensure nodes" as replacement of "create path" (#27)
9d7d66a is described below

commit 9d7d66aaf244d149124fd491dddf6b90e0172efb
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Tue Jan 10 09:38:39 2023 +0100

    SLING-11736 Add "ensure nodes" as replacement of "create path" (#27)
    
    This has stricter semantics of adjusting types of existing nodes
---
 .../repoinit/parser/operations/CreatePath.java     |  5 +++
 .../{CreatePath.java => EnsureNodes.java}          | 10 +++---
 .../parser/operations/OperationVisitor.java        |  2 +-
 src/main/javacc/RepoInitGrammar.jjt                | 42 ++++++++++++++++++++++
 .../parser/test/OperationToStringVisitor.java      | 11 ++++++
 src/test/resources/testcases/test-73-output.txt    | 17 +++++++++
 src/test/resources/testcases/test-73.txt           | 35 ++++++++++++++++++
 7 files changed, 116 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java b/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java
index d40ddba..e1336bc 100644
--- a/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java
@@ -25,7 +25,12 @@ import java.util.List;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.annotation.versioning.ProviderType;
 
+/**
+ * @deprecated Use {@link EnsureNodes} instead.
+ *
+ */
 @ProviderType
+@Deprecated
 public class CreatePath extends Operation {
     private List<PathSegmentDefinition> pathDef;
     private final String defaultPrimaryType;
diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java b/src/main/java/org/apache/sling/repoinit/parser/operations/EnsureNodes.java
similarity index 94%
copy from src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java
copy to src/main/java/org/apache/sling/repoinit/parser/operations/EnsureNodes.java
index d40ddba..4670ff4 100644
--- a/src/main/java/org/apache/sling/repoinit/parser/operations/CreatePath.java
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/EnsureNodes.java
@@ -26,12 +26,12 @@ import org.jetbrains.annotations.NotNull;
 import org.osgi.annotation.versioning.ProviderType;
 
 @ProviderType
-public class CreatePath extends Operation {
+public class EnsureNodes extends Operation {
     private List<PathSegmentDefinition> pathDef;
     private final String defaultPrimaryType;
     private List<PropertyLine> lines = Collections.emptyList();
 
-    public CreatePath(String defaultPrimaryType) {
+    public EnsureNodes(String defaultPrimaryType) {
         this.pathDef = new ArrayList<>();
         this.defaultPrimaryType = defaultPrimaryType;
     }
@@ -70,9 +70,9 @@ public class CreatePath extends Operation {
         //        exactly as they were originally defined in repo-init
         try (Formatter formatter = new Formatter()) {
             if (lines.isEmpty()) {
-                formatter.format("create path %s%s%n",  defaultTypeStr, sb.toString());
+                formatter.format("ensure nodes %s%s%n",  defaultTypeStr, sb.toString());
             } else {
-                formatter.format("create path %s%s with properties%n",  defaultTypeStr, sb.toString());
+                formatter.format("ensure nodes %s%s with properties%n",  defaultTypeStr, sb.toString());
                 for (PropertyLine line : lines) {
                     String type = (line.getPropertyType() == null) ? "" : "{" + line.getPropertyType().name() + "}";
                     String values = SetProperties.valuesToString(line.getPropertyValues(), line.getPropertyType());
@@ -90,7 +90,7 @@ public class CreatePath extends Operation {
 
     @Override
     public void accept(OperationVisitor v) {
-        v.visitCreatePath(this);
+        v.visitEnsureNodes(this);
     }
 
     public void addSegment(String path, String primaryType) {
diff --git a/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java b/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java
index b009434..957d9db 100644
--- a/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java
+++ b/src/main/java/org/apache/sling/repoinit/parser/operations/OperationVisitor.java
@@ -36,6 +36,7 @@ public interface OperationVisitor {
     default void visitRemoveAcePaths(RemoveAcePaths s) { throw new UnsupportedOperationException(); }
     default void visitRemoveAcePrincipalBased(RemoveAcePrincipalBased s) { throw new UnsupportedOperationException(); }
     void visitCreatePath(CreatePath cp);
+    void visitEnsureNodes(EnsureNodes cn);
     void visitRegisterNamespace(RegisterNamespace rn);
     void visitRegisterNodetypes(RegisterNodetypes b);
     void visitRegisterPrivilege(RegisterPrivilege rp);
@@ -46,7 +47,6 @@ public interface OperationVisitor {
     default void visitDeleteAclPrincipals(DeleteAclPrincipals s) { throw new UnsupportedOperationException(); }
     default void visitDeleteAclPaths(DeleteAclPaths s) { throw new UnsupportedOperationException(); }
     default void visitDeleteAclPrincipalBased(DeleteAclPrincipalBased s) { throw new UnsupportedOperationException(); }
-
     default void visitAddMixins(AddMixins s) { throw new UnsupportedOperationException(); }
     default void visitRemoveMixins(RemoveMixins s) { throw new UnsupportedOperationException(); }
 
diff --git a/src/main/javacc/RepoInitGrammar.jjt b/src/main/javacc/RepoInitGrammar.jjt
index c2b9181..c908bea 100644
--- a/src/main/javacc/RepoInitGrammar.jjt
+++ b/src/main/javacc/RepoInitGrammar.jjt
@@ -70,10 +70,13 @@ TOKEN:
 |   < DELETE: "delete" >
 |   < ENSURE: "ensure" >
 |   < DISABLE: "disable" >
+|   < ENSURE: "ensure" >
 |   < SERVICE: "service" >
 |   < ADD: "add" >
 |   < MIXIN: "mixin" >
 |   < PATH: "path" >
+|   < NODE: "node" >
+|   < NODES: "nodes" >
 |   < END: "end" >
 |   < REPOSITORY: "repository" >
 |   < PRINCIPAL: "principal" >
@@ -154,6 +157,7 @@ List<Operation> parse() :
         | removeAcePrincipals(result)
         | removeAcePrincipalBased(result)
         | createPathStatement(result)
+        | ensureNodesStatement(result)
         | addMixins(result)
         | removeMixins(result)
         | registerNamespaceStatement(result)
@@ -337,6 +341,44 @@ void createPathStatement(List<Operation> result) :
     { if(cp != null) result.add(cp); }
 }
 
+// similar to createPath but with stricter semantics of also changing types of existing nodes
+void ensureNodesStatement(List<Operation> result) :
+{
+    EnsureNodes en = null;
+    String defaultPrimaryType = null;
+    Token t1 = null;
+    Token t2 = null;
+    List<String> t3 = null;
+    List<PropertyLine> lines = new ArrayList<PropertyLine>();
+}
+{
+    <ENSURE> <NODES> 
+    ( <LPAREN> t1 = <NAMESPACED_ITEM> <RPAREN> { defaultPrimaryType = t1.image; } ) ?
+    
+    ( t1 = <PATH_STRING> ( <LPAREN> t2 = <NAMESPACED_ITEM> <RPAREN> ) ?
+                         ( <LPAREN> <MIXIN> t3 = namespacedItemsList() <RPAREN>) ?
+                         ( <LPAREN> t2 = <NAMESPACED_ITEM> <MIXIN> t3 = namespacedItemsList() <RPAREN>) ?
+        {
+            if(en == null) {
+                en = new EnsureNodes(defaultPrimaryType);
+            } 
+            en.addSegment(t1.image, t2 == null ? null : t2.image, t3);
+            t2 = null;
+            t3 = null;
+        }
+    ) +
+    ( <WITH> <PROPERTIES> <EOL>
+      ( propertyLine(lines) | blankLine() ) +
+      {
+        en.setPropertyLines(lines);
+      }
+      <END>
+    )?
+    (<EOL> | <EOF>)
+    
+    { if(en != null) result.add(en); }
+}
+
 void addMixins(List<Operation> result) :
 {
     List<String> mixins = null;
diff --git a/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java b/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java
index 419fa0d..7ffabf1 100644
--- a/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java
+++ b/src/test/java/org/apache/sling/repoinit/parser/test/OperationToStringVisitor.java
@@ -23,6 +23,7 @@ import java.util.List;
 
 import org.apache.sling.repoinit.parser.operations.AclLine;
 import org.apache.sling.repoinit.parser.operations.CreateGroup;
+import org.apache.sling.repoinit.parser.operations.EnsureNodes;
 import org.apache.sling.repoinit.parser.operations.CreatePath;
 import org.apache.sling.repoinit.parser.operations.CreateServiceUser;
 import org.apache.sling.repoinit.parser.operations.CreateUser;
@@ -239,6 +240,16 @@ class OperationToStringVisitor implements OperationVisitor {
         }
     }
 
+    @Override
+    public void visitEnsureNodes(EnsureNodes cn) {
+        out.println(cn.toString());
+        List<PropertyLine> propLines = cn.getPropertyLines();
+        for(PropertyLine p : propLines) {
+            out.print("  ");
+            out.println(p);
+        }
+    }
+
     @Override
     public void visitRegisterNamespace(RegisterNamespace rn) {
         out.println(rn.toString());
diff --git a/src/test/resources/testcases/test-73-output.txt b/src/test/resources/testcases/test-73-output.txt
new file mode 100644
index 0000000..8da8d35
--- /dev/null
+++ b/src/test/resources/testcases/test-73-output.txt
@@ -0,0 +1,17 @@
+EnsureNodes [var(sling:Folder), discovery(nt:unstructured), somefolder(sling:Folder)]
+EnsureNodes [one, two, three]
+EnsureNodes [three, four(nt:folk), five(nt:jazz), six]
+EnsureNodes [seven(nt:x), eight(nt:x), nine(nt:x)]
+EnsureNodes [one(mixin [nt:art]), step(mixin [nt:dance]), two, steps]
+EnsureNodes [one(nt:foxtrot), step(nt:foxtrot mixin [nt:dance]), two(nt:foxtrot), steps(nt:foxtrot)]
+EnsureNodes [one, step(mixin [nt:dance, nt:art]), two, steps]
+EnsureNodes [one, step(nt:foxtrot mixin [nt:dance]), two, steps]
+EnsureNodes [one, step(nt:foxtrot mixin [nt:dance, nt:art]), two, steps]
+EnsureNodes [one:and, step, two:and, steps]
+EnsureNodes [one@home, step, two@home, steps]
+EnsureNodes [one+tap, step, two+tap, steps]
+EnsureNodes [(nt:x)]
+EnsureNodes [var(sling:Folder), discovery(nt:unstructured), somefolder2(sling:Folder)]
+  PropertyLine sling:ResourceType{String}=[{String}/x/y/z]
+  PropertyLine cq:allowedTemplates{String}=[{String}/d/e/f/*, {String}m/n/*]
+  PropertyLine default someInteger{Long}=[{Long}42]
diff --git a/src/test/resources/testcases/test-73.txt b/src/test/resources/testcases/test-73.txt
new file mode 100644
index 0000000..454466e
--- /dev/null
+++ b/src/test/resources/testcases/test-73.txt
@@ -0,0 +1,35 @@
+# Various "ensure nodes" tests
+
+# Nodetypes:
+# A nodetype in brackets right after "ensure nodes", like
+# sling:Folder below, sets the default type for all path
+# segments of this statement.
+# A nodetype in brackets at the end of a path segment, like
+# nt:unstructured below, applies just to that path segment.
+# If no specific nodetype is set, the repository uses its
+# default based on node type definitions.
+
+ensure nodes (sling:Folder) /var/discovery(nt:unstructured)/somefolder
+
+# more tests and examples
+ensure nodes /one/two/three
+ensure nodes /three/four(nt:folk)/five(nt:jazz)/six
+ensure nodes (nt:x) /seven/eight/nine
+ensure nodes /one(mixin nt:art)/step(mixin nt:dance)/two/steps
+ensure nodes (nt:foxtrot) /one/step(mixin nt:dance)/two/steps
+ensure nodes /one/step(mixin nt:dance,nt:art)/two/steps
+ensure nodes /one/step(nt:foxtrot mixin nt:dance)/two/steps
+ensure nodes /one/step(nt:foxtrot mixin nt:dance,nt:art)/two/steps
+ensure nodes /one:and/step/two:and/steps
+ensure nodes /one@home/step/two@home/steps
+ensure nodes /one+tap/step/two+tap/steps
+
+# this is to cover an edge case: SLING-11384 (create root node with primary type)
+ensure nodes /(nt:x)
+
+# SLING-10740 - Repoinit ensure nodes statement with properties
+ensure nodes (sling:Folder) /var/discovery(nt:unstructured)/somefolder2 with properties
+  set sling:ResourceType{String} to /x/y/z
+  set cq:allowedTemplates to /d/e/f/*, m/n/*
+  default someInteger{Long} to 42
+end
\ No newline at end of file