diff --git a/src/main/java/org/roda/rodain/creation/BagitSipCreator.java b/src/main/java/org/roda/rodain/creation/BagitSipCreator.java index 8a48a43e..d7259602 100644 --- a/src/main/java/org/roda/rodain/creation/BagitSipCreator.java +++ b/src/main/java/org/roda/rodain/creation/BagitSipCreator.java @@ -186,7 +186,7 @@ private long nodeSize(TreeNode node) throws IOException { Path nodePath = node.getPath(); long result = 0; if (Files.isDirectory(nodePath)) { - for (TreeNode tn : node.getAllFiles().values()) { + for (TreeNode tn : node.getChildren().values()) { result += nodeSize(tn); } } else { @@ -208,7 +208,7 @@ private void recCreateFiles(TreeNode node, Path dest) throws IOException { if (Files.isDirectory(nodePath)) { Path directory = dest.resolve(nodePath.getFileName().toString()); new File(directory.toString()).mkdir(); - for (TreeNode tn : node.getAllFiles().values()) { + for (TreeNode tn : node.getChildren().values()) { recCreateFiles(tn, directory); } } else { diff --git a/src/main/java/org/roda/rodain/creation/EarkSipCreator.java b/src/main/java/org/roda/rodain/creation/EarkSipCreator.java index 2862cc5d..914143d3 100644 --- a/src/main/java/org/roda/rodain/creation/EarkSipCreator.java +++ b/src/main/java/org/roda/rodain/creation/EarkSipCreator.java @@ -164,7 +164,7 @@ private void addFileToRepresentation(TreeNode tn, List relativePath, IPR List newRelativePath = new ArrayList<>(relativePath); newRelativePath.add(tn.getPath().getFileName().toString()); // recursive call to all the node's children - for (TreeNode node : tn.getAllFiles().values()) { + for (TreeNode node : tn.getChildren().values()) { addFileToRepresentation(node, newRelativePath, rep); } } else { @@ -182,7 +182,7 @@ private void addDocToZip(TreeNode tn, List relativePath, SIP earkSip) { List newRelativePath = new ArrayList<>(relativePath); newRelativePath.add(tn.getPath().getFileName().toString()); // recursive call to all the node's children - for (TreeNode node : tn.getAllFiles().values()) { + for (TreeNode node : tn.getChildren().values()) { addDocToZip(node, newRelativePath, earkSip); } } else { diff --git a/src/main/java/org/roda/rodain/inspection/InspectionPane.java b/src/main/java/org/roda/rodain/inspection/InspectionPane.java index 68825ada..ad9a868c 100644 --- a/src/main/java/org/roda/rodain/inspection/InspectionPane.java +++ b/src/main/java/org/roda/rodain/inspection/InspectionPane.java @@ -665,7 +665,8 @@ private void createContent() { HBox.setHgrow(space, Priority.ALWAYS); sipDocumentation = new SipDocumentationTreeView(); - + docsRoot = new SipContentDirectory(new TreeNode(Paths.get("")), null); + sipDocumentation.setRoot(docsRoot); toggleDocumentation = new ToggleButton(); toggleDocumentation.setTooltip(new Tooltip(I18n.t("documentation"))); Platform.runLater(() -> { @@ -693,7 +694,9 @@ private void createContent() { } } else { // from the documentation to the representations toggleDocumentation.setTooltip(new Tooltip(I18n.t("documentation"))); + dataBox.getChildren().clear(); dataBox.getChildren().add(sipFiles); + content.setCenter(dataBox); content.setBottom(contentBottom); } }); @@ -827,6 +830,8 @@ protected Void call() throws Exception { sipRoot = newRoot; if (active) { sipFiles.setRoot(sipRoot); + dataBox.getChildren().clear(); + dataBox.getChildren().add(sipFiles); content.setCenter(dataBox); content.setBottom(contentBottom); } @@ -835,8 +840,7 @@ protected Void call() throws Exception { } private void createDocumentation(SipPreviewNode sip, boolean active) { - SipContentDirectory newRoot = new SipContentDirectory(new TreeNode(Paths.get("")), null); - + docsRoot.getChildren().clear(); if (active) { content.setCenter(loadingPane); content.setBottom(new HBox()); @@ -846,19 +850,21 @@ private void createDocumentation(SipPreviewNode sip, boolean active) { @Override protected Void call() throws Exception { for (TreeNode treeNode : sip.getSip().getDocumentation()) { - TreeItem startingItem = recCreateSipContent(treeNode, newRoot); + TreeItem startingItem = recCreateSipContent(treeNode, docsRoot); startingItem.setExpanded(true); - newRoot.getChildren().add(startingItem); + docsRoot.getChildren().add(startingItem); } - newRoot.sortChildren(); + docsRoot.sortChildren(); return null; } }; docsTask.setOnSucceeded(event -> { - docsRoot = newRoot; if (active) { - sipDocumentation.setRoot(docsRoot); if (!docsRoot.getChildren().isEmpty()) { + if (!dataBox.getChildren().contains(sipDocumentation)) { + dataBox.getChildren().clear(); + dataBox.getChildren().add(sipDocumentation); + } content.setCenter(dataBox); content.setBottom(docsBottom); } else { @@ -867,6 +873,7 @@ protected Void call() throws Exception { } } }); + new Thread(docsTask).start(); } @@ -1047,15 +1054,6 @@ public void update(SipPreviewNode sip) { boolean documentation = toggleDocumentation.isSelected(); createContent(sip, !documentation); createDocumentation(sip, documentation); - if (documentation) { - if (docsRoot.getChildren().isEmpty()) { - content.setBottom(new HBox()); - } else { - content.setBottom(docsBottom); - } - } else { - content.setBottom(contentBottom); - } center.getChildren().addAll(metadata, content); setCenter(center); @@ -1139,8 +1137,10 @@ private void showMetadataHelp() { } private void updateTextArea(String content) { - metaText.replaceText(content); - metaText.setStyleSpans(0, XMLEditor.computeHighlighting(content)); + Platform.runLater(() -> { + metaText.replaceText(content); + metaText.setStyleSpans(0, XMLEditor.computeHighlighting(content)); + }); } /** diff --git a/src/main/java/org/roda/rodain/inspection/SipContentDirectory.java b/src/main/java/org/roda/rodain/inspection/SipContentDirectory.java index 50d3c1ee..631fba56 100644 --- a/src/main/java/org/roda/rodain/inspection/SipContentDirectory.java +++ b/src/main/java/org/roda/rodain/inspection/SipContentDirectory.java @@ -105,7 +105,7 @@ public void skip() { TreeNode parentTreeNode = par.getTreeNode(); parentTreeNode.remove(treeNode.getPath()); // remove this treeNode from the // parent - parentTreeNode.addAll(treeNode.getAllFiles()); // add this treeNode's + parentTreeNode.addAll(treeNode.getChildren()); // add this treeNode's // children to this node's // parent par.sortChildren(); diff --git a/src/main/java/org/roda/rodain/rules/Rule.java b/src/main/java/org/roda/rodain/rules/Rule.java index e853d854..96dd46ae 100644 --- a/src/main/java/org/roda/rodain/rules/Rule.java +++ b/src/main/java/org/roda/rodain/rules/Rule.java @@ -179,7 +179,7 @@ public RuleTypes getAssocType() { * @see SipSingle */ public TreeVisitor apply() { - sips = new HashMap<>(); + sips = new ConcurrentHashMap<>(); sipNodes = new ConcurrentHashMap<>(); schemaNodes = Collections.synchronizedSet(new HashSet<>()); diff --git a/src/main/java/org/roda/rodain/rules/TreeNode.java b/src/main/java/org/roda/rodain/rules/TreeNode.java index 3adbcb85..ee92d021 100644 --- a/src/main/java/org/roda/rodain/rules/TreeNode.java +++ b/src/main/java/org/roda/rodain/rules/TreeNode.java @@ -74,7 +74,7 @@ public Set getFullTreePathsAsPaths() { /** * @return The direct children of the TreeNode. */ - public Map getAllFiles() { + public Map getChildren() { return files; } diff --git a/src/main/java/org/roda/rodain/rules/sip/SipPerFile.java b/src/main/java/org/roda/rodain/rules/sip/SipPerFile.java index babe0ae5..52825ab3 100644 --- a/src/main/java/org/roda/rodain/rules/sip/SipPerFile.java +++ b/src/main/java/org/roda/rodain/rules/sip/SipPerFile.java @@ -1,22 +1,16 @@ package org.roda.rodain.rules.sip; -import org.apache.commons.io.FilenameUtils; import org.roda.rodain.core.PathCollection; import org.roda.rodain.rules.MetadataTypes; import org.roda.rodain.rules.TreeNode; import org.roda.rodain.rules.filters.ContentFilter; -import org.roda.rodain.schema.DescObjMetadata; import org.roda.rodain.source.ui.items.SourceTreeItemState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; import java.util.Set; /** @@ -28,8 +22,6 @@ public class SipPerFile extends SipPreviewCreator { private static final int UPDATEFREQUENCY = 500; // in milliseconds private long lastUIUpdate = 0; - private Map> metadata; - /** * Creates a new SipPreviewCreator where there's a new SIP created for each * visited file. @@ -48,28 +40,6 @@ public class SipPerFile extends SipPreviewCreator { public SipPerFile(String id, Set filters, MetadataTypes metaType, Path metadataPath, String templateType, String templateVersion) { super(id, filters, metaType, metadataPath, templateType, templateVersion); - metadata = new HashMap<>(); - - if (metadataPath != null && metaType == MetadataTypes.DIFF_DIRECTORY) { - try { - Files.walkFileTree(metadataPath, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - String key = FilenameUtils.removeExtension(file.getFileName().toString()); - Set paths = metadata.get(key); - if (paths == null) - paths = new HashSet<>(); - paths.add(file); - metadata.put(key, paths); - return FileVisitResult.CONTINUE; - } - }); - } catch (AccessDeniedException e) { - log.info("Access denied to file", e); - } catch (IOException e) { - log.error("Error walking the file tree", e); - } - } } @Override @@ -148,27 +118,8 @@ public void visitFile(Path path, BasicFileAttributes attrs) { if (filter(path) || cancelled) return; - Path metaPath = getMetadataPath(path); TreeNode node = new TreeNode(path); - Set files = new HashSet<>(); - files.add(node); - - DescObjMetadata dom = null; - if (metaType == MetadataTypes.TEMPLATE) - dom = new DescObjMetadata(metaType, templateType, templateVersion); - else if (metaPath != null) - dom = new DescObjMetadata(metaType, metaPath); - - SipRepresentation rep = new SipRepresentation("rep1"); - rep.setFiles(files); - Set repSet = new HashSet<>(); - repSet.add(rep); - SipPreview sipPreview = new SipPreview(path.getFileName().toString(), repSet, dom); - node.addObserver(sipPreview); - - sips.add(sipPreview); - sipsMap.put(sipPreview.getId(), sipPreview); - added++; + createSip(path, node); long now = System.currentTimeMillis(); if (now - lastUIUpdate > UPDATEFREQUENCY) { @@ -177,52 +128,4 @@ else if (metaPath != null) lastUIUpdate = now; } } - - private Path getMetadataPath(Path path) { - Path result; - switch (metaType) { - case SINGLE_FILE: - result = metadataPath; - break; - case DIFF_DIRECTORY: - result = getFileFromDir(path); - break; - case SAME_DIRECTORY: - result = searchMetadata(path); - break; - default: - return null; - } - return result; - } - - private Path searchMetadata(Path sipPath) { - File dir = sipPath.toFile(); - if (!dir.isDirectory()) - dir = sipPath.getParent().toFile(); - - PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + templateType); - File[] foundFiles = dir.listFiles((dir1, name) -> matcher.matches(Paths.get(name))); - - if (foundFiles != null && foundFiles.length > 0) { - return foundFiles[0].toPath(); - } - return null; - } - - private Path getFileFromDir(Path path) { - String fileNameWithExtension = path.getFileName().toString(); - String fileName = FilenameUtils.removeExtension(fileNameWithExtension); - - Set paths = metadata.get(fileName); - Path result = null; - if (paths != null) { - for (Path p : paths) { - if (!p.getFileName().toString().equals(fileNameWithExtension)) - result = p; - - } - } - return result; - } } diff --git a/src/main/java/org/roda/rodain/rules/sip/SipPerSelection.java b/src/main/java/org/roda/rodain/rules/sip/SipPerSelection.java index fffcbb57..98d6776b 100644 --- a/src/main/java/org/roda/rodain/rules/sip/SipPerSelection.java +++ b/src/main/java/org/roda/rodain/rules/sip/SipPerSelection.java @@ -3,15 +3,11 @@ import org.roda.rodain.rules.MetadataTypes; import org.roda.rodain.rules.TreeNode; import org.roda.rodain.rules.filters.ContentFilter; -import org.roda.rodain.schema.DescObjMetadata; -import java.io.File; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.PathMatcher; -import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; -import java.util.HashSet; import java.util.Set; /** @@ -109,30 +105,6 @@ public void postVisitDirectory(Path path) { } } - private void createSip(Path path, TreeNode node) { - Path metaPath = getMetadataPath(path); - // create a new Sip - Set files = new HashSet<>(); - files.add(node); - - DescObjMetadata metadata; - if (metaType == MetadataTypes.TEMPLATE) - metadata = new DescObjMetadata(metaType, templateType, templateVersion); - else - metadata = new DescObjMetadata(metaType, metaPath); - - SipRepresentation rep = new SipRepresentation("rep1"); - rep.setFiles(files); - Set repSet = new HashSet<>(); - repSet.add(rep); - SipPreview sipPreview = new SipPreview(path.getFileName().toString(), repSet, metadata); - node.addObserver(sipPreview); - - sips.add(sipPreview); - sipsMap.put(sipPreview.getId(), sipPreview); - added++; - } - /** * If the path is in the selected set of paths creates a new SIP using the * file, otherwise, adds the visited file to its parent. @@ -155,30 +127,4 @@ public void visitFile(Path path, BasicFileAttributes attrs) { nodes.peekLast().add(path); } } - - private Path getMetadataPath(Path sipPath) { - Path result = null; - if (metaType == MetadataTypes.SINGLE_FILE) { - result = metadataPath; - } else if (metaType == MetadataTypes.SAME_DIRECTORY) { - result = searchMetadata(sipPath); - } - return result; - } - - private Path searchMetadata(Path sipPath) { - File dir = sipPath.toFile(); - if (!dir.isDirectory()) - dir = sipPath.getParent().toFile(); - - PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + templateType); - File[] foundFiles = dir.listFiles((dir1, name) -> { - return matcher.matches(Paths.get(name)); - }); - - if (foundFiles != null && foundFiles.length > 0) { - return foundFiles[0].toPath(); - } - return null; - } } diff --git a/src/main/java/org/roda/rodain/rules/sip/SipPreviewCreator.java b/src/main/java/org/roda/rodain/rules/sip/SipPreviewCreator.java index e9a7c5f1..0ad5a194 100644 --- a/src/main/java/org/roda/rodain/rules/sip/SipPreviewCreator.java +++ b/src/main/java/org/roda/rodain/rules/sip/SipPreviewCreator.java @@ -1,11 +1,17 @@ package org.roda.rodain.rules.sip; +import org.apache.commons.io.FilenameUtils; import org.roda.rodain.rules.MetadataTypes; import org.roda.rodain.rules.TreeNode; import org.roda.rodain.rules.filters.ContentFilter; +import org.roda.rodain.schema.DescObjMetadata; import org.roda.rodain.utils.TreeVisitor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.nio.file.Path; +import java.io.File; +import java.io.IOException; +import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.*; @@ -14,6 +20,7 @@ * @since 20-10-2015. */ public class SipPreviewCreator extends Observable implements TreeVisitor { + private static final Logger log = LoggerFactory.getLogger(SipPreviewCreator.class.getName()); private String startPath; // This map is returned, in full, to the SipPreviewNode when there's an update protected Map sipsMap; @@ -30,6 +37,7 @@ public class SipPreviewCreator extends Observable implements TreeVisitor { protected MetadataTypes metaType; protected Path metadataPath; protected String templateType, templateVersion; + private Map> metadata; protected boolean cancelled = false; @@ -60,6 +68,28 @@ public SipPreviewCreator(String id, Set filters, MetadataTypes me this.templateType = templateType; this.templateVersion = templateVersion; files = new HashSet<>(); + metadata = new HashMap<>(); + + if (metadataPath != null && metaType == MetadataTypes.DIFF_DIRECTORY) { + try { + Files.walkFileTree(metadataPath, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String key = FilenameUtils.removeExtension(file.getFileName().toString()); + Set paths = metadata.get(key); + if (paths == null) + paths = new HashSet<>(); + paths.add(file); + metadata.put(key, paths); + return FileVisitResult.CONTINUE; + } + }); + } catch (AccessDeniedException e) { + log.info("Access denied to file", e); + } catch (IOException e) { + log.error("Error walking the file tree", e); + } + } } /** @@ -176,10 +206,98 @@ public void end() { notifyObservers("Finished"); } - protected Path getMetadata() { + protected SipPreview createSip(Path path, TreeNode node) { + Path metaPath = getMetadataPath(path); + + Set filesSet = new HashSet<>(); + // start as false otherwise when there's only files they would be jumped + boolean onlyFiles = false; + // check if there's a folder with only files inside + // in that case we will jump the folder and add the files to the root of the + // representation + if (Files.isDirectory(node.getPath())) { + onlyFiles = true; + for (String pt : node.getKeys()) { + if (Files.isDirectory(Paths.get(pt))) { + onlyFiles = false; + break; + } + } + } + if (onlyFiles) { + filesSet.addAll(node.getChildren().values()); + } else { + filesSet.add(node); + } + // create a new Sip + DescObjMetadata metadata = null; + if (metaType == MetadataTypes.TEMPLATE) + metadata = new DescObjMetadata(metaType, templateType, templateVersion); + else { + if (metaPath != null) + metadata = new DescObjMetadata(metaType, metaPath); + } + + SipRepresentation rep = new SipRepresentation("rep1"); + rep.setFiles(filesSet); + Set repSet = new HashSet<>(); + repSet.add(rep); + SipPreview sipPreview = new SipPreview(path.getFileName().toString(), repSet, metadata); + node.addObserver(sipPreview); + + sips.add(sipPreview); + sipsMap.put(sipPreview.getId(), sipPreview); + added++; + return sipPreview; + } + + protected Path getMetadataPath(Path sipPath) { + Path result; + switch (metaType) { + case SINGLE_FILE: + result = metadataPath; + break; + case DIFF_DIRECTORY: + result = getFileFromDir(sipPath); + break; + case SAME_DIRECTORY: + result = searchMetadata(sipPath); + break; + default: + return null; + } + return result; + } + + private Path searchMetadata(Path sipPath) { + File dir = sipPath.toFile(); + if (!dir.isDirectory()) + dir = sipPath.getParent().toFile(); + + PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + templateType); + File[] foundFiles = dir.listFiles((dir1, name) -> { + return matcher.matches(Paths.get(name)); + }); + + if (foundFiles != null && foundFiles.length > 0) { + return foundFiles[0].toPath(); + } + return null; + } + + private Path getFileFromDir(Path path) { + String fileNameWithExtension = path.getFileName().toString(); + String fileName = FilenameUtils.removeExtension(fileNameWithExtension); + + Set paths = metadata.get(fileName); Path result = null; - if (metaType == MetadataTypes.SINGLE_FILE) - result = metadataPath; + if (paths != null) { + for (Path p : paths) { + if (!p.getFileName().toString().equals(fileNameWithExtension)) + result = p; + + } + } return result; } diff --git a/src/main/java/org/roda/rodain/rules/sip/SipSingle.java b/src/main/java/org/roda/rodain/rules/sip/SipSingle.java index bf4f49f5..bba56981 100644 --- a/src/main/java/org/roda/rodain/rules/sip/SipSingle.java +++ b/src/main/java/org/roda/rodain/rules/sip/SipSingle.java @@ -98,15 +98,17 @@ public void visitFile(Path path, BasicFileAttributes attrs) { */ @Override public void end() { - Path metaPath = getMetadata(); // create a new Sip Path path = Paths.get(getStartPath()); + Path metaPath = getMetadataPath(path); - DescObjMetadata metadata; + DescObjMetadata metadata = null; if (metaType == MetadataTypes.TEMPLATE) metadata = new DescObjMetadata(metaType, templateType, templateVersion); - else - metadata = new DescObjMetadata(metaType, metaPath); + else { + if (metaPath != null) + metadata = new DescObjMetadata(metaType, metaPath); + } SipRepresentation rep = new SipRepresentation("rep1"); rep.setFiles(files); diff --git a/src/main/java/org/roda/rodain/rules/sip/SipsWithStructure.java b/src/main/java/org/roda/rodain/rules/sip/SipsWithStructure.java index 8a0ba02f..aee9e4e6 100644 --- a/src/main/java/org/roda/rodain/rules/sip/SipsWithStructure.java +++ b/src/main/java/org/roda/rodain/rules/sip/SipsWithStructure.java @@ -4,13 +4,11 @@ import org.roda.rodain.rules.MetadataTypes; import org.roda.rodain.rules.TreeNode; import org.roda.rodain.rules.filters.ContentFilter; -import org.roda.rodain.schema.DescObjMetadata; import org.roda.rodain.schema.DescriptionObject; import org.roda.rodain.source.ui.items.SourceTreeItemState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; @@ -213,58 +211,15 @@ public void end() { private void createSip(TreeNode node) { Path path = node.getPath(); - Path metaPath = getMetadataPath(path); - // create a new Sip - Set files = new HashSet<>(); - files.add(node); - - DescObjMetadata metadata; - if (metaType == MetadataTypes.TEMPLATE) - metadata = new DescObjMetadata(metaType, templateType, templateVersion); - else - metadata = new DescObjMetadata(metaType, metaPath); - - SipRepresentation rep = new SipRepresentation("rep1"); - rep.setFiles(files); - Set repSet = new HashSet<>(); - repSet.add(rep); - SipPreview sipPreview = new SipPreview(path.getFileName().toString(), repSet, metadata); - node.addObserver(sipPreview); + SipPreview sipPreview = createSip(path, node); // set the SIP's description level as file if there's more than one file in // the content - if (node.getAllFiles().size() > 1) { + if (node.getChildren().size() > 1) { sipPreview.setDescriptionlevel("file"); } sipPreviewMap.put(path, sipPreview); - added++; - } - - private Path getMetadataPath(Path sipPath) { - Path result = null; - if (metaType == MetadataTypes.SINGLE_FILE) { - result = metadataPath; - } else if (metaType == MetadataTypes.SAME_DIRECTORY) { - result = searchMetadata(sipPath); - } - return result; - } - - private Path searchMetadata(Path sipPath) { - File dir = sipPath.toFile(); - if (!dir.isDirectory()) - dir = sipPath.getParent().toFile(); - - PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + templateType); - File[] foundFiles = dir.listFiles((dir1, name) -> { - return matcher.matches(Paths.get(name)); - }); - - if (foundFiles != null && foundFiles.length > 0) { - return foundFiles[0].toPath(); - } - return null; } public Map getRecord() { diff --git a/src/main/java/org/roda/rodain/rules/ui/RuleModalPane.java b/src/main/java/org/roda/rodain/rules/ui/RuleModalPane.java index 7f321338..0c7dc8b8 100644 --- a/src/main/java/org/roda/rodain/rules/ui/RuleModalPane.java +++ b/src/main/java/org/roda/rodain/rules/ui/RuleModalPane.java @@ -396,7 +396,7 @@ public void handle(ActionEvent e) { if (assocList.getSelectionModel().getSelectedIndex() != -1) { setCenter(boxMetadata); currentState = States.METADATA; - enableMetaOptions(); + // enableMetaOptions(); buttons.getChildren().clear(); buttons.getChildren().addAll(btCancel, space, btBack, btContinue); btContinue.setText(I18n.t("confirm")); @@ -452,7 +452,7 @@ public void handle(ActionEvent actionEvent) { if (currentState == States.ASSOCIATION) { setCenter(boxMetadata); currentState = States.METADATA; - enableMetaOptions(); + // enableMetaOptions(); } else if (currentState == States.METADATA) { setCenter(boxAssociation); currentState = States.ASSOCIATION; diff --git a/src/main/java/org/roda/rodain/rules/ui/RuleModalRemoving.java b/src/main/java/org/roda/rodain/rules/ui/RuleModalRemoving.java index 3301d1f5..599348cb 100644 --- a/src/main/java/org/roda/rodain/rules/ui/RuleModalRemoving.java +++ b/src/main/java/org/roda/rodain/rules/ui/RuleModalRemoving.java @@ -1,5 +1,7 @@ package org.roda.rodain.rules.ui; +import java.util.*; + import javafx.application.Platform; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -7,15 +9,11 @@ import javafx.scene.control.ProgressBar; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; + import org.roda.rodain.core.I18n; import org.roda.rodain.rules.Rule; import org.roda.rodain.rules.sip.SipPreview; -import java.util.HashMap; -import java.util.Map; -import java.util.Observable; -import java.util.Observer; - /** * @author Andre Pereira apereira@keep.pt * @since 19/11/2015. @@ -23,24 +21,31 @@ public class RuleModalRemoving extends BorderPane implements Observer { // rule ID -> progress private Map rules; + private Map ruleObjects; private Map sips; + private Map sipObjects; // top private Label sipsRemovedLabel; // center private ProgressBar progress; private int removedSIPs = 0; + private Timer timer; /** * Creates a new RuleModalRemoving object. */ public RuleModalRemoving() { rules = new HashMap<>(); + ruleObjects = new HashMap<>(); sips = new HashMap<>(); + sipObjects = new HashMap<>(); getStyleClass().add("sipcreator"); createTop(); createCenter(); + + createUpdateTask(); } private void createTop() { @@ -71,21 +76,50 @@ private void createCenter() { setCenter(center); } + private void createUpdateTask() { + TimerTask updater = new TimerTask() { + @Override + public void run() { + Iterator it = ruleObjects.keySet().iterator(); + while (it.hasNext()) { + it.next(); + if (ruleObjects.get(it).getSipCount() == 0) + it.remove(); + } + + Iterator its = sipObjects.keySet().iterator(); + while (its.hasNext()) { + its.next(); + if (sipObjects.get(its).isRemoved()) + its.remove(); + } + Platform.runLater(() -> { + if (sipObjects.isEmpty() && ruleObjects.isEmpty()) { + close(); + } + }); + } + }; + + timer = new Timer(); + timer.schedule(updater, 5000, 1000); + } + /** * Updates the progress of the rule removal. * - * @param o - * The Observable object, should be a Rule. - * @param args - * The arguments of the update. + * @param o The Observable object, should be a Rule. + * @param args The arguments of the update. */ @Override public void update(Observable o, Object args) { if (!(args instanceof Float)) { - if (o instanceof Rule) { + if (o instanceof Rule && args instanceof String) { Rule r = (Rule) o; if (rules.containsKey(r.getId())) { - rules.remove(r.getId()); + if ("removed rule".equals(((String) args).toLowerCase())) { + rules.remove(r.getId()); + } } } if (o instanceof SipPreview) { @@ -97,12 +131,9 @@ public void update(Observable o, Object args) { updateProgress(1f); close(); } + updateProgress(computeProgress()); return; } - if (o instanceof Rule) { - Rule rule = (Rule) o; - rules.put(rule.getId(), (float) args); - } if (o instanceof SipPreview) { SipPreview sip = (SipPreview) o; sips.put(sip.getId(), (float) args); @@ -134,7 +165,7 @@ private float computeProgress() { /** * Adds a rule to the removal task. - * + * * @param r */ public void addRule(Rule r) { @@ -154,10 +185,14 @@ private void updateProgress(float progressValue) { Platform.runLater(() -> { progress.setProgress(progressValue); sipsRemovedLabel.setText(String.format(I18n.t("RuleModalRemoving.removedFormat"), (int) (progressValue * 100))); + if (progressValue == 1) { + close(); + } }); } private void close() { + timer.cancel(); RuleModalController.cancel(); } } diff --git a/src/main/java/org/roda/rodain/schema/DescriptionObject.java b/src/main/java/org/roda/rodain/schema/DescriptionObject.java index b0382b3c..2c90692a 100644 --- a/src/main/java/org/roda/rodain/schema/DescriptionObject.java +++ b/src/main/java/org/roda/rodain/schema/DescriptionObject.java @@ -128,7 +128,15 @@ public String getMetadataWithReplaces(DescObjMetadata dom) { Map data = new HashMap<>(); Map values = getMetadataValueMap(dom); if (values != null) { - values.forEach((s, metadataValue) -> data.put(s, metadataValue.getValue())); + values.forEach((s, metadataValue) -> { + String val = metadataValue.getValue(); + if (val != null) { + val = val.replaceAll("\\s", ""); + if (!"".equals(val)) { + data.put(s, metadataValue.getValue()); + } + } + }); } content = tmpl.execute(data); // we need to clean the '\r' character in windows, diff --git a/src/main/java/org/roda/rodain/schema/ui/SchemaPane.java b/src/main/java/org/roda/rodain/schema/ui/SchemaPane.java index 28c59234..4e4dac35 100644 --- a/src/main/java/org/roda/rodain/schema/ui/SchemaPane.java +++ b/src/main/java/org/roda/rodain/schema/ui/SchemaPane.java @@ -28,6 +28,7 @@ import org.roda.rodain.core.AppProperties; import org.roda.rodain.core.I18n; import org.roda.rodain.core.RodaIn; +import org.roda.rodain.rules.Rule; import org.roda.rodain.rules.sip.SipPreview; import org.roda.rodain.rules.ui.RuleModalController; import org.roda.rodain.schema.ClassificationSchema; @@ -299,7 +300,7 @@ public void loadClassificationSchema() { /** * Creates a ClassificationSchema object from the InputStream and builds a * tree using it. - * + * * @param stream * The stream with the JSON file used to create the * ClassificationSchema @@ -347,65 +348,72 @@ private void updateClassificationSchema(ClassificationSchema cs, boolean skipCon Map nodes = new HashMap<>(); Set roots = new HashSet<>(); - for (DescriptionObject descObj : dos) { - // Check if the node is a root node - if (descObj.getParentId() == null) { - // Create a new node if it hasn't been created - if (!nodes.containsKey(descObj.getId())) { - SchemaNode root = new SchemaNode(descObj); - nodes.put(descObj.getId(), root); - } - roots.add(nodes.get(descObj.getId())); - } else { - // Get a list with the items where the id equals the node's parent's id - List parents = dos.stream().filter(p -> p.getId().equals(descObj.getParentId())) - .collect(Collectors.toList()); - // If the input file is well formed, there should be one item in the - // list, no more and no less - if (parents.size() != 1) { - String format = "The node \"%s\" has %d parents"; - String message = String.format(format, descObj.getTitle(), parents.size()); - log.info("Error creating the scheme tree", new MalformedSchemaException(message)); - continue; - } - DescriptionObject parent = parents.get(0); - SchemaNode parentNode; - // If the parent node hasn't been processed yet, add it to the nodes map - if (nodes.containsKey(parent.getId())) { - parentNode = nodes.get(parent.getId()); - } else { - parentNode = new SchemaNode(parent); - nodes.put(parent.getId(), parentNode); - } - SchemaNode node; - // If the node hasn't been added yet, create it and add it to the nodes - // map - if (nodes.containsKey(descObj.getId())) { - node = nodes.get(descObj.getId()); + try { + for (DescriptionObject descObj : dos) { + // Check if the node is a root node + if (descObj.getParentId() == null) { + // Create a new node if it hasn't been created + if (!nodes.containsKey(descObj.getId())) { + SchemaNode root = new SchemaNode(descObj); + nodes.put(descObj.getId(), root); + } + roots.add(nodes.get(descObj.getId())); } else { - node = new SchemaNode(descObj); - nodes.put(descObj.getId(), node); + // Get a list with the items where the id equals the node's parent's + // id + List parents = dos.stream().filter(p -> p.getId().equals(descObj.getParentId())) + .collect(Collectors.toList()); + // If the input file is well formed, there should be one item in the + // list, no more and no less + if (parents.size() != 1) { + String format = "The node \"%s\" has %d parents"; + String message = String.format(format, descObj.getTitle(), parents.size()); + log.info("Error creating the scheme tree", new MalformedSchemaException(message)); + continue; + } + DescriptionObject parent = parents.get(0); + SchemaNode parentNode; + // If the parent node hasn't been processed yet, add it to the nodes + // map + if (nodes.containsKey(parent.getId())) { + parentNode = nodes.get(parent.getId()); + } else { + parentNode = new SchemaNode(parent); + nodes.put(parent.getId(), parentNode); + } + SchemaNode node; + // If the node hasn't been added yet, create it and add it to the + // nodes + // map + if (nodes.containsKey(descObj.getId())) { + node = nodes.get(descObj.getId()); + } else { + node = new SchemaNode(descObj); + nodes.put(descObj.getId(), node); + } + parentNode.getChildren().add(node); + parentNode.addChildrenNode(node); } - parentNode.getChildren().add(node); - parentNode.addChildrenNode(node); } - } - // Add all the root nodes as children of the hidden rootNode - for (SchemaNode sn : roots) { - rootNode.getChildren().add(sn); - schemaNodes.add(sn); - } - // if there were no nodes in the file, show the help panel - if (roots.isEmpty()) { - setTop(new HBox()); - setCenter(centerHelp); - setBottom(new HBox()); - } else { - sortRootChildren(); - hasClassificationScheme.setValue(true); + // Add all the root nodes as children of the hidden rootNode + for (SchemaNode sn : roots) { + rootNode.getChildren().add(sn); + schemaNodes.add(sn); + } + // if there were no nodes in the file, show the help panel + if (roots.isEmpty()) { + setTop(new HBox()); + setCenter(centerHelp); + setBottom(new HBox()); + } else { + sortRootChildren(); + hasClassificationScheme.setValue(true); + } + modifiedPlan = false; + } catch (Exception e) { + log.error("Error updating the classification plan", e); } - modifiedPlan = false; } private boolean confirmUpdate() { @@ -442,7 +450,6 @@ private void createBottom() { bottom.setPadding(new Insets(10, 10, 10, 10)); Button removeLevel = new Button(I18n.t("SchemaPane.remove")); - removeLevel.getStyleClass().add("button-secondary"); removeLevel.setId("removeLevel"); removeLevel.setMinWidth(100); removeLevel.setOnAction(event -> { @@ -459,7 +466,6 @@ private void createBottom() { }); Button addLevel = new Button(I18n.t("SchemaPane.add")); - addLevel.getStyleClass().add("button-secondary"); addLevel.setMinWidth(100); addLevel.setOnAction(event -> addNewLevel()); @@ -477,35 +483,49 @@ private void createBottom() { private void confirmRemove(List> selectedItems, ButtonType type) { if (type.getButtonData() == ButtonBar.ButtonData.OK_DONE) { treeView.getSelectionModel().clearSelection(); + Set sipNodes = new HashSet<>(); + Set fromRules = new HashSet<>(); for (TreeItem selected : selectedItems) { if (selected instanceof SipPreviewNode) { SipPreview currentSIP = ((SipPreviewNode) selected).getSip(); - RuleModalController.removeSipPreview(currentSIP); - Task removeTask = new Task() { - @Override - protected Void call() throws Exception { - currentSIP.removeSIP(); - return null; - } - }; - new Thread(removeTask).start(); + sipNodes.add(currentSIP); } if (selected instanceof SchemaNode) { + for (Rule r : ((SchemaNode) selected).getRules()) { + fromRules.addAll(r.getSips()); + } // remove all the rules under this SchemaNode ((SchemaNode) selected).remove(); } // remove the node from the tree removeNode(selected); } + + sipNodes.removeAll(fromRules); + + for (SipPreview currentSIP : sipNodes) { + RuleModalController.removeSipPreview(currentSIP); + Task removeTask = new Task() { + @Override + protected Void call() throws Exception { + currentSIP.removeSIP(); + return null; + } + }; + new Thread(removeTask).start(); + } } } private void removeNode(TreeItem selected) { TreeItem parent = selected.getParent(); - if (parent instanceof SchemaNode) { - ((SchemaNode) parent).removeChild(selected); - } else - parent.getChildren().remove(selected); + if (parent != null) { + if (parent instanceof SchemaNode) { + ((SchemaNode) parent).removeChild(selected); + parent.getChildren().remove(selected); + } else + parent.getChildren().remove(selected); + } schemaNodes.remove(selected); treeView.getSelectionModel().clearSelection(); } @@ -706,8 +726,7 @@ private void setOnDragDropped(final SchemaTreeCell cell) { schemaNode.getDob().setParentId(node.getDob().getId()); node.sortChildren(); } - } - if (db.getString().startsWith("sip preview")) { + } else if (db.getString().startsWith("sip preview")) { SchemaNode target = null; if (treeItem instanceof SipPreviewNode) { target = (SchemaNode) treeItem.getParent(); diff --git a/src/main/java/org/roda/rodain/source/ui/FileExplorerPane.java b/src/main/java/org/roda/rodain/source/ui/FileExplorerPane.java index 58ed522e..7bcea5cf 100644 --- a/src/main/java/org/roda/rodain/source/ui/FileExplorerPane.java +++ b/src/main/java/org/roda/rodain/source/ui/FileExplorerPane.java @@ -48,7 +48,7 @@ public class FileExplorerPane extends BorderPane implements Observer { private VBox centerHelp; private Button ignore; - private TreeItem dummyRoot; + private SourceTreeDirectory dummyRoot; private Map realRoots; private boolean rootSelected, selectedIsIgnored; @@ -122,7 +122,6 @@ private void createBottom() { bottom.setPadding(new Insets(10, 10, 10, 10)); ignore = new Button(I18n.t("ignore")); - ignore.getStyleClass().add("button-secondary"); ignore.setId("bt_ignore"); ignore.setMinWidth(100); ignore.setOnAction(event -> { @@ -208,7 +207,7 @@ private void createFileExplorer() { treeBox.setPadding(new Insets(10, 0, 0, 0)); Separator separatorBottom = new Separator(); - dummyRoot = new TreeItem<>(); + dummyRoot = new SourceTreeDirectory(); realRoots = new HashMap<>(); treeView = new TreeView<>(); diff --git a/src/main/java/org/roda/rodain/source/ui/items/SourceTreeDirectory.java b/src/main/java/org/roda/rodain/source/ui/items/SourceTreeDirectory.java index df4bbeed..e7947e6f 100644 --- a/src/main/java/org/roda/rodain/source/ui/items/SourceTreeDirectory.java +++ b/src/main/java/org/roda/rodain/source/ui/items/SourceTreeDirectory.java @@ -1,17 +1,9 @@ package org.roda.rodain.source.ui.items; -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.*; -import java.util.stream.Collectors; - import javafx.application.Platform; import javafx.concurrent.Task; import javafx.scene.control.TreeItem; import javafx.scene.image.Image; - import org.roda.rodain.core.PathCollection; import org.roda.rodain.rules.Rule; import org.roda.rodain.rules.filters.IgnoredFilter; @@ -20,6 +12,13 @@ import org.roda.rodain.source.ui.ExpandedEventHandler; import org.roda.rodain.source.ui.FileExplorerPane; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; + /** * @author Andre Pereira apereira@keep.pt * @since 17-09-2015. @@ -76,6 +75,16 @@ public SourceTreeDirectory(Path file, SourceDirectory directory, SourceTreeDirec }); } + public SourceTreeDirectory() { + super("", null); + fullPath = ""; + directory = null; + state = SourceTreeItemState.NORMAL; + ignored = new HashSet<>(); + mapped = new HashSet<>(); + files = new HashSet<>(); + } + /** * Creates a task to hide all this item's mapped items. The task is needed to * prevent the UI thread from hanging due to the computations. diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 02930310..c4b9977e 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -5,9 +5,9 @@ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - error - + + +