diff --git a/src/main/java/fr/inra/po2vocabmanager/MainApp.java b/src/main/java/fr/inra/po2vocabmanager/MainApp.java
index d3bcff218ab0948f2e162e8b264e0d02b4a124f2..17fb91f808e10c87cf617e83535a51a5965e050c 100644
--- a/src/main/java/fr/inra/po2vocabmanager/MainApp.java
+++ b/src/main/java/fr/inra/po2vocabmanager/MainApp.java
@@ -35,6 +35,7 @@ import fr.inrae.po2engine.model.*;
 import fr.inrae.po2engine.model.dataModel.GeneralFile;
 import fr.inrae.po2engine.model.dataModel.ItineraryFile;
 import fr.inrae.po2engine.utils.ProgressPO2;
+import fr.inrae.po2engine.utils.Report;
 import fr.inrae.po2engine.utils.Tools;
 import javafx.application.Application;
 import javafx.application.Platform;
@@ -82,6 +83,8 @@ import org.update4j.LaunchContext;
 import org.update4j.inject.InjectTarget;
 import org.update4j.service.Launcher;
 
+import static org.junit.jupiter.api.DynamicTest.stream;
+
 import java.io.*;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
@@ -1263,6 +1266,159 @@ public class MainApp extends Application implements Launcher  {
         }
     }
 
