From 3a43a3915faa7b3551e66a9b86f9be7deb1fada0 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 6 Oct 2021 20:17:03 -0400 Subject: [PATCH] generic search result table node; needs work in ThreePanelDAO and DataArtifactNodev2 --- .../DataResultTopComponent.java | 16 +- .../datamodel/DataArtifactFactoryv2.java | 29 --- .../datamodel/DataArtifactTypeNodev2.java | 56 ---- .../datamodel/SearchResultChildFactory.java | 31 ++- .../datamodel/SearchResultTableNode.java | 60 +++++ .../autopsy/datamodel/ThreePanelDAO.java | 242 ++++++++++-------- 6 files changed, 229 insertions(+), 205 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/DataArtifactFactoryv2.java delete mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/DataArtifactTypeNodev2.java create mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/SearchResultTableNode.java diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java index cb1cc43114..9feca42ba3 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java @@ -40,10 +40,13 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datamodel.DataArtifactTypeNodev2; +import org.sleuthkit.autopsy.datamodel.DataArtifactNodev2; +import org.sleuthkit.autopsy.datamodel.SearchResultChildFactory.NodeCreator; +import org.sleuthkit.autopsy.datamodel.SearchResultTableNode; import org.sleuthkit.autopsy.datamodel.ThreePanelDAO; -import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableDTO; import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableSearchResultsDTO; +import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.RowResultDTO; +import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.SearchResultsDTO; import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -372,8 +375,7 @@ public final class DataResultTopComponent extends TopComponent implements DataRe public void displayDataArtifact(BlackboardArtifact.Type artifactType, Long dataSourceId) { try { DataArtifactTableSearchResultsDTO table = threePanelDAO.getDataArtifactsForTable(artifactType, dataSourceId); - dataResultPanel.setNode(new DataArtifactTypeNodev2(table)); - dataResultPanel.setNumberOfChildNodes(table.getTotalResultsCount()); + displaySearchResults(table, DataArtifactNodev2::new); } catch (ExecutionException | IllegalArgumentException ex) { logger.log(Level.WARNING, MessageFormat.format( "There was an error fetching data for artifact type: {0} and data source id: {1}.", @@ -382,6 +384,12 @@ public final class DataResultTopComponent extends TopComponent implements DataRe ex); } } + + public , S extends RowResultDTO> void displaySearchResults(T searchResults, NodeCreator nodeCreator) { + dataResultPanel.setNode(new SearchResultTableNode(nodeCreator, searchResults)); + dataResultPanel.setNumberOfChildNodes( + searchResults.getTotalResultsCount() > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) searchResults.getTotalResultsCount()); + } @Override public void setTitle(String title) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataArtifactFactoryv2.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataArtifactFactoryv2.java deleted file mode 100644 index 38fe93fe6f..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataArtifactFactoryv2.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.sleuthkit.autopsy.datamodel; - -import org.openide.nodes.Node; -import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableDTO; -import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableSearchResultsDTO; - -/** - * - * @author gregd - */ -public class DataArtifactFactoryv2 extends SearchResultChildFactory { - - public DataArtifactFactoryv2() { - } - - public DataArtifactFactoryv2(DataArtifactTableSearchResultsDTO initialResults) { - super(initialResults); - } - - @Override - protected Node createNodeForKey(DataArtifactTableSearchResultsDTO searchResults, DataArtifactTableDTO itemData) { - return new DataArtifactNodev2(searchResults, itemData); - } -} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataArtifactTypeNodev2.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataArtifactTypeNodev2.java deleted file mode 100644 index 3d523c4a36..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataArtifactTypeNodev2.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.sleuthkit.autopsy.datamodel; - -import org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.openide.nodes.Sheet; -import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableSearchResultsDTO; -import org.sleuthkit.autopsy.datamodel.utils.IconsUtil; - -/** - * - * @author gregd - */ -public class DataArtifactTypeNodev2 extends AbstractNode { - private final SearchResultChildFactory factory; - - public DataArtifactTypeNodev2(DataArtifactTableSearchResultsDTO initialResults) { - this(initialResults, new DataArtifactFactoryv2(initialResults)); - } - - private DataArtifactTypeNodev2(DataArtifactTableSearchResultsDTO initialResults, DataArtifactFactoryv2 factory) { - super(Children.create(factory, true)); - this.factory = factory; - setName(initialResults.getArtifactType().getTypeName()); - setDisplayName(initialResults.getArtifactType().getDisplayName()); - String iconPath = IconsUtil.getIconFilePath(initialResults.getArtifactType().getTypeID()); - setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath); - } - - @Override - protected Sheet createSheet() { - Sheet sheet = super.createSheet(); - Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); - if (sheetSet == null) { - sheetSet = Sheet.createPropertiesSet(); - sheet.put(sheetSet); - } - - sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.name"), - NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.displayName"), - NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.desc"), - getDisplayName())); - - sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.name"), - NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.displayName"), - NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.desc"), - this.factory.getResultCount())); - - return sheet; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SearchResultChildFactory.java b/Core/src/org/sleuthkit/autopsy/datamodel/SearchResultChildFactory.java index eddb826759..d6127069a6 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/SearchResultChildFactory.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/SearchResultChildFactory.java @@ -11,30 +11,29 @@ import java.util.stream.Collectors; import org.openide.nodes.ChildFactory; import org.openide.nodes.Node; import org.sleuthkit.autopsy.datamodel.SearchResultChildFactory.ChildKey; +import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.RowResultDTO; import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.SearchResultsDTO; /** * * @author gregd */ -public abstract class SearchResultChildFactory, S> extends ChildFactory> { +public class SearchResultChildFactory, S extends RowResultDTO> extends ChildFactory> { + private final NodeCreator nodeCreator; private T results; - - public SearchResultChildFactory() { - this(null); - } - public SearchResultChildFactory(T initialResults) { + public SearchResultChildFactory(NodeCreator nodeCreator, T initialResults) { + this.nodeCreator = nodeCreator; this.results = initialResults; } @Override - protected boolean createKeys(List> toPopulate) { + protected boolean createKeys(List> toPopulate) { T results = this.results; if (results != null) { - List> childKeys = results.getItems().stream() + List> childKeys = results.getItems().stream() .map((item) -> new ChildKey<>(results, item)) .collect(Collectors.toList()); @@ -45,23 +44,27 @@ public abstract class SearchResultChildFactory, S> } @Override - protected Node createNodeForKey(ChildKey key) { - return createNodeForKey(key.getSearchResults(), key.getChild()); + protected Node createNodeForKey(ChildKey key) { + return this.nodeCreator.create(key.getSearchResults(), key.getChild()); } - protected abstract Node createNodeForKey(T searchResults, S itemData); - public void update(T newResults) { this.results = newResults; this.refresh(false); } - public int getResultCount() { + public long getResultCount() { return results == null ? 0 : results.getTotalResultsCount(); } + + + + public static interface NodeCreator, S extends RowResultDTO> { + Node create(T searchResults, S itemData); + } - static class ChildKey> { + static class ChildKey { private final T searchResults; private final S child; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SearchResultTableNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/SearchResultTableNode.java new file mode 100644 index 0000000000..70210e8512 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/SearchResultTableNode.java @@ -0,0 +1,60 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.datamodel; + +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Sheet; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.datamodel.SearchResultChildFactory.NodeCreator; +import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.RowResultDTO; +import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.SearchResultsDTO; + +/** + * + * @author gregd + */ +public class SearchResultTableNode, S extends RowResultDTO> extends AbstractNode { + + private final SearchResultChildFactory factory; + + public SearchResultTableNode(NodeCreator nodeCreator, SearchResultsDTO initialResults) { + this(initialResults, new SearchResultChildFactory(nodeCreator, initialResults)); + } + + private SearchResultTableNode(SearchResultsDTO initialResults, SearchResultChildFactory factory) { + super(Children.create(factory, true)); + this.factory = factory; + + setName(initialResults.getTypeId()); + setDisplayName(initialResults.getDisplayName()); + +// String iconPath = IconsUtil.getIconFilePath(initialResults.getArtifactType().getTypeID()); +// setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath); + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); + if (sheetSet == null) { + sheetSet = Sheet.createPropertiesSet(); + sheet.put(sheetSet); + } + + sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.name"), + NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.displayName"), + NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.desc"), + getDisplayName())); + + sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.name"), + NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.displayName"), + NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.desc"), + this.factory.getResultCount())); + + return sheet; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ThreePanelDAO.java b/Core/src/org/sleuthkit/autopsy/datamodel/ThreePanelDAO.java index 190f78e8f0..fc35c027c4 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ThreePanelDAO.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ThreePanelDAO.java @@ -18,7 +18,6 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; -import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.AbstractFile; @@ -54,7 +53,7 @@ public class ThreePanelDAO { } private final Cache dataArtifactCache = CacheBuilder.newBuilder().maximumSize(1000).build(); - private final Cache> filesCache = CacheBuilder.newBuilder().maximumSize(1000).build(); +// private final Cache> filesCache = CacheBuilder.newBuilder().maximumSize(1000).build(); private SleuthkitCase getCase() throws NoCurrentCaseException { return Case.getCurrentCaseThrows().getSleuthkitCase(); @@ -247,14 +246,13 @@ public class ThreePanelDAO { // } // return filesCache.get(parentId, () -> fetchChildFiles(parentId)); // } - - public void dropFilesCache() { - filesCache.invalidateAll(); - } - - public void dropFilesCache(long parentId) { - filesCache.invalidate(parentId); - } +// public void dropFilesCache() { +// filesCache.invalidateAll(); +// } +// +// public void dropFilesCache(long parentId) { +// filesCache.invalidate(parentId); +// } private static class DataArtifactCacheKey { @@ -305,32 +303,22 @@ public class ThreePanelDAO { } - public static class DataArtifactTableDTO { - - private final long id; - - private final Map attributeValues; + public static class DataArtifactTableDTO extends BaseRowResultDTO { + //private final Map attributeValues; + //private final String dataSourceName; + private final DataArtifact dataArtifact; private final Content srcContent; private final Content linkedFile; - private String dataSourceName; + private final boolean isTimelineSupported; - public DataArtifactTableDTO(long id, Map attributeValues, DataArtifact dataArtifact, Content srcContent, Content linkedFile, String dataSourceName) { - this.id = id; - this.attributeValues = attributeValues; + public DataArtifactTableDTO(DataArtifact dataArtifact, Content srcContent, Content linkedFile, boolean isTimelineSupported, List cellValues, long id) { + super(cellValues, id); this.dataArtifact = dataArtifact; this.srcContent = srcContent; this.linkedFile = linkedFile; - this.dataSourceName = dataSourceName; - } - - public long getId() { - return id; - } - - public Map getAttributeValues() { - return attributeValues; + this.isTimelineSupported = isTimelineSupported; } public DataArtifact getDataArtifact() { @@ -345,14 +333,70 @@ public class ThreePanelDAO { return linkedFile; } - public String getDataSourceName() { - return dataSourceName; + public boolean isIsTimelineSupported() { + return isTimelineSupported; + } + + + + } + + public class ColumnKey { + + private final String fieldName; + private final String displayName; + private final String description; + + public ColumnKey(String fieldName, String displayName, String description) { + this.fieldName = fieldName; + this.displayName = displayName; + this.description = description; + } + + public String getFieldName() { + return fieldName; + } + + public String getDisplayName() { + return displayName; + } + + public String getDescription() { + return description; + } + } + + public interface RowResultDTO { + + List getCellValues(); + + long getId(); + } + + public class BaseRowResultDTO implements RowResultDTO { + + private final List cellValues; + private final long id; + + public BaseRowResultDTO(List cellValues, long id) { + this.cellValues = cellValues; + this.id = id; + } + + @Override + public List getCellValues() { + return cellValues; + } + + @Override + public long getId() { + return id; } @Override public int hashCode() { - int hash = 7; - hash = 67 * hash + (int) (this.id ^ (this.id >>> 32)); + int hash = 3; + hash = 23 * hash + (int) (this.id ^ (this.id >>> 32)); return hash; } @@ -367,95 +411,89 @@ public class ThreePanelDAO { if (getClass() != obj.getClass()) { return false; } - final DataArtifactTableDTO other = (DataArtifactTableDTO) obj; + final BaseRowResultDTO other = (BaseRowResultDTO) obj; if (this.id != other.id) { return false; } return true; } - + } - - public interface SearchResultsDTO { - int getTotalResultsCount(); - List getItems(); + + public interface SearchResultsDTO { + + String getTypeId(); + + String getDisplayName(); + + List getColumns(); + + List getItems(); + + long getTotalResultsCount(); } - public static class DataArtifactTableSearchResultsDTO implements SearchResultsDTO { + public class BaseSearchResultsDTO implements SearchResultsDTO { - private final BlackboardArtifact.Type artifactType; - private final List attributeTypes; - private final List items; - private final int totalResultsCount; + private final String typeId; + private final String displayName; + private final List columns; + private final List items; + private final long totalResultsCount; + - public DataArtifactTableSearchResultsDTO(BlackboardArtifact.Type artifactType, List attributeKeys, List items) { - this(artifactType, attributeKeys, items, items.size()); + public BaseSearchResultsDTO(String typeId, String displayName, List columns, List items) { + this(typeId, displayName, columns, items, items == null ? 0 : items.size()); } - - public DataArtifactTableSearchResultsDTO(BlackboardArtifact.Type artifactType, List attributeKeys, List items, int totalResultsCount) { - this.artifactType = artifactType; - this.attributeTypes = attributeKeys; + public BaseSearchResultsDTO(String typeId, String displayName, List columns, List items, long totalResultsCount) { + this.typeId = typeId; + this.displayName = displayName; + this.columns = columns; this.items = items; this.totalResultsCount = totalResultsCount; } + @Override + public String getTypeId() { + return typeId; + } + + @Override + public String getDisplayName() { + return displayName; + } + + @Override + public List getColumns() { + return columns; + } + + @Override + public List getItems() { + return items; + } + + @Override + public long getTotalResultsCount() { + return totalResultsCount; + } + + } + + public static class DataArtifactTableSearchResultsDTO extends BaseSearchResultsDTO { + private static final String TYPE_ID = "DATA_ARTIFACT"; + + private final BlackboardArtifact.Type artifactType; + + public DataArtifactTableSearchResultsDTO(BlackboardArtifact.Type artifactType, List columns, List items) { + super(TYPE_ID, artifactType.getDisplayName(), columns, items); + this.artifactType = artifactType; + } + public BlackboardArtifact.Type getArtifactType() { return artifactType; } - - public List getAttributeTypes() { - return attributeTypes; - } - - @Override - public List getItems() { - return items; - } - - @Override - public int getTotalResultsCount() { - return totalResultsCount; - } - - - } - - public enum FilesType { - DIR, - FILE - } - - public static class FilesContentTableDTO { - - private final Content content; - private final String displayName; - private final String extension; - private final long id; - - public FilesContentTableDTO(Content content, String displayName, String extension, long id) { - this.content = content; - this.displayName = displayName; - this.extension = extension; - this.id = id; - } - - public Content getContent() { - return content; - } - - public String getDisplayName() { - return displayName; - } - - public String getExtension() { - return extension; - } - - public long getId() { - return id; - } - } }