From 897b98b4e3290f49ba3d6fe38399afcde404f5d4 Mon Sep 17 00:00:00 2001
From: sebastien curt <sebastien.curt@tetras-libre.fr>
Date: Wed, 8 Jul 2020 12:24:55 +0200
Subject: [PATCH] Add fluent api unlDocumentNodeBuilder

---
 .idea/codeStyles/codeStyleConfig.xml          |   5 +
 .../unltools/unl/builders/GraphBuilder.java   |  43 +++++++
 .../unl/builders/GraphRelationBuilder.java    |  94 ++++++++++++++++
 .../unl/builders/RestrictionBuilder.java      | 105 ++++++++++++++++++
 .../unl/builders/RestrictionOrientation.java  |   7 ++
 .../SubGraphReferenceNodeBuilder.java         |  61 ++++++++++
 .../unl/builders/UniversalWordBuilder.java    |  80 +++++++++++++
 .../builders/UniversalWordNodeBuilder.java    |  80 +++++++++++++
 .../unl/builders/UnlDocumentNodeBuilder.java  |  74 ++++++++++++
 9 files changed, 549 insertions(+)
 create mode 100644 .idea/codeStyles/codeStyleConfig.xml
 create mode 100644 unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/GraphBuilder.java
 create mode 100644 unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/GraphRelationBuilder.java
 create mode 100644 unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/RestrictionBuilder.java
 create mode 100644 unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/RestrictionOrientation.java
 create mode 100644 unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/SubGraphReferenceNodeBuilder.java
 create mode 100644 unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UniversalWordBuilder.java
 create mode 100644 unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UniversalWordNodeBuilder.java
 create mode 100644 unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UnlDocumentNodeBuilder.java

diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+  <state>
+    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
+  </state>
+</component>
\ No newline at end of file
diff --git a/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/GraphBuilder.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/GraphBuilder.java
new file mode 100644
index 0000000..3673142
--- /dev/null
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/GraphBuilder.java
@@ -0,0 +1,43 @@
+package fr.tetras_libre.unltools.unl.builders;
+
+import fr.tetras_libre.unltools.unl.Graph;
+
+import java.util.function.Function;
+
+public class GraphBuilder {
+    Graph graph;
+
+    private GraphBuilder() {
+        this.graph = new Graph();
+    }
+
+    public static IBuild graph() {
+        return new GraphBuilder.Builder();
+    }
+
+    public interface IBuild {
+        IBuild addGraphRelation(Function<GraphRelationBuilder.RequiredLabel, GraphRelationBuilder.IBuild> c);
+
+        Graph buildGraph();
+    }
+
+    private static class Builder implements IBuild {
+        private final GraphBuilder instance;
+
+        public Builder() {
+            instance = new GraphBuilder();
+        }
+
+        @Override
+        public IBuild addGraphRelation(Function<GraphRelationBuilder.RequiredLabel, GraphRelationBuilder.IBuild> c) {
+            instance.graph.add(c.apply(GraphRelationBuilder.createBuilder()).buildGraphRelation());
+            return this;
+        }
+
+        @Override
+        public Graph buildGraph() {
+            return instance.graph;
+        }
+    }
+
+}
diff --git a/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/GraphRelationBuilder.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/GraphRelationBuilder.java
new file mode 100644
index 0000000..85ce480
--- /dev/null
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/GraphRelationBuilder.java
@@ -0,0 +1,94 @@
+package fr.tetras_libre.unltools.unl.builders;
+
+import fr.tetras_libre.unltools.unl.GraphNode;
+import fr.tetras_libre.unltools.unl.GraphRelation;
+
+import java.util.function.Function;
+
+
+public class GraphRelationBuilder {
+    private String label;
+    private String graphReference;
+    private GraphNode node1;
+    private GraphNode node2;
+
+    public static RequiredLabel createBuilder() {
+        return new GraphRelationBuilder.Builder();
+    }
+
+
+    public interface RequiredLabel {
+        OptionalGraphReference label(String label);
+    }
+
+    public interface OptionalGraphReference {
+        RequiredLeftNode reference(String nodeName);
+
+        RequiredLeftNode noReference();
+    }
+
+    public interface RequiredLeftNode {
+        RequiredRightNode leftNode(Function<UniversalWordNodeBuilder.IRequiredUniversalWord, UniversalWordNodeBuilder.IBuild> f);
+
+        IBuild rightSubGraphNode(Function<SubGraphReferenceNodeBuilder.IRequiredReferenceNumber, SubGraphReferenceNodeBuilder.IBuild> f);
+    }
+
+    public interface RequiredRightNode {
+        IBuild rightNode(Function<UniversalWordNodeBuilder.IRequiredUniversalWord, UniversalWordNodeBuilder.IBuild> f);
+
+        IBuild rightSubGraphNode(Function<SubGraphReferenceNodeBuilder.IRequiredReferenceNumber, SubGraphReferenceNodeBuilder.IBuild> f);
+    }
+
+    public interface IBuild {
+        GraphRelation buildGraphRelation();
+    }
+
+    private static class Builder implements RequiredLabel, OptionalGraphReference, RequiredLeftNode, RequiredRightNode, IBuild {
+        private final GraphRelationBuilder instance;
+
+        public Builder() {
+            instance = new GraphRelationBuilder();
+        }
+
+        @Override
+        public RequiredLeftNode reference(String nodeName) {
+            instance.graphReference = nodeName;
+            return this;
+        }
+
+        @Override
+        public RequiredLeftNode noReference() {
+            instance.graphReference = "";
+            return this;
+        }
+
+        @Override
+        public RequiredRightNode leftNode(Function<UniversalWordNodeBuilder.IRequiredUniversalWord, UniversalWordNodeBuilder.IBuild> f) {
+            this.instance.node1 = f.apply(UniversalWordNodeBuilder.createBuilder()).buildUniversalWordNode();
+            return this;
+        }
+
+        @Override
+        public IBuild rightSubGraphNode(Function<SubGraphReferenceNodeBuilder.IRequiredReferenceNumber, SubGraphReferenceNodeBuilder.IBuild> f) {
+            instance.node2 = f.apply(SubGraphReferenceNodeBuilder.createBuilder()).buildSubGraphReferenceNode();
+            return this;
+        }
+
+        @Override
+        public GraphRelation buildGraphRelation() {
+            return new GraphRelation(instance.node1, instance.node2, instance.label, instance.graphReference);
+        }
+
+        @Override
+        public OptionalGraphReference label(String label) {
+            instance.label = label;
+            return this;
+        }
+
+        @Override
+        public IBuild rightNode(Function<UniversalWordNodeBuilder.IRequiredUniversalWord, UniversalWordNodeBuilder.IBuild> f) {
+            instance.node2 = f.apply(UniversalWordNodeBuilder.createBuilder()).buildUniversalWordNode();
+            return this;
+        }
+    }
+}
diff --git a/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/RestrictionBuilder.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/RestrictionBuilder.java
new file mode 100644
index 0000000..934e518
--- /dev/null
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/RestrictionBuilder.java
@@ -0,0 +1,105 @@
+package fr.tetras_libre.unltools.unl.builders;
+
+import fr.tetras_libre.unltools.unl.Restriction;
+import fr.tetras_libre.unltools.unl.UniversalWord;
+
+public class RestrictionBuilder {
+    private String label;
+    private char orientation;
+    private UniversalWord universalWord;
+
+    private RestrictionBuilder() {
+        label = "";
+        orientation = ' ';
+        universalWord = null;
+    }
+
+    public interface IRequiredLabel {
+        IOrientation label(String label);
+    }
+
+    public static Restriction simpleRestriction(String label, RestrictionOrientation orientation, String headwordLabel) {
+        return RestrictionBuilder
+            .createBuilder()
+            .label(label)
+            .withOrientation(orientation)
+            .universalWord(UniversalWordBuilder.simpleUniversalWord(headwordLabel))
+            .buildRestriction();
+    }
+
+    public static IRequiredLabel createBuilder() {
+        return new RestrictionBuilder.Builder();
+    }
+
+    public static Restriction ternaryTransitiveRestriction(String label1, String label2, String label3, RestrictionOrientation orientation) {
+        return RestrictionBuilder
+            .createBuilder()
+            .label(label1)
+            .withOrientation(orientation)
+            .universalWord(
+                UniversalWordBuilder
+                    .createBuilder()
+                    .headWord(label2)
+                    .addSimpleRestriction(label1, orientation, label3                    )
+                    .buildUniversalWord()
+            )
+            .buildRestriction();
+    }
+
+    public interface IOrientation {
+        IRequiredUniversalWord withOrientation(RestrictionOrientation orientation);
+    }
+
+    public interface IRequiredUniversalWord {
+        IBuild universalWord(UniversalWord universalWord);
+    }
+
+    public interface IBuild {
+        Restriction buildRestriction();
+    }
+
+    private static class Builder implements IRequiredLabel, IRequiredUniversalWord, IOrientation, IBuild {
+        private final RestrictionBuilder instance;
+
+        public Builder(){
+            instance = new RestrictionBuilder();
+        }
+
+        @Override
+        public IBuild universalWord(UniversalWord universalWord) {
+            instance.universalWord = universalWord;
+            return this;
+        }
+
+        @Override
+        public IRequiredUniversalWord withOrientation(RestrictionOrientation orientation) {
+            switch (orientation) {
+                case Left:
+                    instance.orientation = '<';
+                    break;
+                case None:
+                    instance.orientation = ' ';
+                    break;
+                case Right:
+                    instance.orientation = '>';
+                    break;
+            }
+
+            return this;
+        }
+
+        @Override
+        public Restriction buildRestriction() {
+            return new Restriction(instance.label, instance.orientation, instance.universalWord);
+        }
+
+        @Override
+        public IOrientation label(String label) {
+            if(null == label)
+                throw new IllegalArgumentException();
+            instance.label = label;
+
+            return this;
+        }
+    }
+}
diff --git a/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/RestrictionOrientation.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/RestrictionOrientation.java
new file mode 100644
index 0000000..9d61c1a
--- /dev/null
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/RestrictionOrientation.java
@@ -0,0 +1,7 @@
+package fr.tetras_libre.unltools.unl.builders;
+
+public enum RestrictionOrientation {
+    None,
+    Right,
+    Left
+}
diff --git a/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/SubGraphReferenceNodeBuilder.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/SubGraphReferenceNodeBuilder.java
new file mode 100644
index 0000000..0d8193e
--- /dev/null
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/SubGraphReferenceNodeBuilder.java
@@ -0,0 +1,61 @@
+package fr.tetras_libre.unltools.unl.builders;
+
+import fr.tetras_libre.unltools.unl.SubGraphReferenceNode;
+
+import java.util.HashSet;
+
+public class SubGraphReferenceNodeBuilder {
+    private String referenceNumber;
+    private HashSet<String> attributes;
+
+    public static IRequiredReferenceNumber createBuilder()
+    {
+        return new SubGraphReferenceNodeBuilder.Builder();
+    }
+
+    private SubGraphReferenceNodeBuilder() {
+        referenceNumber = null;
+        attributes = new HashSet<>();
+    }
+
+    public interface IRequiredReferenceNumber {
+        IBuild referenceNumber(String referenceNumber);
+    }
+
+    public interface IBuild {
+        IBuild addAttribute(String attribute);
+
+        SubGraphReferenceNode buildSubGraphReferenceNode();
+    }
+
+    private static class Builder implements IRequiredReferenceNumber, IBuild {
+        SubGraphReferenceNodeBuilder instance;
+
+        public Builder() {
+            instance = new SubGraphReferenceNodeBuilder();
+        }
+
+        @Override
+        public IBuild referenceNumber(String referenceNumber) {
+            if (null == referenceNumber || referenceNumber.isBlank())
+                throw new IllegalArgumentException();
+
+            this.instance.referenceNumber = referenceNumber;
+
+            return this;
+        }
+
+        @Override
+        public IBuild addAttribute(String attribute) {
+            if (null != attribute && !attribute.isBlank())
+                this.instance.attributes.add(attribute);
+
+            return this;
+        }
+
+        @Override
+        public SubGraphReferenceNode buildSubGraphReferenceNode() {
+            return new SubGraphReferenceNode(instance.referenceNumber, instance.attributes);
+        }
+    }
+}
diff --git a/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UniversalWordBuilder.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UniversalWordBuilder.java
new file mode 100644
index 0000000..b6bb120
--- /dev/null
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UniversalWordBuilder.java
@@ -0,0 +1,80 @@
+package fr.tetras_libre.unltools.unl.builders;
+
+import fr.tetras_libre.unltools.unl.Restriction;
+import fr.tetras_libre.unltools.unl.UniversalWord;
+
+import java.util.TreeSet;
+import java.util.function.Function;
+
+public class UniversalWordBuilder {
+    private final TreeSet<Restriction> restrictions;
+    private String headWord;
+
+    private UniversalWordBuilder() {
+        restrictions = new TreeSet<>();
+    }
+
+    public static IRequiredHeadWord createBuilder() {
+        return new UniversalWordBuilder.Builder();
+    }
+
+    public static UniversalWord simpleUniversalWord(String headWord) {
+        return UniversalWordBuilder.createBuilder()
+            .headWord(headWord)
+            .buildUniversalWord();
+    }
+
+    public interface IBuild {
+
+        IBuild addRestriction(Function<RestrictionBuilder.IRequiredLabel, RestrictionBuilder.IBuild> f);
+
+        IBuild addSimpleRestriction(String label1, RestrictionOrientation orientation, String label2);
+
+        IBuild addTernaryTransitiveRestriction(String firstLabel, String secondLabel, String thirdLabel, RestrictionOrientation orientation);
+
+        UniversalWord buildUniversalWord();
+    }
+
+    public interface IRequiredHeadWord {
+        IBuild headWord(String headword);
+    }
+
+    private static class Builder implements IRequiredHeadWord, IBuild {
+        private final UniversalWordBuilder instance;
+
+        Builder() {
+            instance = new UniversalWordBuilder();
+        }
+
+        @Override
+        public IBuild addRestriction(Function<RestrictionBuilder.IRequiredLabel, RestrictionBuilder.IBuild> f) {
+            instance.restrictions.add(f.apply(RestrictionBuilder.createBuilder()).buildRestriction());
+            return this;
+        }
+
+        @Override
+        public IBuild addSimpleRestriction(String label1, RestrictionOrientation orientation, String label2) {
+            instance.restrictions.add(RestrictionBuilder.simpleRestriction(label1, orientation, label2));
+            return this;
+        }
+
+        @Override
+        public IBuild addTernaryTransitiveRestriction(String firstLabel, String secondLabel, String thirdLabel, RestrictionOrientation orientation) {
+            instance.restrictions.add(RestrictionBuilder.ternaryTransitiveRestriction(firstLabel, secondLabel, thirdLabel, orientation));
+            return this;
+        }
+
+        @Override
+        public UniversalWord buildUniversalWord() {
+            return new UniversalWord(instance.headWord, instance.restrictions);
+        }
+
+        @Override
+        public IBuild headWord(String headword) {
+            if (null == headword)
+                throw new IllegalArgumentException();
+            instance.headWord = headword;
+            return this;
+        }
+    }
+}
diff --git a/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UniversalWordNodeBuilder.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UniversalWordNodeBuilder.java
new file mode 100644
index 0000000..7702180
--- /dev/null
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UniversalWordNodeBuilder.java
@@ -0,0 +1,80 @@
+package fr.tetras_libre.unltools.unl.builders;
+
+import fr.tetras_libre.unltools.unl.UniversalWord;
+import fr.tetras_libre.unltools.unl.UniversalWordNode;
+
+import java.util.HashSet;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class UniversalWordNodeBuilder {
+    private final HashSet<String> attributes;
+    private UniversalWord universalWord;
+    private String instanceNumber;
+
+    private UniversalWordNodeBuilder() {
+        this.attributes = new HashSet<>();
+        this.instanceNumber = "";
+    }
+
+    public static IRequiredUniversalWord createBuilder() {
+        return new UniversalWordNodeBuilder.Builder();
+    }
+
+    public interface IRequiredUniversalWord {
+        IBuild universalWord(Function<UniversalWordBuilder.IRequiredHeadWord, UniversalWordBuilder.IBuild> f);
+
+        IBuild simpleUniversalWord(Supplier<String> s);
+    }
+
+    public interface IBuild {
+        IBuild addAttribute(String attribute);
+
+        IBuild instanceNumber(String nodeReference);
+
+        UniversalWordNode buildUniversalWordNode();
+    }
+
+    private static class Builder implements IRequiredUniversalWord, IBuild {
+        private final UniversalWordNodeBuilder instance;
+
+        public Builder() {
+            this.instance = new UniversalWordNodeBuilder();
+        }
+
+        @Override
+        public IBuild addAttribute(String attribute) {
+            if (null != attribute
+                && !attribute.isBlank())
+                this.instance.attributes.add(attribute);
+
+            return this;
+        }
+
+        @Override
+        public IBuild instanceNumber(String nodeReference) {
+            if(null == nodeReference){
+                throw new IllegalArgumentException();
+            }
+            this.instance.instanceNumber = nodeReference;
+            return this;
+        }
+
+        @Override
+        public UniversalWordNode buildUniversalWordNode() {
+            return new UniversalWordNode(instance.universalWord, instance.attributes, instance.instanceNumber);
+        }
+
+        @Override
+        public IBuild universalWord(Function<UniversalWordBuilder.IRequiredHeadWord, UniversalWordBuilder.IBuild> f) {
+            instance.universalWord = f.apply(UniversalWordBuilder.createBuilder()).buildUniversalWord();
+            return this;
+        }
+
+        @Override
+        public IBuild simpleUniversalWord(Supplier<String> s) {
+            instance.universalWord = UniversalWordBuilder.simpleUniversalWord(s.get());
+            return this;
+        }
+    }
+}
diff --git a/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UnlDocumentNodeBuilder.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UnlDocumentNodeBuilder.java
new file mode 100644
index 0000000..2db0555
--- /dev/null
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/builders/UnlDocumentNodeBuilder.java
@@ -0,0 +1,74 @@
+package fr.tetras_libre.unltools.unl.builders;
+
+import fr.tetras_libre.unltools.unl.Graph;
+import fr.tetras_libre.unltools.unl.UnlDocumentNode;
+import fr.tetras_libre.unltools.unl.UnlDocumentNodeType;
+
+import java.util.function.Function;
+
+public class UnlDocumentNodeBuilder {
+    private UnlDocumentNodeType unlDocumentNodeType;
+    private String docNodeLabel;
+    private Graph graph;
+
+    private UnlDocumentNodeBuilder() {
+        docNodeLabel = null;
+        graph = null;
+    }
+
+    public static IUnlDocumentNodeType createBuilder() {
+        return new UnlDocumentNodeBuilder.Builder();
+    }
+
+    public interface IUnlDocumentNodeType {
+        ILabel withNodeType(UnlDocumentNodeType nodeType);
+    }
+
+    public interface ILabel {
+        IGraph withLabel(String label);
+    }
+
+    public interface IGraph {
+        IBuild withGraph(Function<GraphBuilder.IBuild, GraphBuilder.IBuild> f);
+    }
+
+    public interface IBuild {
+        UnlDocumentNode buildUnlDocumentNode();
+    }
+
+    private static class Builder implements IBuild, ILabel, IGraph, IUnlDocumentNodeType {
+        private final UnlDocumentNodeBuilder instance;
+
+        Builder() {
+            instance = new UnlDocumentNodeBuilder();
+        }
+
+        @Override
+        public UnlDocumentNode buildUnlDocumentNode() {
+            return new UnlDocumentNode(instance.unlDocumentNodeType, instance.docNodeLabel, instance.graph);
+        }
+
+        @Override
+        public IGraph withLabel(String label) {
+            if (null == label || label.isBlank())
+                throw new IllegalArgumentException();
+
+            instance.docNodeLabel = label;
+            return this;
+        }
+
+        @Override
+        public IBuild withGraph(Function<GraphBuilder.IBuild, GraphBuilder.IBuild> f) {
+            if (null != instance.graph)
+                throw new IllegalStateException();
+            instance.graph = f.apply(GraphBuilder.graph()).buildGraph();
+            return this;
+        }
+
+        @Override
+        public ILabel withNodeType(UnlDocumentNodeType nodeType) {
+            instance.unlDocumentNodeType = nodeType;
+            return this;
+        }
+    }
+}
-- 
GitLab