+    public void startSHACLValidation() {
+
+        // Au prealable :
+        // - le jeu de donnees doit avoir ete publie
+        // - le fichier de contrainte a du etre transmis (download)
+        
+        ArrayList<String> errorCantStartSValidation = new ArrayList<>();
+        String dataName = Tools.normalize(getDataControler().getCurrentData().getProjectFile().getNameProperty().getValue());
+
+        // Verification que le jeu de donnees a bien ete publie ?
+        String repoName = RDF4JTools.getRepository(dataName);
+        if (repoName.equals("error"))
+            errorCantStartSValidation.add("First, publish the dataset to validate");
+
+        // Verification que le fichier de contraintes a bien ete transmis ?
+
+        if (errorCantStartSValidation.size() > 0) {
+            Alert alert = new Alert(AlertType.ERROR);
+            alert.setTitle("Unable to start SHACL validation");
+            alert.setHeaderText("Please correct the errors before starting SHACL validation");
+            alert.setContentText(errorCantStartSValidation.stream().map(x -> " - " + x).collect(Collectors.joining("\n")));
+            alert.initOwner(MainApp.primaryStage);
+            alert.initModality(Modality.WINDOW_MODAL);
+            alert.showAndWait();
+            return;
+        }
+
+        // Option 1
+        /*
+        unbindVersion();
+        Thread t = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    JSONObject listMessages ;
+                    listMessages = getDataControler().getCurrentData().startShaclValidation();
+
+                    if (listMessages.getJSONArray("error").length() > 0) {
+                        // Validation KO.
+                        Alert KOVal = new Alert(AlertType.ERROR);
+                        KOVal.setResizable(true);
+                        KOVal.setTitle("Validation Errors");
+                        KOVal.setHeaderText("An error occured");
+                        KOVal.setContentText(listMessages.getJSONArray("error").toString());
+                        KOVal.initOwner(MainApp.primaryStage);
+                        KOVal.initModality(Modality.WINDOW_MODAL);
+                        KOVal.show();
+                    } else {
+                        Alert OKVal = new Alert(AlertType.INFORMATION);
+                        OKVal.setResizable(true);
+                        OKVal.setTitle("Success");
+                        OKVal.setHeaderText("Validation successfull");
+                        OKVal.initOwner(MainApp.primaryStage);
+                        OKVal.initModality(Modality.WINDOW_MODAL);
+                        OKVal.show();
+                    }
+
+                } catch (IOException | RDFParseException e) {
+                    e.printStackTrace();
+                    Platform.runLater(() -> {
+                        Alert errorSem = new Alert(AlertType.ERROR);
+                        errorSem.setTitle("ERROR");
+                        errorSem.setHeaderText("An error occurred");
+                        errorSem.setContentText("An error occurred. If the problem persist, contact the administrator");
+                        errorSem.initOwner(MainApp.primaryStage);
+                        errorSem.initModality(Modality.WINDOW_MODAL);
+                        errorSem.show();
+                    });
+                }
+            }
+        });
+        t.start();*/
+        
+        // Option 2
+        unbindVersion();
+        Thread t = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Tools.addProgress(ProgressPO2.ANALYSE, "Validating ?");
+                    Tools.updateProgress(ProgressPO2.ANALYSE, "Validating...");
+
+                    long start = System.nanoTime();
+                    Report r = RDF4JTools.startShaclValidation(Tools.normalize(dataName));
+                    //try{
+                    //    Thread.sleep(3000);
+                    //} catch (InterruptedException e){
+                    //    e.printStackTrace();
+                    //}
+                    long finish = System.nanoTime();
+                    long timeElapsed = (long)((finish - start)*0.000001);
+
+                    Platform.runLater(() -> {
+                        Alert SHACLValidationEndMessage = new Alert(AlertType.INFORMATION);
+                        SHACLValidationEndMessage.setResizable(true);
+                        SHACLValidationEndMessage.setTitle("SHACL validation ended");
+                        SHACLValidationEndMessage.setHeaderText("REPORT");
+                        if (r.success()) {
+                            SHACLValidationEndMessage.setContentText("Elapsed time : "
+                            + ((Long)timeElapsed).toString() + " ms\r\n"
+                            + "No validation error ?");
+                        }
+                        else {
+                            SHACLValidationEndMessage.setContentText("Elapsed time : "
+                            + ((Long)timeElapsed).toString() + " ms\r\n"
+                            + "Validations errors...");//r.prettyPrintError());
+                            ButtonType saveLog = new ButtonType("Download log file", ButtonData.LEFT);
+                            SHACLValidationEndMessage.getButtonTypes().add(saveLog);
+                            SHACLValidationEndMessage.getDialogPane().lookupButton(saveLog).addEventFilter(
+                                ActionEvent.ACTION,
+                                event -> {
+                                    event.consume();
+                                    FileChooser fileChooser = new FileChooser();
+                                    fileChooser.setTitle("save log file");
+                                    fileChooser.setInitialFileName("results_SHACL_validation.txt");
+                                    File fileExport = fileChooser.showSaveDialog(MainApp.primaryStage);
+                                    if (fileExport != null) {
+                                        try {
+                                            FileOutputStream fout = new FileOutputStream(fileExport, false);
+                                            org.apache.commons.io.IOUtils.write(r.prettyPrintError(), fout, StandardCharsets.UTF_8);
+                                            fout.close();
+                                        } catch (IOException ex) {
+                                            MainApp.logger.error(ex.getMessage());
+                                        }
+                                    }
+                                }
+                            );
+                        }
+
+                        SHACLValidationEndMessage.initOwner(MainApp.primaryStage);
+                        SHACLValidationEndMessage.initModality(Modality.WINDOW_MODAL);
+                        SHACLValidationEndMessage.showAndWait();
+                    });
+                                
+                    Tools.delProgress(ProgressPO2.ANALYSE);
+                } catch (RDFParseException e) {
+                    Tools.delProgress(ProgressPO2.ANALYSE);
+                    e.printStackTrace();
+                    Platform.runLater(() -> {
+                        Alert errorSem = new Alert(AlertType.ERROR);
+                        errorSem.setTitle("ERROR");
+                        errorSem.setHeaderText("An error occurred");
+                        errorSem.setContentText("An error occurred. If the problem persist, contact the administrator");
+                        errorSem.initOwner(MainApp.primaryStage);
+                        errorSem.initModality(Modality.WINDOW_MODAL);
+                        errorSem.show();
+                    });
+                }
+            }
+        });
+        t.start();
+    }
+
     public String buildTextLogPublish(Integer niv, JSONArray jsonArray) {
         StringBuilder builder = new StringBuilder();
 
diff --git a/src/main/java/fr/inra/po2vocabmanager/utils/DataTreeCell.java b/src/main/java/fr/inra/po2vocabmanager/utils/DataTreeCell.java
index 596fe74c0304db9bfbb0d40ca361a72b3e866bef..75db53d54b2b224d9e12e35f163edd4bef5c35d6 100644
--- a/src/main/java/fr/inra/po2vocabmanager/utils/DataTreeCell.java
+++ b/src/main/java/fr/inra/po2vocabmanager/utils/DataTreeCell.java
@@ -20,6 +20,7 @@ package fr.inra.po2vocabmanager.utils;
 
 import fr.inra.po2vocabmanager.MainApp;
 import fr.inra.po2vocabmanager.model.DataNode;
+import fr.inrae.po2engine.externalTools.RDF4JTools;
 import fr.inrae.po2engine.model.dataModel.*;
 import fr.inrae.po2engine.utils.ImportReport;
 import fr.inrae.po2engine.utils.Report;
@@ -49,9 +50,7 @@ import org.controlsfx.control.CheckTreeView;
 import org.json.JSONArray;
 import org.json.JSONObject;
 
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
+import java.io.*;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -435,9 +434,96 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> {
                         });
                     });
 
