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 & 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" />