diff --git a/src/main/java/fr/inra/po2vocabmanager/utils/DataTreeCell.java b/src/main/java/fr/inra/po2vocabmanager/utils/DataTreeCell.java index e7deb82ecdea8c6faf94bec608065a74144a704c..325cd0277eb4ba244e3c7b8c95b2aa9e0b47199e 100644 --- a/src/main/java/fr/inra/po2vocabmanager/utils/DataTreeCell.java +++ b/src/main/java/fr/inra/po2vocabmanager/utils/DataTreeCell.java @@ -21,6 +21,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.Replicate; import fr.inrae.po2engine.model.dataModel.*; import fr.inrae.po2engine.utils.ImportReport; import fr.inrae.po2engine.utils.Report; @@ -182,7 +183,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { return s; } - private static void newStepImport(ItineraryFile iti, StepFile parent) { + private static void newStepImport(ItineraryFile iti, StepFile parent, int replicateID) { File fileImport = getFile(MainApp.primaryStage); if (fileImport == null) { return; @@ -190,7 +191,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { MainApp.logger.info("start importing file " + fileImport.getName()); ImportReport importReport = iti.checkImportStepFromXLSX(fileImport); if(importReport.success()) { - StepFile step = iti.importStepFromXLSX(fileImport); + StepFile step = iti.importStepFromXLSX(fileImport, replicateID); if(parent != null && step != null) { parent.addSubStep(step); } @@ -274,15 +275,15 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { } - private static void newItineraryObsImport(ItineraryFile iti) { + private static void newItineraryObsImport(ItineraryFile iti, int replicateID) { File fileImport = getFile(MainApp.primaryStage); if (fileImport == null) { return; } MainApp.logger.info("start importing/create file " + fileImport.getName()); - Report r = iti.checkCreateObservationFromXLSX(fileImport); + Report r = iti.checkCreateObservationFromXLSX(fileImport, replicateID); if(r.success()) { - ObservationFile obs = iti.createObservationFromXLSX(fileImport); + ObservationFile obs = iti.createObservationFromXLSX(fileImport, replicateID); handleInterfaceUpdate(obs.getItineraryFile().getProcessFile(), r.success(), "File import completed"); MainApp.getDataControler().selectNode(obs); MainApp.logger.info("import done with sucess"); @@ -328,15 +329,402 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { result.ifPresent(step -> addStepData(itineraryFile, parentStep, current, true, step)); } - private void newStepObsImport(StepFile step) { + private static void stepImport(StepFile file, boolean isNewStep, int replicateID) { + File fileImport = getFile(MainApp.primaryStage); + if (fileImport != null) { + MainApp.logger.info("start importing file " + fileImport.getName()); + ImportReport importReport = file.realPreConst(fileImport, isNewStep); + if(importReport.success()) { + + // validation de l'import par l'utilisateur + Dialog<ButtonType> validateImport = new Dialog(); + validateImport.setTitle("import validation"); + validateImport.initOwner(MainApp.primaryStage); + validateImport.initModality(Modality.WINDOW_MODAL); + ButtonType importButtonType = new ButtonType("Import", ButtonBar.ButtonData.OK_DONE); + validateImport.getDialogPane().getButtonTypes().addAll(importButtonType, ButtonType.CANCEL); + + GridPane paneImport = new GridPane(); + paneImport.setHgap(20); + paneImport.setVgap(20); + + Integer comptLine = 0; + Text stepText = new Text(file.getNameProperty().getValue()); + Text sepa = new Text(" : "); + paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/step.png")), 0, comptLine); + paneImport.add(stepText, 1, comptLine); + paneImport.add(sepa, 2, comptLine); + paneImport.add(new ImageView(UITools.getImage("resources/images/update_30.png")), 3, comptLine); + + comptLine++; + + + for (ObservationFile obsF : file.getObservationFiles()) { + Text obsText = new Text(obsF.getCID().getValue().get()); + Text sepa2 = new Text(" : "); + paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/observation.png")), 0, comptLine); + paneImport.add(obsText, 1, comptLine); + paneImport.add(sepa2, 2, comptLine); + if (importReport.getObsMapping().containsValue(obsF)) { + paneImport.add(new ImageView(UITools.getImage("resources/images/update_30.png")), 3, comptLine); + } else { + paneImport.add(new ImageView(UITools.getImage("resources/images/del_30.png")), 3, comptLine); + } + comptLine++; + } + + for(XSSFSheet oo : importReport.getObsMapping().keySet()) { + if(importReport.getObsMapping().get(oo) == null) { // new obs + Text obsText = new Text(oo.getSheetName()); + Text sepa2 = new Text(" : "); + paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/observation.png")), 0, comptLine); + paneImport.add(obsText, 1, comptLine); + paneImport.add(sepa2, 2, comptLine); + paneImport.add(new ImageView(UITools.getImage("resources/images/add_30.png")), 3, comptLine); + comptLine++; + } + } + + for (CompositionFile compoF : file.getCompositionFile().keySet()) { + Text compoText = new Text(compoF.getCompositionID().getValue().get()); + Text sepa2 = new Text(" : "); + paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/composition.png")), 0, comptLine); + paneImport.add(compoText, 1, comptLine); + paneImport.add(sepa2, 2, comptLine); + if(importReport.getCompoMapping().values().stream().map(org.apache.commons.lang3.tuple.Pair::getLeft).noneMatch(c -> c.equals(compoF))) { + paneImport.add(new ImageView(UITools.getImage("resources/images/del_30.png")), 3, comptLine); + } else { + paneImport.add(new ImageView(UITools.getImage("resources/images/update_30.png")), 3, comptLine); + } + comptLine++; + } + + for(XSSFSheet oo : importReport.getCompoMapping().keySet()) { + if(importReport.getCompoMapping().get(oo).getLeft() == null) { // new Compo + Text compoText = new Text(oo.getSheetName()); + Text sepa2 = new Text(" : "); + paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/composition.png")), 0, comptLine); + paneImport.add(compoText, 1, comptLine); + paneImport.add(sepa2, 2, comptLine); + paneImport.add(new ImageView(UITools.getImage("resources/images/add_30.png")), 3, comptLine); + comptLine++; + } + } + + validateImport.getDialogPane().setContent(paneImport); + Optional<ButtonType> result = Optional.empty(); + if(!isNewStep) { + result = validateImport.showAndWait(); + } + if (isNewStep || result.isPresent() && result.get() == importButtonType) { + // l'utilisateur valide la la mise à jour + Report report = file.constructDataFromImport(fileImport, isNewStep, replicateID); + handleInterfaceUpdate(file.getGeneralFile(), report.success(), report.toString()); + MainApp.getDataControler().selectNode(file); + } + } else { + showErrorImportAlert(importReport.toString()); + } + } else { + } + } + + private static void importObservation(ObservationFile obsFile, int replicateID) { + File fileImport = getFile(MainApp.primaryStage); + if (fileImport != null) { + MainApp.logger.info("start importing/update file " + fileImport.getName()); + // temp obs file + ObservationFile tempF = null; + if(obsFile.getStepFile() != null) { + Report r = obsFile.getStepFile().checkUpdateObservationFromXLSX(fileImport, obsFile, replicateID); + if(r.success()) { + obsFile.getStepFile().updateObservationFromXLSX(fileImport, obsFile, replicateID); + MainApp.getDataControler().refreshTree(); + MainApp.getDataControler().showNodeDetails(obsFile, obsFile); + MainApp.logger.info("import done with sucess"); + } else { + showErrorImportAlert(r.prettyPrintError()); + } + } + if(obsFile.getItineraryFile() != null) { + Report r = obsFile.getItineraryFile().checkUpdateObservationFromXLSX(fileImport, obsFile, replicateID); + if(r.success()) { + obsFile.getItineraryFile().updateObservationFromXLSX(fileImport, obsFile, replicateID); + MainApp.getDataControler().refreshTree(); + MainApp.getDataControler().showNodeDetails(obsFile, obsFile); + MainApp.logger.info("import done with sucess"); + } else { + showErrorImportAlert(r.prettyPrintError()); + } + } + } + } + + private static void exportObservation(ObservationFile obsFile, int replicateID) { + List<String> choices = new ArrayList<>(); + choices.add("with ontology"); + choices.add("without ontology"); + ChoiceDialog<String> dialog = new ChoiceDialog<>("without ontology", choices); + dialog.setTitle("Export Observation"); + dialog.setHeaderText(null); + dialog.setContentText("Export Observation data "); + dialog.initModality(Modality.WINDOW_MODAL); + dialog.initOwner(MainApp.primaryStage); + Boolean exportOnto = false; + Optional<String> result = dialog.showAndWait(); + + if (result.isPresent() ) { + exportOnto = result.get().equals("with ontology"); + Boolean finalExportOnto = exportOnto; + if (exportOnto && MainApp.getOntologyControler().getCurrentOntology() == null) { + Alert noOntology = new Alert(Alert.AlertType.ERROR); + noOntology.setTitle("No ontology loaded"); + noOntology.setHeaderText("Please load an ontology"); + noOntology.setContentText("In order to create an export file, please load the corresponding ontology"); + noOntology.initOwner(MainApp.primaryStage); + noOntology.initModality(Modality.APPLICATION_MODAL); + noOntology.showAndWait(); + } else { + XSSFWorkbook book = new XSSFWorkbook(); + + + Task<Boolean> taskExport = new Task<Boolean>() { + @Override + protected Boolean call() throws Exception { + XSSFSheet sheet = Tools.createSheet(book,"obs|"+Tools.removeNonAlphaNumChar(obsFile.getNameProperty().getValue())); + + Integer compteur = 0; + Integer maxColumn = 0; + for (LinkedList<String> line : obsFile.getDataForExcel(replicateID)) { + XSSFRow r = sheet.createRow(compteur++); + Integer compteurCell = 0; + for (String val : line) { + r.createCell(compteurCell++).setCellValue(val); + maxColumn = Math.max(maxColumn, compteurCell); + } + } + Tools.autoResize(sheet, maxColumn); + + + if(finalExportOnto) { + + JSONObject hierarchyVocab = MainApp.getOntologyControler().getHierarchyVocabJSON(); + // Récupération de l'ontology au format JSON + XSSFSheet sheetOntoVocab = Tools.createSheet(book,"onto-vocab|" + Tools.removeNonAlphaNumChar(MainApp.getOntologyControler().getCurrentOntology().getName().getValue())); + JSONArray vocab = (JSONArray) hierarchyVocab.get("vocabulary"); + + compteur = 0; + maxColumn = 0; + for ( + int i = 0; i < vocab.length(); i++) { + JSONArray array = (JSONArray) vocab.get(i); + XSSFRow r = sheetOntoVocab.createRow(compteur++); + for (int j = 0; j < array.length(); j++) { + r.createCell(j).setCellValue((String) array.get(j)); + maxColumn = Math.max(maxColumn, j); + } + } + Tools.autoResize(sheetOntoVocab, maxColumn); + + + XSSFSheet sheetOntohierarchy = Tools.createSheet(book,"onto-hierarchy|" + Tools.removeNonAlphaNumChar(MainApp.getOntologyControler().getCurrentOntology().getName().getValue())); + JSONArray hierarchy = (JSONArray) hierarchyVocab.get("hierarchy"); + + compteur = 0; + maxColumn = 0; + + for ( + int x = 0; x < hierarchy.length(); x++) { + XSSFRow r = sheetOntohierarchy.createRow(compteur++); + JSONArray arrayDesc = (JSONArray) hierarchy.get(x); + for (int j = 0; j < arrayDesc.length(); j++) { + r.createCell(j).setCellValue((String) arrayDesc.get(j)); + maxColumn = Math.max(maxColumn, j); + } + } + Tools.autoResize(sheetOntohierarchy, maxColumn); + } + return true; + } + }; + taskExport.setOnSucceeded(workerStateEvent -> { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Export file"); + String fileName = obsFile.getFileName(); + if(replicateID != -1) { + fileName+="-"+replicateID; + } + fileChooser.setInitialFileName(fileName+".xlsx"); + File fileExport = fileChooser.showSaveDialog(MainApp.primaryStage); + if (fileExport != null) { + try { + FileOutputStream fout = new FileOutputStream(fileExport, false); + book.write(fout); + fout.close(); + } catch (IOException ex) { + MainApp.logger.error(ex.getMessage()); + } + } + }); + new Thread(taskExport).start(); + } + } + } + + private static void exportStepFile(StepFile stepFile, int replicateID) { + + List<String> choices = new ArrayList<>(); + choices.add("with ontology"); + choices.add("without ontology"); + ChoiceDialog<String> dialog = new ChoiceDialog<>("without ontology", choices); + dialog.setTitle("Export Step"); + dialog.setHeaderText(null); + dialog.setContentText("Export step data "); + dialog.initModality(Modality.WINDOW_MODAL); + dialog.initOwner(MainApp.primaryStage); + Boolean exportOnto = false; + Optional<String> result = dialog.showAndWait(); + + if (result.isPresent() ) { + exportOnto = result.get().equals("with ontology"); + if(exportOnto && MainApp.getOntologyControler().getCurrentOntology() == null) { + Alert noOntology = new Alert(Alert.AlertType.ERROR); + noOntology.setTitle("No ontology loaded"); + noOntology.setHeaderText("Please load an ontology"); + noOntology.setContentText("In order to create an export file, please load the corresponding ontology"); + noOntology.initOwner(MainApp.primaryStage); + noOntology.initModality(Modality.APPLICATION_MODAL); + noOntology.showAndWait(); + } else { + XSSFWorkbook book = new XSSFWorkbook(); + Boolean finalExportOnto = exportOnto; + Task<Boolean> taskExport = new Task<Boolean>() { + @Override + protected Boolean call() throws Exception { + XSSFSheet sheet = Tools.createSheet(book,"step|"+ DigestUtils.md5Hex(stepFile.getNameProperty().getValue())); + + Integer compteur = 0; + Integer maxColumn = 0; + + for (LinkedList<String> line : stepFile.getDataForExcel(true, replicateID)) { + XSSFRow r = sheet.createRow(compteur++); + Integer compteurCell = 0; + for (String val : line) { + r.createCell(compteurCell++).setCellValue(val); + maxColumn = Math.max(maxColumn, compteurCell); + } + } + + + // composition + for (Map.Entry<CompositionFile, Boolean> entry : stepFile.getCompositionFile().entrySet()) { + XSSFSheet sheetCompo = Tools.createSheet(book,"compo-"+(entry.getValue() ? "input" : "output")+"|"+Tools.removeNonAlphaNumChar(entry.getKey().getCompositionID().getValue().get())); + Integer compteurCompo = 0; + Integer maxColumnCompo = 0; + for (LinkedList<String> line : entry.getKey().getDataForExcel()) { + XSSFRow r = sheetCompo.createRow(compteurCompo++); + Integer compteurCell = 0; + for (String val : line) { + r.createCell(compteurCell++).setCellValue(val); + maxColumnCompo = Math.max(maxColumnCompo, compteurCell); + } + } + Tools.autoResize(sheetCompo, maxColumnCompo); + } + + + + Tools.autoResize(sheet, maxColumn); + + for(ObservationFile obs : stepFile.getObservationFiles()) { + XSSFSheet sheetObs = Tools.createSheet(book,"obs|"+Tools.removeNonAlphaNumChar(obs.getCID().getValue().get())); + + Integer compteurObs = 0; + Integer maxColumnObs = 0; + for (LinkedList<String> line : obs.getDataForExcel(replicateID)) { + XSSFRow r = sheetObs.createRow(compteurObs++); + Integer compteurCell = 0; + for (String val : line) { + r.createCell(compteurCell++).setCellValue(val); + maxColumnObs = Math.max(maxColumnObs, compteurCell); + } + } + Tools.autoResize(sheetObs, maxColumnObs); + } + + if(finalExportOnto) { + + JSONObject hierarchyVocab = MainApp.getOntologyControler().getHierarchyVocabJSON(); + // Récupération de l'ontology au format JSON + XSSFSheet sheetOntoVocab = Tools.createSheet(book,"onto-vocab|" + Tools.removeNonAlphaNumChar(MainApp.getOntologyControler().getCurrentOntology().getName().getValue())); + JSONArray vocab = (JSONArray) hierarchyVocab.get("vocabulary"); + + compteur = 0; + maxColumn = 0; + for (int i = 0; i < vocab.length(); i++) { + JSONArray array = (JSONArray) vocab.get(i); + XSSFRow r = sheetOntoVocab.createRow(compteur++); + for (int j = 0; j < array.length(); j++) { + r.createCell(j).setCellValue((String) array.get(j)); + maxColumn = Math.max(maxColumn, j); + } + } + Tools.autoResize(sheetOntoVocab, maxColumn); + + + XSSFSheet sheetOntohierarchy = Tools.createSheet(book,"onto-hierarchy|" + Tools.removeNonAlphaNumChar(MainApp.getOntologyControler().getCurrentOntology().getName().getValue())); + JSONArray hierarchy = (JSONArray) hierarchyVocab.get("hierarchy"); + + compteur = 0; + maxColumn = 0; + + for (int x = 0; x < hierarchy.length(); x++) { + XSSFRow r = sheetOntohierarchy.createRow(compteur++); + JSONArray arrayDesc = (JSONArray) hierarchy.get(x); + for (int j = 0; j < arrayDesc.length(); j++) { + r.createCell(j).setCellValue((String) arrayDesc.get(j)); + maxColumn = Math.max(maxColumn, j); + } + } + Tools.autoResize(sheetOntohierarchy, maxColumn); + } + return true; + } + }; + taskExport.setOnSucceeded(workerStateEvent -> { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Export file"); + String fileName = stepFile.getNameProperty().getValue(); + if(replicateID != -1) { + fileName+="-"+replicateID; + } + fileChooser.setInitialFileName(fileName+".xlsx"); + File fileExport = fileChooser.showSaveDialog(MainApp.primaryStage); + if (fileExport != null) { + try { + FileOutputStream fout = new FileOutputStream(fileExport, false); + book.write(fout); + fout.close(); + } catch (IOException ex) { + MainApp.logger.error(ex.getMessage()); + } + } + }); + new Thread(taskExport).start(); + } + } + + } + + private void newStepObsImport(StepFile step, int replicateID) { File fileImport = getFile(MainApp.primaryStage); if (fileImport == null) { return; } MainApp.logger.info("start importing/create file " + fileImport.getName()); - Report r = step.checkCreateObservationFromXLSX(fileImport); + Report r = step.checkCreateObservationFromXLSX(fileImport, replicateID); if(r.success()) { - ObservationFile obs = step.createObservationFromXLSX(fileImport); + ObservationFile obs = step.createObservationFromXLSX(fileImport, replicateID); handleInterfaceUpdate(obs.getStepFile().getGeneralFile(), r.success(), "File import completed"); MainApp.getDataControler().selectNode(obs); MainApp.logger.info("import done with sucess"); @@ -345,10 +733,38 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { } } + private static void handleInterfaceUpdate(GeneralFile file, boolean reportBoolean, String reportString) { + if(reportBoolean) { + MainApp.getDataControler().buildProcessTree(file); + showOkImportAlert(); + } else { + showErrorImportAlert(reportString); + } + } + + private static void showErrorImportAlert(String report) { + Alert errorImport = new Alert(Alert.AlertType.ERROR); + errorImport.setTitle("Import error"); + errorImport.setContentText(report); + errorImport.initModality(Modality.APPLICATION_MODAL); + errorImport.initOwner(MainApp.primaryStage); + errorImport.showAndWait(); + } + + private static void showOkImportAlert() { + Alert okImport = new Alert(Alert.AlertType.INFORMATION); + okImport.setGraphic(new ImageView(UITools.getImage("resources/images/valid.png"))); + okImport.setHeaderText(null); + okImport.setTitle("Successful import"); + okImport.setContentText("Successful import"); + okImport.initModality(Modality.APPLICATION_MODAL); + okImport.initOwner(MainApp.primaryStage); + okImport.showAndWait(); + } + @Override public void updateItem(DataNode item, boolean empty) { super.updateItem(item, empty); - if (empty || item == null) { setText(null); setGraphic(null); @@ -356,30 +772,41 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { setContextMenu(null); } else { setText(item.toString()); - if(/*!item.getType().equals(DataNodeType.ITINERARY) && */item.getFile() != null) { + if(item.getFile() != null) { if(item.getFile().isSelectedInTree()) { setBackground(new Background(new BackgroundFill(Color.DEEPSKYBLUE,CornerRadii.EMPTY,Insets.EMPTY))); } else { setBackground(null); } + } + if (item.getType().equals(DataNodeType.PROCESS)) { + GeneralFile processFile = (GeneralFile)item.getFile(); +// setContentDisplay(ContentDisplay.RIGHT); + if(processFile.getListReplicate().size() > 1) { + Label l = new Label(); + l.textProperty().bind(item.nameProperty()); + ComboBox<Replicate> comboReplicate = new ComboBox<>(); + comboReplicate.setItems(processFile.getListReplicate()); + if(processFile.getCurrentReplicate() != null) { + comboReplicate.setValue(processFile.getCurrentReplicate()); + } + comboReplicate.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + if(newValue != null && newValue != oldValue) { + processFile.setCurrentReplicate(newValue); + if(MainApp.getDataControler().getTree().getSelectionModel().getSelectedItem() != null) { + DataNode currentSelectedNode = MainApp.getDataControler().getTree().getSelectionModel().getSelectedItem().getValue(); + if(currentSelectedNode.getType().equals(DataNodeType.OBSERVATION) || currentSelectedNode.getType().equals(DataNodeType.STEP) || currentSelectedNode.getType().equals(DataNodeType.PROCESS) ) { + MainApp.getDataControler().showNodeDetails(currentSelectedNode, currentSelectedNode); + } + } + } + }); + setText(""); + setGraphic(new HBox(item.getGraphic(), l, comboReplicate)); + } } -// if(item.getType().equals(DataNodeType.ITINERARY) ) { -// if(item.getItineraryFile().getItiPart().isSelectedInTree()) { -// setBackground(new Background(new BackgroundFill(Color.DEEPSKYBLUE,CornerRadii.EMPTY,Insets.EMPTY))); -// } else { -// setBackground(null); -// } -// } -// if(item.getItineraryPart() != null) { -// if(item.getItineraryPart().isSelectedInTree()) { -// setBackground(new Background(new BackgroundFill(Color.LIGHTGRAY,CornerRadii.EMPTY,Insets.EMPTY))); -// } else { -// setBackground(null); -// } -// -// } setEditable(false); ContextMenu menu = new ContextMenu(); switch (item.getType()) { @@ -658,6 +1085,19 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { menu.getItems().add(downloadSHACLConstraints); break; case PROCESS: + MenuItem newRep = new MenuItem("New biological replicate"); + newRep.setGraphic(new ImageView(UITools.getImage("resources/images/treeview/replicate_16.png"))); + newRep.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); + newRep.setOnAction(event -> { + GeneralFile current = (GeneralFile) item.getFile(); + Replicate newReplicate = current.addReplicate("new replicate", ""); + if(newReplicate != null) { + current.setCurrentReplicate(newReplicate); + MainApp.getDataControler().showNodeDetails(getItem(), getItem()); + } + }); + menu.getItems().add(newRep); + Menu newIti = new Menu("New Itinerary"); newIti.setGraphic(new ImageView(UITools.getImage("resources/images/treeview/itinerary.png"))); newIti.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); @@ -752,6 +1192,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { menu.getItems().add(deleteProcess); break; case OBSERVATION: + ObservationFile obsFile = (ObservationFile) item.getFile(); MenuItem addDataObs = new MenuItem("New Data Table"); addDataObs.setGraphic(new ImageView(UITools.getImage("resources/images/add_16.png"))); addDataObs.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); @@ -797,166 +1238,78 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { }); menu.getItems().add(addDataObs); - MenuItem exportObs = new MenuItem("Export Observation"); - exportObs.setGraphic(new ImageView(UITools.getImage("resources/images/file-export-16.png"))); - exportObs.setOnAction(event -> { - - List<String> choices = new ArrayList<>(); - choices.add("with ontology"); - choices.add("without ontology"); - ChoiceDialog<String> dialog = new ChoiceDialog<>("without ontology", choices); - dialog.setTitle("Export Observation"); - dialog.setHeaderText(null); - dialog.setContentText("Export Observation data "); - dialog.initModality(Modality.WINDOW_MODAL); - dialog.initOwner(MainApp.primaryStage); - Boolean exportOnto = false; - Optional<String> result = dialog.showAndWait(); - - if (result.isPresent() ) { - exportOnto = result.get().equals("with ontology"); - Boolean finalExportOnto = exportOnto; - if (exportOnto && mainApp.getOntologyControler().getCurrentOntology() == null) { - Alert noOntology = new Alert(Alert.AlertType.ERROR); - noOntology.setTitle("No ontology loaded"); - noOntology.setHeaderText("Please load an ontology"); - noOntology.setContentText("In order to create an export file, please load the corresponding ontology"); - noOntology.initOwner(MainApp.primaryStage); - noOntology.initModality(Modality.APPLICATION_MODAL); - noOntology.showAndWait(); - } else { - ObservationFile file = (ObservationFile) item.getFile(); - XSSFWorkbook book = new XSSFWorkbook(); - - - Task<Boolean> taskExport = new Task<Boolean>() { - @Override - protected Boolean call() throws Exception { - XSSFSheet sheet = Tools.createSheet(book,"obs|"+Tools.removeNonAlphaNumChar(file.getNameProperty().getValue())); - - Integer compteur = 0; - Integer maxColumn = 0; - for (LinkedList<String> line : file.getDataForExcel()) { - XSSFRow r = sheet.createRow(compteur++); - Integer compteurCell = 0; - for (String val : line) { - r.createCell(compteurCell++).setCellValue(val); - maxColumn = Math.max(maxColumn, compteurCell); - } - } - Tools.autoResize(sheet, maxColumn); + GeneralFile processFile = null; + if(obsFile.getStepFile() != null) { + processFile = obsFile.getStepFile().getGeneralFile(); + } else { + processFile = obsFile.getItineraryFile().getProcessFile(); + } + if(processFile.getListReplicate().size() > 1) { + Menu exportObs = new Menu("Export Observation"); + exportObs.setGraphic(new ImageView(UITools.getImage("resources/images/file-export-16.png"))); - if(finalExportOnto) { + MenuItem exportCurRep = new MenuItem("for current replicate"); + GeneralFile finalProcessFile = processFile; + exportCurRep.setOnAction(event -> { + exportObservation(obsFile, finalProcessFile.getCurrentReplicate().getId()); + }); + MenuItem exportAllRep = new MenuItem("for all replicates"); + exportAllRep.setOnAction(event -> { + exportObservation(obsFile, -1); + }); - JSONObject hierarchyVocab = mainApp.getOntologyControler().getHierarchyVocabJSON(); - // Récupération de l'ontology au format JSON - XSSFSheet sheetOntoVocab = Tools.createSheet(book,"onto-vocab|" + Tools.removeNonAlphaNumChar(mainApp.getOntologyControler().getCurrentOntology().getName().getValue())); - JSONArray vocab = (JSONArray) hierarchyVocab.get("vocabulary"); + exportObs.getItems().add(exportCurRep); + exportObs.getItems().add(exportAllRep); + menu.getItems().add(exportObs); + } else { + MenuItem exportObs = new MenuItem("Export Observation"); + exportObs.setGraphic(new ImageView(UITools.getImage("resources/images/file-export-16.png"))); + exportObs.setOnAction(event -> { + exportObservation(obsFile, 0); + }); + menu.getItems().add(exportObs); + } - compteur = 0; - maxColumn = 0; - for ( - int i = 0; i < vocab.length(); i++) { - JSONArray array = (JSONArray) vocab.get(i); - XSSFRow r = sheetOntoVocab.createRow(compteur++); - for (int j = 0; j < array.length(); j++) { - r.createCell(j).setCellValue((String) array.get(j)); - maxColumn = Math.max(maxColumn, j); - } - } - Tools.autoResize(sheetOntoVocab, maxColumn); - XSSFSheet sheetOntohierarchy = Tools.createSheet(book,"onto-hierarchy|" + Tools.removeNonAlphaNumChar(mainApp.getOntologyControler().getCurrentOntology().getName().getValue())); - JSONArray hierarchy = (JSONArray) hierarchyVocab.get("hierarchy"); - compteur = 0; - maxColumn = 0; + if(processFile.getListReplicate().size() > 1) { + Menu importObs = new Menu("Import Observation"); + importObs.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); + importObs.setGraphic(new ImageView(UITools.getImage("resources/images/file-import-16.png"))); - for ( - int x = 0; x < hierarchy.length(); x++) { - XSSFRow r = sheetOntohierarchy.createRow(compteur++); - JSONArray arrayDesc = (JSONArray) hierarchy.get(x); - for (int j = 0; j < arrayDesc.length(); j++) { - r.createCell(j).setCellValue((String) arrayDesc.get(j)); - maxColumn = Math.max(maxColumn, j); - } - } - Tools.autoResize(sheetOntohierarchy, maxColumn); - } - return true; - } - }; - taskExport.setOnSucceeded(workerStateEvent -> { - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle("Export file"); - fileChooser.setInitialFileName(file.getFileName()+".xlsx"); - File fileExport = fileChooser.showSaveDialog(MainApp.primaryStage); - if (fileExport != null) { - try { - FileOutputStream fout = new FileOutputStream(fileExport, false); - book.write(fout); - fout.close(); - } catch (IOException ex) { - MainApp.logger.error(ex.getMessage()); - } - } - }); - new Thread(taskExport).start(); - } - } - }); - menu.getItems().add(exportObs); - - MenuItem importObs = new MenuItem("Import Observation"); - importObs.setGraphic(new ImageView(UITools.getImage("resources/images/file-import-16.png"))); - importObs.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); - importObs.setOnAction(event -> { - ObservationFile file = (ObservationFile) item.getFile(); - File fileImport = getFile(mainApp.primaryStage); - if (fileImport != null) { - MainApp.logger.info("start importing/update file " + fileImport.getName()); - // temp obs file - ObservationFile tempF = null; - if(file.getStepFile() != null) { - Report r = file.getStepFile().checkUpdateObservationFromXLSX(fileImport, file); - if(r.success()) { - file.getStepFile().updateObservationFromXLSX(fileImport, file); - MainApp.getDataControler().refreshTree(); - MainApp.getDataControler().showNodeDetails(file, file); - MainApp.logger.info("import done with sucess"); - } else { - showErrorImportAlert(r.prettyPrintError()); - } - } - if(file.getItineraryFile() != null) { - Report r = file.getItineraryFile().checkUpdateObservationFromXLSX(fileImport, file); - if(r.success()) { - file.getItineraryFile().updateObservationFromXLSX(fileImport, file); - MainApp.getDataControler().refreshTree(); - MainApp.getDataControler().showNodeDetails(file, file); - MainApp.logger.info("import done with sucess"); - } else { - showErrorImportAlert(r.prettyPrintError()); - } - } - } - }); - menu.getItems().add(importObs); + MenuItem importCurRep = new MenuItem("for current replicate"); + importCurRep.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); + GeneralFile finalProcessFile = processFile; + importCurRep.setOnAction(event -> { + importObservation(obsFile, finalProcessFile.getCurrentReplicate().getId()); + }); + MenuItem importAllRep = new MenuItem("for all replicates"); + importAllRep.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); + importAllRep.setOnAction(event -> { + importObservation(obsFile, -1); + }); + + importObs.getItems().add(importCurRep); + importObs.getItems().add(importAllRep); + menu.getItems().add(importObs); + } else { + MenuItem importObs = new MenuItem("Import Observation"); + importObs.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); + importObs.setGraphic(new ImageView(UITools.getImage("resources/images/file-import-16.png"))); + importObs.setOnAction(event -> { + importObservation(obsFile, 0); + }); + menu.getItems().add(importObs); + } MenuItem moveObs = new MenuItem("Move Observation"); moveObs.setGraphic(new ImageView(UITools.getImage("resources/images/move_16.png"))); moveObs.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); menu.getItems().add(moveObs); + GeneralFile finalProcessFile2 = processFile; moveObs.setOnAction(event -> { - ObservationFile obsFile = (ObservationFile) item.getFile(); - GeneralFile processFile = null; - if(obsFile.getStepFile() != null) { - processFile = obsFile.getStepFile().getGeneralFile(); - } else { - processFile = obsFile.getItineraryFile().getProcessFile(); - } Dialog<ButtonType> moveObsDiag = new Dialog<>(); moveObsDiag.getDialogPane().setPrefSize(500, 400); moveObsDiag.initModality(Modality.WINDOW_MODAL); @@ -970,7 +1323,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { treeStep.setCellFactory(factory -> new TextFieldTreeCell<>(){}); treeStep.setShowRoot(false); - processFile.getItinerary().forEach(itiFile -> { + finalProcessFile2.getItinerary().forEach(itiFile -> { TreeItem<GenericFile> ckIti = new TreeItem<>(itiFile); fakeRoot.getChildren().add(ckIti); itiFile.getListStep().forEach(step -> { @@ -1044,7 +1397,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { case STEP: StepFile s = (StepFile) item.getFile(); - + processFile = s.getGeneralFile(); Menu newSubStep = new Menu("New SubStep"); newSubStep.setGraphic(new ImageView(UITools.getImage("resources/images/treeview/step.png"))); newSubStep.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); @@ -1067,7 +1420,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { addProcessSubStepFromCSV.setGraphic(new ImageView(UITools.getImage("resources/images/treeview/step_csv.png"))); addProcessSubStepFromCSV.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); addProcessSubStepFromCSV.setOnAction(event -> { - newStepImport(item.getItineraryFile(), s); + newStepImport(item.getItineraryFile(), s, -1); }); newSubStep.getItems().add(newSubStepFC); @@ -1098,7 +1451,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { addNewStepObservationFromCsv.setGraphic(new ImageView(UITools.getImage("resources/images/treeview/observation_csv.png"))); addNewStepObservationFromCsv.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); addNewStepObservationFromCsv.setOnAction(event -> { - newStepObsImport(s); + newStepObsImport(s, -1); }); newObs.getItems().add(newObsFC); @@ -1210,9 +1563,10 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { moveStep.setDisable(false); moveStep.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); moveStep.setGraphic(new ImageView(UITools.getImage("resources/images/move_16.png"))); + GeneralFile finalProcessFile1 = processFile; moveStep.setOnAction(event -> { StepFile stepFile = (StepFile) item.getFile(); - GeneralFile processFile = stepFile.getGeneralFile(); +// GeneralFile processFile = stepFile.getGeneralFile(); Dialog<ButtonType> moveStepDiag = new Dialog<>(); moveStepDiag.getDialogPane().setPrefSize(500, 400); @@ -1227,7 +1581,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { treeStep.setCellFactory(factory -> new TextFieldTreeCell<>(){}); treeStep.setShowRoot(false); - processFile.getItinerary().forEach(itiFile -> { + finalProcessFile1.getItinerary().forEach(itiFile -> { TreeItem<GenericFile> ckIti = new TreeItem<>(itiFile); fakeRoot.getChildren().add(ckIti); itiFile.getListStep().forEach(step -> { @@ -1268,12 +1622,12 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { if(moveTo instanceof StepFile) { StepFile stepFileFather = (StepFile) moveTo; stepFileFather.addSubStep(stepFile); - for(ItineraryFile iti : processFile.getItinerary()) { + for(ItineraryFile iti : finalProcessFile1.getItinerary()) { if(iti.contains(stepFileFather)) { iti.addStep(stepFile); } } - MainApp.getDataControler().buildProcessTree(processFile); + MainApp.getDataControler().buildProcessTree(finalProcessFile1); } MainApp.getDataControler().selectNode(stepFile); } @@ -1284,154 +1638,59 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { menu.getItems().add(moveStep); - MenuItem exportStep = new MenuItem("Export Step"); - exportStep.setDisable(false); - exportStep.setGraphic(new ImageView(UITools.getImage("resources/images/file-export-16.png"))); - exportStep.setOnAction(event -> { - List<String> choices = new ArrayList<>(); - choices.add("with ontology"); - choices.add("without ontology"); - ChoiceDialog<String> dialog = new ChoiceDialog<>("without ontology", choices); - dialog.setTitle("Export Step"); - dialog.setHeaderText(null); - dialog.setContentText("Export step data "); - dialog.initModality(Modality.WINDOW_MODAL); - dialog.initOwner(MainApp.primaryStage); - Boolean exportOnto = false; - Optional<String> result = dialog.showAndWait(); - - if (result.isPresent() ) { - exportOnto = result.get().equals("with ontology"); - if(exportOnto && mainApp.getOntologyControler().getCurrentOntology() == null) { - Alert noOntology = new Alert(Alert.AlertType.ERROR); - noOntology.setTitle("No ontology loaded"); - noOntology.setHeaderText("Please load an ontology"); - noOntology.setContentText("In order to create an export file, please load the corresponding ontology"); - noOntology.initOwner(MainApp.primaryStage); - noOntology.initModality(Modality.APPLICATION_MODAL); - noOntology.showAndWait(); - } else { - XSSFWorkbook book = new XSSFWorkbook(); - Boolean finalExportOnto = exportOnto; - Task<Boolean> taskExport = new Task<Boolean>() { - @Override - protected Boolean call() throws Exception { - XSSFSheet sheet = Tools.createSheet(book,"step|"+ DigestUtils.md5Hex(s.getNameProperty().getValue())); - - Integer compteur = 0; - Integer maxColumn = 0; - - for (LinkedList<String> line : s.getDataForExcel(true)) { - XSSFRow r = sheet.createRow(compteur++); - Integer compteurCell = 0; - for (String val : line) { - r.createCell(compteurCell++).setCellValue(val); - maxColumn = Math.max(maxColumn, compteurCell); - } - } - - - // composition - for (Map.Entry<CompositionFile, Boolean> entry : s.getCompositionFile().entrySet()) { - XSSFSheet sheetCompo = Tools.createSheet(book,"compo-"+(entry.getValue() ? "input" : "output")+"|"+Tools.removeNonAlphaNumChar(entry.getKey().getCompositionID().getValue().get())); - Integer compteurCompo = 0; - Integer maxColumnCompo = 0; - for (LinkedList<String> line : entry.getKey().getDataForExcel()) { - XSSFRow r = sheetCompo.createRow(compteurCompo++); - Integer compteurCell = 0; - for (String val : line) { - r.createCell(compteurCell++).setCellValue(val); - maxColumnCompo = Math.max(maxColumnCompo, compteurCell); - } - } - Tools.autoResize(sheetCompo, maxColumnCompo); - } - - + if(processFile.getListReplicate().size() > 1) { + Menu exportStep = new Menu("Export Step"); + exportStep.setGraphic(new ImageView(UITools.getImage("resources/images/file-export-16.png"))); - Tools.autoResize(sheet, maxColumn); - - for(ObservationFile obs : s.getObservationFiles()) { - XSSFSheet sheetObs = Tools.createSheet(book,"obs|"+Tools.removeNonAlphaNumChar(obs.getCID().getValue().get())); - - Integer compteurObs = 0; - Integer maxColumnObs = 0; - for (LinkedList<String> line : obs.getDataForExcel()) { - XSSFRow r = sheetObs.createRow(compteurObs++); - Integer compteurCell = 0; - for (String val : line) { - r.createCell(compteurCell++).setCellValue(val); - maxColumnObs = Math.max(maxColumnObs, compteurCell); - } - } - Tools.autoResize(sheetObs, maxColumnObs); - } + MenuItem exportCurRep = new MenuItem("for current replicate"); + GeneralFile finalProcessFile = processFile; + exportCurRep.setOnAction(event -> { + exportStepFile(s, finalProcessFile.getCurrentReplicate().getId()); + }); + MenuItem exportAllRep = new MenuItem("for all replicates"); + exportAllRep.setOnAction(event -> { + exportStepFile(s, -1); + }); - if(finalExportOnto) { - - JSONObject hierarchyVocab = mainApp.getOntologyControler().getHierarchyVocabJSON(); - // Récupération de l'ontology au format JSON - XSSFSheet sheetOntoVocab = Tools.createSheet(book,"onto-vocab|" + Tools.removeNonAlphaNumChar(mainApp.getOntologyControler().getCurrentOntology().getName().getValue())); - JSONArray vocab = (JSONArray) hierarchyVocab.get("vocabulary"); - - compteur = 0; - maxColumn = 0; - for (int i = 0; i < vocab.length(); i++) { - JSONArray array = (JSONArray) vocab.get(i); - XSSFRow r = sheetOntoVocab.createRow(compteur++); - for (int j = 0; j < array.length(); j++) { - r.createCell(j).setCellValue((String) array.get(j)); - maxColumn = Math.max(maxColumn, j); - } - } - Tools.autoResize(sheetOntoVocab, maxColumn); + exportStep.getItems().add(exportCurRep); + exportStep.getItems().add(exportAllRep); + menu.getItems().add(exportStep); + } else { + MenuItem exportStep = new MenuItem("Export Step"); + exportStep.setGraphic(new ImageView(UITools.getImage("resources/images/file-export-16.png"))); + exportStep.setOnAction(event -> { + exportStepFile(s, 0); + }); + menu.getItems().add(exportStep); + } - XSSFSheet sheetOntohierarchy = Tools.createSheet(book,"onto-hierarchy|" + Tools.removeNonAlphaNumChar(mainApp.getOntologyControler().getCurrentOntology().getName().getValue())); - JSONArray hierarchy = (JSONArray) hierarchyVocab.get("hierarchy"); + if(processFile.getListReplicate().size() > 1) { + Menu importStep = new Menu("Import Step"); + importStep.setGraphic(new ImageView(UITools.getImage("resources/images/file-import-16.png"))); - compteur = 0; - maxColumn = 0; + MenuItem importCurRep = new MenuItem("for current replicate"); + GeneralFile finalProcessFile = processFile; + importCurRep.setOnAction(event -> { + stepImport(s, false, finalProcessFile.getCurrentReplicate().getId()); + }); + MenuItem importAllRep = new MenuItem("for all replicates"); + importAllRep.setOnAction(event -> { + stepImport(s, false, -1); + }); - for (int x = 0; x < hierarchy.length(); x++) { - XSSFRow r = sheetOntohierarchy.createRow(compteur++); - JSONArray arrayDesc = (JSONArray) hierarchy.get(x); - for (int j = 0; j < arrayDesc.length(); j++) { - r.createCell(j).setCellValue((String) arrayDesc.get(j)); - maxColumn = Math.max(maxColumn, j); - } - } - Tools.autoResize(sheetOntohierarchy, maxColumn); - } - return true; - } - }; - taskExport.setOnSucceeded(workerStateEvent -> { - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle("Export file"); - fileChooser.setInitialFileName(s.getNameProperty().getValue()+".xlsx"); - File fileExport = fileChooser.showSaveDialog(MainApp.primaryStage); - if (fileExport != null) { - try { - FileOutputStream fout = new FileOutputStream(fileExport, false); - book.write(fout); - fout.close(); - } catch (IOException ex) { - MainApp.logger.error(ex.getMessage()); - } - } - }); - new Thread(taskExport).start(); - } - } - }); - menu.getItems().add(exportStep); + importStep.getItems().add(importCurRep); + importStep.getItems().add(importAllRep); + menu.getItems().add(importStep); + } else { + MenuItem importStep = new MenuItem("Export Step"); + importStep.setGraphic(new ImageView(UITools.getImage("resources/images/file-export-16.png"))); + importStep.setOnAction(event -> { + stepImport(s, false, 0); + }); + menu.getItems().add(importStep); + } - MenuItem importStep = new MenuItem("Import Step"); - importStep.setGraphic(new ImageView(UITools.getImage("resources/images/file-import-16.png"))); - importStep.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); - importStep.setOnAction(event -> stepImport((StepFile) item.getFile(), false)); - menu.getItems().add(importStep); MenuItem deleteStepButton = new MenuItem("Delete Step"); deleteStepButton.setGraphic(new ImageView(UITools.getImage("resources/images/del_16.png"))); @@ -1537,7 +1796,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { addProcessStepFromCSV.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); addProcessStepFromCSV.setOnAction(event -> { ItineraryFile iti = (ItineraryFile) item.getFile(); - newStepImport(iti, null); + newStepImport(iti, null, -1); }); newStep.getItems().add(addProcessStep); @@ -1573,7 +1832,7 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { addNewItineraryObservationFromCsv.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); addNewItineraryObservationFromCsv.setOnAction(event -> { ItineraryFile iti = (ItineraryFile) item.getFile(); - newItineraryObsImport(iti); + newItineraryObsImport(iti, -1); }); newObsIti.getItems().add(newObsItiFC); @@ -1593,136 +1852,4 @@ public class DataTreeCell extends TextFieldTreeCell<DataNode> { this.setContextMenu(menu); } } - - private static void stepImport(StepFile file, boolean isNewStep) { - File fileImport = getFile(MainApp.primaryStage); - if (fileImport != null) { - MainApp.logger.info("start importing file " + fileImport.getName()); - ImportReport importReport = file.realPreConst(fileImport, isNewStep); - if(importReport.success()) { - - // validation de l'import par l'utilisateur - Dialog<ButtonType> validateImport = new Dialog(); - validateImport.setTitle("import validation"); - validateImport.initOwner(MainApp.primaryStage); - validateImport.initModality(Modality.WINDOW_MODAL); - ButtonType importButtonType = new ButtonType("Import", ButtonBar.ButtonData.OK_DONE); - validateImport.getDialogPane().getButtonTypes().addAll(importButtonType, ButtonType.CANCEL); - - GridPane paneImport = new GridPane(); - paneImport.setHgap(20); - paneImport.setVgap(20); - - Integer comptLine = 0; - Text stepText = new Text(file.getNameProperty().getValue()); - Text sepa = new Text(" : "); - paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/step.png")), 0, comptLine); - paneImport.add(stepText, 1, comptLine); - paneImport.add(sepa, 2, comptLine); - paneImport.add(new ImageView(UITools.getImage("resources/images/update_30.png")), 3, comptLine); - - comptLine++; - - - for (ObservationFile obsF : file.getObservationFiles()) { - Text obsText = new Text(obsF.getCID().getValue().get()); - Text sepa2 = new Text(" : "); - paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/observation.png")), 0, comptLine); - paneImport.add(obsText, 1, comptLine); - paneImport.add(sepa2, 2, comptLine); - if (importReport.getObsMapping().containsValue(obsF)) { - paneImport.add(new ImageView(UITools.getImage("resources/images/update_30.png")), 3, comptLine); - } else { - paneImport.add(new ImageView(UITools.getImage("resources/images/del_30.png")), 3, comptLine); - } - comptLine++; - } - - for(XSSFSheet oo : importReport.getObsMapping().keySet()) { - if(importReport.getObsMapping().get(oo) == null) { // new obs - Text obsText = new Text(oo.getSheetName()); - Text sepa2 = new Text(" : "); - paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/observation.png")), 0, comptLine); - paneImport.add(obsText, 1, comptLine); - paneImport.add(sepa2, 2, comptLine); - paneImport.add(new ImageView(UITools.getImage("resources/images/add_30.png")), 3, comptLine); - comptLine++; - } - } - - for (CompositionFile compoF : file.getCompositionFile().keySet()) { - Text compoText = new Text(compoF.getCompositionID().getValue().get()); - Text sepa2 = new Text(" : "); - paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/composition.png")), 0, comptLine); - paneImport.add(compoText, 1, comptLine); - paneImport.add(sepa2, 2, comptLine); - if(importReport.getCompoMapping().values().stream().map(org.apache.commons.lang3.tuple.Pair::getLeft).noneMatch(c -> c.equals(compoF))) { - paneImport.add(new ImageView(UITools.getImage("resources/images/del_30.png")), 3, comptLine); - } else { - paneImport.add(new ImageView(UITools.getImage("resources/images/update_30.png")), 3, comptLine); - } - comptLine++; - } - - for(XSSFSheet oo : importReport.getCompoMapping().keySet()) { - if(importReport.getCompoMapping().get(oo).getLeft() == null) { // new Compo - Text compoText = new Text(oo.getSheetName()); - Text sepa2 = new Text(" : "); - paneImport.add(new ImageView(UITools.getImage("resources/images/treeview/composition.png")), 0, comptLine); - paneImport.add(compoText, 1, comptLine); - paneImport.add(sepa2, 2, comptLine); - paneImport.add(new ImageView(UITools.getImage("resources/images/add_30.png")), 3, comptLine); - comptLine++; - } - } - - validateImport.getDialogPane().setContent(paneImport); - Optional<ButtonType> result = Optional.empty(); - if(!isNewStep) { - result = validateImport.showAndWait(); - } - if (isNewStep || result.isPresent() && result.get() == importButtonType) { - // l'utilisateur valide la la mise à jour - Report report = file.constructDataFromImport(fileImport, isNewStep); - handleInterfaceUpdate(file.getGeneralFile(), report.success(), report.toString()); - MainApp.getDataControler().selectNode(file); - } - - } else { - showErrorImportAlert(importReport.toString()); - } - } else { - } - } - - private static void handleInterfaceUpdate(GeneralFile file, boolean reportBoolean, String reportString) { - if(reportBoolean) { - MainApp.getDataControler().buildProcessTree(file); - showOkImportAlert(); - } else { - showErrorImportAlert(reportString); - } - } - - private static void showErrorImportAlert(String report) { - Alert errorImport = new Alert(Alert.AlertType.ERROR); - errorImport.setTitle("Import error"); - errorImport.setContentText(report); - errorImport.initModality(Modality.APPLICATION_MODAL); - errorImport.initOwner(MainApp.primaryStage); - errorImport.showAndWait(); - } - - private static void showOkImportAlert() { - Alert okImport = new Alert(Alert.AlertType.INFORMATION); - okImport.setGraphic(new ImageView(UITools.getImage("resources/images/valid.png"))); - okImport.setHeaderText(null); - okImport.setTitle("Successful import"); - okImport.setContentText("Successful import"); - okImport.initModality(Modality.APPLICATION_MODAL); - okImport.initOwner(MainApp.primaryStage); - okImport.showAndWait(); - } - - } diff --git a/src/main/java/fr/inra/po2vocabmanager/utils/UITools.java b/src/main/java/fr/inra/po2vocabmanager/utils/UITools.java index d4ed78b183fd82f9b0180e7da7ea8914797c7031..a087e37f7f999465d4ea4ad978df17a7e26e4dae 100644 --- a/src/main/java/fr/inra/po2vocabmanager/utils/UITools.java +++ b/src/main/java/fr/inra/po2vocabmanager/utils/UITools.java @@ -20,9 +20,7 @@ package fr.inra.po2vocabmanager.utils; import fr.inra.po2vocabmanager.MainApp; import fr.inrae.po2engine.externalTools.CloudConnector; -import fr.inrae.po2engine.model.ComplexField; -import fr.inrae.po2engine.model.Ontology; -import fr.inrae.po2engine.model.VocabConcept; +import fr.inrae.po2engine.model.*; import fr.inrae.po2engine.model.dataModel.KeyWords; import fr.inrae.po2engine.model.partModel.ComplexTable; import fr.inrae.po2engine.model.partModel.GenericTable; @@ -39,10 +37,12 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.MapChangeListener; import javafx.collections.ObservableList; +import javafx.collections.ObservableMap; import javafx.collections.transformation.FilteredList; import javafx.concurrent.Task; import javafx.event.ActionEvent; @@ -562,13 +562,26 @@ public class UITools { tField.styleProperty().bind(Bindings.when(cField.stateProperty().isEqualTo(FieldState.WARNING)).then("-fx-border-color: orange;").otherwise(Bindings.when(cField.stateProperty().isEqualTo(FieldState.ERROR)).then("-fx-border-color: red;").otherwise(""))); } public static void simpleBindValue(ComplexField cField, TextField tField) { - cField.getValue().unbind(); + cField.unbindReplicatesValues(); tField.setText(cField.getValue().getValue()); cField.getValue().bind(tField.textProperty()); tField.styleProperty().unbind(); tField.styleProperty().bind(Bindings.when(cField.stateProperty().isEqualTo(FieldState.WARNING)).then("-fx-border-color: orange;").otherwise(Bindings.when(cField.stateProperty().isEqualTo(FieldState.ERROR)).then("-fx-border-color: red;").otherwise(""))); } + public static void simpleBindValue(ComplexField cField, Replicate replicate, TextField tField) { + cField.unbindReplicatesValues(); + int replicateID = replicate != null ? replicate.getId() : 0; + tField.setText(cField.getValueWithReplicate(replicateID).getValue()); + cField.getValueWithReplicate(replicateID).bind(tField.textProperty()); + tField.styleProperty().unbind(); + if(replicate == null) { + tField.styleProperty().bind(Bindings.when(cField.stateProperty().isEqualTo(FieldState.WARNING)).then("-fx-border-color: orange;").otherwise(Bindings.when(cField.stateProperty().isEqualTo(FieldState.ERROR)).then("-fx-border-color: red;").otherwise(""))); + } else { + tField.styleProperty().bind(Bindings.when(cField.stateProperty().isEqualTo(FieldState.WARNING)).then("-fx-border-color: orange;").otherwise(Bindings.when(cField.stateProperty().isEqualTo(FieldState.ERROR)).then("-fx-border-color: red;").otherwise("-fx-border-color: DarkSlateBlue;"))); + } + } + public static void simpleBindValue(ComplexField cField, TextArea tField) { cField.getValue().unbind(); tField.setText(cField.getValue().getValue()); @@ -577,6 +590,68 @@ public class UITools { tField.styleProperty().bind(Bindings.when(cField.stateProperty().isEqualTo(FieldState.WARNING)).then("-fx-border-color: orange;").otherwise(Bindings.when(cField.stateProperty().isEqualTo(FieldState.ERROR)).then("-fx-border-color: red;").otherwise(""))); } + public static void bindComboBoxAgent(ObservableMap<Integer, ObjectProperty<HashMap<KeyWords, ComplexField>>> agentProp, ObservableList<HashMap<KeyWords, ComplexField>> list, Replicate replicate, ComboBox<HashMap<KeyWords, ComplexField>> comboField) { + int replicateID = replicate != null ? replicate.getId() : 0; + comboField.setConverter(new StringConverter<HashMap<KeyWords, ComplexField>>() { + @Override + public String toString(HashMap<KeyWords, ComplexField> keyWordsComplexFieldHashMap) { + if (keyWordsComplexFieldHashMap == null){ + return null; + } else { + return Tools.agentToString(keyWordsComplexFieldHashMap); + } + } + + @Override + public HashMap<KeyWords, ComplexField> fromString(String s) { + HashMap<KeyWords, ComplexField> val = list.stream().filter(keyWordsComplexFieldHashMap -> { + return s.equalsIgnoreCase(Tools.agentToString(keyWordsComplexFieldHashMap)); + }).findFirst().orElse(null); + return val; + } + }); + comboField.setCellFactory(p -> { + return new ListCell<HashMap<KeyWords, ComplexField>>() { + + @Override + protected void updateItem(HashMap<KeyWords, ComplexField> item, boolean empty) { + super.updateItem(item, empty); + if (item == null || empty) { + setGraphic(null); + setText(""); + } else { + setGraphic(null); + setText(Tools.agentToString(item)); + } + } + }; + }); + + comboField.setValue(null); + ObservableList<HashMap<KeyWords, ComplexField>> listCopy = FXCollections.observableArrayList(); + listCopy.add(Tools.createFakeAgentFromString("")); + + agentProp.computeIfAbsent(replicateID, k -> { + SimpleObjectProperty sop = new SimpleObjectProperty<>(); + sop.addListener(Data.changeListener); + return sop; + } ); + + if(!list.contains(agentProp.get(replicateID).getValue())) { + if(!Tools.agentToString(agentProp.get(replicateID).getValue()).isBlank()) { + listCopy.add(agentProp.get(replicateID).getValue()); + } + } + listCopy.addAll(list); + comboField.setItems(listCopy); + comboField.setValue(agentProp.get(replicateID).getValue()); + agentProp.get(replicateID).bind(comboField.valueProperty()); + + comboField.styleProperty().unbind(); + BooleanBinding containAgent = Bindings.createBooleanBinding( () -> list.contains( agentProp.get(replicateID).getValue() ) || Tools.agentToString(agentProp.get(replicateID).getValue()).isEmpty(), list, agentProp ); + comboField.styleProperty().bind(Bindings.when(containAgent).then("-fx-border-color: DarkSlateBlue;").otherwise("-fx-border-color: red;")); + } + public static void bindComboBoxAgent(ObjectProperty<HashMap<KeyWords, ComplexField>> agentProp, ObservableList<HashMap<KeyWords, ComplexField>> list, ComboBox<HashMap<KeyWords, ComplexField>> comboField) { comboField.setConverter(new StringConverter<HashMap<KeyWords, ComplexField>>() { @Override @@ -631,18 +706,22 @@ public class UITools { comboField.styleProperty().bind(Bindings.when(containAgent).then("").otherwise("-fx-border-color: red;")); } - public static void bindTable(GenericTable table, TableView tableView) { + public static void bindTable(GenericTable table, Replicate replicate, TableView tableView) { if(table instanceof SimpleTable) { - bindSimpleTable((SimpleTable) table, tableView); + bindSimpleTable((SimpleTable) table, replicate, tableView); } if(table instanceof ComplexTable) { - bindComplexTable((ComplexTable) table, tableView); + bindComplexTable((ComplexTable) table, replicate, tableView); } } - public static void bindComplexTable(ComplexTable complexTable, TableView tableView) { + public static void bindComplexTable(ComplexTable complexTable, Replicate replicate, TableView tableView) { + ChangeListener changeListener = (observable, oldValue, newValue) -> { + complexTable.getData().setModified(true); + }; tableView.getColumns().clear(); tableView.setTableMenuButtonVisible(true); + int replicateID = replicate != null ? replicate.getId() : 0; Button addLine = new Button("New line "); addLine.disableProperty().bind(tableView.editableProperty().not()); @@ -688,7 +767,7 @@ public class UITools { colAdd.setGraphic(new ImageView(UITools.getImage("resources/images/add_col-16.png"))); colAdd.setOnAction(actionEvent -> { complexTable.addColumn(-1); - UITools.bindComplexTable(complexTable, tableView); + UITools.bindComplexTable(complexTable, replicate, tableView); }); colAdd.disableProperty().bind(tableView.editableProperty().not()); colAction.setGraphic(colAdd); @@ -738,7 +817,7 @@ public class UITools { }; }); - for(ComplexField c : complexTable.getTableHeader()) { + for(ComplexField c : complexTable.getTableHeader()) { if(!c.equals(ComplexTable.numC) && !c.equals(ComplexTable.actionC)) { TableColumn<Map<ComplexField, ComplexField>, ComplexField> colType = new TableColumn(); tableView.getColumns().add(colType); @@ -748,7 +827,7 @@ public class UITools { delete.setOnAction(event -> { complexTable.deleteColumn(c); complexTable.getData().setModified(true); - UITools.bindComplexTable(complexTable, tableView); + UITools.bindComplexTable(complexTable, replicate, tableView); }); Button edit = new Button(""); edit.disableProperty().bind(tableView.editableProperty().not()); @@ -938,10 +1017,10 @@ public class UITools { TextField text = new TextField(); text.editableProperty().bind(tableView.editableProperty()); text.styleProperty().bind(item.styleProperty()); - item.getValue().unbind(); - text.setText(item.getValue().get()); - item.getValue().bind(text.textProperty()); - + item.unbindReplicatesValues(); + text.setText(item.getValueWithReplicate(replicateID).get()); + item.getValueWithReplicate(replicateID).bind(text.textProperty()); + item.setValuesListener(changeListener); text.setOnMouseClicked(event -> { if(text.isEditable() && event.getClickCount() == 2) { @@ -1002,9 +1081,6 @@ public class UITools { } }); setGraphic(text); - item.getValue().addListener((observable, oldValue, newValue) -> { - complexTable.getData().setModified(true); - }); } } }; @@ -1020,7 +1096,11 @@ public class UITools { tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); } - public static void bindSimpleTable(SimpleTable simpleTable, TableView tableView) { + public static void bindSimpleTable(SimpleTable simpleTable, Replicate replicate, TableView tableView) { + ChangeListener changeListener = (observable, oldValue, newValue) -> { + simpleTable.getData().setModified(true); + }; + tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); tableView.setTableMenuButtonVisible(true); Button addLine = new Button("New line "); @@ -1150,10 +1230,7 @@ public class UITools { UITools.addAutoComplete(combo, item.getListConstraint()); // UITools.addPopOver(combo, Ontology.Attribut); item.getValue().bind(combo.textProperty()); - - item.getValue().addListener((observable, oldValue, newValue) -> { - simpleTable.getData().setModified(true); - }); + item.setValuesListener(changeListener); combo.styleProperty().bind(item.styleProperty()); setGraphic(combo); } else { @@ -1319,10 +1396,7 @@ public class UITools { UITools.addAutoComplete(combo, item.getListConstraint()); // UITools.addPopOver(combo, Ontology.Component); item.getValue().bind(combo.textProperty()); - - item.getValue().addListener((observable, oldValue, newValue) -> { - simpleTable.getData().setModified(true); - }); + item.setValuesListener(changeListener); combo.styleProperty().bind(item.styleProperty()); setGraphic(combo); } else { @@ -1356,10 +1430,11 @@ public class UITools { TextField text = new TextField(); text.editableProperty().bind(tableView.editableProperty()); text.styleProperty().bind(item.styleProperty()); - item.getValue().unbind(); - text.setText(item.getValue().get()); - item.getValue().bind(text.textProperty()); - + item.unbindReplicatesValues(); + int replicateID = replicate != null ? replicate.getId() : 0; + text.setText(item.getValueWithReplicate(replicateID).getValue()); + item.getValueWithReplicate(replicateID).bind(text.textProperty()); + item.setValuesListener(changeListener); text.setOnMouseClicked(event -> { if (text.isEditable() && event.getClickCount() == 2) { @@ -1421,13 +1496,10 @@ public class UITools { }); setGraphic(text); - item.getValue().addListener((observable, oldValue, newValue) -> { - simpleTable.getData().setModified(true); - }); } else { TextField combo = new TextField(); combo.maxWidthProperty().bind(widthProperty()); - item.getValue().unbind(); + item.unbindReplicatesValues(); if (item.isEditable()) { combo.editableProperty().bind(tableView.editableProperty()); } else { @@ -1436,17 +1508,12 @@ public class UITools { combo.disableProperty().bind(combo.editableProperty().not()); combo.setText(item.getValue().get()); UITools.addAutoComplete(combo, item.getListConstraint()); -// if(item.getConceptConstraint() != null && item.getConceptConstraint().size() > 0) { -// UITools.addPopOver(combo, item.getConceptConstraint().toArray(new String[0])); -// } - item.getValue().bind(combo.textProperty()); + int replicateID = replicate != null ? replicate.getId() : 0; + item.getValueWithReplicate(replicateID).bind(combo.textProperty()); combo.styleProperty().bind(item.styleProperty()); setGraphic(combo); - item.getValue().addListener((observable, oldValue, newValue) -> { - simpleTable.getData().setModified(true); - }); - + item.setValuesListener(changeListener); } } } @@ -1470,11 +1537,8 @@ public class UITools { item.getValue().unbind(); text.setText(item.getValue().get()); item.getValue().bind(text.textProperty()); - + item.setValuesListener(changeListener); setGraphic(text); - item.getValue().addListener((observable, oldValue, newValue) -> { - simpleTable.getData().setModified(true); - }); } } }; diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/DataOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/DataOverviewController.java index 8f86f5dc0f1653beb59c14816715c02f9dc35ad1..66b40f84f1f72d09a2767911d4969da03350160a 100644 --- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/DataOverviewController.java +++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/DataOverviewController.java @@ -287,13 +287,13 @@ public class DataOverviewController { case STEP: newNode.getFile().setSelectedInTree(true); stepControler.setMainApp(this.mainApp); - stepControler.showNodeDetails(newNode); + stepControler.showNodeDetails(newNode, newNode.getItineraryFile().getProcessFile().getCurrentReplicate()); infoPane.getChildren().add(stepOverview); break; case OBSERVATION: newNode.getFile().setSelectedInTree(true); observationControler.setMainApp(this.mainApp); - observationControler.showNodeDetails(newNode); + observationControler.showNodeDetails(newNode, newNode.getItineraryFile().getProcessFile().getCurrentReplicate()); infoPane.getChildren().add(observationOverview); break; case ITINERARY: @@ -521,6 +521,12 @@ public class DataOverviewController { } listDataNode.get(file).add(node); node.setFile(file); + if(node.getType().equals(DataNodeType.ITINERARY)) { + node.setItineraryFile((ItineraryFile) file); + } + if(father != null && father.getItineraryFile() != null) { + node.setItineraryFile(father.getItineraryFile()); + } node.nameProperty().bindBidirectional(file.getNameProperty()); if(father != null) { father.addSubNode(node); diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/MaterialMethodLinkOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/MaterialMethodLinkOverviewController.java index 09517f7781db13f307ee939a620271d5aa977b89..ba2fecc1f2d813f382be353ab4a5538fbdeae449 100644 --- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/MaterialMethodLinkOverviewController.java +++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/MaterialMethodLinkOverviewController.java @@ -325,7 +325,7 @@ public class MaterialMethodLinkOverviewController { TableView tableConsign = new TableView(); tableConsign.editableProperty().bind(mainApp.getEditProperty()); - UITools.bindSimpleTable(newValue.getConsignPart().getDataTable(), tableConsign); + UITools.bindSimpleTable(newValue.getConsignPart().getDataTable(), null, tableConsign); grid.add(tableConsign, 0, 1); GridPane.setFillWidth(tableConsign, true); grid.getColumnConstraints().addAll(c); diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/MaterialMethodOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/MaterialMethodOverviewController.java index ba314ab12135f6c033554e48c103b4cec12e9bbe..7d53888f193f3838b8cce75bfe151071feb5a1e1 100644 --- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/MaterialMethodOverviewController.java +++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/MaterialMethodOverviewController.java @@ -318,7 +318,7 @@ public class MaterialMethodOverviewController { // addLine.setOnMouseClicked(event -> newValue.addLine()); TableView tableView = new TableView(); tableView.editableProperty().bind(mainApp.getEditProperty()); - UITools.bindSimpleTable(newValue.getDataTable(), tableView); + UITools.bindSimpleTable(newValue.getDataTable(), null, tableView); // newValue.bindData(tableView); // grid.add(tableView, 0, 0); // grid.add(addLine, 0, 1); diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/ObservationOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/ObservationOverviewController.java index 4f593653190f24cbadea601896093ae2d51ac42f..2409e55faf685b7e6f5bad4644a268d39d18ecb1 100644 --- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/ObservationOverviewController.java +++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/ObservationOverviewController.java @@ -22,6 +22,7 @@ import fr.inra.po2vocabmanager.MainApp; import fr.inra.po2vocabmanager.model.DataNode; import fr.inra.po2vocabmanager.utils.UITools; import fr.inrae.po2engine.model.ComplexField; +import fr.inrae.po2engine.model.Replicate; import fr.inrae.po2engine.model.dataModel.CompositionFile; import fr.inrae.po2engine.model.dataModel.KeyWords; import fr.inrae.po2engine.model.dataModel.ObservationFile; @@ -135,22 +136,26 @@ public class ObservationOverviewController { } - public void showNodeDetails(DataNode node) { + public void showNodeDetails(DataNode node, Replicate replicate) { ToggleGroup groupFOI = new ToggleGroup(); - file = (ObservationFile) node.getFile(); file.checkValue(); + if(replicate != null) { + observationPanel.setText("Observation (replicate : " + replicate.getName() + ")"); + } else { + observationPanel.setText("Observation"); + } UITools.simpleBindValue(file.getCName(), observationType); UITools.simpleBindValue(file.getCID(), observationName); - UITools.simpleBindValue(file.getCDate(), observationDate); - UITools.simpleBindValue(file.getCDuree(), observationTimeD); - UITools.simpleBindValue(file.getCHeure(), observationTime); + UITools.simpleBindValue(file.getCDate(),replicate, observationDate); + UITools.simpleBindValue(file.getCDuree(),replicate, observationTimeD); + UITools.simpleBindValue(file.getCHeure(),replicate,observationTime); UITools.simpleBindValue(file.getCDescrition(), observationDesc); UITools.simpleBindValue(file.getCScale(), observationScale); - UITools.bindComboBoxAgent(file.getAgentProperty(),file.getData().getProjectFile().getListAgent(), orgAgent); + UITools.bindComboBoxAgent(file.getAgentsMap(),file.getData().getProjectFile().getListAgent(), replicate, orgAgent); UITools.addAutoComplete(observationScale, file.getCScale().getListConstraint()); @@ -165,7 +170,7 @@ public class ObservationOverviewController { listItem.add(new MutablePair<>("Step - " + file.getStepFile().getId(), new MutablePair<>("step", new SimpleBooleanProperty(false)))); for (CompositionFile comp : file.getStepFile().getCompositionFile().keySet()) { - String inout = file.getStepFile().getCompositionFile().get(comp) ? "Input" : "Output"; + String inout = Boolean.TRUE.equals(file.getStepFile().getCompositionFile().get(comp)) ? "Input" : "Output"; listItem.add(new MutablePair<>(inout+" - " + comp.getHeaderPart().getCompositionID() , new MutablePair<>(comp.getFileName(), new SimpleBooleanProperty(false)))); } @@ -208,36 +213,6 @@ public class ObservationOverviewController { return cell; }); - Label titlePane = new Label("Observation"); - titlePane.setAlignment(Pos.CENTER_LEFT); -// Button exportExcel = new Button(null, new ImageView(UITools.getImage("resources/images/file-export-16.png"))); -// exportExcel.setTooltip(new Tooltip("Export Observation")); -// exportExcel.setOnMouseClicked(event -> { -// // Export des données. -// -// }); - Button importExcel = new Button(null, new ImageView(UITools.getImage("resources/images/file-import-16.png"))); - importExcel.setTooltip(new Tooltip("Export Observation")); - importExcel.setOnMouseClicked(event -> { - - }); - - - - - importExcel.disableProperty().bind(this.mainApp.getEditProperty().not()); - - Label emptyLabelTitle = new Label(" "); - emptyLabelTitle.setMaxWidth(Double.MAX_VALUE); - HBox bbT = new HBox(); - bbT.setAlignment(Pos.CENTER_RIGHT); - bbT.getChildren().addAll(titlePane,emptyLabelTitle/*, exportExcel, importExcel*/); - HBox.setHgrow(emptyLabelTitle, Priority.ALWAYS); - bbT.setPadding(new Insets(0,3,0,0)); - bbT.minWidthProperty().bind(observationPanel.widthProperty().subtract(25)); - - observationPanel.setGraphic(bbT); - boxContent.getChildren().retainAll(observationPanel); TitledPane matMetPane = new TitledPane(); @@ -268,7 +243,7 @@ public class ObservationOverviewController { TableView table = new TableView(); table.setMinHeight(200); table.editableProperty().bind(this.mainApp.getEditProperty()); - UITools.bindTable(tablePart.getTable(), table); + UITools.bindTable(tablePart.getTable(), replicate, table); tablePane.setContent(table); boxContent.getChildren().add(tablePane); @@ -304,7 +279,7 @@ public class ObservationOverviewController { Optional<ButtonType> res = a.showAndWait(); if(res.get() == ButtonType.OK) { file.removeTablePart(tablePart); - showNodeDetails(node); + showNodeDetails(node, replicate); } }); diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/ProcessOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/ProcessOverviewController.java index fb9108daa337a9e7ef519bb4d648a76adb3a096c..530d629bfb99c63993fdaffcfc60326bd4dbd391 100644 --- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/ProcessOverviewController.java +++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/ProcessOverviewController.java @@ -22,12 +22,15 @@ import fr.inra.po2vocabmanager.MainApp; import fr.inra.po2vocabmanager.model.DataNode; import fr.inra.po2vocabmanager.utils.UITools; import fr.inra.po2vocabmanager.utils.XCell; +import fr.inrae.po2engine.model.Replicate; import fr.inrae.po2engine.model.dataModel.GeneralFile; import fr.inrae.po2engine.model.dataModel.StepFile; import javafx.animation.TranslateTransition; import javafx.beans.binding.Bindings; +import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; +import javafx.beans.value.ChangeListener; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; @@ -44,6 +47,7 @@ import org.controlsfx.control.textfield.AutoCompletionBinding; import java.util.ArrayList; import java.util.Arrays; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; public class ProcessOverviewController { @@ -59,6 +63,8 @@ public class ProcessOverviewController { @FXML TitledPane stepAvailable; @FXML + TitledPane replicatesPane; + @FXML TextArea description; @FXML Label linksLabel; @@ -70,6 +76,12 @@ public class ProcessOverviewController { TreeTableColumn<StepFile, String> colIti; TreeTableColumn<StepFile, StepFile> colDel; + TableView<Replicate> replicateTable; + TableColumn<Replicate, Replicate> colRepName; + TableColumn<Replicate, Integer> colRepId; + TableColumn<Replicate, Replicate> colRepDesc; + TableColumn<Replicate, Replicate> colRepDel; + TreeItem<StepFile> rootTree; @@ -89,7 +101,6 @@ public class ProcessOverviewController { endDate.editableProperty().bind(mainApp.getEditProperty()); processType.editableProperty().bind(mainApp.getEditProperty()); description.editableProperty().bind(mainApp.getEditProperty()); - } private TranslateTransition createTranslateTransition(final Shape group) { @@ -135,6 +146,9 @@ public class ProcessOverviewController { generalFile.unbind(); generalFile.checkValue(); + ChangeListener changeListener = (observable, oldValue, newValue) -> { + generalFile.getData().setModified(true); + }; UITools.simpleBindValue(generalFile.getCTitle(), processTitle); UITools.simpleBindValue(generalFile.getCStartDate(), startDate); @@ -145,7 +159,7 @@ public class ProcessOverviewController { UITools.simpleBindValue(generalFile.getCDescription(), description); listAutoCompletion.add(UITools.addAutoComplete(processType, generalFile.getCType().getListConstraint())); - + generalFile.getListReplicate().forEach(r -> r.setValuesListener(changeListener)); ArrayList<String> ls = generalFile.getExternalLinks(); String[] arrayLink = new String [ls.size()]; @@ -248,6 +262,109 @@ public class ProcessOverviewController { stepAvailable.setContent(treeTableView); + replicateTable = new TableView<>(); + replicateTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); + replicateTable.editableProperty().bind(mainApp.getEditProperty()); + colRepId = new TableColumn<>("id"); + colRepId.setCellValueFactory(cellData -> new SimpleIntegerProperty(cellData.getValue().getId()).asObject()); + colRepId.setMaxWidth(60); + colRepId.setMinWidth(60); + colRepId.setPrefWidth(60); + + colRepName = new TableColumn<>("Name"); + colRepName.setCellValueFactory(cellData -> new SimpleObjectProperty<>(cellData.getValue())); + colRepName.setCellFactory(param -> { + return new TableCell<Replicate, Replicate>() { + @Override + public void updateItem(Replicate item, boolean empty) { + super.updateItem(item, empty); + TextField text = new TextField(); + if (item != null && !empty) { + text.editableProperty().bind(replicateTable.editableProperty()); + item.nameProperty().unbind(); + text.setText(item.getName()); + item.nameProperty().bind(text.textProperty()); + setGraphic(text); + } else { + setText(null); + setStyle(null); + setGraphic(null); + } + } + }; + }); + + colRepDesc = new TableColumn<>("Description"); + colRepDesc.setCellValueFactory(cellData -> new SimpleObjectProperty<>(cellData.getValue())); + colRepDesc.setCellFactory(param -> { + return new TableCell<Replicate, Replicate>() { + @Override + public void updateItem(Replicate item, boolean empty) { + super.updateItem(item, empty); + TextField text = new TextField(); + if (item != null && !empty) { + text.editableProperty().bind(replicateTable.editableProperty()); + item.descriptionProperty().unbind(); + text.setText(item.getDescription()); + item.descriptionProperty().bind(text.textProperty()); + setGraphic(text); + } else { + setText(null); + setStyle(null); + setGraphic(null); + } + } + }; + }); + + colRepDel = new TableColumn<>(); + colRepDel.setCellValueFactory(cellData -> new SimpleObjectProperty<>(cellData.getValue())); + colRepDel.setMaxWidth(60); + colRepDel.setMinWidth(60); + colRepDel.setPrefWidth(60); + AtomicReference<GeneralFile> currentGF = new AtomicReference<>(generalFile); + + colRepDel.setCellFactory(cell -> { + + return new TableCell<>(){ + @Override + protected void updateItem(Replicate replicate, boolean b) { + super.updateItem(replicate, b); + + if(replicate == null || b) { + setGraphic(null); + } else { + Button buttonDel = new Button(); + buttonDel.setGraphic(new ImageView(UITools.getImage("resources/images/del_16.png"))); + if(replicate.getId() == 0) { + buttonDel.setDisable(true); + } else { + buttonDel.disableProperty().bind(Bindings.not(mainApp.getEditProperty())); + } + buttonDel.setOnAction(event -> { + Alert a = new Alert(Alert.AlertType.CONFIRMATION); + a.setTitle("Delete Replicate"); + a.setHeaderText("Delete Replicate " + replicate.getName()); + a.initModality(Modality.WINDOW_MODAL); + a.initOwner(MainApp.primaryStage); + Optional<ButtonType> res = a.showAndWait(); + if (res.get() == ButtonType.OK) { + GeneralFile gf = currentGF.get(); + gf.removeReplicate(replicate); + gf.getData().setModified(true); + } + }); + setGraphic(buttonDel); + } + } + }; + }); + + replicateTable.getColumns().addAll(colRepId, colRepName, colRepDesc, colRepDel); + + replicatesPane.setContent(replicateTable); + replicateTable.setItems(generalFile.getListReplicate()); + } private void updateListLink() { diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/StepOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/StepOverviewController.java index b8b498c4f07b276e858a0db60d23169c833a944e..208ca9da8add26d8c107531d7146135c5f6de548 100644 --- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/StepOverviewController.java +++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/StepOverviewController.java @@ -22,6 +22,7 @@ import fr.inra.po2vocabmanager.MainApp; import fr.inra.po2vocabmanager.model.DataNode; import fr.inra.po2vocabmanager.utils.UITools; import fr.inrae.po2engine.model.ComplexField; +import fr.inrae.po2engine.model.Replicate; import fr.inrae.po2engine.model.dataModel.CompositionFile; import fr.inrae.po2engine.model.dataModel.KeyWords; import fr.inrae.po2engine.model.dataModel.StepFile; @@ -108,19 +109,26 @@ public class StepOverviewController { scale.disableProperty().bind(this.mainApp.getEditProperty().not()); } - public void showNodeDetails(DataNode node) { + public void showNodeDetails(DataNode node, Replicate replicate) { for(AutoCompletionBinding auto : listAutoCompletion) { auto.dispose(); } f = (StepFile) node.getFile(); f.checkValue(); + + if(replicate != null) { + stepPanel.setText("Step (replicate : " + replicate.getName() + ")"); + } else { + stepPanel.setText("Step"); + } + UITools.simpleBindValue(f.getCType(), stepTitle); UITools.simpleBindValue(f.getCId(), stepID); UITools.simpleBindValue(f.getCDescrition(), description); - UITools.simpleBindValue(f.getCDate(), date); - UITools.simpleBindValue(f.getCTime(), time); - UITools.simpleBindValue(f.getCDuration(), duree); - UITools.bindComboBoxAgent(f.getAgentProperty(),f.getData().getProjectFile().getListAgent(), orgAgent); + UITools.simpleBindValue(f.getCDate(), replicate, date); + UITools.simpleBindValue(f.getCTime(), replicate, time); + UITools.simpleBindValue(f.getCDuration(), replicate, duree); + UITools.bindComboBoxAgent(f.getAgentsMap(),f.getData().getProjectFile().getListAgent(), replicate, orgAgent); UITools.simpleBindValue(f.getCScale(), scale); listAutoCompletion.add(UITools.addAutoComplete(scale, f.getCScale().getListConstraint())); @@ -216,7 +224,7 @@ public class StepOverviewController { Optional<ButtonType> res = a.showAndWait(); if(res.get() == ButtonType.OK) { f.removeCompositionFile(compoFile); - showNodeDetails(node); + showNodeDetails(node, replicate); } }); diff --git a/src/main/resources/fr/inra/po2vocabmanager/view/dataView/ProcessOverview.fxml b/src/main/resources/fr/inra/po2vocabmanager/view/dataView/ProcessOverview.fxml index ef01250e85cc3bff006a9a3a4a44cc524a8bc05c..43ecc3bcb3b6b452edbb8ee8487e180ae2fe786e 100644 --- a/src/main/resources/fr/inra/po2vocabmanager/view/dataView/ProcessOverview.fxml +++ b/src/main/resources/fr/inra/po2vocabmanager/view/dataView/ProcessOverview.fxml @@ -91,6 +91,7 @@ </TitledPane> <TitledPane fx:id="stepAvailable" maxHeight="Infinity" prefHeight="428.0" prefWidth="718.0" text="Steps available" VBox.vgrow="ALWAYS" /> + <TitledPane fx:id="replicatesPane" animated="false" text="Replicates" /> </children> </VBox> </children>