From 1fe39ee0e2a05aabf3c0833c3c45e5fd0f132c73 Mon Sep 17 00:00:00 2001
From: sebastien curt <sebastien.curt@tetras-libre.fr>
Date: Thu, 28 May 2020 19:03:28 +0200
Subject: [PATCH] + Code Re-relocation + UnitTest completion

---
 .idea/compiler.xml                            |  16 +-
 .idea/encodings.xml                           |  10 +-
 .idea/misc.xml                                |   5 -
 .idea/modules.xml                             |   7 +-
 pom.xml                                       |   8 +-
 .../vocabulary/R1SentenceWithExpectedRdf.java | 167 -----------------
 ...lationLabelToUnlPropertyConverterTest.java |  14 --
 .../unl/AllSetenceWithExpectedDotChecker.java | 177 ------------------
 .../CatSentenceWithExpectedDotChecker.java    |  32 ----
 .../unltools/unl/EqualsBuilderTest.java       |  25 ---
 .../unl/print/dotFile/DotFileBuilderTest.java |  82 --------
 {unl2rdf-app => unl-tools-app}/pom.xml        |  16 +-
 .../src/main/java/unl2rdf/Options.java        |   0
 .../src/main/java/unl2rdf/OutFileType.java    |   0
 .../src/main/java/unl2rdf/Unl2Rdf.java        |  18 +-
 .../src/main/resources/META-INF/MANIFEST.MF   |   0
 .../src/test/java/unl2rdf/Unl2RdfTest.java    |   0
 .../unl-tools-app.iml                         |  12 +-
 {unl-parser => unl-tools-core}/pom.xml        |   4 +-
 .../unltools/unl/EqualsBuilder.java           |   0
 .../fr/tetras_libre/unltools/unl/Graph.java   |  17 ++
 .../unltools/unl/GraphExporter.java           |   0
 .../unltools/unl/GraphExporterFactory.java    |   7 +
 .../tetras_libre/unltools/unl/GraphNode.java  |   0
 .../unltools/unl/GraphRelation.java           |  28 +++
 .../unltools/unl/HashCodeBuilder.java         |   0
 .../unltools/unl/NoEntryNodeException.java    |   0
 .../unltools/unl/Restriction.java             |   0
 .../unltools/unl/SubGraphReferenceNode.java   |   0
 .../unltools/unl/UniversalWord.java           |   0
 .../unltools/unl/UniversalWordNode.java       |   0
 .../unltools/unl/UnlDocument.java             |  17 ++
 .../unltools/unl/UnlDocumentNode.java         |  21 +++
 .../unltools/unl/UnlDocumentNodeType.java     |   0
 .../unltools/unl/EqualsBuilderTest.java       |  24 +++
 .../unl-tools-core.iml                        |   0
 {rdf => unl-tools-infrastructure}/pom.xml     |  16 +-
 .../unltools/unl}/GraphExtensions.java        |   2 +-
 .../unl}/GraphRelationExtensions.java         |   4 +-
 .../unl}/SubGraphReferenceNodeExtensions.java |   2 +-
 .../DefaultGraphExporterFactory.java          |  26 +++
 .../unl/exporters/GraphExporterNames.java     |   6 +
 .../exporters/dot/DotFileGraphExporter.java   |   6 +-
 .../exporters/rdf/RdfFileGraphExporter.java   |   6 +-
 .../RelationLabelToUnlPropertyConverter.java  |   2 +-
 .../unltools/unl/exporters/rdf}/Slugify.java  |   2 +-
 .../rdf}/UnlDocumentToRdfConverter.java       |  16 +-
 .../unl/exporters/rdf}/UtilGraphNodeUri.java  |   6 +-
 .../unltools/unl/parser/ParseException.java   |   0
 .../unltools/unl/parser/SimpleCharStream.java |   0
 .../unltools/unl/parser/Token.java            |   0
 .../unltools/unl/parser/TokenMgrError.java    |   0
 .../unltools/unl/parser/UnlParser.java        |   0
 .../unltools/unl/parser/UnlParser.jj          |   0
 .../unl/parser/UnlParserConstants.java        |   0
 .../unl/parser/UnlParserTokenManager.java     |   0
 .../AbstractFlyweightUnlArgumentProvider.java |  25 +++
 .../unl/AbstractUnlArgumentProvider.java      |  18 ++
 .../fr/tetras_libre/unltools/unl/AllUnl.java  |  18 ++
 .../fr/tetras_libre/unltools/unl/CatsUnl.java |  74 ++++++++
 .../fr/tetras_libre/unltools/unl/R1Unl.java   |  42 ++---
 .../fr/tetras_libre/unltools/unl/R2Unl.java   | 145 ++++++++++++++
 .../unltools/unl/UnlSentences.java            |  96 ++++++++++
 .../dot/AllSetenceWithExpectedDotChecker.java | 114 +++++++++++
 .../CatSentenceWithExpectedDotChecker.java    |  23 +++
 .../unl/exporters/dot/DotFileBuilderTest.java |  49 +++++
 .../R1SentenceWithExpectedDotChecker.java     |  22 +--
 .../R2SentenceWithExpectedDotChecker.java     |  22 +--
 ...ntenceWithExpectedDotArgumentProvider.java |   6 +-
 .../dot}/SentenceWithExpectedDotChecker.java  |  10 +-
 .../exporters/rdf}/RdfSchemaOfUNLTest.java    |  26 ++-
 ...lationLabelToUnlPropertyConverterTest.java |  29 +++
 ...ntenceWithExpectedUnlDocumentsChecker.java |  10 +
 ...ntenceWithExpectedUnlDocumentsChecker.java |  10 +
 ...ntenceWithExpectedUnlDocumentsChecker.java |  10 +
 ...ntenceWithExpectedUnlDocumentsChecker.java |  10 +
 ...hExpectedUnlDocumentsArgumentProvider.java |  21 +++
 ...ntenceWithExpectedUnlDocumentsChecker.java |  40 ++++
 .../unltools/unl/parser/UnlParserFactory.java |   0
 .../parser/UnlParserFactoryFromString.java    |   0
 .../unltools/unl/parser/UnlParserTest.java    |  42 +++--
 .../unltools/unl/parser/WrapperUnlParser.java |  41 +++-
 .../unl-tools-infrastructure.iml              |   3 +-
 unlTools.iml                                  |  20 ++
 84 files changed, 1038 insertions(+), 689 deletions(-)
 delete mode 100644 rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/R1SentenceWithExpectedRdf.java
 delete mode 100644 rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/RelationLabelToUnlPropertyConverterTest.java
 delete mode 100644 unl-parser/src/test/java/fr/tetras_libre/unltools/unl/AllSetenceWithExpectedDotChecker.java
 delete mode 100644 unl-parser/src/test/java/fr/tetras_libre/unltools/unl/CatSentenceWithExpectedDotChecker.java
 delete mode 100644 unl-parser/src/test/java/fr/tetras_libre/unltools/unl/EqualsBuilderTest.java
 delete mode 100644 unl-parser/src/test/java/fr/tetras_libre/unltools/unl/print/dotFile/DotFileBuilderTest.java
 rename {unl2rdf-app => unl-tools-app}/pom.xml (90%)
 rename {unl2rdf-app => unl-tools-app}/src/main/java/unl2rdf/Options.java (100%)
 rename {unl2rdf-app => unl-tools-app}/src/main/java/unl2rdf/OutFileType.java (100%)
 rename {unl2rdf-app => unl-tools-app}/src/main/java/unl2rdf/Unl2Rdf.java (77%)
 rename {unl2rdf-app => unl-tools-app}/src/main/resources/META-INF/MANIFEST.MF (100%)
 rename {unl2rdf-app => unl-tools-app}/src/test/java/unl2rdf/Unl2RdfTest.java (100%)
 rename unl2rdf-app/unl2rdf-app.iml => unl-tools-app/unl-tools-app.iml (90%)
 rename {unl-parser => unl-tools-core}/pom.xml (87%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/EqualsBuilder.java (100%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/Graph.java (91%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/GraphExporter.java (100%)
 create mode 100644 unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphExporterFactory.java
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/GraphNode.java (100%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/GraphRelation.java (63%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/HashCodeBuilder.java (100%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/NoEntryNodeException.java (100%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/Restriction.java (100%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/SubGraphReferenceNode.java (100%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/UniversalWord.java (100%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/UniversalWordNode.java (100%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/UnlDocument.java (81%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNode.java (78%)
 rename {unl-parser => unl-tools-core}/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNodeType.java (100%)
 create mode 100644 unl-tools-core/src/test/java/fr/tetras_libre/unltools/unl/EqualsBuilderTest.java
 rename unl-parser/unl-parser.iml => unl-tools-core/unl-tools-core.iml (100%)
 rename {rdf => unl-tools-infrastructure}/pom.xml (92%)
 rename {rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions => unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl}/GraphExtensions.java (95%)
 rename {rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions => unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl}/GraphRelationExtensions.java (93%)
 rename {rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions => unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl}/SubGraphReferenceNodeExtensions.java (92%)
 create mode 100644 unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/DefaultGraphExporterFactory.java
 create mode 100644 unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/GraphExporterNames.java
 rename unl-parser/src/main/java/fr/tetras_libre/unltools/unl/print/dotFile/DotFileBuilder.java => unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/dot/DotFileGraphExporter.java (97%)
 rename rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/RdfFileBuilder.java => unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/RdfFileGraphExporter.java (82%)
 rename {rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary => unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf}/RelationLabelToUnlPropertyConverter.java (94%)
 rename {rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary => unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf}/Slugify.java (73%)
 rename {rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary => unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf}/UnlDocumentToRdfConverter.java (95%)
 rename {rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary => unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf}/UtilGraphNodeUri.java (84%)
 rename {unl-parser => unl-tools-infrastructure}/src/main/java/fr/tetras_libre/unltools/unl/parser/ParseException.java (100%)
 rename {unl-parser => unl-tools-infrastructure}/src/main/java/fr/tetras_libre/unltools/unl/parser/SimpleCharStream.java (100%)
 rename {unl-parser => unl-tools-infrastructure}/src/main/java/fr/tetras_libre/unltools/unl/parser/Token.java (100%)
 rename {unl-parser => unl-tools-infrastructure}/src/main/java/fr/tetras_libre/unltools/unl/parser/TokenMgrError.java (100%)
 rename {unl-parser => unl-tools-infrastructure}/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.java (100%)
 rename {unl-parser => unl-tools-infrastructure}/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.jj (100%)
 rename {unl-parser => unl-tools-infrastructure}/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserConstants.java (100%)
 rename {unl-parser => unl-tools-infrastructure}/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserTokenManager.java (100%)
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AbstractFlyweightUnlArgumentProvider.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AbstractUnlArgumentProvider.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AllUnl.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/CatsUnl.java
 rename rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/CatUnlSentence.java => unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/R1Unl.java (89%)
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/R2Unl.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/UnlSentences.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/AllSetenceWithExpectedDotChecker.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/CatSentenceWithExpectedDotChecker.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/DotFileBuilderTest.java
 rename {unl-parser/src/test/java/fr/tetras_libre/unltools/unl => unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot}/R1SentenceWithExpectedDotChecker.java (60%)
 rename {unl-parser/src/test/java/fr/tetras_libre/unltools/unl => unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot}/R2SentenceWithExpectedDotChecker.java (63%)
 rename {unl-parser/src/test/java/fr/tetras_libre/unltools/unl => unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot}/SentenceWithExpectedDotArgumentProvider.java (64%)
 rename {unl-parser/src/test/java/fr/tetras_libre/unltools/unl => unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot}/SentenceWithExpectedDotChecker.java (79%)
 rename {rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary => unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/rdf}/RdfSchemaOfUNLTest.java (67%)
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/rdf/RelationLabelToUnlPropertyConverterTest.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/AllSentenceWithExpectedUnlDocumentsChecker.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/CatsSentenceWithExpectedUnlDocumentsChecker.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/R1SentenceWithExpectedUnlDocumentsChecker.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/R2SentenceWithExpectedUnlDocumentsChecker.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/SentenceWithExpectedUnlDocumentsArgumentProvider.java
 create mode 100644 unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/SentenceWithExpectedUnlDocumentsChecker.java
 rename {unl-parser => unl-tools-infrastructure}/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactory.java (100%)
 rename {unl-parser => unl-tools-infrastructure}/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactoryFromString.java (100%)
 rename {unl-parser => unl-tools-infrastructure}/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserTest.java (55%)
 rename {unl-parser => unl-tools-infrastructure}/src/test/java/fr/tetras_libre/unltools/unl/parser/WrapperUnlParser.java (66%)
 rename rdf/rdf.iml => unl-tools-infrastructure/unl-tools-infrastructure.iml (97%)
 create mode 100644 unlTools.iml

diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 7ec4916..112be42 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -6,31 +6,35 @@
         <sourceOutputDir name="target/generated-sources/annotations" />
         <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
         <outputRelativeToContentRoot value="true" />
-        <module name="rdf" />
-        <module name="unl-parser" />
+        <module name="unl-tools-infrastructure" />
+        <module name="unl-tools-core" />
       </profile>
-      <profile name="Annotation profile for unlTools" enabled="true">
+      <profile name="Annotation profile for unl-tools-main" enabled="true">
         <sourceOutputDir name="target/generated-sources/annotations" />
         <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
         <outputRelativeToContentRoot value="true" />
-        <option name="project" value="fr.tetras_libre.unl/unl2rdf-app" />
+        <option name="project" value="fr.tetras_libre.unl/unl-tools-app" />
         <processorPath useClasspath="false">
           <entry name="$MAVEN_REPOSITORY$/info/picocli/picocli-codegen/4.2.0/picocli-codegen-4.2.0.jar" />
           <entry name="$MAVEN_REPOSITORY$/info/picocli/picocli/4.2.0/picocli-4.2.0.jar" />
         </processorPath>
-        <module name="unl2rdf-app" />
+        <module name="unl-tools-app" />
       </profile>
     </annotationProcessing>
     <bytecodeTargetLevel target="11">
-      <module name="rdf" target="11" />
       <module name="unl-parser" target="11" />
+      <module name="unl-tools-app" target="11" />
+      <module name="unl-tools-core" target="11" />
+      <module name="unl-tools-infrastructure" target="11" />
       <module name="unl2rdf" target="11" />
       <module name="unl2rdf-app" target="11" />
+      <module name="unlTools" target="11" />
     </bytecodeTargetLevel>
   </component>
   <component name="JavacSettings">
     <option name="ADDITIONAL_OPTIONS_OVERRIDE">
       <module name="unl-parser" options="" />
+      <module name="unl-tools-app" options="-Aproject=fr.tetras_libre.unl/unl-tools-app" />
       <module name="unl2rdf" options="-Aproject=unl2rdf/unl2rdf" />
       <module name="unl2rdf-app" options="-Aproject=fr.tetras_libre.unl/unl2rdf-app" />
     </option>
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index 574f024..6301566 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="Encoding">
-    <file url="file://$PROJECT_DIR$/rdf/src/main/java" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/rdf/src/main/resources" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/unl-parser/src/main/java" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/unl2rdf-app/src/main/java" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/unl2rdf-app/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/unl-tools-app/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/unl-tools-app/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/unl-tools-core/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/unl-tools-infrastructure/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/unl-tools-infrastructure/src/main/resources" charset="UTF-8" />
   </component>
 </project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index ee0869e..ba348da 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -7,11 +7,6 @@
         <option value="$PROJECT_DIR$/../rdf/pom.xml" />
       </list>
     </option>
-    <option name="ignoredFiles">
-      <set>
-        <option value="$PROJECT_DIR$/pom.xml" />
-      </set>
-    </option>
   </component>
   <component name="ProjectRootManager" version="2" languageLevel="JDK_13" default="false" project-jdk-name="11" project-jdk-type="JavaSDK" />
 </project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 0224bb7..7e06cd3 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,9 +2,10 @@
 <project version="4">
   <component name="ProjectModuleManager">
     <modules>
-      <module fileurl="file://$PROJECT_DIR$/rdf/rdf.iml" filepath="$PROJECT_DIR$/rdf/rdf.iml" />
-      <module fileurl="file://$PROJECT_DIR$/unl-parser/unl-parser.iml" filepath="$PROJECT_DIR$/unl-parser/unl-parser.iml" />
-      <module fileurl="file://$PROJECT_DIR$/unl2rdf-app/unl2rdf-app.iml" filepath="$PROJECT_DIR$/unl2rdf-app/unl2rdf-app.iml" />
+      <module fileurl="file://$PROJECT_DIR$/unl-tools-app/unl-tools-app.iml" filepath="$PROJECT_DIR$/unl-tools-app/unl-tools-app.iml" />
+      <module fileurl="file://$PROJECT_DIR$/unl-tools-core/unl-tools-core.iml" filepath="$PROJECT_DIR$/unl-tools-core/unl-tools-core.iml" />
+      <module fileurl="file://$PROJECT_DIR$/unl-tools-infrastructure/unl-tools-infrastructure.iml" filepath="$PROJECT_DIR$/unl-tools-infrastructure/unl-tools-infrastructure.iml" />
+      <module fileurl="file://$PROJECT_DIR$/unlTools.iml" filepath="$PROJECT_DIR$/unlTools.iml" />
     </modules>
   </component>
 </project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index e68c2c6..cd3992a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,10 +13,12 @@
 
     <packaging>pom</packaging>
 
+    <name>unl-tools-main</name>
+
     <modules>
-        <module>unl-parser</module>
-        <module>unl2rdf-app</module>
-        <module>rdf</module>
+        <module>unl-tools-core</module>
+        <module>unl-tools-app</module>
+        <module>unl-tools-infrastructure</module>
     </modules>
 
     <build>
diff --git a/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/R1SentenceWithExpectedRdf.java b/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/R1SentenceWithExpectedRdf.java
deleted file mode 100644
index 98534b9..0000000
--- a/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/R1SentenceWithExpectedRdf.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package fr.tetras_libre.unltools.rdf.vocabulary;
-
-import fr.tetras_libre.unltools.unl.*;
-import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.ArgumentsProvider;
-
-import java.util.*;
-import java.util.stream.Stream;
-
-public class R1SentenceWithExpectedRdf implements ArgumentsProvider {
-    private static LinkedList<UnlDocument> unlDocuments;
-
-    public R1SentenceWithExpectedRdf() {
-        unlDocuments = new LinkedList<>();
-    }
-
-    private static void buildUnlDocument() {
-
-        var unlDocument = new UnlDocument("[D]");
-
-        var graph = new Graph();
-
-        // aoj
-        var restrictions = new TreeSet<Restriction>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("be", new TreeSet<>())));
-        restrictions.add(new Restriction("aoj", '>', new UniversalWord("thing", new TreeSet<>())));
-        restrictions.add(new Restriction("ben", '>', new UniversalWord("thing", new TreeSet<>())));
-        restrictions.add(new Restriction("obj", '>', new UniversalWord("uw", new TreeSet<>())));
-        restrictions.add(new Restriction("equ", '>', new UniversalWord("make_possible", new TreeSet<>())));
-        var uw = new UniversalWord("allow", restrictions);
-        var uwNode = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@entry")));
-
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("group", new TreeSet<>())));
-        uw = new UniversalWord("system", restrictions);
-        var uwNode2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@def")));
-
-        graph.add(new GraphRelation(uwNode, uwNode2, "aoj"));
-
-        // obj
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("be", new TreeSet<>())));
-        restrictions.add(new Restriction("aoj", '>', new UniversalWord("thing", new TreeSet<>())));
-        restrictions.add(new Restriction("ben", '>', new UniversalWord("thing", new TreeSet<>())));
-        restrictions.add(new Restriction("obj", '>', new UniversalWord("uw", new TreeSet<>())));
-        restrictions.add(new Restriction("equ", '>', new UniversalWord("make_possible", new TreeSet<>())));
-        uw = new UniversalWord("allow", restrictions);
-        uwNode = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@entry")));
-
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("aoj", '>', new UniversalWord("thing", new TreeSet<>())));
-        restrictions.add(new Restriction("equ", '>', new UniversalWord("assume", new TreeSet<>())));
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("change", new TreeSet<>())));
-        restrictions.add(new Restriction("obj", '>', new UniversalWord("thing", new TreeSet<>())));
-        uw = new UniversalWord("take_on", restrictions);
-        uwNode2 = new UniversalWordNode(uw, new HashSet<>());
-
-        graph.add(new GraphRelation(uwNode, uwNode2, "obj"));
-
-        // ben
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("be", new TreeSet<>())));
-        restrictions.add(new Restriction("aoj", '>', new UniversalWord("thing", new TreeSet<>())));
-        restrictions.add(new Restriction("ben", '>', new UniversalWord("thing", new TreeSet<>())));
-        restrictions.add(new Restriction("obj", '>', new UniversalWord("uw", new TreeSet<>())));
-        restrictions.add(new Restriction("equ", '>', new UniversalWord("make_possible", new TreeSet<>())));
-        uw = new UniversalWord("allow", restrictions);
-        uwNode = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@entry")));
-
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("radiowave", new TreeSet<>())));
-        uw = new UniversalWord("radiowave", restrictions);
-        uwNode2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@indef")));
-
-        graph.add(new GraphRelation(uwNode, uwNode2, "ben"));
-
-        // aoj
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("aoj", '>', new UniversalWord("thing", new TreeSet<>())));
-        restrictions.add(new Restriction("equ", '>', new UniversalWord("assume", new TreeSet<>())));
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("change", new TreeSet<>())));
-        restrictions.add(new Restriction("obj", '>', new UniversalWord("thing", new TreeSet<>())));
-        uw = new UniversalWord("take_on", restrictions);
-        uwNode = new UniversalWordNode(uw, new HashSet<>());
-
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("radiowave", new TreeSet<>())));
-        uw = new UniversalWord("channel", restrictions);
-        uwNode2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@indef")));
-
-        graph.add(new GraphRelation(uwNode, uwNode2, "aoj"));
-
-        // obj
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("aoj", '>', new UniversalWord("thing", new TreeSet<>())));
-        restrictions.add(new Restriction("equ", '>', new UniversalWord("assume", new TreeSet<>())));
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("change", new TreeSet<>())));
-        restrictions.add(new Restriction("obj", '>', new UniversalWord("thing", new TreeSet<>())));
-        uw = new UniversalWord("take_on", restrictions);
-        uwNode = new UniversalWordNode(uw, new HashSet<>());
-
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("attribute", new TreeSet<>())));
-        uw = new UniversalWord("state", restrictions);
-        uwNode2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@plu")));
-
-        graph.add(new GraphRelation(uwNode, uwNode2, "obj"));
-
-        // qua
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("attribute", new TreeSet<>())));
-        uw = new UniversalWord("state", restrictions);
-        uwNode = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@plu")));
-
-        uwNode2 = new UniversalWordNode(new UniversalWord("2", new TreeSet<>()), new HashSet<>());
-
-        graph.add(new GraphRelation(uwNode, uwNode2, "qua"));
-
-        // cnt
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("attribute", new TreeSet<>())));
-        uw = new UniversalWord("state", restrictions);
-        uwNode = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@plu")));
-
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("sensing", new TreeSet<>())));
-        uw = new UniversalWord("listening", restrictions);
-        uwNode2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@plu")));
-
-        graph.add(new GraphRelation(uwNode, uwNode2, "cnt"));
-
-        // and
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("sensing", new TreeSet<>())));
-        uw = new UniversalWord("listening", restrictions);
-        uwNode = new UniversalWordNode(uw, new HashSet<>());
-
-        restrictions = new TreeSet<>();
-        restrictions.add(new Restriction("icl", '>', new UniversalWord("communication", new TreeSet<>())));
-        uw = new UniversalWord("traffic", restrictions);
-        uwNode2 = new UniversalWordNode(uw, new HashSet<>());
-
-        graph.add(new GraphRelation(uwNode, uwNode2, "and"));
-
-        var unlDocumentNode = new UnlDocumentNode(UnlDocumentNodeType.Sentence, "[S:R1]", graph);
-
-        unlDocument.add(unlDocumentNode);
-
-        unlDocuments.add(unlDocument);
-    }
-
-    private static List<UnlDocument> getUnlDocuments() {
-        if (null == unlDocuments) {
-            buildUnlDocument();
-        }
-
-        return unlDocuments;
-    }
-
-
-    @Override
-    public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) {
-        buildUnlDocument();
-        return Stream.of(Arguments.of(unlDocuments));
-    }
-}
diff --git a/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/RelationLabelToUnlPropertyConverterTest.java b/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/RelationLabelToUnlPropertyConverterTest.java
deleted file mode 100644
index e1edbec..0000000
--- a/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/RelationLabelToUnlPropertyConverterTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package fr.tetras_libre.unltools.rdf.vocabulary;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-class RelationLabelToUnlPropertyConverterTest {
-
-    @Test
-    public void Check(){
-        var relationLabelToUnlProperty = new RelationLabelToUnlPropertyConverter();
-
-        Assertions.assertDoesNotThrow(() -> relationLabelToUnlProperty.getObjectProperty("aoj", null));
-    }
-}
\ No newline at end of file
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/AllSetenceWithExpectedDotChecker.java b/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/AllSetenceWithExpectedDotChecker.java
deleted file mode 100644
index 60bd471..0000000
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/AllSetenceWithExpectedDotChecker.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package fr.tetras_libre.unltools.unl;
-
-public class AllSetenceWithExpectedDotChecker extends SentenceWithExpectedDotChecker {
-    private static final String ALL = "[D]" +
-            "[S:R1]\n" +
-            "{org:en}\n" +
-            "The system allows a radio channel to take on two states: Listening and Traffic.\n" +
-            "{/org}\n" +
-            "{unl}\n" +
-            "aoj( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, system(icl>group).@def )\n" +
-            "obj( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, take_on(aoj>thing, equ>assume,icl>change, obj>thing) )\n" +
-            "ben( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, channel(icl>radiowave).@indef)\n" +
-            "aoj( take_on(aoj>thing, equ>assume, icl>change, obj>thing), channel(icl>radiowave).@indef) \n" +
-            "obj( take_on(aoj>thing, equ>assume, icl>change, obj>thing), state(icl>attribute).@plu )   \n" +
-            "qua( state(icl>attribute).@plu, 2 )   \n" +
-            "cnt( state(icl>attribute).@plu, listening(icl>sensing) )\n" +
-            "and( listening(icl>sensing),traffic(icl>communication) )\n" +
-            "{/unl}\n" +
-            "[/S]\n" +
-            "[S:R2]\n" +
-            "{org:en}\n" +
-            "The system displays a channel in green when it is in broadcast state. \n" +
-            "{/org}\n" +
-            "{unl}\n" +
-            "agt(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,system(icl>group).@def)\n" +
-            "mod(channel(icl>radiowave).@indef,green(icl>adj,iof>color))\n" +
-            "obj(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,channel(icl>radiowave).@indef)\n" +
-            "tim(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,when(icl>how,com>always,tim<uw,obj>uw))\n" +
-            "aoj:01(be_in_a_state(aoj>thing,icl>be,obj>state).@entry.@present,channel(icl>radiowave).@indef)\n" +
-            "plc:01(state(icl>attribute),broadcast(icl>message))\n" +
-            "obj:01(be_in_a_state(aoj>thing,icl>be,obj>state).@entry.@present,state(icl>attribute))\n" +
-            "obj(when(icl>how,com>always,tim<uw,obj>uw),:01)\n" +
-            "{/unl}\n" +
-            "[/S] \n" +
-            "[S:00]\n" +
-            "{org:en}\n" +
-            "The black cat and the white cat are eating.\n" +
-            "{/org}\n" +
-            "{unl}\n" +
-            "mod:01(cat1(icl>feline>thing).@entry.@def,black(icl>adj))\n" +
-            "and:01(cat1(icl>feline>thing).@entry.@def,cat2(icl>feline>thing).@entry.@def)\n" +
-            "mod:01(cat2(icl>feline>thing).@entry.@def,white(icl>adj))\n" +
-            "agt(eat(icl>consume>do,agt>living_thing,obj>concrete_thing,ins>thing).@entry.@pl.@present.@progress,:01.@_hn-scope)\n" +
-            "{/unl}\n" +
-            "[/S]\n" +
-            "[/D]";
-
-    private static final String ALL_DOT = "digraph G {\n" +
-            "graph [fontname=\"courier\", compound=\"true\"];\n" +
-            "1 [\n" +
-            "label=\"allow(aoj>thing,ben>thing,equ>make_possible,icl>be,obj>uw)\\n.@entry\"\n" +
-            "shape=\"box\"\n" +
-            "fontname=\"courb\"\n" +
-            "];\n" +
-            "2 [\n" +
-            "label=\"system(icl>group)\\n.@def\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "3 [\n" +
-            "label=\"take_on(aoj>thing,equ>assume,icl>change,obj>thing)\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "4 [\n" +
-            "label=\"channel(icl>radiowave)\\n.@indef\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "5 [\n" +
-            "label=\"state(icl>attribute)\\n.@plu\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "6 [\n" +
-            "label=\"2\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "7 [\n" +
-            "label=\"listening(icl>sensing)\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "8 [\n" +
-            "label=\"traffic(icl>communication)\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "1 -> 2 [label=\"aoj\" ];\n" +
-            "1 -> 3 [label=\"obj\" ];\n" +
-            "1 -> 4 [label=\"ben\" ];\n" +
-            "3 -> 4 [label=\"aoj\" ];\n" +
-            "3 -> 5 [label=\"obj\" ];\n" +
-            "5 -> 6 [label=\"qua\" ];\n" +
-            "5 -> 7 [label=\"cnt\" ];\n" +
-            "7 -> 8 [label=\"and\" ];\n" +
-            "}\n" +
-            "digraph G {\n" +
-            "graph [fontname=\"courier\", compound=\"true\"];\n" +
-            "1 [\n" +
-            "label=\"display(agt>thing,equ>exhibit,icl>show,obj>thing)\\n.@entry.@present\"\n" +
-            "shape=\"box\"\n" +
-            "fontname=\"courb\"\n" +
-            "];\n" +
-            "2 [\n" +
-            "label=\"system(icl>group)\\n.@def\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "3 [\n" +
-            "label=\"channel(icl>radiowave)\\n.@indef\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "4 [\n" +
-            "label=\"green(icl>adj,iof>color)\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "5 [\n" +
-            "label=\"when(com>always,icl>how,obj>uw,tim<uw)\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "6 [\n" +
-            "label=\"be_in_a_state(aoj>thing,icl>be,obj>state)\\n.@entry.@present\"\n" +
-            "shape=\"box\"\n" +
-            "fontname=\"courb\"\n" +
-            "];\n" +
-            "7 [\n" +
-            "label=\"state(icl>attribute)\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "8 [\n" +
-            "label=\"broadcast(icl>message)\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "subgraph cluster_01{\n" +
-            "   color = black;\n" +
-            "   label = \":01\"6 -> 3 [label=\"aoj\" ];\n" +
-            "7 -> 8 [label=\"plc\" ];\n" +
-            "6 -> 7 [label=\"obj\" ];\n" +
-            "}\n" +
-            "1 -> 2 [label=\"agt\" ];\n" +
-            "3 -> 4 [label=\"mod\" ];\n" +
-            "1 -> 3 [label=\"obj\" ];\n" +
-            "1 -> 5 [label=\"tim\" ];\n" +
-            "5 -> 6 [label=\"obj\"  lhead=\"cluster_01\"];\n" +
-            "}\n" +
-            "digraph G {\n" +
-            "graph [fontname=\"courier\", compound=\"true\"];\n" +
-            "1 [\n" +
-            "label=\"cat1(icl>feline(icl>thing))\\n.@def.@entry\"\n" +
-            "shape=\"box\"\n" +
-            "fontname=\"courb\"\n" +
-            "];\n" +
-            "2 [\n" +
-            "label=\"black(icl>adj)\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "3 [\n" +
-            "label=\"cat2(icl>feline(icl>thing))\\n.@def.@entry\"\n" +
-            "shape=\"box\"\n" +
-            "fontname=\"courb\"\n" +
-            "];\n" +
-            "4 [\n" +
-            "label=\"white(icl>adj)\\n\"\n" +
-            "shape=\"box\"\n" +
-            "];\n" +
-            "5 [\n" +
-            "label=\"eat(agt>living_thing,icl>consume(icl>do),ins>thing,obj>concrete_thing)\\n.@entry.@pl.@present.@progress\"\n" +
-            "shape=\"box\"\n" +
-            "fontname=\"courb\"\n" +
-            "];\n" +
-            "subgraph cluster_01{\n" +
-            "   color = black;\n" +
-            "   label = \":01\"1 -> 2 [label=\"mod\" ];\n" +
-            "1 -> 3 [label=\"and\" ];\n" +
-            "3 -> 4 [label=\"mod\" ];\n" +
-            "}\n" +
-            "5 -> 1 [label=\"agt\"  lhead=\"cluster_01\"];\n" +
-            "}\n";
-
-    public AllSetenceWithExpectedDotChecker() {
-        super(ALL, ALL_DOT);
-    }
-}
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/CatSentenceWithExpectedDotChecker.java b/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/CatSentenceWithExpectedDotChecker.java
deleted file mode 100644
index 4d398d2..0000000
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/CatSentenceWithExpectedDotChecker.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package fr.tetras_libre.unltools.unl;
-
-public class CatSentenceWithExpectedDotChecker extends SentenceWithExpectedDotChecker {
-
-    private static final String CAT_UNL = "[D]" +
-            "[S:00]\n" +
-            "{org:en}\n" +
-            "The black cat and the white cat are eating.\n" +
-            "{/org}\n" +
-            "{unl}\n" +
-            "mod:01(cat(icl>feline>thing):01.@entry.@def,black(icl>adj))\n" +
-            "and:01(cat(icl>feline>thing):01.@entry.@def,cat(icl>feline>thing):02.@entry.@def)\n" +
-            "mod:01(cat(icl>feline>thing):02.@entry.@def,white(icl>adj))\n" +
-            "agt(eat(icl>consume>do,agt>living_thing,obj>concrete_thing,ins>thing).@entry.@pl.@present.@progress,:01.@_hn-scope)\n" +
-            "{/unl}\n" +
-            "[/S]\n";
-
-    private static final String CAT_DOT = "digraph G {\n" +
-            "graph [fontname=\"courier\", compound=\"true\"];\n" +
-            "1 [ label=\"cat(icl>feline(icl>thing)):01\\n.@def.@entry\" shape=\"box\" fontname=\"courb\" ];\n" +
-            "2 [ label=\"black(icl>adj)\\n\" shape=\"box\" ];\n" +
-            "3 [ label=\"cat(icl>feline(icl>thing)):02\\n.@def.@entry\" shape=\"box\" fontname=\"courb\" ];\n" +
-            "4 [ label=\"white(icl>adj)\\n\" shape=\"box\" ];\n" +
-            "5 [ label=\"eat(agt>living_thing,icl>consume(icl>do),ins>thing,obj>concrete_thing)\\n.@entry.@pl.@present.@progress\" shape=\"box\" fontname=\"courb\" ];" +
-            " subgraph cluster_01{ color = black; label = \":01\"1 -> 2 [label=\"mod\" ]; 1 -> 3 [label=\"and\" ]; 3 -> 4 [label=\"mod\" ]; }\n" +
-            "5 -> 1 [label=\"agt\" lhead=\"cluster_01\"];\n" +
-            "}\n";
-
-    public CatSentenceWithExpectedDotChecker() {
-        super(CAT_UNL, CAT_DOT);
-    }
-}
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/EqualsBuilderTest.java b/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/EqualsBuilderTest.java
deleted file mode 100644
index c6e0a2b..0000000
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/EqualsBuilderTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package fr.tetras_libre.unltools.unl;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-class EqualsBuilderTest {
-
-    @Test
-    void isEqual() {
-        String s1 = "qdfsf";
-        int i1 = 1;
-        long l1 = 2L;
-        EqualsBuilder builder = new EqualsBuilder()
-                .append(s1)
-                .append(i1)
-                .append(l1);
-
-        EqualsBuilder builder2 = new EqualsBuilder()
-                .append(s1)
-                .append(i1)
-                .append(l1);
-
-        Assertions.assertTrue(() -> builder.isEqual(builder2));
-    }
-}
\ No newline at end of file
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/print/dotFile/DotFileBuilderTest.java b/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/print/dotFile/DotFileBuilderTest.java
deleted file mode 100644
index 3ec313b..0000000
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/print/dotFile/DotFileBuilderTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package fr.tetras_libre.unltools.unl.print.dotFile;
-
-import fr.tetras_libre.unltools.unl.*;
-import fr.tetras_libre.unltools.unl.parser.UnlParser;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestReporter;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.io.*;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Vector;
-import java.util.concurrent.atomic.AtomicReference;
-
-class DotFileBuilderTest {
-
-    @TempDir
-    static Path SharedTempDir;
-
-    private TestReporter testReporter;
-
-    @Test
-    public void dotFileBuilderShouldCreateDotFileR1WithoutException(TestReporter testReporter) {
-        this.testReporter = testReporter;
-        Path dotPAth = SharedTempDir.resolve("r1.dot");
-        writeInFile(dotPAth, new R1SentenceWithExpectedDotChecker());
-    }
-
-    @Test
-    public void dotFileBuilderShouldCreateDotFileWithoutException(TestReporter testReporter) {
-        this.testReporter = testReporter;
-        Path dotPAth = SharedTempDir.resolve("r2.dot");
-        this.writeInFile(dotPAth, new R2SentenceWithExpectedDotChecker());
-    }
-
-    @Test
-    public void dotFileBuilderShouldCreateDotFileCatWithoutException(TestReporter testReporter) {
-        this.testReporter = testReporter;
-        Path dotPAth = SharedTempDir.resolve("cat.dot");
-        this.writeInFile(dotPAth, new CatSentenceWithExpectedDotChecker());
-    }
-
-    @Test
-    public void dotFileBuilderShouldCreateDotFileAllWithoutException(TestReporter testReporter) {
-        this.testReporter = testReporter;
-        Path dotPAth = SharedTempDir.resolve("all.dot");
-
-        this.writeInFile(dotPAth, new AllSetenceWithExpectedDotChecker());
-    }
-
-    private void writeInFile(Path filePath, SentenceWithExpectedDotChecker sentenceChecker) {
-        // Startup
-        UnlParser parser = new UnlParser(new BufferedReader(new StringReader(sentenceChecker.getUnlSentence())));
-        AtomicReference<Vector<UnlDocument>> documentsAtomic = new AtomicReference<>();
-        Assertions.assertDoesNotThrow(() -> documentsAtomic.set(parser.createUnlDocumentList()));
-
-        AtomicReference<File> outFile = new AtomicReference<>();
-        Assertions.assertDoesNotThrow(() -> outFile.set(new File(filePath.toAbsolutePath().toString())));
-
-        AtomicReference<BufferedWriter> outFileWriter = new AtomicReference<>();
-        Assertions.assertDoesNotThrow(() -> outFileWriter.set(new BufferedWriter(new FileWriter(outFile.get(), false))));
-
-        DotFileBuilder dotFileBuilder = new DotFileBuilder(outFileWriter.get());
-
-        // Test
-
-        Assertions.assertDoesNotThrow(() -> dotFileBuilder.write(documentsAtomic.get()));
-
-
-        // Teardown
-        Assertions.assertDoesNotThrow(() -> {
-            outFileWriter.get().flush();
-            outFileWriter.get().close();
-        });
-        Assertions.assertTrue(() -> outFile.get().length() != 0);
-        Assertions.assertDoesNotThrow(() -> sentenceChecker.setCurrentDotContent(Files.readString(filePath, StandardCharsets.UTF_8)));
-        sentenceChecker.assetSameAsExpected();
-
-    }
-}
\ No newline at end of file
diff --git a/unl2rdf-app/pom.xml b/unl-tools-app/pom.xml
similarity index 90%
rename from unl2rdf-app/pom.xml
rename to unl-tools-app/pom.xml
index 2c661ef..450e947 100644
--- a/unl2rdf-app/pom.xml
+++ b/unl-tools-app/pom.xml
@@ -10,8 +10,7 @@
         <version>1.0-SNAPSHOT</version>
     </parent>
 
-    <name>main-App</name>
-    <artifactId>unl2rdf-app</artifactId>
+    <artifactId>unl-tools-app</artifactId>
 
     <packaging>jar</packaging>
 
@@ -101,21 +100,10 @@
         </dependency>
         <dependency>
             <groupId>fr.tetras_libre.unl</groupId>
-            <artifactId>unl-parser</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>fr.tetras_libre.unl</groupId>
-            <artifactId>rdf</artifactId>
+            <artifactId>unl-tools-infrastructure</artifactId>
             <version>1.0-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-nop</artifactId>
-            <version>1.7.30</version>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 
 
diff --git a/unl2rdf-app/src/main/java/unl2rdf/Options.java b/unl-tools-app/src/main/java/unl2rdf/Options.java
similarity index 100%
rename from unl2rdf-app/src/main/java/unl2rdf/Options.java
rename to unl-tools-app/src/main/java/unl2rdf/Options.java
diff --git a/unl2rdf-app/src/main/java/unl2rdf/OutFileType.java b/unl-tools-app/src/main/java/unl2rdf/OutFileType.java
similarity index 100%
rename from unl2rdf-app/src/main/java/unl2rdf/OutFileType.java
rename to unl-tools-app/src/main/java/unl2rdf/OutFileType.java
diff --git a/unl2rdf-app/src/main/java/unl2rdf/Unl2Rdf.java b/unl-tools-app/src/main/java/unl2rdf/Unl2Rdf.java
similarity index 77%
rename from unl2rdf-app/src/main/java/unl2rdf/Unl2Rdf.java
rename to unl-tools-app/src/main/java/unl2rdf/Unl2Rdf.java
index fb796a3..2761d69 100644
--- a/unl2rdf-app/src/main/java/unl2rdf/Unl2Rdf.java
+++ b/unl-tools-app/src/main/java/unl2rdf/Unl2Rdf.java
@@ -1,11 +1,11 @@
 package unl2rdf;
 
-import fr.tetras_libre.unltools.rdf.vocabulary.RdfFileBuilder;
 import fr.tetras_libre.unltools.unl.GraphExporter;
 import fr.tetras_libre.unltools.unl.UnlDocument;
+import fr.tetras_libre.unltools.unl.exporters.DefaultGraphExporterFactory;
+import fr.tetras_libre.unltools.unl.exporters.GraphExporterNames;
 import fr.tetras_libre.unltools.unl.parser.ParseException;
 import fr.tetras_libre.unltools.unl.parser.UnlParser;
-import fr.tetras_libre.unltools.unl.print.dotFile.DotFileBuilder;
 import picocli.CommandLine;
 
 import java.io.BufferedReader;
@@ -14,7 +14,9 @@ import java.io.IOException;
 import java.util.Vector;
 
 public class Unl2Rdf {
-    public static void main(String[] args) throws ParseException, IOException {
+
+    private static DefaultGraphExporterFactory defaultGraphExporterFactory = new DefaultGraphExporterFactory();
+    public static void main(String[] args) throws IOException, ParseException {
 
         Options options = new Options();
 
@@ -58,13 +60,17 @@ public class Unl2Rdf {
     }
 
     private static GraphExporter GetExporter(OutFileType fileType, FileWriter writer) {
+        String exporterName = null;
         switch (fileType) {
             case rdf:
-                return new RdfFileBuilder(writer);
+                exporterName = GraphExporterNames.RDF_EXPORTER;
+                break;
             case dot:
-                return new DotFileBuilder(writer);
+                exporterName = GraphExporterNames.DOT_EXPORTER;
+                break;
         }
-        throw new IllegalArgumentException(String.format("unknown fileType '%s", fileType.toString()));
+
+        return defaultGraphExporterFactory.createGraphExporter(writer, exporterName);
     }
 
 }
diff --git a/unl2rdf-app/src/main/resources/META-INF/MANIFEST.MF b/unl-tools-app/src/main/resources/META-INF/MANIFEST.MF
similarity index 100%
rename from unl2rdf-app/src/main/resources/META-INF/MANIFEST.MF
rename to unl-tools-app/src/main/resources/META-INF/MANIFEST.MF
diff --git a/unl2rdf-app/src/test/java/unl2rdf/Unl2RdfTest.java b/unl-tools-app/src/test/java/unl2rdf/Unl2RdfTest.java
similarity index 100%
rename from unl2rdf-app/src/test/java/unl2rdf/Unl2RdfTest.java
rename to unl-tools-app/src/test/java/unl2rdf/Unl2RdfTest.java
diff --git a/unl2rdf-app/unl2rdf-app.iml b/unl-tools-app/unl-tools-app.iml
similarity index 90%
rename from unl2rdf-app/unl2rdf-app.iml
rename to unl-tools-app/unl-tools-app.iml
index 11ac912..f7b5b3c 100644
--- a/unl2rdf-app/unl2rdf-app.iml
+++ b/unl-tools-app/unl-tools-app.iml
@@ -5,19 +5,15 @@
     <output-test url="file://$MODULE_DIR$/target/test-classes" />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/target/generated-sources/annotations" isTestSource="false" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
       <excludeFolder url="file://$MODULE_DIR$/target" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="Maven: fr.tetras_libre.rdf:rdf-unl-java-vocabulary:1.0-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.slf4j:slf4j-nop:1.7.30" level="project" />
-    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
     <orderEntry type="library" name="Maven: info.picocli:picocli:4.2.0" level="project" />
-    <orderEntry type="module" module-name="unl-parser" />
-    <orderEntry type="module" module-name="rdf" />
+    <orderEntry type="module" module-name="unl-tools-infrastructure" />
     <orderEntry type="library" name="Maven: org.apache.jena:jena-shacl:3.14.0" level="project" />
     <orderEntry type="library" name="Maven: org.apache.jena:jena-arq:3.14.0" level="project" />
     <orderEntry type="library" name="Maven: org.apache.jena:jena-core:3.14.0" level="project" />
@@ -49,9 +45,9 @@
     <orderEntry type="library" name="Maven: org.apache.jena:jena-dboe-base:3.14.0" level="project" />
     <orderEntry type="library" name="Maven: org.apache.jena:jena-dboe-index:3.14.0" level="project" />
     <orderEntry type="library" name="Maven: org.apache.jena:jena-rdfconnection:3.14.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.26" level="project" />
     <orderEntry type="library" name="Maven: fr.tetras_libre.rdf:rdf-unl-java-vocabulary:1.0-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.slf4j:slf4j-nop:1.7.30" level="project" />
-    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
+    <orderEntry type="module" module-name="unl-tools-core" />
     <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.7.0-M1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.7.0-M1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
diff --git a/unl-parser/pom.xml b/unl-tools-core/pom.xml
similarity index 87%
rename from unl-parser/pom.xml
rename to unl-tools-core/pom.xml
index 1ab77b9..cbdcd7d 100644
--- a/unl-parser/pom.xml
+++ b/unl-tools-core/pom.xml
@@ -10,8 +10,6 @@
         <version>1.0-SNAPSHOT</version>
     </parent>
 
-    <artifactId>unl-parser</artifactId>
+    <artifactId>unl-tools-core</artifactId>
     <packaging>jar</packaging>
-
-    <name>Unl-parser</name>
 </project>
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/EqualsBuilder.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/EqualsBuilder.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/EqualsBuilder.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/EqualsBuilder.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/Graph.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/Graph.java
similarity index 91%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/Graph.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/Graph.java
index 28288be..6d710a7 100644
--- a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/Graph.java
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/Graph.java
@@ -140,4 +140,21 @@ public class Graph {
         return strBuilder.toString();
     }
 
+    @Override
+    public boolean equals(Object obj) {
+        if(null == obj) {
+            return false;
+        }
+
+        if(!(obj instanceof Graph)) {
+            return false;
+        }
+
+        return equals((Graph) obj);
+    }
+
+    private boolean equals(Graph other){
+        return this.nodes.equals(other.nodes)
+                && this.relations.equals(other.relations);
+    }
 }
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/GraphExporter.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphExporter.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/GraphExporter.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphExporter.java
diff --git a/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphExporterFactory.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphExporterFactory.java
new file mode 100644
index 0000000..6c9a32a
--- /dev/null
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphExporterFactory.java
@@ -0,0 +1,7 @@
+package fr.tetras_libre.unltools.unl;
+
+import java.io.Writer;
+
+public interface GraphExporterFactory {
+    GraphExporter createGraphExporter(Writer writer, String exporterName);
+}
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/GraphNode.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphNode.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/GraphNode.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphNode.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/GraphRelation.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphRelation.java
similarity index 63%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/GraphRelation.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphRelation.java
index bbd1248..7b56dc5 100644
--- a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/GraphRelation.java
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/GraphRelation.java
@@ -49,4 +49,32 @@ public class GraphRelation {
                 this.node1.toString(),
                 this.node2.toString());
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(null == obj) {
+            return false;
+        }
+
+        if(!(obj instanceof GraphRelation)) {
+            return false;
+        }
+
+        return equals((GraphRelation) obj);
+    }
+
+    private boolean equals(GraphRelation other) {
+        var equalityBuilder = new EqualsBuilder()
+                .append(this.node1)
+                .append(this.node2)
+                .append(this.SubGraphReferenceLabel)
+                .append(this.relationLabel);
+
+        return new EqualsBuilder()
+                .append(other.node1)
+                .append(other.node2)
+                .append(other.SubGraphReferenceLabel)
+                .append(other.relationLabel)
+                .isEqual(equalityBuilder);
+    }
 }
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/HashCodeBuilder.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/HashCodeBuilder.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/HashCodeBuilder.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/HashCodeBuilder.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/NoEntryNodeException.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/NoEntryNodeException.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/NoEntryNodeException.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/NoEntryNodeException.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/Restriction.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/Restriction.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/Restriction.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/Restriction.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/SubGraphReferenceNode.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/SubGraphReferenceNode.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/SubGraphReferenceNode.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/SubGraphReferenceNode.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UniversalWord.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UniversalWord.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UniversalWord.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UniversalWord.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UniversalWordNode.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UniversalWordNode.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UniversalWordNode.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UniversalWordNode.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UnlDocument.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UnlDocument.java
similarity index 81%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UnlDocument.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UnlDocument.java
index 816ab21..eb55529 100644
--- a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UnlDocument.java
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UnlDocument.java
@@ -70,4 +70,21 @@ public class UnlDocument {
 
         return sb.toString();
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(obj == null) {
+            return false;
+        }
+
+        if(!(obj instanceof UnlDocument)){
+            return false;
+        }
+        return equals((UnlDocument)obj);
+    }
+
+    private boolean equals(UnlDocument other){
+        return this.docElements.equals(other.docElements)
+                && (this.hasError() == other.hasError());
+    }
 }
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNode.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNode.java
similarity index 78%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNode.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNode.java
index 2b70841..08e63d8 100644
--- a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNode.java
+++ b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNode.java
@@ -72,4 +72,25 @@ public class UnlDocumentNode {
 
         throw new IllegalStateException(String.format("Unknown type of sentence node '%s'", this.kindOfNode.toString()));
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(null == obj){
+            return false;
+        }
+
+        if(!(obj instanceof UnlDocumentNode)){
+            return false;
+        }
+
+        return this.equals((UnlDocumentNode) obj);
+    }
+
+    private boolean equals(UnlDocumentNode other) {
+        return this.docNodeLabel.equals(other.docNodeLabel)
+                && this.kindOfNode.equals(other.kindOfNode)
+                && this.hasError() == other.hasError()
+                && this.graph.equals(other.graph);
+
+    }
 }
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNodeType.java b/unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNodeType.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNodeType.java
rename to unl-tools-core/src/main/java/fr/tetras_libre/unltools/unl/UnlDocumentNodeType.java
diff --git a/unl-tools-core/src/test/java/fr/tetras_libre/unltools/unl/EqualsBuilderTest.java b/unl-tools-core/src/test/java/fr/tetras_libre/unltools/unl/EqualsBuilderTest.java
new file mode 100644
index 0000000..9918265
--- /dev/null
+++ b/unl-tools-core/src/test/java/fr/tetras_libre/unltools/unl/EqualsBuilderTest.java
@@ -0,0 +1,24 @@
+package fr.tetras_libre.unltools.unl;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class EqualsBuilderTest {
+        @Test
+        void isEqual() {
+            String s1 = "qdfsf";
+            int i1 = 1;
+            long l1 = 2L;
+            EqualsBuilder builder = new EqualsBuilder()
+                    .append(s1)
+                    .append(i1)
+                    .append(l1);
+
+            EqualsBuilder builder2 = new EqualsBuilder()
+                    .append(s1)
+                    .append(i1)
+                    .append(l1);
+
+            Assertions.assertTrue(() -> builder.isEqual(builder2));
+        }
+}
\ No newline at end of file
diff --git a/unl-parser/unl-parser.iml b/unl-tools-core/unl-tools-core.iml
similarity index 100%
rename from unl-parser/unl-parser.iml
rename to unl-tools-core/unl-tools-core.iml
diff --git a/rdf/pom.xml b/unl-tools-infrastructure/pom.xml
similarity index 92%
rename from rdf/pom.xml
rename to unl-tools-infrastructure/pom.xml
index 5f2225f..537df2b 100644
--- a/rdf/pom.xml
+++ b/unl-tools-infrastructure/pom.xml
@@ -11,9 +11,7 @@
     </parent>
 
 
-    <name>rdf2Unl</name>
-
-    <artifactId>rdf</artifactId>
+    <artifactId>unl-tools-infrastructure</artifactId>
     <packaging>jar</packaging>
 
     <dependencies>
@@ -23,12 +21,6 @@
             <type>pom</type>
             <version>3.14.0</version>
         </dependency>
-        <dependency>
-            <groupId>fr.tetras_libre.unl</groupId>
-            <artifactId>unl-parser</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>compile</scope>
-        </dependency>
         <dependency>
             <groupId>fr.tetras_libre.rdf</groupId>
             <artifactId>rdf-unl-java-vocabulary</artifactId>
@@ -40,6 +32,12 @@
             <version>1.7.30</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>fr.tetras_libre.unl</groupId>
+            <artifactId>unl-tools-core</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
 
diff --git a/rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions/GraphExtensions.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/GraphExtensions.java
similarity index 95%
rename from rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions/GraphExtensions.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/GraphExtensions.java
index 817f709..73bf85d 100644
--- a/rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions/GraphExtensions.java
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/GraphExtensions.java
@@ -1,4 +1,4 @@
-package fr.tetras_libre.unltools.unl.extensions;
+package fr.tetras_libre.unltools.unl;
 
 import fr.tetras_libre.unltools.unl.Graph;
 import fr.tetras_libre.unltools.unl.GraphRelation;
diff --git a/rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions/GraphRelationExtensions.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/GraphRelationExtensions.java
similarity index 93%
rename from rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions/GraphRelationExtensions.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/GraphRelationExtensions.java
index 429f4c4..d66455a 100644
--- a/rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions/GraphRelationExtensions.java
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/GraphRelationExtensions.java
@@ -1,6 +1,4 @@
-package fr.tetras_libre.unltools.unl.extensions;
-
-import fr.tetras_libre.unltools.unl.*;
+package fr.tetras_libre.unltools.unl;
 
 public class GraphRelationExtensions {
     public static String getRealNode1Id(GraphRelation graphRelation, Graph g) throws NoEntryNodeException {
diff --git a/rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions/SubGraphReferenceNodeExtensions.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/SubGraphReferenceNodeExtensions.java
similarity index 92%
rename from rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions/SubGraphReferenceNodeExtensions.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/SubGraphReferenceNodeExtensions.java
index 6a9f80d..19144d2 100644
--- a/rdf/src/main/java/fr/tetras_libre/unltools/unl/extensions/SubGraphReferenceNodeExtensions.java
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/SubGraphReferenceNodeExtensions.java
@@ -1,4 +1,4 @@
-package fr.tetras_libre.unltools.unl.extensions;
+package fr.tetras_libre.unltools.unl;
 
 import fr.tetras_libre.unltools.unl.Graph;
 import fr.tetras_libre.unltools.unl.NoEntryNodeException;
diff --git a/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/DefaultGraphExporterFactory.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/DefaultGraphExporterFactory.java
new file mode 100644
index 0000000..cb12595
--- /dev/null
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/DefaultGraphExporterFactory.java
@@ -0,0 +1,26 @@
+package fr.tetras_libre.unltools.unl.exporters;
+
+import fr.tetras_libre.unltools.unl.GraphExporter;
+import fr.tetras_libre.unltools.unl.GraphExporterFactory;
+import fr.tetras_libre.unltools.unl.exporters.dot.DotFileGraphExporter;
+import fr.tetras_libre.unltools.unl.exporters.rdf.RdfFileGraphExporter;
+
+import java.io.Writer;
+
+public class DefaultGraphExporterFactory implements GraphExporterFactory {
+    @Override
+    public GraphExporter createGraphExporter(Writer writer, String name) {
+        if (null == writer) throw new IllegalArgumentException("A writer should be provided");
+        if (null == name || name.isBlank()) throw new IllegalArgumentException("Graph exporter should be provided");
+
+        if (GraphExporterNames.RDF_EXPORTER.equals(name)) {
+            return new RdfFileGraphExporter(writer);
+        }
+
+        if (GraphExporterNames.DOT_EXPORTER.equals(name)) {
+            return new DotFileGraphExporter(writer);
+        }
+
+        throw new IllegalArgumentException(String.format("Unknown graph exporter name (current:'%s')", name));
+    }
+}
diff --git a/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/GraphExporterNames.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/GraphExporterNames.java
new file mode 100644
index 0000000..50a8355
--- /dev/null
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/GraphExporterNames.java
@@ -0,0 +1,6 @@
+package fr.tetras_libre.unltools.unl.exporters;
+
+public class GraphExporterNames {
+    public static final String DOT_EXPORTER = "DOT";
+    public static final String RDF_EXPORTER = "RDF";
+}
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/print/dotFile/DotFileBuilder.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/dot/DotFileGraphExporter.java
similarity index 97%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/print/dotFile/DotFileBuilder.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/dot/DotFileGraphExporter.java
index 133bbd2..7710598 100644
--- a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/print/dotFile/DotFileBuilder.java
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/dot/DotFileGraphExporter.java
@@ -1,4 +1,4 @@
-package fr.tetras_libre.unltools.unl.print.dotFile;
+package fr.tetras_libre.unltools.unl.exporters.dot;
 
 import fr.tetras_libre.unltools.unl.*;
 
@@ -8,7 +8,7 @@ import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-public class DotFileBuilder implements GraphExporter {
+public class DotFileGraphExporter implements GraphExporter {
     private final Writer writer;
 
     /**
@@ -17,7 +17,7 @@ public class DotFileBuilder implements GraphExporter {
      * @param writer the writer
      * @throws IllegalArgumentException the writer is null
      */
-    public DotFileBuilder(Writer writer) {
+    public DotFileGraphExporter(Writer writer) {
         if (null == writer) throw new IllegalArgumentException("The writer is null");
         this.writer = writer;
     }
diff --git a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/RdfFileBuilder.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/RdfFileGraphExporter.java
similarity index 82%
rename from rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/RdfFileBuilder.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/RdfFileGraphExporter.java
index 856ffc6..c8c7364 100644
--- a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/RdfFileBuilder.java
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/RdfFileGraphExporter.java
@@ -1,4 +1,4 @@
-package fr.tetras_libre.unltools.rdf.vocabulary;
+package fr.tetras_libre.unltools.unl.exporters.rdf;
 
 import fr.tetras_libre.unltools.unl.GraphExporter;
 import fr.tetras_libre.unltools.unl.UnlDocument;
@@ -8,11 +8,11 @@ import org.apache.jena.rdf.model.ModelFactory;
 import java.io.Writer;
 import java.util.List;
 
-public class RdfFileBuilder implements GraphExporter {
+public class RdfFileGraphExporter implements GraphExporter {
     private final UnlDocumentToRdfConverter converter;
     private final Writer writer;
 
-    public RdfFileBuilder(Writer writer) {
+    public RdfFileGraphExporter(Writer writer) {
         this.writer = writer;
         this.converter = new UnlDocumentToRdfConverter();
     }
diff --git a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/RelationLabelToUnlPropertyConverter.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/RelationLabelToUnlPropertyConverter.java
similarity index 94%
rename from rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/RelationLabelToUnlPropertyConverter.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/RelationLabelToUnlPropertyConverter.java
index ac906bc..8715202 100644
--- a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/RelationLabelToUnlPropertyConverter.java
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/RelationLabelToUnlPropertyConverter.java
@@ -1,4 +1,4 @@
-package fr.tetras_libre.unltools.rdf.vocabulary;
+package fr.tetras_libre.unltools.unl.exporters.rdf;
 
 import org.apache.jena.ontology.ObjectProperty;
 import org.apache.jena.ontology.OntModel;
diff --git a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/Slugify.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/Slugify.java
similarity index 73%
rename from rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/Slugify.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/Slugify.java
index 0fa0ed9..ef9d717 100644
--- a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/Slugify.java
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/Slugify.java
@@ -1,4 +1,4 @@
-package fr.tetras_libre.unltools.rdf.vocabulary;
+package fr.tetras_libre.unltools.unl.exporters.rdf;
 
 class Slugify {
     public static String slugify(String stringSource) {
diff --git a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/UnlDocumentToRdfConverter.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/UnlDocumentToRdfConverter.java
similarity index 95%
rename from rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/UnlDocumentToRdfConverter.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/UnlDocumentToRdfConverter.java
index 83d04c6..1966719 100644
--- a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/UnlDocumentToRdfConverter.java
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/UnlDocumentToRdfConverter.java
@@ -1,9 +1,9 @@
-package fr.tetras_libre.unltools.rdf.vocabulary;
+package fr.tetras_libre.unltools.unl.exporters.rdf;
 
 import fr.tetras_libre.rdf.vocabulary.UNL;
 import fr.tetras_libre.unltools.unl.*;
-import fr.tetras_libre.unltools.unl.extensions.GraphExtensions;
-import fr.tetras_libre.unltools.unl.extensions.SubGraphReferenceNodeExtensions;
+import fr.tetras_libre.unltools.unl.GraphExtensions;
+import fr.tetras_libre.unltools.unl.SubGraphReferenceNodeExtensions;
 import org.apache.jena.ontology.Individual;
 import org.apache.jena.ontology.OntModel;
 import org.apache.jena.ontology.Ontology;
@@ -15,13 +15,11 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
-import static fr.tetras_libre.unltools.rdf.vocabulary.Slugify.slugify;
-
 public class UnlDocumentToRdfConverter {
     private final static String DOMAIN = "http://rdf-unl.org";
     private final static String Lang = null;
 
-    private RelationLabelToUnlPropertyConverter relationLabelToUnlPropertyConverter;
+    private final RelationLabelToUnlPropertyConverter relationLabelToUnlPropertyConverter;
 
     public UnlDocumentToRdfConverter() {
         relationLabelToUnlPropertyConverter = new RelationLabelToUnlPropertyConverter();
@@ -78,7 +76,7 @@ public class UnlDocumentToRdfConverter {
                             var uw = (UniversalWordNode) sentenceNode;
 
                             // Création de l'universalWord dans le dictionnaire
-                            var universalWordIndividual = sentenceOntModel.createIndividual(String.format("%s/%s#%s", DOMAIN, uniqId, slugify(uw.getUniversalWord().toString())), UNL.UW_Lexeme);
+                            var universalWordIndividual = sentenceOntModel.createIndividual(String.format("%s/%s#%s", DOMAIN, uniqId, Slugify.slugify(uw.getUniversalWord().toString())), UNL.UW_Lexeme);
                             universalWordIndividual.addLabel(uw.getUniversalWord().toString(), UnlDocumentToRdfConverter.Lang);
 
                             // Création de l'occurence du l'universalWord
@@ -164,9 +162,9 @@ public class UnlDocumentToRdfConverter {
         public static String constructRelationUri(String scopeName, GraphRelation graphRelation) {
             return String.format("%s%s_%s_%s",
                     scopeName,
-                    slugify(constructRelationUri(graphRelation.getNode1())),
+                    Slugify.slugify(constructRelationUri(graphRelation.getNode1())),
                     graphRelation.getRelationLabel(),
-                    slugify(constructRelationUri(graphRelation.getNode2())));
+                    Slugify.slugify(constructRelationUri(graphRelation.getNode2())));
         }
 
         private static String constructRelationUri(GraphNode node) {
diff --git a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/UtilGraphNodeUri.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/UtilGraphNodeUri.java
similarity index 84%
rename from rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/UtilGraphNodeUri.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/UtilGraphNodeUri.java
index 9737041..f8d5e5c 100644
--- a/rdf/src/main/java/fr/tetras_libre/unltools/rdf/vocabulary/UtilGraphNodeUri.java
+++ b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/exporters/rdf/UtilGraphNodeUri.java
@@ -1,11 +1,11 @@
-package fr.tetras_libre.unltools.rdf.vocabulary;
+package fr.tetras_libre.unltools.unl.exporters.rdf;
 
 import fr.tetras_libre.unltools.unl.GraphNode;
 import fr.tetras_libre.unltools.unl.SubGraphReferenceNode;
 import fr.tetras_libre.unltools.unl.UniversalWordNode;
-import fr.tetras_libre.unltools.unl.extensions.SubGraphReferenceNodeExtensions;
+import fr.tetras_libre.unltools.unl.SubGraphReferenceNodeExtensions;
 
-import static fr.tetras_libre.unltools.rdf.vocabulary.Slugify.slugify;
+import static fr.tetras_libre.unltools.unl.exporters.rdf.Slugify.slugify;
 
 class UtilGraphNodeUri {
     public static String constructGraphNodeUri(String namespace, GraphNode node) {
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/ParseException.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/ParseException.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/ParseException.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/ParseException.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/SimpleCharStream.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/SimpleCharStream.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/SimpleCharStream.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/SimpleCharStream.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/Token.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/Token.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/Token.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/Token.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/TokenMgrError.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/TokenMgrError.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/TokenMgrError.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/TokenMgrError.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.jj b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.jj
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.jj
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParser.jj
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserConstants.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserConstants.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserConstants.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserConstants.java
diff --git a/unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserTokenManager.java b/unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserTokenManager.java
similarity index 100%
rename from unl-parser/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserTokenManager.java
rename to unl-tools-infrastructure/src/main/java/fr/tetras_libre/unltools/unl/parser/UnlParserTokenManager.java
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AbstractFlyweightUnlArgumentProvider.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AbstractFlyweightUnlArgumentProvider.java
new file mode 100644
index 0000000..f09f058
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AbstractFlyweightUnlArgumentProvider.java
@@ -0,0 +1,25 @@
+package fr.tetras_libre.unltools.unl;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
+public abstract class AbstractFlyweightUnlArgumentProvider extends AbstractUnlArgumentProvider {
+    private static final Dictionary<Class<?>, List<UnlDocument>> values = new Hashtable<>();
+
+    protected abstract List<UnlDocument> buildUnlDocuments();
+
+    final public List<UnlDocument> getUnlDocuments() {
+        if (null == values.get(this.getClass())) {
+            synchronized (AbstractFlyweightUnlArgumentProvider.class) {
+                if (null == values.get(this.getClass())) {
+                    values.put(this.getClass(), this.buildUnlDocuments());
+                }
+            }
+        }
+
+        return values.get(this.getClass());
+    }
+
+
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AbstractUnlArgumentProvider.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AbstractUnlArgumentProvider.java
new file mode 100644
index 0000000..8c9ac6b
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AbstractUnlArgumentProvider.java
@@ -0,0 +1,18 @@
+package fr.tetras_libre.unltools.unl;
+
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+public abstract class AbstractUnlArgumentProvider implements ArgumentsProvider {
+
+    public abstract List<UnlDocument> getUnlDocuments();
+
+    @Override
+    public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
+        return Stream.of(Arguments.of(getUnlDocuments()));
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AllUnl.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AllUnl.java
new file mode 100644
index 0000000..106890e
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/AllUnl.java
@@ -0,0 +1,18 @@
+package fr.tetras_libre.unltools.unl;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class AllUnl extends AbstractFlyweightUnlArgumentProvider {
+    @Override
+    protected List<UnlDocument> buildUnlDocuments() {
+        var unlDocument = new UnlDocument("[D]");
+
+        unlDocument.add(R1Unl.buildSentenceNode());
+        unlDocument.add(R2Unl.buildSentenceNode());
+        unlDocument.add(CatsUnl.buildSentenceNode());
+
+        return Collections.singletonList(unlDocument);
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/CatsUnl.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/CatsUnl.java
new file mode 100644
index 0000000..d656209
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/CatsUnl.java
@@ -0,0 +1,74 @@
+package fr.tetras_libre.unltools.unl;
+
+import java.util.*;
+
+public class CatsUnl extends AbstractFlyweightUnlArgumentProvider {
+    public static UnlDocumentNode buildSentenceNode() {
+        var graph = new Graph();
+
+        // mod
+        var restrictions = new TreeSet<Restriction>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("feline", new TreeSet<>(Collections.singletonList(new Restriction("icl", '>', new UniversalWord("thing", new TreeSet<>())))))));
+        var uw = new UniversalWord("cat1", restrictions);
+        GraphNode uwNode = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@def")), ":01");
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("adj", new TreeSet<>())));
+        uw = new UniversalWord("black", restrictions);
+        GraphNode uwNode2 = new UniversalWordNode(uw, new HashSet<>());
+
+        graph.add(new GraphRelation(uwNode, uwNode2, "mod", ":01"));
+
+        // and
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("feline", new TreeSet<>(Collections.singletonList(new Restriction("icl", '>', new UniversalWord("thing", new TreeSet<>())))))));
+        uw = new UniversalWord("cat1", restrictions);
+        uwNode = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@def")), ":01");
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("feline", new TreeSet<>(Collections.singletonList(new Restriction("icl", '>', new UniversalWord("thing", new TreeSet<>())))))));
+        uw = new UniversalWord("cat2", restrictions);
+        uwNode2 = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@def")), ":02");
+
+        graph.add(new GraphRelation(uwNode, uwNode2, "and", ":01"));
+
+        // mod
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("feline", new TreeSet<>(Collections.singletonList(new Restriction("icl", '>', new UniversalWord("thing", new TreeSet<>())))))));
+        uw = new UniversalWord("cat2", restrictions);
+        uwNode = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@def")), ":02");
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("adj", new TreeSet<>())));
+        uw = new UniversalWord("white", restrictions);
+        uwNode2 = new UniversalWordNode(uw, new HashSet<>());
+
+        graph.add(new GraphRelation(uwNode, uwNode2, "mod", ":01"));
+
+
+        // agt
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("consume", new TreeSet<>(Collections.singletonList(new Restriction("icl", '>', new UniversalWord("do", new TreeSet<>())))))));
+        restrictions.add(new Restriction("agt", '>', new UniversalWord("living_thing", new TreeSet<>())));
+        restrictions.add(new Restriction("obj", '>', new UniversalWord("concrete_thing", new TreeSet<>())));
+        restrictions.add(new Restriction("ins", '>', new UniversalWord("thing", new TreeSet<>())));
+        uw = new UniversalWord("eat", restrictions);
+        uwNode = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@pl", ".@present", ".@progress")));
+
+        uwNode2 = new SubGraphReferenceNode(":01", new HashSet<>(Collections.singletonList(".@_hn-scope")));
+
+        graph.add(new GraphRelation(uwNode, uwNode2, "agt"));
+
+        return new UnlDocumentNode(UnlDocumentNodeType.Sentence, "[S:00]", graph);
+    }
+
+    protected List<UnlDocument> buildUnlDocuments() {
+        var unlDocument = new UnlDocument("[D]");
+
+        UnlDocumentNode unlDocumentNode = buildSentenceNode();
+
+        unlDocument.add(unlDocumentNode);
+
+        return Collections.singletonList(unlDocument);
+    }
+}
diff --git a/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/CatUnlSentence.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/R1Unl.java
similarity index 89%
rename from rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/CatUnlSentence.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/R1Unl.java
index 3e6d86d..323ed47 100644
--- a/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/CatUnlSentence.java
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/R1Unl.java
@@ -1,21 +1,25 @@
-package fr.tetras_libre.unltools.rdf.vocabulary;
+package fr.tetras_libre.unltools.unl;
 
-import fr.tetras_libre.unltools.unl.*;
+import java.util.*;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.TreeSet;
+public class R1Unl extends AbstractFlyweightUnlArgumentProvider {
 
-public class CatUnlSentence {
-    private static List<UnlDocument> unlDocuments;
+    @Override
+    final protected List<UnlDocument> buildUnlDocuments() {
 
-    private static void buildUnlDocuments() {
         var unlDocument = new UnlDocument("[D]");
 
+        UnlDocumentNode unlDocumentNode = buildSentenceNode();
+
+        unlDocument.add(unlDocumentNode);
+
+        return Collections.singletonList(unlDocument);
+    }
+
+    public static UnlDocumentNode buildSentenceNode() {
         var graph = new Graph();
 
-        // aoj
+        // agt
         var restrictions = new TreeSet<Restriction>();
         restrictions.add(new Restriction("icl", '>', new UniversalWord("be", new TreeSet<>())));
         restrictions.add(new Restriction("aoj", '>', new UniversalWord("thing", new TreeSet<>())));
@@ -64,7 +68,7 @@ public class CatUnlSentence {
 
         restrictions = new TreeSet<>();
         restrictions.add(new Restriction("icl", '>', new UniversalWord("radiowave", new TreeSet<>())));
-        uw = new UniversalWord("radiowave", restrictions);
+        uw = new UniversalWord("channel", restrictions);
         uwNode2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@indef")));
 
         graph.add(new GraphRelation(uwNode, uwNode2, "ben"));
@@ -120,7 +124,7 @@ public class CatUnlSentence {
         restrictions = new TreeSet<>();
         restrictions.add(new Restriction("icl", '>', new UniversalWord("sensing", new TreeSet<>())));
         uw = new UniversalWord("listening", restrictions);
-        uwNode2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@plu")));
+        uwNode2 = new UniversalWordNode(uw, new HashSet<>());
 
         graph.add(new GraphRelation(uwNode, uwNode2, "cnt"));
 
@@ -137,18 +141,6 @@ public class CatUnlSentence {
 
         graph.add(new GraphRelation(uwNode, uwNode2, "and"));
 
-        var unlDocumentNode = new UnlDocumentNode(UnlDocumentNodeType.Sentence, "[S:R1]", graph);
-
-        unlDocument.add(unlDocumentNode);
-
-        unlDocuments.add(unlDocument);
-    }
-
-    public static List<UnlDocument> getUnlDocuments() {
-        if (null == unlDocuments) {
-            buildUnlDocuments();
-        }
-
-        return unlDocuments;
+        return new UnlDocumentNode(UnlDocumentNodeType.Sentence, "[S:R1]", graph);
     }
 }
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/R2Unl.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/R2Unl.java
new file mode 100644
index 0000000..7b0ad0d
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/R2Unl.java
@@ -0,0 +1,145 @@
+package fr.tetras_libre.unltools.unl;
+
+import java.util.*;
+
+public class R2Unl extends AbstractFlyweightUnlArgumentProvider {
+
+    @Override
+    final protected List<UnlDocument> buildUnlDocuments() {
+
+        var unlDocument = new UnlDocument("[D]");
+
+        UnlDocumentNode unlDocumentNode = buildSentenceNode();
+
+        unlDocument.add(unlDocumentNode);
+
+        return Collections.singletonList(unlDocument);
+    }
+
+    public static UnlDocumentNode buildSentenceNode() {
+        var graph = new Graph();
+
+        // agt
+        var restrictions = new TreeSet<Restriction>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("show", new TreeSet<>())));
+        restrictions.add(new Restriction("equ", '>', new UniversalWord("exhibit", new TreeSet<>())));
+        restrictions.add(new Restriction("agt", '>', new UniversalWord("thing", new TreeSet<>())));
+        restrictions.add(new Restriction("obj", '>', new UniversalWord("thing", new TreeSet<>())));
+        var uw = new UniversalWord("display", restrictions);
+        GraphNode node1 = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@present")));
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("group", new TreeSet<>())));
+        uw = new UniversalWord("system", restrictions);
+        GraphNode node2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@def")));
+
+        graph.add(new GraphRelation(node1, node2, "agt"));
+
+        // mod
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("radiowave", new TreeSet<>())));
+        uw = new UniversalWord("channel", restrictions);
+        node1 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@indef")));
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("adj", new TreeSet<>())));
+        restrictions.add(new Restriction("iof", '>', new UniversalWord("color", new TreeSet<>())));
+        uw = new UniversalWord("green", restrictions);
+        node2 = new UniversalWordNode(uw, new HashSet<>());
+
+        graph.add(new GraphRelation(node1, node2, "mod"));
+
+        // obj
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("show", new TreeSet<>())));
+        restrictions.add(new Restriction("equ", '>', new UniversalWord("exhibit", new TreeSet<>())));
+        restrictions.add(new Restriction("agt", '>', new UniversalWord("thing", new TreeSet<>())));
+        restrictions.add(new Restriction("obj", '>', new UniversalWord("thing", new TreeSet<>())));
+        uw = new UniversalWord("display", restrictions);
+        node1 = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@present")));
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("radiowave", new TreeSet<>())));
+        uw = new UniversalWord("channel", restrictions);
+        node2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@indef")));
+
+        graph.add(new GraphRelation(node1, node2, "obj"));
+
+        // tim
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("show", new TreeSet<>())));
+        restrictions.add(new Restriction("equ", '>', new UniversalWord("exhibit", new TreeSet<>())));
+        restrictions.add(new Restriction("agt", '>', new UniversalWord("thing", new TreeSet<>())));
+        restrictions.add(new Restriction("obj", '>', new UniversalWord("thing", new TreeSet<>())));
+        uw = new UniversalWord("display", restrictions);
+        node1 = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@present")));
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("how", new TreeSet<>())));
+        restrictions.add(new Restriction("com", '>', new UniversalWord("always", new TreeSet<>())));
+        restrictions.add(new Restriction("tim", '<', new UniversalWord("uw", new TreeSet<>())));
+        restrictions.add(new Restriction("obj", '>', new UniversalWord("uw", new TreeSet<>())));
+        uw = new UniversalWord("when", restrictions);
+        node2 = new UniversalWordNode(uw, new HashSet<>());
+
+        graph.add(new GraphRelation(node1, node2, "tim"));
+
+        // aoj
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("aoj", '>', new UniversalWord("thing", new TreeSet<>())));
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("be", new TreeSet<>())));
+        restrictions.add(new Restriction("obj", '>', new UniversalWord("state", new TreeSet<>())));
+        uw = new UniversalWord("be_in_a_state", restrictions);
+        node1 = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@present")));
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("radiowave", new TreeSet<>())));
+        uw = new UniversalWord("channel", restrictions);
+        node2 = new UniversalWordNode(uw, new HashSet<>(Collections.singletonList(".@indef")));
+
+        graph.add(new GraphRelation(node1, node2, "aoj", ":01"));
+
+        // plc
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("attribute", new TreeSet<>())));
+        uw = new UniversalWord("state", restrictions);
+        node1 = new UniversalWordNode(uw, new HashSet<>());
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("message", new TreeSet<>())));
+        uw = new UniversalWord("broadcast", restrictions);
+        node2 = new UniversalWordNode(uw, new HashSet<>());
+
+        graph.add(new GraphRelation(node1, node2, "plc", ":01"));
+
+        // obj
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("aoj", '>', new UniversalWord("thing", new TreeSet<>())));
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("be", new TreeSet<>())));
+        restrictions.add(new Restriction("obj", '>', new UniversalWord("state", new TreeSet<>())));
+        uw = new UniversalWord("be_in_a_state", restrictions);
+        node1 = new UniversalWordNode(uw, new HashSet<>(Arrays.asList(".@entry", ".@present")));
+
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("attribute", new TreeSet<>())));
+        uw = new UniversalWord("state", restrictions);
+        node2 = new UniversalWordNode(uw, new HashSet<>());
+
+        graph.add(new GraphRelation(node1, node2, "obj", ":01"));
+
+        // obj
+        restrictions = new TreeSet<>();
+        restrictions.add(new Restriction("icl", '>', new UniversalWord("how", new TreeSet<>())));
+        restrictions.add(new Restriction("com", '>', new UniversalWord("always", new TreeSet<>())));
+        restrictions.add(new Restriction("tim", '<', new UniversalWord("uw", new TreeSet<>())));
+        restrictions.add(new Restriction("obj", '>', new UniversalWord("uw", new TreeSet<>())));
+        uw = new UniversalWord("when", restrictions);
+        node1 = new UniversalWordNode(uw, new HashSet<>());
+
+        node2 = new SubGraphReferenceNode(":01");
+
+        graph.add(new GraphRelation(node1, node2, "obj"));
+
+        return new UnlDocumentNode(UnlDocumentNodeType.Sentence, "[S:R2]", graph);
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/UnlSentences.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/UnlSentences.java
new file mode 100644
index 0000000..6c4c525
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/UnlSentences.java
@@ -0,0 +1,96 @@
+package fr.tetras_libre.unltools.unl;
+
+public class UnlSentences {
+    public static final String R1 = "[D]\n" +
+            "[S:R1]\n" +
+            "{org:en}\n" +
+            "The system allows a radio channel to take on two states: Listening and Traffic.\n" +
+            "{/org}\n" +
+            "{unl}\n" +
+            "aoj( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, system(icl>group).@def )\n" +
+            "obj( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, take_on(aoj>thing, equ>assume,icl>change, obj>thing) )\n" +
+            "ben( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, channel(icl>radiowave).@indef)\n" +
+            "aoj( take_on(aoj>thing, equ>assume, icl>change, obj>thing), channel(icl>radiowave).@indef ) \n" +
+            "obj( take_on(aoj>thing, equ>assume, icl>change, obj>thing), state(icl>attribute).@plu )   \n" +
+            "qua( state(icl>attribute).@plu, 2 )   \n" +
+            "cnt( state(icl>attribute).@plu, listening(icl>sensing) )\n" +
+            "and( listening(icl>sensing),traffic(icl>communication) )\n" +
+            "{/unl}\n" +
+            "[/S]\n" +
+            "[/D]";
+
+    public static final String R2 = "[D]\n" +
+            "[S:R2]\n" +
+            "{org:en}\n" +
+            "The system displays a channel in green when it is in broadcast state. \n" +
+            "{/org}\n" +
+            "{unl}\n" +
+            "agt(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,system(icl>group).@def)\n" +
+            "mod(channel(icl>radiowave).@indef,green(icl>adj,iof>color))\n" +
+            "obj(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,channel(icl>radiowave).@indef)\n" +
+            "tim(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,when(icl>how,com>always,tim<uw,obj>uw))\n" +
+            "aoj:01(be_in_a_state(aoj>thing,icl>be,obj>state).@entry.@present,channel(icl>radiowave).@indef)\n" +
+            "plc:01(state(icl>attribute),broadcast(icl>message))\n" +
+            "obj:01(be_in_a_state(aoj>thing,icl>be,obj>state).@entry.@present,state(icl>attribute))\n" +
+            "obj(when(icl>how,com>always,tim<uw,obj>uw),:01)\n" +
+            "{/unl}\n" +
+            "[/S] \n" +
+            "[/D] \n";
+
+    public static final String Cats = "[D]" +
+            "[S:00]\n" +
+            "{org:en}\n" +
+            "The black cat and the white cat are eating.\n" +
+            "{/org}\n" +
+            "{unl}\n" +
+            "mod:01(cat1(icl>feline>thing):01.@entry.@def,black(icl>adj))\n" +
+            "and:01(cat1(icl>feline>thing):01.@entry.@def,cat2(icl>feline>thing):02.@entry.@def)\n" +
+            "mod:01(cat2(icl>feline>thing):02.@entry.@def,white(icl>adj))\n" +
+            "agt(eat(icl>consume>do,agt>living_thing,obj>concrete_thing,ins>thing).@entry.@pl.@present.@progress,:01.@_hn-scope)\n" +
+            "{/unl}\n" +
+            "[/S]\n";
+
+    public static final String All = "[D]" +
+            "[S:R1]\n" +
+            "{org:en}\n" +
+            "The system allows a radio channel to take on two states: Listening and Traffic.\n" +
+            "{/org}\n" +
+            "{unl}\n" +
+            "aoj( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, system(icl>group).@def )\n" +
+            "obj( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, take_on(aoj>thing, equ>assume,icl>change, obj>thing) )\n" +
+            "ben( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, channel(icl>radiowave).@indef)\n" +
+            "aoj( take_on(aoj>thing, equ>assume, icl>change, obj>thing), channel(icl>radiowave).@indef) \n" +
+            "obj( take_on(aoj>thing, equ>assume, icl>change, obj>thing), state(icl>attribute).@plu )   \n" +
+            "qua( state(icl>attribute).@plu, 2 )   \n" +
+            "cnt( state(icl>attribute).@plu, listening(icl>sensing) )\n" +
+            "and( listening(icl>sensing),traffic(icl>communication) )\n" +
+            "{/unl}\n" +
+            "[/S]\n" +
+            "[S:R2]\n" +
+            "{org:en}\n" +
+            "The system displays a channel in green when it is in broadcast state. \n" +
+            "{/org}\n" +
+            "{unl}\n" +
+            "agt(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,system(icl>group).@def)\n" +
+            "mod(channel(icl>radiowave).@indef,green(icl>adj,iof>color))\n" +
+            "obj(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,channel(icl>radiowave).@indef)\n" +
+            "tim(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,when(icl>how,com>always,tim<uw,obj>uw))\n" +
+            "aoj:01(be_in_a_state(aoj>thing,icl>be,obj>state).@entry.@present,channel(icl>radiowave).@indef)\n" +
+            "plc:01(state(icl>attribute),broadcast(icl>message))\n" +
+            "obj:01(be_in_a_state(aoj>thing,icl>be,obj>state).@entry.@present,state(icl>attribute))\n" +
+            "obj(when(icl>how,com>always,tim<uw,obj>uw),:01)\n" +
+            "{/unl}\n" +
+            "[/S] \n" +
+            "[S:00]\n" +
+            "{org:en}\n" +
+            "The black cat and the white cat are eating.\n" +
+            "{/org}\n" +
+            "{unl}\n" +
+            "mod:01(cat1(icl>feline>thing):01.@entry.@def,black(icl>adj))\n" +
+            "and:01(cat1(icl>feline>thing):01.@entry.@def,cat2(icl>feline>thing):02.@entry.@def)\n" +
+            "mod:01(cat2(icl>feline>thing):02.@entry.@def,white(icl>adj))\n" +
+            "agt(eat(icl>consume>do,agt>living_thing,obj>concrete_thing,ins>thing).@entry.@pl.@present.@progress,:01.@_hn-scope)\n" +
+            "{/unl}\n" +
+            "[/S]\n" +
+            "[/D]";
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/AllSetenceWithExpectedDotChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/AllSetenceWithExpectedDotChecker.java
new file mode 100644
index 0000000..1d014e5
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/AllSetenceWithExpectedDotChecker.java
@@ -0,0 +1,114 @@
+package fr.tetras_libre.unltools.unl.exporters.dot;
+
+import fr.tetras_libre.unltools.unl.UnlSentences;
+
+public class AllSetenceWithExpectedDotChecker extends SentenceWithExpectedDotChecker {
+    private static final String ALL = UnlSentences.All;
+
+    private static final String ALL_DOT = "digraph G {\n" +
+            "graph [fontname=\"courier\", compound=\"true\"];\n" +
+            "1 [\n" +
+            "label=\"allow(aoj>thing,ben>thing,equ>make_possible,icl>be,obj>uw)\\n.@entry\"\n" +
+            "shape=\"box\"\n" +
+            "fontname=\"courb\"\n" +
+            "];\n" +
+            "2 [\n" +
+            "label=\"system(icl>group)\\n.@def\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "3 [\n" +
+            "label=\"take_on(aoj>thing,equ>assume,icl>change,obj>thing)\\n\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "4 [\n" +
+            "label=\"channel(icl>radiowave)\\n.@indef\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "5 [\n" +
+            "label=\"state(icl>attribute)\\n.@plu\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "6 [\n" +
+            "label=\"2\\n\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "7 [\n" +
+            "label=\"listening(icl>sensing)\\n\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "8 [\n" +
+            "label=\"traffic(icl>communication)\\n\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "1 -> 2 [label=\"aoj\" ];\n" +
+            "1 -> 3 [label=\"obj\" ];\n" +
+            "1 -> 4 [label=\"ben\" ];\n" +
+            "3 -> 4 [label=\"aoj\" ];\n" +
+            "3 -> 5 [label=\"obj\" ];\n" +
+            "5 -> 6 [label=\"qua\" ];\n" +
+            "5 -> 7 [label=\"cnt\" ];\n" +
+            "7 -> 8 [label=\"and\" ];\n" +
+            "}\n" +
+            "digraph G {\n" +
+            "graph [fontname=\"courier\", compound=\"true\"];\n" +
+            "1 [\n" +
+            "label=\"display(agt>thing,equ>exhibit,icl>show,obj>thing)\\n.@entry.@present\"\n" +
+            "shape=\"box\"\n" +
+            "fontname=\"courb\"\n" +
+            "];\n" +
+            "2 [\n" +
+            "label=\"system(icl>group)\\n.@def\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "3 [\n" +
+            "label=\"channel(icl>radiowave)\\n.@indef\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "4 [\n" +
+            "label=\"green(icl>adj,iof>color)\\n\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "5 [\n" +
+            "label=\"when(com>always,icl>how,obj>uw,tim<uw)\\n\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "6 [\n" +
+            "label=\"be_in_a_state(aoj>thing,icl>be,obj>state)\\n.@entry.@present\"\n" +
+            "shape=\"box\"\n" +
+            "fontname=\"courb\"\n" +
+            "];\n" +
+            "7 [\n" +
+            "label=\"state(icl>attribute)\\n\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "8 [\n" +
+            "label=\"broadcast(icl>message)\\n\"\n" +
+            "shape=\"box\"\n" +
+            "];\n" +
+            "subgraph cluster_01{\n" +
+            "   color = black;\n" +
+            "   label = \":01\"6 -> 3 [label=\"aoj\" ];\n" +
+            "7 -> 8 [label=\"plc\" ];\n" +
+            "6 -> 7 [label=\"obj\" ];\n" +
+            "}\n" +
+            "1 -> 2 [label=\"agt\" ];\n" +
+            "3 -> 4 [label=\"mod\" ];\n" +
+            "1 -> 3 [label=\"obj\" ];\n" +
+            "1 -> 5 [label=\"tim\" ];\n" +
+            "5 -> 6 [label=\"obj\"  lhead=\"cluster_01\"];\n" +
+            "}\n" +
+            "digraph G {\n" +
+            "graph [fontname=\"courier\", compound=\"true\"];\n" +
+            "1 [ label=\"cat1(icl>feline(icl>thing)):01\\n.@def.@entry\" shape=\"box\" fontname=\"courb\" ];\n" +
+            "2 [ label=\"black(icl>adj)\\n\" shape=\"box\" ];\n" +
+            "3 [ label=\"cat2(icl>feline(icl>thing)):02\\n.@def.@entry\" shape=\"box\" fontname=\"courb\" ];\n" +
+            "4 [ label=\"white(icl>adj)\\n\" shape=\"box\" ];\n" +
+            "5 [ label=\"eat(agt>living_thing,icl>consume(icl>do),ins>thing,obj>concrete_thing)\\n.@entry.@present.@pl.@progress\" shape=\"box\" fontname=\"courb\" ];" +
+            " subgraph cluster_01{ color = black; label = \":01\"1 -> 2 [label=\"mod\" ]; 1 -> 3 [label=\"and\" ]; 3 -> 4 [label=\"mod\" ]; }\n" +
+            "5 -> 1 [label=\"agt\" lhead=\"cluster_01\"];\n" +
+            "}\n";
+
+    public AllSetenceWithExpectedDotChecker() {
+        super(ALL, ALL_DOT);
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/CatSentenceWithExpectedDotChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/CatSentenceWithExpectedDotChecker.java
new file mode 100644
index 0000000..6a0e545
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/CatSentenceWithExpectedDotChecker.java
@@ -0,0 +1,23 @@
+package fr.tetras_libre.unltools.unl.exporters.dot;
+
+import fr.tetras_libre.unltools.unl.UnlSentences;
+
+public class CatSentenceWithExpectedDotChecker extends SentenceWithExpectedDotChecker {
+
+    private static final String CAT_UNL = UnlSentences.Cats;
+
+    private static final String CAT_DOT = "digraph G {\n" +
+            "graph [fontname=\"courier\", compound=\"true\"];\n" +
+            "1 [ label=\"cat1(icl>feline(icl>thing)):01\\n.@def.@entry\" shape=\"box\" fontname=\"courb\" ];\n" +
+            "2 [ label=\"black(icl>adj)\\n\" shape=\"box\" ];\n" +
+            "3 [ label=\"cat2(icl>feline(icl>thing)):02\\n.@def.@entry\" shape=\"box\" fontname=\"courb\" ];\n" +
+            "4 [ label=\"white(icl>adj)\\n\" shape=\"box\" ];\n" +
+            "5 [ label=\"eat(agt>living_thing,icl>consume(icl>do),ins>thing,obj>concrete_thing)\\n.@entry.@present.@pl.@progress\" shape=\"box\" fontname=\"courb\" ];" +
+            " subgraph cluster_01{ color = black; label = \":01\"1 -> 2 [label=\"mod\" ]; 1 -> 3 [label=\"and\" ]; 3 -> 4 [label=\"mod\" ]; }\n" +
+            "5 -> 1 [label=\"agt\" lhead=\"cluster_01\"];\n" +
+            "}\n";
+
+    public CatSentenceWithExpectedDotChecker() {
+        super(CAT_UNL, CAT_DOT);
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/DotFileBuilderTest.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/DotFileBuilderTest.java
new file mode 100644
index 0000000..daba156
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/DotFileBuilderTest.java
@@ -0,0 +1,49 @@
+package fr.tetras_libre.unltools.unl.exporters.dot;
+
+import fr.tetras_libre.unltools.unl.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.List;
+
+class DotFileBuilderTest {
+
+    @Test
+    public void r1ShouldBeConvertedToDotFileWithoutException() {
+        writeInFile(new R1Unl().getUnlDocuments(), new R1SentenceWithExpectedDotChecker());
+    }
+
+    @Test
+    public void r2ShouldBeConvertedToDotFileWithoutException() {
+        this.writeInFile(new R2Unl().getUnlDocuments(), new R2SentenceWithExpectedDotChecker());
+    }
+
+    @Test
+    public void CatsShouldBeConvertedToDotFileWithoutException() {
+        this.writeInFile(new CatsUnl().getUnlDocuments(), new CatSentenceWithExpectedDotChecker());
+    }
+
+    @Test
+    public void allShouldBeConvertedToDotFileWithoutException() {
+        this.writeInFile(new AllUnl().getUnlDocuments(), new AllSetenceWithExpectedDotChecker());
+    }
+
+    private void writeInFile(List<UnlDocument> unlDocuments, SentenceWithExpectedDotChecker sentenceChecker) {
+        // Startup
+        Writer strResult = new StringWriter();
+        DotFileGraphExporter dotFileBuilder = new DotFileGraphExporter(strResult);
+
+        // Test
+        Assertions.assertDoesNotThrow(() -> dotFileBuilder.write(unlDocuments));
+
+        // Teardown
+        Assertions.assertDoesNotThrow(() -> strResult.flush());
+        Assertions.assertTrue(() -> strResult.toString().length() != 0);
+        Assertions.assertDoesNotThrow(() -> sentenceChecker.setCurrentDotContent(strResult.toString()));
+        sentenceChecker.assetSameAsExpected();
+        Assertions.assertDoesNotThrow(() -> strResult.close());
+
+    }
+}
\ No newline at end of file
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/R1SentenceWithExpectedDotChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/R1SentenceWithExpectedDotChecker.java
similarity index 60%
rename from unl-parser/src/test/java/fr/tetras_libre/unltools/unl/R1SentenceWithExpectedDotChecker.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/R1SentenceWithExpectedDotChecker.java
index 3960166..62f8bb4 100644
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/R1SentenceWithExpectedDotChecker.java
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/R1SentenceWithExpectedDotChecker.java
@@ -1,23 +1,9 @@
-package fr.tetras_libre.unltools.unl;
+package fr.tetras_libre.unltools.unl.exporters.dot;
+
+import fr.tetras_libre.unltools.unl.UnlSentences;
 
 public class R1SentenceWithExpectedDotChecker extends SentenceWithExpectedDotChecker {
-    private static final String R1_UNL = "[D]\n" +
-            "[S:R1]\n" +
-            "{org:en}\n" +
-            "The system allows a radio channel to take on two states: Listening and Traffic.\n" +
-            "{/org}\n" +
-            "{unl}\n" +
-            "aoj( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, system(icl>group).@def )\n" +
-            "obj( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, take_on(aoj>thing, equ>assume,icl>change, obj>thing) )\n" +
-            "ben( allow(icl>be, aoj>thing, ben>thing, obj>uw, equ>make_possible).@entry, channel(icl>radiowave).@indef)\n" +
-            "aoj( take_on(aoj>thing, equ>assume, icl>change, obj>thing), channel(icl>radiowave).@indef ) \n" +
-            "obj( take_on(aoj>thing, equ>assume, icl>change, obj>thing), state(icl>attribute).@plu )   \n" +
-            "qua( state(icl>attribute).@plu, 2 )   \n" +
-            "cnt( state(icl>attribute).@plu, listening(icl>sensing) )\n" +
-            "and( listening(icl>sensing),traffic(icl>communication) )\n" +
-            "{/unl}\n" +
-            "[/S]\n" +
-            "[/D]";
+    private static final String R1_UNL = UnlSentences.R1;
 
     private static final String R1_DOT = "digraph G {\n" +
             "graph [fontname=\"courier\", compound=\"true\"];\n" +
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/R2SentenceWithExpectedDotChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/R2SentenceWithExpectedDotChecker.java
similarity index 63%
rename from unl-parser/src/test/java/fr/tetras_libre/unltools/unl/R2SentenceWithExpectedDotChecker.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/R2SentenceWithExpectedDotChecker.java
index 141d786..374cc97 100644
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/R2SentenceWithExpectedDotChecker.java
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/R2SentenceWithExpectedDotChecker.java
@@ -1,23 +1,9 @@
-package fr.tetras_libre.unltools.unl;
+package fr.tetras_libre.unltools.unl.exporters.dot;
+
+import fr.tetras_libre.unltools.unl.UnlSentences;
 
 public class R2SentenceWithExpectedDotChecker extends SentenceWithExpectedDotChecker {
-    private static final String R2_UNL = "[D]\n" +
-            "[S:R2]\n" +
-            "{org:en}\n" +
-            "The system displays a channel in green when it is in broadcast state. \n" +
-            "{/org}\n" +
-            "{unl}\n" +
-            "agt(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,system(icl>group).@def)\n" +
-            "mod(channel(icl>radiowave).@indef,green(icl>adj,iof>color))\n" +
-            "obj(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,channel(icl>radiowave).@indef)\n" +
-            "tim(display(icl>show,equ>exhibit,agt>thing,obj>thing).@entry.@present,when(icl>how,com>always,tim<uw,obj>uw))\n" +
-            "aoj:01(be_in_a_state(aoj>thing,icl>be,obj>state).@entry.@present,channel(icl>radiowave).@indef)\n" +
-            "plc:01(state(icl>attribute),broadcast(icl>message))\n" +
-            "obj:01(be_in_a_state(aoj>thing,icl>be,obj>state).@entry.@present,state(icl>attribute))\n" +
-            "obj(when(icl>how,com>always,tim<uw,obj>uw),:01)\n" +
-            "{/unl}\n" +
-            "[/S] \n" +
-            "[/D] \n";
+    private static final String R2_UNL = UnlSentences.R2;
 
     private static final String R2_DOT = "digraph G {\n" +
             "graph [fontname=\"courier\", compound=\"true\"];\n" +
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/SentenceWithExpectedDotArgumentProvider.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/SentenceWithExpectedDotArgumentProvider.java
similarity index 64%
rename from unl-parser/src/test/java/fr/tetras_libre/unltools/unl/SentenceWithExpectedDotArgumentProvider.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/SentenceWithExpectedDotArgumentProvider.java
index f8a239d..6245169 100644
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/SentenceWithExpectedDotArgumentProvider.java
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/SentenceWithExpectedDotArgumentProvider.java
@@ -1,5 +1,9 @@
-package fr.tetras_libre.unltools.unl;
+package fr.tetras_libre.unltools.unl.exporters.dot;
 
+import fr.tetras_libre.unltools.unl.exporters.dot.AllSetenceWithExpectedDotChecker;
+import fr.tetras_libre.unltools.unl.exporters.dot.CatSentenceWithExpectedDotChecker;
+import fr.tetras_libre.unltools.unl.exporters.dot.R1SentenceWithExpectedDotChecker;
+import fr.tetras_libre.unltools.unl.exporters.dot.R2SentenceWithExpectedDotChecker;
 import org.junit.jupiter.api.extension.ExtensionContext;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.ArgumentsProvider;
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/SentenceWithExpectedDotChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/SentenceWithExpectedDotChecker.java
similarity index 79%
rename from unl-parser/src/test/java/fr/tetras_libre/unltools/unl/SentenceWithExpectedDotChecker.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/SentenceWithExpectedDotChecker.java
index 93b691d..e59ac0b 100644
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/SentenceWithExpectedDotChecker.java
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/dot/SentenceWithExpectedDotChecker.java
@@ -1,4 +1,4 @@
-package fr.tetras_libre.unltools.unl;
+package fr.tetras_libre.unltools.unl.exporters.dot;
 
 import org.junit.jupiter.api.Assertions;
 
@@ -19,18 +19,10 @@ public abstract class SentenceWithExpectedDotChecker {
         return this.unlSentence;
     }
 
-    protected void setUnlSentence(String unlSentence) {
-        this.unlSentence = null == unlSentence ? "" : unlSentence;
-    }
-
     public String getExpectedDotContent() {
         return this.expectedDotContent;
     }
 
-    public void setExpectedDotContent(String expectedDotContent) {
-        this.expectedDotContent = expectedDotContent;
-    }
-
     public String getCurrentDotContent() {
         return currentDotContent;
     }
diff --git a/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/RdfSchemaOfUNLTest.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/rdf/RdfSchemaOfUNLTest.java
similarity index 67%
rename from rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/RdfSchemaOfUNLTest.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/rdf/RdfSchemaOfUNLTest.java
index 7e0ec87..7012835 100644
--- a/rdf/src/test/java/fr/tetras_libre/unltools/rdf/vocabulary/RdfSchemaOfUNLTest.java
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/rdf/RdfSchemaOfUNLTest.java
@@ -1,6 +1,7 @@
-package fr.tetras_libre.unltools.rdf.vocabulary;
+package fr.tetras_libre.unltools.unl.exporters.rdf;
 
 import fr.tetras_libre.rdf.vocabulary.UNL;
+import fr.tetras_libre.unltools.unl.R1Unl;
 import fr.tetras_libre.unltools.unl.UnlDocument;
 import org.apache.jena.rdf.model.ModelFactory;
 import org.junit.jupiter.api.Assertions;
@@ -11,21 +12,28 @@ import org.junit.jupiter.params.provider.ArgumentsSource;
 import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
-import java.util.LinkedList;
+import java.util.List;
 
 class RdfSchemaOfUNLTest {
 
     @Test
-    void createRdfOfUnlSentence() throws IOException {
+    void createIndividualsWithSameUriGivesSameInstance() {
         var model = ModelFactory.createOntologyModel();
         var el1 = model.createIndividual("blablabla", UNL.UNL_Sentence);
         var el2 = model.createIndividual("blablabla", UNL.UNL_Sentence);
 
-        // egalité réference
-        var refEquals = el1 == el2;
+        // reference equality
+        Assertions.assertSame(el1, el2);
+
+        // content equality
+        Assertions.assertEquals(el1, el2);
+    }
 
-        // egalite de contenu
-        var contentEquals = el1.equals(el2);
+    @Test
+    void createRdfOfUnlSentence() throws IOException {
+        var model = ModelFactory.createOntologyModel();
+        var el1 = model.createIndividual("blablabla", UNL.UNL_Sentence);
+        var el2 = model.createIndividual("blablabla", UNL.UNL_Sentence);
 
         Writer writer = new StringWriter();
         model.write(writer, "TURTLE");
@@ -35,8 +43,8 @@ class RdfSchemaOfUNLTest {
     }
 
     @ParameterizedTest
-    @ArgumentsSource(R1SentenceWithExpectedRdf.class)
-    void createUnlDocument(LinkedList<UnlDocument> unlDocuments) throws IOException {
+    @ArgumentsSource(R1Unl.class)
+    void createUnlDocument(List<UnlDocument> unlDocuments) throws IOException {
         var unlDocumentToRdfConverter = new UnlDocumentToRdfConverter();
         var ontModels = unlDocumentToRdfConverter.convertToOntModel(unlDocuments);
 
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/rdf/RelationLabelToUnlPropertyConverterTest.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/rdf/RelationLabelToUnlPropertyConverterTest.java
new file mode 100644
index 0000000..4a7c80f
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/exporters/rdf/RelationLabelToUnlPropertyConverterTest.java
@@ -0,0 +1,29 @@
+package fr.tetras_libre.unltools.unl.exporters.rdf;
+
+import org.apache.jena.ontology.ObjectProperty;
+import org.apache.jena.ontology.OntModel;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+class RelationLabelToUnlPropertyConverterTest {
+
+    @Test
+    public void getObjectPropertyShouldGiveAssociatedUNLressource(){
+        var relationLabelToUnlProperty = new RelationLabelToUnlPropertyConverter();
+
+        Assertions.assertDoesNotThrow(() -> relationLabelToUnlProperty.getObjectProperty("aoj", null));
+    }
+
+    @Test
+    public void getObjectPropertyShouldNotThrowOnUnknownResource(){
+        AtomicReference<ObjectProperty> objectPropertyAtomicReference = new AtomicReference<>();
+        var relationLabelToUnlProperty = new RelationLabelToUnlPropertyConverter();
+        var unknownProperty = "dfadsfijoplknkjadfljgliukjelkjkdm";
+        var docModel = ModelFactory.createOntologyModel();
+
+        Assertions.assertDoesNotThrow(() -> objectPropertyAtomicReference.set(relationLabelToUnlProperty.getObjectProperty(unknownProperty, docModel)));
+    }
+}
\ No newline at end of file
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/AllSentenceWithExpectedUnlDocumentsChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/AllSentenceWithExpectedUnlDocumentsChecker.java
new file mode 100644
index 0000000..da29d16
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/AllSentenceWithExpectedUnlDocumentsChecker.java
@@ -0,0 +1,10 @@
+package fr.tetras_libre.unltools.unl.parser;
+
+import fr.tetras_libre.unltools.unl.AllUnl;
+import fr.tetras_libre.unltools.unl.UnlSentences;
+
+public class AllSentenceWithExpectedUnlDocumentsChecker extends SentenceWithExpectedUnlDocumentsChecker {
+    public AllSentenceWithExpectedUnlDocumentsChecker() {
+        super(UnlSentences.All, new AllUnl().getUnlDocuments());
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/CatsSentenceWithExpectedUnlDocumentsChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/CatsSentenceWithExpectedUnlDocumentsChecker.java
new file mode 100644
index 0000000..51b46f7
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/CatsSentenceWithExpectedUnlDocumentsChecker.java
@@ -0,0 +1,10 @@
+package fr.tetras_libre.unltools.unl.parser;
+
+import fr.tetras_libre.unltools.unl.CatsUnl;
+import fr.tetras_libre.unltools.unl.UnlSentences;
+
+public class CatsSentenceWithExpectedUnlDocumentsChecker extends SentenceWithExpectedUnlDocumentsChecker {
+    public CatsSentenceWithExpectedUnlDocumentsChecker() {
+        super(UnlSentences.Cats, new CatsUnl().getUnlDocuments());
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/R1SentenceWithExpectedUnlDocumentsChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/R1SentenceWithExpectedUnlDocumentsChecker.java
new file mode 100644
index 0000000..b6aa89b
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/R1SentenceWithExpectedUnlDocumentsChecker.java
@@ -0,0 +1,10 @@
+package fr.tetras_libre.unltools.unl.parser;
+
+import fr.tetras_libre.unltools.unl.R1Unl;
+import fr.tetras_libre.unltools.unl.UnlSentences;
+
+public class R1SentenceWithExpectedUnlDocumentsChecker extends SentenceWithExpectedUnlDocumentsChecker {
+    public R1SentenceWithExpectedUnlDocumentsChecker() {
+        super(UnlSentences.R1, new R1Unl().getUnlDocuments());
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/R2SentenceWithExpectedUnlDocumentsChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/R2SentenceWithExpectedUnlDocumentsChecker.java
new file mode 100644
index 0000000..15fdeb5
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/R2SentenceWithExpectedUnlDocumentsChecker.java
@@ -0,0 +1,10 @@
+package fr.tetras_libre.unltools.unl.parser;
+
+import fr.tetras_libre.unltools.unl.R2Unl;
+import fr.tetras_libre.unltools.unl.UnlSentences;
+
+public class R2SentenceWithExpectedUnlDocumentsChecker extends SentenceWithExpectedUnlDocumentsChecker {
+    public R2SentenceWithExpectedUnlDocumentsChecker() {
+        super(UnlSentences.R2, new R2Unl().getUnlDocuments());
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/SentenceWithExpectedUnlDocumentsArgumentProvider.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/SentenceWithExpectedUnlDocumentsArgumentProvider.java
new file mode 100644
index 0000000..b3d7f6b
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/SentenceWithExpectedUnlDocumentsArgumentProvider.java
@@ -0,0 +1,21 @@
+package fr.tetras_libre.unltools.unl.parser;
+
+import fr.tetras_libre.unltools.unl.exporters.dot.AllSetenceWithExpectedDotChecker;
+import fr.tetras_libre.unltools.unl.exporters.dot.CatSentenceWithExpectedDotChecker;
+import fr.tetras_libre.unltools.unl.exporters.dot.R1SentenceWithExpectedDotChecker;
+import fr.tetras_libre.unltools.unl.exporters.dot.R2SentenceWithExpectedDotChecker;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+import java.util.stream.Stream;
+
+public class SentenceWithExpectedUnlDocumentsArgumentProvider implements ArgumentsProvider {
+    @Override
+    public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) {
+        return Stream.of(Arguments.of(new R1SentenceWithExpectedDotChecker()),
+                Arguments.of(new R2SentenceWithExpectedDotChecker()),
+                Arguments.of(new CatSentenceWithExpectedDotChecker()),
+                Arguments.of(new AllSetenceWithExpectedDotChecker()));
+    }
+}
diff --git a/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/SentenceWithExpectedUnlDocumentsChecker.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/SentenceWithExpectedUnlDocumentsChecker.java
new file mode 100644
index 0000000..6aebfb0
--- /dev/null
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/SentenceWithExpectedUnlDocumentsChecker.java
@@ -0,0 +1,40 @@
+package fr.tetras_libre.unltools.unl.parser;
+
+import fr.tetras_libre.unltools.unl.UnlDocument;
+import org.junit.jupiter.api.Assertions;
+
+import java.util.List;
+
+public class SentenceWithExpectedUnlDocumentsChecker {
+    private final List<UnlDocument> expectedUnlDocuments;
+    private String unlSentence;
+    private List<UnlDocument> currentUnlDocuments;
+
+    public SentenceWithExpectedUnlDocumentsChecker(String unlSentence, List<UnlDocument> expectedUnlDocuments) {
+        if ((null == unlSentence) || (null == expectedUnlDocuments)) {
+            throw new IllegalArgumentException();
+        }
+        this.unlSentence = unlSentence;
+        this.expectedUnlDocuments = expectedUnlDocuments;
+    }
+
+    public String getUnlSentence() {
+        return this.unlSentence;
+    }
+
+    public List<UnlDocument> getExpectedDotContent() {
+        return this.expectedUnlDocuments;
+    }
+
+    public List<UnlDocument> getCurrentDotContent() {
+        return this.currentUnlDocuments;
+    }
+
+    public void setCurrentUnlDocuments(List<UnlDocument> currentUnlDocuments) {
+        this.currentUnlDocuments = currentUnlDocuments;
+    }
+
+    public void assetSameAsExpected() {
+        Assertions.assertIterableEquals(this.expectedUnlDocuments, this.currentUnlDocuments);
+    }
+}
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactory.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactory.java
similarity index 100%
rename from unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactory.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactory.java
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactoryFromString.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactoryFromString.java
similarity index 100%
rename from unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactoryFromString.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserFactoryFromString.java
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserTest.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserTest.java
similarity index 55%
rename from unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserTest.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserTest.java
index ff62eaa..28dd3e0 100644
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserTest.java
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/UnlParserTest.java
@@ -1,28 +1,23 @@
 package fr.tetras_libre.unltools.unl.parser;
 
-import fr.tetras_libre.unltools.unl.SentenceWithExpectedDotArgumentProvider;
-import fr.tetras_libre.unltools.unl.SentenceWithExpectedDotChecker;
 import fr.tetras_libre.unltools.unl.UnlDocument;
+import fr.tetras_libre.unltools.unl.UnlSentences;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ArgumentsSource;
+import org.junit.jupiter.params.provider.ArgumentsSources;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Stream;
 
 class UnlParserTest {
 
     @ParameterizedTest
-    @ArgumentsSource(SentenceWithExpectedDotArgumentProvider.class)
-    void UnlParserShouldParseSimpleSentenceWithoutException(SentenceWithExpectedDotChecker input) {
-        UnlParserFactory unlFactory = new UnlParserFactoryFromString(input.getUnlSentence());
-        createAndCheckUnlParserValidity(unlFactory);
-    }
-
-    @ParameterizedTest
-    @ArgumentsSource(SentenceWithExpectedDotArgumentProvider.class)
-    void UnlDocumentsShouldBeSerializedToStringWithoutException(SentenceWithExpectedDotChecker input) {
-        UnlParserFactory unlFactory = new UnlParserFactoryFromString(input.getUnlSentence());
-        WrapperUnlParser wrapper = createAndCheckUnlParserValidity(unlFactory);
+    @ValueSource(strings = {UnlSentences.R1, UnlSentences.R2, UnlSentences.Cats, UnlSentences.All})
+    void unlParserShouldParseSimpleSentenceWithoutException(String input) {
+        UnlParserFactory unlFactory = new UnlParserFactoryFromString(input);
+        var wrapper = createAndCheckUnlParserValidity(unlFactory);
 
         for (UnlDocument unlDocument : wrapper.getUnlDocumentList()) {
             AtomicReference<String> stringOfUnlDocument = new AtomicReference<>();
@@ -48,4 +43,23 @@ class UnlParserTest {
         return unlParser.get();
     }
 
+
+
+    @ParameterizedTest
+    @MethodSource
+    void unlParserShouldParseSentenceAndGetExpectedUnlDocuments(SentenceWithExpectedUnlDocumentsChecker input) {
+        UnlParserFactory unlFactory = new UnlParserFactoryFromString(input.getUnlSentence());
+        var wrapper = createAndCheckUnlParserValidity(unlFactory);
+
+        input.setCurrentUnlDocuments(wrapper.getUnlDocumentList());
+        input.assetSameAsExpected();
+    }
+
+    private static Stream<SentenceWithExpectedUnlDocumentsChecker> unlParserShouldParseSentenceAndGetExpectedUnlDocuments(){
+        return Stream.of(new R1SentenceWithExpectedUnlDocumentsChecker(),
+                new R2SentenceWithExpectedUnlDocumentsChecker(),
+                new CatsSentenceWithExpectedUnlDocumentsChecker(),
+                new AllSentenceWithExpectedUnlDocumentsChecker());
+    }
+
 }
\ No newline at end of file
diff --git a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/WrapperUnlParser.java b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/WrapperUnlParser.java
similarity index 66%
rename from unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/WrapperUnlParser.java
rename to unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/WrapperUnlParser.java
index 054fa22..97c487f 100644
--- a/unl-parser/src/test/java/fr/tetras_libre/unltools/unl/parser/WrapperUnlParser.java
+++ b/unl-tools-infrastructure/src/test/java/fr/tetras_libre/unltools/unl/parser/WrapperUnlParser.java
@@ -15,18 +15,30 @@ public class WrapperUnlParser {
         this.errors = null;
     }
 
+    /**
+     * get UnlDocuments once the parsing is done
+     * @return A list of UnlDocuments
+     */
     public Vector<UnlDocument> getUnlDocumentList() {
-        initializeIfNecessary();
+        parseContentIfNecessary();
         return this.documents;
     }
 
-    private void initializeIfNecessary() {
+    /**
+     * Parse the content with the local parser if not already done.
+     */
+    private void parseContentIfNecessary() {
         if (null == this.documents) {
-            initialize();
+            parseContentAndRetrieveErrors();
         }
     }
 
-    private void initialize() {
+
+    /**
+     * Parse the content with the local parser.
+     * Retrieves also errors during parsing
+     */
+    private void parseContentAndRetrieveErrors() {
         this.errors = new ErrorCollection(false);
         try {
             this.documents = this.parser.createUnlDocumentList();
@@ -40,10 +52,13 @@ public class WrapperUnlParser {
             return;
         }
 
-        fillErrors();
+        getUnlDocumentsErrors();
     }
 
-    private void fillErrors() {
+    /**
+     * retrieves errors within documents
+     */
+    private void getUnlDocumentsErrors() {
         for (UnlDocument document : this.documents) {
             if (document.HasError()) {
                 this.errors.addError(document.getError());
@@ -51,13 +66,21 @@ public class WrapperUnlParser {
         }
     }
 
+    /**
+     * An error as occured during the parsing
+     * @return true if an error occured, false otherwise
+     */
     public boolean hasError() {
-        initializeIfNecessary();
+        parseContentIfNecessary();
         return errors.hasError;
     }
 
+    /**
+     * Get errors of parsing
+     * @return A vector of errors
+     */
     public Vector<String> getErrors() {
-        initializeIfNecessary();
+        parseContentIfNecessary();
         return errors.errors;
     }
 
@@ -71,7 +94,7 @@ public class WrapperUnlParser {
         }
 
         public void addError(String error) {
-            hasError = true;
+            this.hasError = true;
             if (!this.errors.contains(error)) {
                 this.errors.add(error);
             }
diff --git a/rdf/rdf.iml b/unl-tools-infrastructure/unl-tools-infrastructure.iml
similarity index 97%
rename from rdf/rdf.iml
rename to unl-tools-infrastructure/unl-tools-infrastructure.iml
index deff331..095605e 100644
--- a/rdf/rdf.iml
+++ b/unl-tools-infrastructure/unl-tools-infrastructure.iml
@@ -11,7 +11,6 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="rdf-vocabulary-1.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.apache.jena:jena-shacl:3.14.0" level="project" />
     <orderEntry type="library" name="Maven: org.apache.jena:jena-arq:3.14.0" level="project" />
     <orderEntry type="library" name="Maven: org.apache.jena:jena-core:3.14.0" level="project" />
@@ -44,9 +43,9 @@
     <orderEntry type="library" name="Maven: org.apache.jena:jena-dboe-index:3.14.0" level="project" />
     <orderEntry type="library" name="Maven: org.apache.jena:jena-rdfconnection:3.14.0" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.26" level="project" />
-    <orderEntry type="module" module-name="unl-parser" />
     <orderEntry type="library" name="Maven: fr.tetras_libre.rdf:rdf-unl-java-vocabulary:1.0-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.slf4j:slf4j-nop:1.7.30" level="project" />
+    <orderEntry type="module" module-name="unl-tools-core" />
     <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.7.0-M1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.7.0-M1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
diff --git a/unlTools.iml b/unlTools.iml
new file mode 100644
index 0000000..a10c5f4
--- /dev/null
+++ b/unlTools.iml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11">
+    <output url="file://$MODULE_DIR$/target/classes" />
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.7.0-M1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.7.0-M1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.7.0-M1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-params:5.7.0-M1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.7.0-M1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.7.0-M1" level="project" />
+  </component>
+</module>
\ No newline at end of file
-- 
GitLab