+                    MenuItem uploadSCHACLConstraints = new MenuItem("Upload SCHACL");
+                    uploadSCHACLConstraints.disableProperty().bind(Bindings.not(mainApp.getEditProperty()));
+                    uploadSCHACLConstraints.setGraphic(new ImageView(UITools.getImage("resources/images/file-export-16.png")));
+                    uploadSCHACLConstraints.setOnAction(event -> {
+                        ProjectFile projectFile = (ProjectFile) item.getFile();
+                        Platform.runLater(() -> {
+                            FileChooser fileChooser = new FileChooser();
+                            fileChooser.setTitle("Choose SCHACL Constraints File");
+                            fileChooser.setInitialFileName(projectFile.getNameProperty().get()+"_SCHACL_Constraints.xlsx");
+                            //fileChooser.setInitialFileName("shaclConstraints.xlsx");
+                            fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Turtle file (*.ttl)", "*.ttl"));
+                            File schaclConstraintsFile = fileChooser.showOpenDialog(MainApp.primaryStage);
+                            if (schaclConstraintsFile != null) {
+                                new Thread(() -> {
+                                    Platform.runLater(() -> {
+                                        try {
+                                            String ID = projectFile.getNameProperty().get();
+                                            InputStream stream = new FileInputStream(schaclConstraintsFile);
+
+                                            long start = System.nanoTime();
+                                            RDF4JTools.updateShaclGraph(ID, stream);
+                                            long finish = System.nanoTime();
+                                            long timeElapsed = (long)((finish - start)*0.000001);
+                                            
+                                            // Autre option pour mesurer le temps
+                                            //Instant start = Instant.now();    
+                                            //...
+                                            //Instant finish = Instant.now();   
+                                            //long timeElapsed = Duration.between(start, finish).toMillis();
+                                            
+                                            Alert okImport = new Alert(Alert.AlertType.INFORMATION);
+                                            okImport.setGraphic(new ImageView(UITools.getImage("resources/images/valid.png")));
+                                            okImport.setHeaderText(null);
+                                            okImport.setTitle("Uploading duration");
+                                            okImport.setContentText(((Long)timeElapsed).toString() + " ms");
+                                            okImport.initModality(Modality.APPLICATION_MODAL);
+                                            okImport.initOwner(MainApp.primaryStage);
+                                            okImport.showAndWait();
+
+                                        } catch (IOException ex) {
+                                            MainApp.logger.error(ex.getMessage());
+                                        }
+                                    });
+                                }).start();
+                            };
+                        });
+                    });
+
+                    MenuItem downloadSCHACLConstraints = new MenuItem("Download SHACL");
+                    downloadSCHACLConstraints.setGraphic(new ImageView(UITools.getImage("resources/images/file-export-16.png")));
+                    downloadSCHACLConstraints.setOnAction(event -> {
+                        ProjectFile projectFile = (ProjectFile) item.getFile();
+                        Platform.runLater(() -> {
+                            String repositoryID = projectFile.getNameProperty().get();
+                            FileChooser fileChooser = new FileChooser();
+                            fileChooser.setTitle("Choose name for SHACL Constraints File");
+                            fileChooser.setInitialFileName(repositoryID + "_SHACL_Constraints.ttl");
+                            fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Turtle file (*.ttl)", "*.ttl"));
+                            File schaclConstraintsFile = fileChooser.showSaveDialog(MainApp.primaryStage);
+                            if (schaclConstraintsFile != null) {
+                                new Thread(() -> {
+                                    Platform.runLater(() -> {
+                                        try {
+                                            OutputStream stream = new FileOutputStream(schaclConstraintsFile);
+                                            
+                                            RDF4JTools.downloadShaclGraph(repositoryID, stream);
+
+                                            Alert okImport = new Alert(Alert.AlertType.INFORMATION);
+                                            okImport.setGraphic(new ImageView(UITools.getImage("resources/images/valid.png")));
+                                            okImport.setHeaderText(null);
+                                            okImport.setTitle("Downloading SHACL file");
+                                            okImport.setContentText("Fichier téléchargé...");
+                                            okImport.initModality(Modality.APPLICATION_MODAL);
+                                            okImport.initOwner(MainApp.primaryStage);
+                                            okImport.showAndWait();
+
+                                        } catch (IOException ex) {
+                                            MainApp.logger.error(ex.getMessage());
+                                        }
+                                    });
+                                }).start();
+                            };
+                        });
+                    });
+
                     menu.getItems().add(addProcess);
                     menu.getItems().add(exportProject);
                     menu.getItems().add(importProject);
+                    menu.getItems().add(uploadSCHACLConstraints);
+                    menu.getItems().add(downloadSCHACLConstraints);
                     break;
                 case PROCESS:
                     MenuItem addItinerary = new MenuItem("New Itinerary");
diff --git a/src/main/java/fr/inra/po2vocabmanager/view/RootLayoutController.java b/src/main/java/fr/inra/po2vocabmanager/view/RootLayoutController.java
index 2044e37d74b7091d7e068d5064e1f8b3b8ac3126..b2bc6372cc5585c22e20d1865b6374fe6acacc1d 100644
--- a/src/main/java/fr/inra/po2vocabmanager/view/RootLayoutController.java
+++ b/src/main/java/fr/inra/po2vocabmanager/view/RootLayoutController.java
@@ -62,6 +62,8 @@ public class RootLayoutController {
     @FXML
     MenuItem itemPublish;
     @FXML
+    MenuItem itemSCHACLValidation;
+    @FXML
     MenuItem itemSem;
     @FXML
     MenuItem itemReadMode;
@@ -90,6 +92,8 @@ public class RootLayoutController {
         itemOpen.setDisable(true);
         itemPublish.setDisable(true);
         itemPublish.setVisible(true);
+        itemSCHACLValidation.setDisable(true);
+        itemSCHACLValidation.setVisible(true);
         itemImportExport.setVisible(false);
         itemExportOnto.setDisable(true);
         itemImportOnto.setDisable(true);
@@ -119,6 +123,8 @@ public class RootLayoutController {
         itemPublish.textProperty().bind(Bindings.when(mainApp.onOntologyViewProperty()).then("Semantize & Publish ontology").otherwise("Semantize & Publish data"));
         itemPublish.disableProperty().bind(mainApp.getEditProperty().not());
 
+        itemSCHACLValidation.disableProperty().bind(Bindings.when(mainApp.fileNameProperty().isEqualTo("")).then(true).otherwise(false));
+
         itemImportExport.visibleProperty().bind(mainApp.onOntologyViewProperty());
         itemExportOnto.disableProperty().bind(mainApp.onOntologyViewProperty().not());
         itemImportOnto.disableProperty().bind(mainApp.onOntologyViewProperty().not().or(mainApp.getEditProperty().not()));
@@ -350,6 +356,10 @@ public class RootLayoutController {
         mainApp.semantize();
     }
 
+    public void startSHACLValidation() {
+        mainApp.startSHACLValidation();
+    }
+
     /**
      * Function Call on search click or CTRL+F
      */
diff --git a/src/main/resources/PO2Engine.properties b/src/main/resources/PO2Engine.properties
index f850efa8c5abdc723edbf940fc462e550085adc5..79ed2093f11e1e2ca0276b4d2c28ccc377dafd72 100644
--- a/src/main/resources/PO2Engine.properties
+++ b/src/main/resources/PO2Engine.properties
@@ -16,6 +16,8 @@
 # SPDX-License-Identifier: MIT
 #
 
+# Serveur de test : icotest.iate.inra.fr
+# Serveur de production : quantum.mia-ps.inrae.fr
 server.host=quantum.mia-ps.inrae.fr
 
 nextCloud.listFile.login=listFiles
diff --git a/src/main/resources/fr/inra/po2vocabmanager/view/RootLayout.fxml b/src/main/resources/fr/inra/po2vocabmanager/view/RootLayout.fxml
index 213578d0f8813e01aade62340f97acab1d337c3e..7bb1b2b963924a716138f8992feea09fa45c865f 100644
--- a/src/main/resources/fr/inra/po2vocabmanager/view/RootLayout.fxml
+++ b/src/main/resources/fr/inra/po2vocabmanager/view/RootLayout.fxml
@@ -18,10 +18,13 @@
   ~ SPDX-License-Identifier: MIT
   -->
 
-<?import javafx.scene.control.*?>
+<?import javafx.scene.control.Menu?>
+<?import javafx.scene.control.MenuBar?>
+<?import javafx.scene.control.MenuItem?>
 <?import javafx.scene.input.KeyCodeCombination?>
 <?import javafx.scene.layout.BorderPane?>
-<BorderPane xmlns:fx="http://javafx.com/fxml/1" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="700.0" prefWidth="1300.0" xmlns="http://javafx.com/javafx/10.0.1" fx:controller="fr.inra.po2vocabmanager.view.RootLayoutController">
+
+<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="700.0" prefWidth="1300.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.inra.po2vocabmanager.view.RootLayoutController">
     <top>
         <MenuBar BorderPane.alignment="CENTER">
             <menus>
@@ -53,6 +56,7 @@
                   <MenuItem fx:id="itemReadMode" mnemonicParsing="false" onAction="#enterWriteMode" text="Read Mode" />
                   <MenuItem fx:id="addConceptScheme" mnemonicParsing="false" onAction="#newConceptScheme" text="New Concept Scheme" />
                   <MenuItem fx:id="itemPublish" mnemonicParsing="false" onAction="#publish" text="Semantize &amp; Publish" visible="false" />
+                  <MenuItem fx:id="itemSCHACLValidation" mnemonicParsing="false" onAction="#startSHACLValidation" text="Start SHACL Validation" />
                   <Menu fx:id="itemImportExport" mnemonicParsing="false" text="Import/Export" visible="false">
                     <items>
                       <MenuItem fx:id="itemImportOnto" mnemonicParsing="false" onAction="#importOnto" text="Import" />