mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-20 03:24:55 +00:00
Merge branch 'new_table_load' of github.com:sleuthkit/autopsy into 8235-hostPersonDaoDto
This commit is contained in:
commit
e05463e76b
@ -671,6 +671,38 @@ public class Case {
|
|||||||
public void publishAnalysisResultDeleted(TskEvent.AnalysisResultsDeletedTskEvent event) {
|
public void publishAnalysisResultDeleted(TskEvent.AnalysisResultsDeletedTskEvent event) {
|
||||||
eventPublisher.publish(new AnalysisResultDeletedEvent(event.getAnalysisResultObjectIds()));
|
eventPublisher.publish(new AnalysisResultDeletedEvent(event.getAnalysisResultObjectIds()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void publishBlackboardArtifactTagDeleted(TskEvent.BlackboardArtifactTagsDeletedTskEvent event) {
|
||||||
|
List<BlackboardArtifactTag> tags = event.getTags();
|
||||||
|
for(BlackboardArtifactTag tag: tags) {
|
||||||
|
eventPublisher.publish(new BlackBoardArtifactTagDeletedEvent(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void publishBlackboardTagAdded(TskEvent.BlackboardArtifactTagsAddedTskEvent event) {
|
||||||
|
List<BlackboardArtifactTag> tags = event.getTags();
|
||||||
|
for(BlackboardArtifactTag tag: tags) {
|
||||||
|
eventPublisher.publish(new BlackBoardArtifactTagAddedEvent(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void publishContentTagAdded(TskEvent.ContentTagsAddedTskEvent event) {
|
||||||
|
List<ContentTag> tags = event.getTags();
|
||||||
|
for(ContentTag tag: tags) {
|
||||||
|
eventPublisher.publish(new ContentTagAddedEvent(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void publishContentTagDeleted(TskEvent.ContentTagsDeletedTskEvent event) {
|
||||||
|
List<ContentTag> tags = event.getTags();
|
||||||
|
for(ContentTag tag: tags) {
|
||||||
|
eventPublisher.publish(new ContentTagDeletedEvent(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1820,41 +1852,6 @@ public class Case {
|
|||||||
eventPublisher.publish(new DataSourceNameChangedEvent(dataSource, newName));
|
eventPublisher.publish(new DataSourceNameChangedEvent(dataSource, newName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies case event subscribers that a content tag has been added.
|
|
||||||
*
|
|
||||||
* This should not be called from the event dispatch thread (EDT)
|
|
||||||
*
|
|
||||||
* @param newTag new ContentTag added
|
|
||||||
*/
|
|
||||||
public void notifyContentTagAdded(ContentTag newTag) {
|
|
||||||
notifyContentTagAdded(newTag, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies case event subscribers that a content tag has been added.
|
|
||||||
*
|
|
||||||
* This should not be called from the event dispatch thread (EDT)
|
|
||||||
*
|
|
||||||
* @param newTag The added ContentTag.
|
|
||||||
* @param deletedTagList List of ContentTags that were removed as a result
|
|
||||||
* of the addition of newTag.
|
|
||||||
*/
|
|
||||||
public void notifyContentTagAdded(ContentTag newTag, List<ContentTag> deletedTagList) {
|
|
||||||
eventPublisher.publish(new ContentTagAddedEvent(newTag, deletedTagList));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies case event subscribers that a content tag has been deleted.
|
|
||||||
*
|
|
||||||
* This should not be called from the event dispatch thread (EDT)
|
|
||||||
*
|
|
||||||
* @param deletedTag ContentTag deleted
|
|
||||||
*/
|
|
||||||
public void notifyContentTagDeleted(ContentTag deletedTag) {
|
|
||||||
eventPublisher.publish(new ContentTagDeletedEvent(deletedTag));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies case event subscribers that a tag definition has changed.
|
* Notifies case event subscribers that a tag definition has changed.
|
||||||
*
|
*
|
||||||
@ -1885,41 +1882,6 @@ public class Case {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies case event subscribers that an artifact tag has been added.
|
|
||||||
*
|
|
||||||
* This should not be called from the event dispatch thread (EDT)
|
|
||||||
*
|
|
||||||
* @param newTag new BlackboardArtifactTag added
|
|
||||||
*/
|
|
||||||
public void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag) {
|
|
||||||
notifyBlackBoardArtifactTagAdded(newTag, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies case event subscribers that an artifact tag has been added.
|
|
||||||
*
|
|
||||||
* This should not be called from the event dispatch thread (EDT)
|
|
||||||
*
|
|
||||||
* @param newTag The added ContentTag.
|
|
||||||
* @param removedTagList List of ContentTags that were removed as a result
|
|
||||||
* of the addition of newTag.
|
|
||||||
*/
|
|
||||||
public void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag, List<BlackboardArtifactTag> removedTagList) {
|
|
||||||
eventPublisher.publish(new BlackBoardArtifactTagAddedEvent(newTag, removedTagList));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies case event subscribers that an artifact tag has been deleted.
|
|
||||||
*
|
|
||||||
* This should not be called from the event dispatch thread (EDT)
|
|
||||||
*
|
|
||||||
* @param deletedTag BlackboardArtifactTag deleted
|
|
||||||
*/
|
|
||||||
public void notifyBlackBoardArtifactTagDeleted(BlackboardArtifactTag deletedTag) {
|
|
||||||
eventPublisher.publish(new BlackBoardArtifactTagDeletedEvent(deletedTag));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a report to the case.
|
* Adds a report to the case.
|
||||||
*
|
*
|
||||||
|
@ -66,9 +66,9 @@ public class TagsManager implements Closeable {
|
|||||||
private static String PROJECT_VIC_TAG_SET_NAME = "Project VIC";
|
private static String PROJECT_VIC_TAG_SET_NAME = "Project VIC";
|
||||||
|
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
|
|
||||||
private final Map<String, TagName> allTagNameMap = Collections.synchronizedMap(new HashMap<>());
|
private final Map<String, TagName> allTagNameMap = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
private final PropertyChangeListener listener = new PropertyChangeListener() {
|
private final PropertyChangeListener listener = new PropertyChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
@ -95,7 +95,7 @@ public class TagsManager implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final PropertyChangeListener weakListener = WeakListeners.propertyChange(listener, null);
|
private final PropertyChangeListener weakListener = WeakListeners.propertyChange(listener, null);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -300,12 +300,12 @@ public class TagsManager implements Closeable {
|
|||||||
try {
|
try {
|
||||||
List<TagSet> tagSetsInCase = taggingMgr.getTagSets();
|
List<TagSet> tagSetsInCase = taggingMgr.getTagSets();
|
||||||
if (tagSetsInCase.isEmpty()) {
|
if (tagSetsInCase.isEmpty()) {
|
||||||
|
|
||||||
// add the standard tag names
|
// add the standard tag names
|
||||||
for (TagNameDefinition def : TagNameDefinition.getStandardTagNameDefinitions()) {
|
for (TagNameDefinition def : TagNameDefinition.getStandardTagNameDefinitions()) {
|
||||||
taggingMgr.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus());
|
taggingMgr.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
//Assume new case and add all tag sets
|
//Assume new case and add all tag sets
|
||||||
for (TagSetDefinition setDef : TagSetDefinition.readTagSetDefinitions()) {
|
for (TagSetDefinition setDef : TagSetDefinition.readTagSetDefinitions()) {
|
||||||
List<TagName> tagNamesInSet = new ArrayList<>();
|
List<TagName> tagNamesInSet = new ArrayList<>();
|
||||||
@ -317,12 +317,12 @@ public class TagsManager implements Closeable {
|
|||||||
taggingMgr.addTagSet(setDef.getName(), tagNamesInSet);
|
taggingMgr.addTagSet(setDef.getName(), tagNamesInSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(TagName tagName: caseDb.getAllTagNames()) {
|
for (TagName tagName : caseDb.getAllTagNames()) {
|
||||||
allTagNameMap.put(tagName.getDisplayName(), tagName);
|
allTagNameMap.put(tagName.getDisplayName(), tagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error updating standard tag name and tag set definitions", ex);
|
LOGGER.log(Level.SEVERE, "Error updating standard tag name and tag set definitions", ex);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
@ -332,7 +332,7 @@ public class TagsManager implements Closeable {
|
|||||||
for (TagNameDefinition tagName : TagNameDefinition.getTagNameDefinitions()) {
|
for (TagNameDefinition tagName : TagNameDefinition.getTagNameDefinitions()) {
|
||||||
tagName.saveToCase(caseDb);
|
tagName.saveToCase(caseDb);
|
||||||
}
|
}
|
||||||
|
|
||||||
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_UPDATED), weakListener);
|
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_UPDATED), weakListener);
|
||||||
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_ADDED), weakListener);
|
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_ADDED), weakListener);
|
||||||
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_DELETED), weakListener);
|
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_DELETED), weakListener);
|
||||||
@ -359,7 +359,7 @@ public class TagsManager implements Closeable {
|
|||||||
* @throws TskCoreException If there is an error querying the case database.
|
* @throws TskCoreException If there is an error querying the case database.
|
||||||
*/
|
*/
|
||||||
public TagSet getTagSet(TagName tagName) throws TskCoreException {
|
public TagSet getTagSet(TagName tagName) throws TskCoreException {
|
||||||
return caseDb.getTaggingManager().getTagSet(tagName);
|
return caseDb.getTaggingManager().getTagSet(tagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -383,7 +383,7 @@ public class TagsManager implements Closeable {
|
|||||||
* @return A list, possibly empty, of TagName objects.
|
* @return A list, possibly empty, of TagName objects.
|
||||||
*/
|
*/
|
||||||
public synchronized List<TagName> getAllTagNames() {
|
public synchronized List<TagName> getAllTagNames() {
|
||||||
|
|
||||||
List<TagName> tagNames = new ArrayList<>();
|
List<TagName> tagNames = new ArrayList<>();
|
||||||
tagNames.addAll(allTagNameMap.values());
|
tagNames.addAll(allTagNameMap.values());
|
||||||
return tagNames;
|
return tagNames;
|
||||||
@ -636,14 +636,6 @@ public class TagsManager implements Closeable {
|
|||||||
*/
|
*/
|
||||||
public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException {
|
public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException {
|
||||||
TaggingManager.ContentTagChange tagChange = caseDb.getTaggingManager().addContentTag(content, tagName, comment, beginByteOffset, endByteOffset);
|
TaggingManager.ContentTagChange tagChange = caseDb.getTaggingManager().addContentTag(content, tagName, comment, beginByteOffset, endByteOffset);
|
||||||
try {
|
|
||||||
Case currentCase = Case.getCurrentCaseThrows();
|
|
||||||
|
|
||||||
currentCase.notifyContentTagAdded(tagChange.getAddedTag(), tagChange.getRemovedTags().isEmpty() ? null : tagChange.getRemovedTags());
|
|
||||||
|
|
||||||
} catch (NoCurrentCaseException ex) {
|
|
||||||
throw new TskCoreException("Added a tag to a closed case", ex);
|
|
||||||
}
|
|
||||||
return tagChange.getAddedTag();
|
return tagChange.getAddedTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,11 +649,6 @@ public class TagsManager implements Closeable {
|
|||||||
*/
|
*/
|
||||||
public void deleteContentTag(ContentTag tag) throws TskCoreException {
|
public void deleteContentTag(ContentTag tag) throws TskCoreException {
|
||||||
caseDb.deleteContentTag(tag);
|
caseDb.deleteContentTag(tag);
|
||||||
try {
|
|
||||||
Case.getCurrentCaseThrows().notifyContentTagDeleted(tag);
|
|
||||||
} catch (NoCurrentCaseException ex) {
|
|
||||||
throw new TskCoreException("Deleted a tag from a closed case", ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -857,12 +844,6 @@ public class TagsManager implements Closeable {
|
|||||||
*/
|
*/
|
||||||
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
|
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
|
||||||
TaggingManager.BlackboardArtifactTagChange tagChange = caseDb.getTaggingManager().addArtifactTag(artifact, tagName, comment);
|
TaggingManager.BlackboardArtifactTagChange tagChange = caseDb.getTaggingManager().addArtifactTag(artifact, tagName, comment);
|
||||||
try {
|
|
||||||
Case currentCase = Case.getCurrentCaseThrows();
|
|
||||||
currentCase.notifyBlackBoardArtifactTagAdded(tagChange.getAddedTag(), tagChange.getRemovedTags().isEmpty() ? null : tagChange.getRemovedTags());
|
|
||||||
} catch (NoCurrentCaseException ex) {
|
|
||||||
throw new TskCoreException("Added a tag to a closed case", ex);
|
|
||||||
}
|
|
||||||
return tagChange.getAddedTag();
|
return tagChange.getAddedTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -876,11 +857,6 @@ public class TagsManager implements Closeable {
|
|||||||
*/
|
*/
|
||||||
public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
|
public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
|
||||||
caseDb.deleteBlackboardArtifactTag(tag);
|
caseDb.deleteBlackboardArtifactTag(tag);
|
||||||
try {
|
|
||||||
Case.getCurrentCaseThrows().notifyBlackBoardArtifactTagDeleted(tag);
|
|
||||||
} catch (NoCurrentCaseException ex) {
|
|
||||||
throw new TskCoreException("Deleted a tag from a closed case", ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,12 +91,6 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
*/
|
*/
|
||||||
T visit(Tags.RootNode node);
|
T visit(Tags.RootNode node);
|
||||||
|
|
||||||
T visit(Tags.TagNameNode node);
|
|
||||||
|
|
||||||
T visit(Tags.ContentTagTypeNode node);
|
|
||||||
|
|
||||||
T visit(Tags.BlackboardArtifactTagTypeNode node);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reports
|
* Reports
|
||||||
@ -270,21 +264,6 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
return defaultVisit(node);
|
return defaultVisit(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public T visit(Tags.TagNameNode node) {
|
|
||||||
return defaultVisit(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T visit(Tags.ContentTagTypeNode node) {
|
|
||||||
return defaultVisit(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T visit(Tags.BlackboardArtifactTagTypeNode node) {
|
|
||||||
return defaultVisit(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(Reports.ReportsListNode node) {
|
public T visit(Reports.ReportsListNode node) {
|
||||||
return defaultVisit(node);
|
return defaultVisit(node);
|
||||||
|
@ -97,7 +97,7 @@ public class RootContentChildren extends Children.Keys<Object> {
|
|||||||
public static Node createNode(Object key) {
|
public static Node createNode(Object key) {
|
||||||
if (key instanceof Tags) {
|
if (key instanceof Tags) {
|
||||||
Tags tagsNodeKey = (Tags) key;
|
Tags tagsNodeKey = (Tags) key;
|
||||||
return tagsNodeKey.new RootNode(tagsNodeKey.filteringDataSourceObjId());
|
return new Tags.RootNode(tagsNodeKey.filteringDataSourceObjId());
|
||||||
} else if (key instanceof DataSources) {
|
} else if (key instanceof DataSources) {
|
||||||
DataSources dataSourcesKey = (DataSources) key;
|
DataSources dataSourcesKey = (DataSources) key;
|
||||||
return new DataSourceFilesNode(dataSourcesKey.filteringDataSourceObjId());
|
return new DataSourceFilesNode(dataSourcesKey.filteringDataSourceObjId());
|
||||||
|
@ -18,39 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import java.beans.PropertyChangeEvent;
|
|
||||||
import java.beans.PropertyChangeListener;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Observable;
|
|
||||||
import java.util.Observer;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import org.openide.nodes.ChildFactory;
|
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.WeakListeners;
|
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.mainui.nodes.TagNameFactory;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
|
||||||
import org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams;
|
|
||||||
import static org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams.TagType.FILE;
|
|
||||||
import static org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams.TagType.RESULT;
|
|
||||||
import org.sleuthkit.autopsy.corecomponents.SelectionResponder;
|
|
||||||
import org.sleuthkit.autopsy.tags.TagUtils;
|
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
|
||||||
import org.sleuthkit.datamodel.ContentTag;
|
|
||||||
import org.sleuthkit.datamodel.TagName;
|
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instances of this class act as keys for use by instances of the
|
* Instances of this class act as keys for use by instances of the
|
||||||
@ -58,16 +31,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* factory built on top of the NetBeans Children.Keys class.
|
* factory built on top of the NetBeans Children.Keys class.
|
||||||
*/
|
*/
|
||||||
public class Tags {
|
public class Tags {
|
||||||
// Creation of a RootNode object corresponding to a Tags object is done
|
|
||||||
// by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren
|
|
||||||
// override of Children.Keys<T>.createNodes().
|
|
||||||
|
|
||||||
private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text");
|
private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text");
|
||||||
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED);
|
|
||||||
private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS
|
|
||||||
private final TagResults tagResults = new TagResults();
|
|
||||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
|
||||||
|
|
||||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||||
|
|
||||||
Tags() {
|
Tags() {
|
||||||
@ -90,35 +54,24 @@ public class Tags {
|
|||||||
long filteringDataSourceObjId() {
|
long filteringDataSourceObjId() {
|
||||||
return this.filteringDSObjId;
|
return this.filteringDSObjId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class largely does nothing except act as a top-level object that the
|
|
||||||
* other nodes can listen to. This mimics what other nodes have (keword
|
|
||||||
* search, etc.), but theirs stores data.
|
|
||||||
*/
|
|
||||||
private class TagResults extends Observable {
|
|
||||||
|
|
||||||
public void update() {
|
|
||||||
setChanged();
|
|
||||||
notifyObservers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instances of this class are the root nodes of tree that is a sub-tree of
|
* Instances of this class are the root nodes of tree that is a sub-tree of
|
||||||
* the Autopsy presentation of the SleuthKit data model. The sub-tree
|
* the Autopsy presentation of the SleuthKit data model. The sub-tree
|
||||||
* consists of content and blackboard artifact tags, grouped first by tag
|
* consists of content and blackboard artifact tags, grouped first by tag
|
||||||
* type, then by tag name.
|
* type, then by tag name.
|
||||||
*/
|
*/
|
||||||
public class RootNode extends DisplayableItemNode {
|
public static class RootNode extends DisplayableItemNode {
|
||||||
|
|
||||||
|
private final static String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
||||||
|
private final Long dataSourceObjId;
|
||||||
|
|
||||||
public RootNode(long objId) {
|
public RootNode(Long dsId) {
|
||||||
super(Children.create(new TagNameNodeFactory(objId), true), Lookups.singleton(DISPLAY_NAME));
|
super(Children.create(new TagNameFactory(dsId != null && dsId> 0 ? dsId : null), true), Lookups.singleton(DISPLAY_NAME));
|
||||||
super.setName(DISPLAY_NAME);
|
super.setName(DISPLAY_NAME);
|
||||||
super.setDisplayName(DISPLAY_NAME);
|
super.setDisplayName(DISPLAY_NAME);
|
||||||
this.setIconBaseWithExtension(ICON_PATH);
|
this.setIconBaseWithExtension(ICON_PATH);
|
||||||
|
this.dataSourceObjId = dsId != null && dsId> 0 ? dsId : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -148,423 +101,16 @@ public class Tags {
|
|||||||
public String getItemType() {
|
public String getItemType() {
|
||||||
return getClass().getName();
|
return getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Node clone() {
|
||||||
|
return new RootNode(dataSourceObjId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cause the contents of the RootNode and its children to be updated.
|
* Cause the contents of the RootNode and its children to be updated.
|
||||||
*/
|
*/
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
tagResults.update();
|
this.refresh();
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TagNameNodeFactory extends ChildFactory.Detachable<TagName> implements Observer {
|
|
||||||
|
|
||||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
|
||||||
|
|
||||||
private final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED,
|
|
||||||
Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED,
|
|
||||||
Case.Events.CONTENT_TAG_ADDED,
|
|
||||||
Case.Events.CONTENT_TAG_DELETED,
|
|
||||||
Case.Events.CURRENT_CASE);
|
|
||||||
|
|
||||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
|
||||||
String eventType = evt.getPropertyName();
|
|
||||||
if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString())
|
|
||||||
|| eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString())
|
|
||||||
|| eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())
|
|
||||||
|| eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
|
|
||||||
/**
|
|
||||||
* Checking for a current case is a stop gap measure until a
|
|
||||||
* different way of handling the closing of cases is worked
|
|
||||||
* out. Currently, remote events may be received for a case
|
|
||||||
* that is already closed.
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
Case.getCurrentCaseThrows();
|
|
||||||
refresh(true);
|
|
||||||
tagResults.update();
|
|
||||||
} catch (NoCurrentCaseException notUsed) {
|
|
||||||
/**
|
|
||||||
* Case is closed, do nothing.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
|
||||||
/**
|
|
||||||
* Checking for a current case is a stop gap measure until a
|
|
||||||
* different way of handling the closing of cases is worked
|
|
||||||
* out. Currently, remote events may be received for a case
|
|
||||||
* that is already closed.
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
Case.getCurrentCaseThrows();
|
|
||||||
refresh(true);
|
|
||||||
tagResults.update();
|
|
||||||
} catch (NoCurrentCaseException notUsed) {
|
|
||||||
/**
|
|
||||||
* Case is closed, do nothing.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
|
||||||
// case was closed. Remove listeners so that this can be garbage collected
|
|
||||||
if (evt.getNewValue() == null) {
|
|
||||||
removeNotify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param objId data source object id
|
|
||||||
*/
|
|
||||||
TagNameNodeFactory(long objId) {
|
|
||||||
this.filteringDSObjId = objId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addNotify() {
|
|
||||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
|
||||||
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
|
|
||||||
tagResults.update();
|
|
||||||
tagResults.addObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
|
||||||
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
|
|
||||||
tagResults.deleteObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean createKeys(List<TagName> keys) {
|
|
||||||
try {
|
|
||||||
List<TagName> tagNamesInUse;
|
|
||||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
|
||||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
|
||||||
tagNamesInUse = (filteringDSObjId > 0)
|
|
||||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(filteringDSObjId, userName)
|
|
||||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(userName);
|
|
||||||
} else {
|
|
||||||
tagNamesInUse = (filteringDSObjId > 0)
|
|
||||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(filteringDSObjId)
|
|
||||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse();
|
|
||||||
}
|
|
||||||
Collections.sort(tagNamesInUse, new Comparator<TagName>() {
|
|
||||||
@Override
|
|
||||||
public int compare(TagName o1, TagName o2) {
|
|
||||||
return TagUtils.getDecoratedTagDisplayName(o1).compareTo(TagUtils.getDecoratedTagDisplayName(o2));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
keys.addAll(tagNamesInUse);
|
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
|
||||||
Logger.getLogger(TagNameNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Node createNodeForKey(TagName key) {
|
|
||||||
return new TagNameNode(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(Observable o, Object arg) {
|
|
||||||
refresh(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are elements of Node hierarchies consisting of
|
|
||||||
* content and blackboard artifact tags, grouped first by tag type, then by
|
|
||||||
* tag name.
|
|
||||||
*/
|
|
||||||
public class TagNameNode extends DisplayableItemNode implements Observer {
|
|
||||||
|
|
||||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
|
||||||
private final String BOOKMARK_TAG_ICON_PATH = "org/sleuthkit/autopsy/images/star-bookmark-icon-16.png"; //NON-NLS
|
|
||||||
private final TagName tagName;
|
|
||||||
|
|
||||||
public TagNameNode(TagName tagName) {
|
|
||||||
super(Children.create(new TagTypeNodeFactory(tagName), true), Lookups.singleton(NbBundle.getMessage(TagNameNode.class, "TagNameNode.namePlusTags.text", tagName.getDisplayName())));
|
|
||||||
this.tagName = tagName;
|
|
||||||
setName(TagUtils.getDecoratedTagDisplayName(tagName));
|
|
||||||
updateDisplayName();
|
|
||||||
if (tagName.getDisplayName().equals(TagsManager.getBookmarkTagDisplayName())) {
|
|
||||||
setIconBaseWithExtension(BOOKMARK_TAG_ICON_PATH);
|
|
||||||
} else {
|
|
||||||
setIconBaseWithExtension(ICON_PATH);
|
|
||||||
}
|
|
||||||
tagResults.addObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDisplayName() {
|
|
||||||
long tagsCount = 0;
|
|
||||||
try {
|
|
||||||
TagsManager tm = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
|
||||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
|
||||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
|
||||||
if (filteringDSObjId > 0) {
|
|
||||||
tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, filteringDSObjId, userName);
|
|
||||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, filteringDSObjId, userName);
|
|
||||||
} else {
|
|
||||||
tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, userName);
|
|
||||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (filteringDSObjId > 0) {
|
|
||||||
tagsCount = tm.getContentTagsCountByTagName(tagName, filteringDSObjId);
|
|
||||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, filteringDSObjId);
|
|
||||||
} else {
|
|
||||||
tagsCount = tm.getContentTagsCountByTagName(tagName);
|
|
||||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
|
||||||
Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
setDisplayName(TagUtils.getDecoratedTagDisplayName(tagName) + " \u200E(\u200E" + tagsCount + ")\u200E");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Sheet createSheet() {
|
|
||||||
Sheet propertySheet = super.createSheet();
|
|
||||||
Sheet.Set properties = propertySheet.get(Sheet.PROPERTIES);
|
|
||||||
if (properties == null) {
|
|
||||||
properties = Sheet.createPropertiesSet();
|
|
||||||
propertySheet.put(properties);
|
|
||||||
}
|
|
||||||
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "TagNameNode.createSheet.name.name"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "TagNameNode.createSheet.name.displayName"), tagName.getDescription(), getName()));
|
|
||||||
return propertySheet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
|
||||||
// See classes derived from DisplayableItemNodeVisitor<AbstractNode>
|
|
||||||
// for behavior added using the Visitor pattern.
|
|
||||||
return visitor.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLeafTypeNode() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(Observable o, Object arg) {
|
|
||||||
updateDisplayName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getItemType() {
|
|
||||||
return getClass().getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates nodes for the two types of tags: file and artifact. Does not need
|
|
||||||
* observer / messages since it always has the same children
|
|
||||||
*/
|
|
||||||
private class TagTypeNodeFactory extends ChildFactory<String> {
|
|
||||||
|
|
||||||
private final TagName tagName;
|
|
||||||
private final String CONTENT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.contentTagTypeNodeKey.text");
|
|
||||||
private final String BLACKBOARD_ARTIFACT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.bbArtTagTypeNodeKey.text");
|
|
||||||
|
|
||||||
TagTypeNodeFactory(TagName tagName) {
|
|
||||||
super();
|
|
||||||
this.tagName = tagName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean createKeys(List<String> keys) {
|
|
||||||
keys.add(CONTENT_TAG_TYPE_NODE_KEY);
|
|
||||||
keys.add(BLACKBOARD_ARTIFACT_TAG_TYPE_NODE_KEY);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Node createNodeForKey(String key) {
|
|
||||||
if (CONTENT_TAG_TYPE_NODE_KEY.equals(key)) {
|
|
||||||
return new ContentTagTypeNode(tagName);
|
|
||||||
} else if (BLACKBOARD_ARTIFACT_TAG_TYPE_NODE_KEY.equals(key)) {
|
|
||||||
return new BlackboardArtifactTagTypeNode(tagName);
|
|
||||||
} else {
|
|
||||||
Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "{0} not a recognized key", key); //NON-NLS
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String CONTENT_DISPLAY_NAME = NbBundle.getMessage(ContentTagTypeNode.class, "ContentTagTypeNode.displayName.text");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Node for the content tags. Children are specific tags. Instances of this
|
|
||||||
* class are are elements of a directory tree sub-tree consisting of content
|
|
||||||
* and blackboard artifact tags, grouped first by tag type, then by tag
|
|
||||||
* name.
|
|
||||||
*/
|
|
||||||
public class ContentTagTypeNode extends DisplayableItemNode implements Observer, SelectionResponder {
|
|
||||||
|
|
||||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
|
||||||
private final TagName tagName;
|
|
||||||
|
|
||||||
public ContentTagTypeNode(TagName tagName) {
|
|
||||||
super(Children.LEAF, Lookups.singleton(tagName.getDisplayName() + " " + CONTENT_DISPLAY_NAME));
|
|
||||||
this.tagName = tagName;
|
|
||||||
super.setName(CONTENT_DISPLAY_NAME);
|
|
||||||
updateDisplayName();
|
|
||||||
this.setIconBaseWithExtension(ICON_PATH);
|
|
||||||
tagResults.addObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void respondSelection(DataResultTopComponent dataResultPanel) {
|
|
||||||
dataResultPanel.displayTags(new TagsSearchParams(tagName, FILE,
|
|
||||||
filteringDataSourceObjId() > 0 ? filteringDataSourceObjId() : null));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDisplayName() {
|
|
||||||
long tagsCount = 0;
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
|
||||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
|
||||||
tagsCount = (filteringDSObjId > 0)
|
|
||||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, filteringDSObjId, userName)
|
|
||||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, userName);
|
|
||||||
} else {
|
|
||||||
tagsCount = (filteringDSObjId > 0)
|
|
||||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, filteringDSObjId)
|
|
||||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName);
|
|
||||||
}
|
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
|
||||||
Logger.getLogger(ContentTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get content tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
super.setDisplayName(CONTENT_DISPLAY_NAME + " (" + tagsCount + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Sheet createSheet() {
|
|
||||||
Sheet propertySheet = super.createSheet();
|
|
||||||
Sheet.Set properties = propertySheet.get(Sheet.PROPERTIES);
|
|
||||||
if (properties == null) {
|
|
||||||
properties = Sheet.createPropertiesSet();
|
|
||||||
propertySheet.put(properties);
|
|
||||||
}
|
|
||||||
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagTypeNode.createSheet.name.name"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "ContentTagTypeNode.createSheet.name.displayName"), "", getName()));
|
|
||||||
return propertySheet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
|
||||||
return visitor.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLeafTypeNode() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(Observable o, Object arg) {
|
|
||||||
updateDisplayName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getItemType() {
|
|
||||||
return getClass().getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String ARTIFACT_DISPLAY_NAME = NbBundle.getMessage(BlackboardArtifactTagTypeNode.class, "BlackboardArtifactTagTypeNode.displayName.text");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are elements in a sub-tree of the Autopsy
|
|
||||||
* presentation of the SleuthKit data model. The sub-tree consists of
|
|
||||||
* content and blackboard artifact tags, grouped first by tag type, then by
|
|
||||||
* tag name.
|
|
||||||
*/
|
|
||||||
public class BlackboardArtifactTagTypeNode extends DisplayableItemNode implements Observer, SelectionResponder {
|
|
||||||
|
|
||||||
private final TagName tagName;
|
|
||||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
|
||||||
|
|
||||||
public BlackboardArtifactTagTypeNode(TagName tagName) {
|
|
||||||
super(Children.LEAF, Lookups.singleton(tagName.getDisplayName() + " " + ARTIFACT_DISPLAY_NAME));
|
|
||||||
this.tagName = tagName;
|
|
||||||
super.setName(ARTIFACT_DISPLAY_NAME);
|
|
||||||
this.setIconBaseWithExtension(ICON_PATH);
|
|
||||||
updateDisplayName();
|
|
||||||
tagResults.addObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void respondSelection(DataResultTopComponent dataResultPanel) {
|
|
||||||
dataResultPanel.displayTags(new TagsSearchParams(tagName, RESULT,
|
|
||||||
filteringDataSourceObjId() > 0 ? filteringDataSourceObjId() : null));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDisplayName() {
|
|
||||||
long tagsCount = 0;
|
|
||||||
try {
|
|
||||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
|
||||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
|
||||||
tagsCount = (filteringDSObjId > 0)
|
|
||||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, filteringDSObjId, userName)
|
|
||||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName);
|
|
||||||
} else {
|
|
||||||
tagsCount = (filteringDSObjId > 0)
|
|
||||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, filteringDSObjId)
|
|
||||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName);
|
|
||||||
}
|
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
|
||||||
Logger.getLogger(BlackboardArtifactTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get blackboard artifact tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
super.setDisplayName(ARTIFACT_DISPLAY_NAME + " (" + tagsCount + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Sheet createSheet() {
|
|
||||||
Sheet propertySheet = super.createSheet();
|
|
||||||
Sheet.Set properties = propertySheet.get(Sheet.PROPERTIES);
|
|
||||||
if (properties == null) {
|
|
||||||
properties = Sheet.createPropertiesSet();
|
|
||||||
propertySheet.put(properties);
|
|
||||||
}
|
|
||||||
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "BlackboardArtifactTagTypeNode.createSheet.name.name"),
|
|
||||||
NbBundle.getMessage(this.getClass(), "BlackboardArtifactTagTypeNode.createSheet.name.displayName"), "", getName()));
|
|
||||||
return propertySheet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
|
||||||
return visitor.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLeafTypeNode() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(Observable o, Object arg) {
|
|
||||||
updateDisplayName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getItemType() {
|
|
||||||
return getClass().getName();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
|
|||||||
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
|
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.LocalDirectoryNode;
|
import org.sleuthkit.autopsy.datamodel.LocalDirectoryNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
|
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||||
import org.sleuthkit.autopsy.datamodel.ViewsNode;
|
import org.sleuthkit.autopsy.datamodel.ViewsNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.VolumeNode;
|
import org.sleuthkit.autopsy.datamodel.VolumeNode;
|
||||||
@ -92,6 +93,9 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
|
|||||||
} else if (origNode instanceof AnalysisResults.RootNode) {
|
} else if (origNode instanceof AnalysisResults.RootNode) {
|
||||||
Node cloned = ((AnalysisResults.RootNode) origNode).clone();
|
Node cloned = ((AnalysisResults.RootNode) origNode).clone();
|
||||||
return new Node[]{cloned};
|
return new Node[]{cloned};
|
||||||
|
} else if (origNode instanceof Tags.RootNode) {
|
||||||
|
Node cloned = ((Tags.RootNode) origNode).clone();
|
||||||
|
return new Node[]{cloned};
|
||||||
} else if (origNode instanceof ViewsNode) {
|
} else if (origNode instanceof ViewsNode) {
|
||||||
Node cloned = ((ViewsNode) origNode).clone();
|
Node cloned = ((ViewsNode) origNode).clone();
|
||||||
return new Node[]{cloned};
|
return new Node[]{cloned};
|
||||||
|
@ -327,7 +327,7 @@ public class ExtractActionHelper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ExtractFscContentVisitor<T, V> getChildVisitor(File childFile, ProgressHandle progress, SwingWorker<T, V> worker) {
|
protected ExtractFscContentVisitor<T, V> getChildVisitor(File childFile, ProgressHandle progress, SwingWorker<T, V> worker) {
|
||||||
return new UIExtractionVisitor(childFile, progress, worker, false);
|
return new UIExtractionVisitor<>(childFile, progress, worker, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,3 +117,5 @@ TagsDAO.tagColumns.sourceNameColLbl=Source Name
|
|||||||
TagsDAO.tagColumns.sourcePathColLbl=Source File Path
|
TagsDAO.tagColumns.sourcePathColLbl=Source File Path
|
||||||
TagsDAO.tagColumns.typeColLbl=Result Type
|
TagsDAO.tagColumns.typeColLbl=Result Type
|
||||||
TagsDAO.tagColumns.userNameColLbl=User Name
|
TagsDAO.tagColumns.userNameColLbl=User Name
|
||||||
|
TagType_File_displayName=File Tags
|
||||||
|
TagType_Result_displayName=Result Tags
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2022 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.mainui.datamodel;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Search param for a tag name.
|
||||||
|
*/
|
||||||
|
public class TagNameSearchParams {
|
||||||
|
|
||||||
|
private static final String TYPE_ID = "TAG_TYPE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The type id for this search parameter.
|
||||||
|
*/
|
||||||
|
public static String getTypeId() {
|
||||||
|
return TYPE_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final TagName tagName;
|
||||||
|
private final Long dataSourceId;
|
||||||
|
|
||||||
|
public TagNameSearchParams(TagName tagName, Long dataSourceId) {
|
||||||
|
this.dataSourceId = dataSourceId;
|
||||||
|
this.tagName = tagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TagName getTagName() {
|
||||||
|
return tagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDataSourceId() {
|
||||||
|
return dataSourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 3;
|
||||||
|
hash = 67 * hash + Objects.hashCode(this.tagName);
|
||||||
|
hash = 67 * hash + Objects.hashCode(this.dataSourceId);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final TagNameSearchParams other = (TagNameSearchParams) obj;
|
||||||
|
if (!Objects.equals(this.tagName, other.tagName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.dataSourceId, other.dataSourceId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -22,15 +22,20 @@ import org.sleuthkit.autopsy.mainui.datamodel.events.DAOEvent;
|
|||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@ -42,21 +47,29 @@ import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
|
|||||||
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||||
import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_DURATION;
|
import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_DURATION;
|
||||||
import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_DURATION_UNITS;
|
import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_DURATION_UNITS;
|
||||||
import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_SIZE;
|
import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_SIZE;
|
||||||
import org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams.TagType;
|
import org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams.TagType;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.TreeResultsDTO.TreeDisplayCount;
|
||||||
import org.sleuthkit.autopsy.mainui.datamodel.TreeResultsDTO.TreeItemDTO;
|
import org.sleuthkit.autopsy.mainui.datamodel.TreeResultsDTO.TreeItemDTO;
|
||||||
import org.sleuthkit.autopsy.mainui.datamodel.events.TagsEvent;
|
import org.sleuthkit.autopsy.mainui.datamodel.events.TagsEvent;
|
||||||
import org.sleuthkit.autopsy.mainui.datamodel.events.TreeCounts;
|
import org.sleuthkit.autopsy.mainui.datamodel.events.TreeCounts;
|
||||||
import org.sleuthkit.autopsy.mainui.datamodel.events.TreeEvent;
|
import org.sleuthkit.autopsy.mainui.datamodel.events.TreeEvent;
|
||||||
import org.sleuthkit.autopsy.mainui.nodes.DAOFetcher;
|
import org.sleuthkit.autopsy.mainui.nodes.DAOFetcher;
|
||||||
|
import org.sleuthkit.autopsy.tags.TagUtils;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.Account;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||||
|
import org.sleuthkit.datamodel.CaseDbAccessManager;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ContentTag;
|
import org.sleuthkit.datamodel.ContentTag;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.Tag;
|
import org.sleuthkit.datamodel.Tag;
|
||||||
import org.sleuthkit.datamodel.TagName;
|
import org.sleuthkit.datamodel.TagName;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -85,6 +98,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
"TagsDAO.tagColumns.userNameColLbl=User Name"})
|
"TagsDAO.tagColumns.userNameColLbl=User Name"})
|
||||||
public class TagsDAO extends AbstractDAO {
|
public class TagsDAO extends AbstractDAO {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(TagsDAO.class.getName());
|
||||||
|
|
||||||
private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS
|
private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS
|
||||||
|
|
||||||
private static final List<ColumnKey> FILE_TAG_COLUMNS = Arrays.asList(
|
private static final List<ColumnKey> FILE_TAG_COLUMNS = Arrays.asList(
|
||||||
@ -122,14 +137,12 @@ public class TagsDAO extends AbstractDAO {
|
|||||||
return new ColumnKey(name, name, Bundle.TagsDAO_fileColumns_noDescription());
|
return new ColumnKey(name, name, Bundle.TagsDAO_fileColumns_noDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Cache<SearchParams<TagsSearchParams>, SearchResultsDTO> searchParamsCache =
|
private final Cache<SearchParams<TagsSearchParams>, SearchResultsDTO> searchParamsCache
|
||||||
CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).expireAfterAccess(CACHE_DURATION, CACHE_DURATION_UNITS).build();
|
= CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).expireAfterAccess(CACHE_DURATION, CACHE_DURATION_UNITS).build();
|
||||||
private final TreeCounts<TagsEvent> treeCounts = new TreeCounts<>();
|
private final TreeCounts<TagsEvent> treeCounts = new TreeCounts<>();
|
||||||
|
|
||||||
public SearchResultsDTO getTags(TagsSearchParams key, long startItem, Long maxCount) throws ExecutionException, IllegalArgumentException {
|
public SearchResultsDTO getTags(TagsSearchParams key, long startItem, Long maxCount) throws ExecutionException, IllegalArgumentException {
|
||||||
if (key.getTagName() == null) {
|
if (key.getDataSourceId() != null && key.getDataSourceId() <= 0) {
|
||||||
throw new IllegalArgumentException("Must have non-null tag name");
|
|
||||||
} else if (key.getDataSourceId() != null && key.getDataSourceId() <= 0) {
|
|
||||||
throw new IllegalArgumentException("Data source id must be greater than 0 or null");
|
throw new IllegalArgumentException("Data source id must be greater than 0 or null");
|
||||||
} else if (key.getTagType() == null) {
|
} else if (key.getTagType() == null) {
|
||||||
throw new IllegalArgumentException("Must have non-null tag type");
|
throw new IllegalArgumentException("Must have non-null tag type");
|
||||||
@ -175,13 +188,14 @@ public class TagsDAO extends AbstractDAO {
|
|||||||
private SearchResultsDTO fetchResultTags(SearchParams<TagsSearchParams> cacheKey) throws NoCurrentCaseException, TskCoreException {
|
private SearchResultsDTO fetchResultTags(SearchParams<TagsSearchParams> cacheKey) throws NoCurrentCaseException, TskCoreException {
|
||||||
|
|
||||||
Long dataSourceId = cacheKey.getParamData().getDataSourceId();
|
Long dataSourceId = cacheKey.getParamData().getDataSourceId();
|
||||||
TagName tagName = cacheKey.getParamData().getTagName();
|
TagName tagNameId = cacheKey.getParamData().getTagName();
|
||||||
|
|
||||||
|
TagsManager tm = Case.getCurrentCase().getServices().getTagsManager();
|
||||||
// get all tag results
|
// get all tag results
|
||||||
List<BlackboardArtifactTag> allTags = new ArrayList<>();
|
List<BlackboardArtifactTag> allTags = new ArrayList<>();
|
||||||
List<BlackboardArtifactTag> artifactTags = (dataSourceId != null && dataSourceId > 0)
|
List<BlackboardArtifactTag> artifactTags = (dataSourceId != null && dataSourceId > 0)
|
||||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, dataSourceId)
|
? tm.getBlackboardArtifactTagsByTagName(tagNameId, dataSourceId)
|
||||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName);
|
: tm.getBlackboardArtifactTagsByTagName(tagNameId);
|
||||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
for (BlackboardArtifactTag tag : artifactTags) {
|
for (BlackboardArtifactTag tag : artifactTags) {
|
||||||
@ -233,13 +247,15 @@ public class TagsDAO extends AbstractDAO {
|
|||||||
private SearchResultsDTO fetchFileTags(SearchParams<TagsSearchParams> cacheKey) throws NoCurrentCaseException, TskCoreException {
|
private SearchResultsDTO fetchFileTags(SearchParams<TagsSearchParams> cacheKey) throws NoCurrentCaseException, TskCoreException {
|
||||||
|
|
||||||
Long dataSourceId = cacheKey.getParamData().getDataSourceId();
|
Long dataSourceId = cacheKey.getParamData().getDataSourceId();
|
||||||
TagName tagName = cacheKey.getParamData().getTagName();
|
TagName tagNameId = cacheKey.getParamData().getTagName();
|
||||||
|
|
||||||
|
TagsManager tm = Case.getCurrentCase().getServices().getTagsManager();
|
||||||
|
|
||||||
// get all tag results
|
// get all tag results
|
||||||
List<ContentTag> allTags = new ArrayList<>();
|
List<ContentTag> allTags = new ArrayList<>();
|
||||||
List<ContentTag> contentTags = (dataSourceId != null && dataSourceId > 0)
|
List<ContentTag> contentTags = (dataSourceId != null && dataSourceId > 0)
|
||||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, dataSourceId)
|
? tm.getContentTagsByTagName(tagNameId, dataSourceId)
|
||||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName);
|
: tm.getContentTagsByTagName(tagNameId);
|
||||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
for (ContentTag tag : contentTags) {
|
for (ContentTag tag : contentTags) {
|
||||||
@ -307,10 +323,10 @@ public class TagsDAO extends AbstractDAO {
|
|||||||
|
|
||||||
private TreeItemDTO<TagsSearchParams> getTreeItem(TagsEvent evt, TreeResultsDTO.TreeDisplayCount count) {
|
private TreeItemDTO<TagsSearchParams> getTreeItem(TagsEvent evt, TreeResultsDTO.TreeDisplayCount count) {
|
||||||
return new TreeItemDTO<>(
|
return new TreeItemDTO<>(
|
||||||
TagsSearchParams.getTypeId(),
|
TagsSearchParams.getTypeId(),
|
||||||
new TagsSearchParams(evt.getTagName(), evt.getTagType(), evt.getDataSourceId()),
|
new TagsSearchParams(evt.getTagName(), evt.getTagType(), evt.getDataSourceId()),
|
||||||
evt.getTagName().getId(),
|
evt.getTagName().getId(),
|
||||||
evt.getTagName().getDisplayName(),
|
evt.getTagName().getDisplayName(),
|
||||||
count);
|
count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,9 +361,9 @@ public class TagsDAO extends AbstractDAO {
|
|||||||
|
|
||||||
Collection<TagsEvent> daoEvents = Collections.singletonList(data);
|
Collection<TagsEvent> daoEvents = Collections.singletonList(data);
|
||||||
|
|
||||||
Collection<TreeEvent> treeEvents = this.treeCounts.enqueueAll(daoEvents).stream()
|
Collection<TreeEvent> treeEvents = daoEvents.stream()
|
||||||
.map(arEvt -> new TreeEvent(getTreeItem(arEvt, TreeResultsDTO.TreeDisplayCount.INDETERMINATE), false))
|
.map(arEvt -> new TreeEvent(getTreeItem(arEvt, TreeResultsDTO.TreeDisplayCount.UNSPECIFIED), true))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
return Stream.of(daoEvents, treeEvents)
|
return Stream.of(daoEvents, treeEvents)
|
||||||
.flatMap(lst -> lst.stream())
|
.flatMap(lst -> lst.stream())
|
||||||
@ -398,6 +414,208 @@ public class TagsDAO extends AbstractDAO {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the counts of each tag name.
|
||||||
|
*
|
||||||
|
* @param dataSourceId The data source object id to filter on.
|
||||||
|
*
|
||||||
|
* @return The tree item results.
|
||||||
|
*
|
||||||
|
* @throws ExecutionException
|
||||||
|
*/
|
||||||
|
public TreeResultsDTO<? extends TagNameSearchParams> getNameCounts(Long dataSourceId) throws ExecutionException {
|
||||||
|
Set<TagName> indeterminateTagNameIds = this.treeCounts.getEnqueued().stream()
|
||||||
|
.filter(evt -> dataSourceId == null || evt.getDataSourceId() == dataSourceId)
|
||||||
|
.map(evt -> evt.getTagName())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
Map<TagName, TreeDisplayCount> tagNameCount = new HashMap<>();
|
||||||
|
try {
|
||||||
|
TagsManager tm = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||||
|
|
||||||
|
List<TagName> tagNamesInUse;
|
||||||
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
|
tagNamesInUse = (dataSourceId != null)
|
||||||
|
? tm.getTagNamesInUseForUser(dataSourceId, userName)
|
||||||
|
: tm.getTagNamesInUseForUser(userName);
|
||||||
|
} else {
|
||||||
|
tagNamesInUse = (dataSourceId != null)
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(dataSourceId)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TagName tagName : tagNamesInUse) {
|
||||||
|
if (indeterminateTagNameIds.contains(tagName)) {
|
||||||
|
tagNameCount.put(tagName, TreeDisplayCount.INDETERMINATE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
long tagsCount;
|
||||||
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
|
if (dataSourceId != null) {
|
||||||
|
tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, dataSourceId, userName);
|
||||||
|
tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, dataSourceId, userName);
|
||||||
|
} else {
|
||||||
|
tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, userName);
|
||||||
|
tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dataSourceId != null) {
|
||||||
|
tagsCount = tm.getContentTagsCountByTagName(tagName, dataSourceId);
|
||||||
|
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, dataSourceId);
|
||||||
|
} else {
|
||||||
|
tagsCount = tm.getContentTagsCountByTagName(tagName);
|
||||||
|
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tagNameCount.put(tagName, TreeDisplayCount.getDeterminate(tagsCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||||
|
throw new ExecutionException("An error occurred while fetching data artifact counts.", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TreeResultsDTO.TreeItemDTO<TagNameSearchParams>> tagNameParams = tagNameCount.entrySet().stream()
|
||||||
|
.map(e -> createTagNameTreeItem(e.getKey(), dataSourceId, e.getValue()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// return results
|
||||||
|
return new TreeResultsDTO<>(tagNameParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tag name tree item.
|
||||||
|
*
|
||||||
|
* @param tagName The tag name.
|
||||||
|
* @param dataSourceId The data source object id or null if not present.
|
||||||
|
* @param treeDisplayCount The tree display count.
|
||||||
|
*
|
||||||
|
* @return The tree item dto.
|
||||||
|
*/
|
||||||
|
public TreeItemDTO<TagNameSearchParams> createTagNameTreeItem(TagName tagName, Long dataSourceId, TreeResultsDTO.TreeDisplayCount treeDisplayCount) {
|
||||||
|
return new TreeItemDTO<>(
|
||||||
|
TagNameSearchParams.getTypeId(),
|
||||||
|
new TagNameSearchParams(tagName, dataSourceId),
|
||||||
|
tagName.getId(),
|
||||||
|
tagName.getDisplayName(),
|
||||||
|
treeDisplayCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The count of content tags.
|
||||||
|
*
|
||||||
|
* @param dataSourceId The data source id where the content tag should
|
||||||
|
* appear or null.
|
||||||
|
* @param tagName The tag name.
|
||||||
|
*
|
||||||
|
* @return The count.
|
||||||
|
*
|
||||||
|
* @throws NoCurrentCaseException
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
private long getContentTagCount(Long dataSourceId, TagName tagName) throws NoCurrentCaseException, TskCoreException {
|
||||||
|
|
||||||
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
|
return (dataSourceId != null)
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, dataSourceId, userName)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, userName);
|
||||||
|
} else {
|
||||||
|
return (dataSourceId != null)
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, dataSourceId)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The count of result tags.
|
||||||
|
*
|
||||||
|
* @param dataSourceId The data source id where the result tag should appear
|
||||||
|
* or null.
|
||||||
|
* @param tagName The tag name.
|
||||||
|
*
|
||||||
|
* @return The count.
|
||||||
|
*
|
||||||
|
* @throws NoCurrentCaseException
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
private long getArtifactTagCount(Long dataSourceId, TagName tagName) throws NoCurrentCaseException, TskCoreException {
|
||||||
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
|
return (dataSourceId != null)
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, dataSourceId, userName)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName);
|
||||||
|
} else {
|
||||||
|
return (dataSourceId != null)
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, dataSourceId)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the counts of file and result type given the search params.
|
||||||
|
*
|
||||||
|
* @param searchParams The tag name search params.
|
||||||
|
*
|
||||||
|
* @return The tree item results.
|
||||||
|
*
|
||||||
|
* @throws ExecutionException
|
||||||
|
*/
|
||||||
|
public TreeResultsDTO<? extends TagsSearchParams> getTypeCounts(TagNameSearchParams searchParams) throws ExecutionException {
|
||||||
|
Long dataSourceId = searchParams.getDataSourceId();
|
||||||
|
TagName tagName = searchParams.getTagName();
|
||||||
|
|
||||||
|
Set<TagType> indeterminateTagTypes = this.treeCounts.getEnqueued().stream()
|
||||||
|
.filter(evt -> (dataSourceId == null || Objects.equals(evt.getDataSourceId(), dataSourceId)) && Objects.equals(tagName, evt.getTagName()))
|
||||||
|
.map(evt -> evt.getTagType())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new TreeResultsDTO<>(Arrays.asList(
|
||||||
|
createTagTypeTreeItem(
|
||||||
|
tagName,
|
||||||
|
TagType.FILE,
|
||||||
|
dataSourceId,
|
||||||
|
indeterminateTagTypes.contains(TagType.FILE)
|
||||||
|
? TreeDisplayCount.INDETERMINATE
|
||||||
|
: TreeDisplayCount.getDeterminate(getContentTagCount(dataSourceId, tagName))),
|
||||||
|
createTagTypeTreeItem(
|
||||||
|
tagName,
|
||||||
|
TagType.RESULT,
|
||||||
|
dataSourceId,
|
||||||
|
indeterminateTagTypes.contains(TagType.RESULT)
|
||||||
|
? TreeDisplayCount.INDETERMINATE
|
||||||
|
: TreeDisplayCount.getDeterminate(getArtifactTagCount(dataSourceId, tagName)))
|
||||||
|
));
|
||||||
|
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||||
|
throw new ExecutionException("An error occurred while fetching tag type counts.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tag type tree item.
|
||||||
|
*
|
||||||
|
* @param tagName The tag name.
|
||||||
|
* @param tagType The tag type.
|
||||||
|
* @param dataSourceId The data source object id or null if not present.
|
||||||
|
* @param treeDisplayCount The tree display count.
|
||||||
|
*
|
||||||
|
* @return The tree item dto.
|
||||||
|
*/
|
||||||
|
public TreeItemDTO<TagsSearchParams> createTagTypeTreeItem(TagName tagName, TagType tagType, Long dataSourceId, TreeResultsDTO.TreeDisplayCount treeDisplayCount) {
|
||||||
|
return new TreeItemDTO<>(
|
||||||
|
TagsSearchParams.getTypeId(),
|
||||||
|
new TagsSearchParams(tagName, tagType, dataSourceId),
|
||||||
|
tagName.getId() + "_" + tagType.name(),
|
||||||
|
tagType.getDisplayName(),
|
||||||
|
treeDisplayCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles fetching and paging of data for allTags.
|
* Handles fetching and paging of data for allTags.
|
||||||
*/
|
*/
|
||||||
|
@ -19,12 +19,13 @@
|
|||||||
package org.sleuthkit.autopsy.mainui.datamodel;
|
package org.sleuthkit.autopsy.mainui.datamodel;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.datamodel.TagName;
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key for accessing data about tags from the DAO.
|
* Key for accessing data about tags from the DAO.
|
||||||
*/
|
*/
|
||||||
public class TagsSearchParams {
|
public class TagsSearchParams extends TagNameSearchParams {
|
||||||
|
|
||||||
private static final String TYPE_ID = "TAG";
|
private static final String TYPE_ID = "TAG";
|
||||||
|
|
||||||
@ -35,39 +36,40 @@ public class TagsSearchParams {
|
|||||||
return TYPE_ID;
|
return TYPE_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"TagType_File_displayName=File Tags",
|
||||||
|
"TagType_Result_displayName=Result Tags",})
|
||||||
public enum TagType {
|
public enum TagType {
|
||||||
FILE,
|
FILE(Bundle.TagType_File_displayName()),
|
||||||
RESULT;
|
RESULT(Bundle.TagType_Result_displayName());
|
||||||
|
|
||||||
|
private final String displayName;
|
||||||
|
|
||||||
|
TagType(String displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final TagType type;
|
private final TagType type;
|
||||||
private final TagName tagName;
|
|
||||||
private final Long dataSourceId;
|
|
||||||
|
|
||||||
public TagsSearchParams(TagName tagName, TagType type, Long dataSourceId) {
|
public TagsSearchParams(TagName tagName, TagType type, Long dataSourceId) {
|
||||||
this.tagName = tagName;
|
super(tagName, dataSourceId);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.dataSourceId = dataSourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TagName getTagName() {
|
|
||||||
return tagName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagType getTagType() {
|
public TagType getTagType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getDataSourceId() {
|
|
||||||
return dataSourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hash = 7;
|
int hash = 3;
|
||||||
hash = 23 * hash + Objects.hashCode(this.tagName);
|
hash = 97 * hash + Objects.hashCode(this.type);
|
||||||
hash = 23 * hash + Objects.hashCode(this.type);
|
hash = 97 * hash + super.hashCode();
|
||||||
hash = 23 * hash + Objects.hashCode(this.dataSourceId);
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,16 +85,10 @@ public class TagsSearchParams {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final TagsSearchParams other = (TagsSearchParams) obj;
|
final TagsSearchParams other = (TagsSearchParams) obj;
|
||||||
if (!Objects.equals(this.tagName, other.tagName)) {
|
if (this.type != other.type) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Objects.equals(this.dataSourceId, other.dataSourceId)) {
|
return super.equals(obj);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!Objects.equals(this.type, other.type)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
173
Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java
Normal file
173
Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2021 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.mainui.nodes;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import org.openide.nodes.Children;
|
||||||
|
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.MainDAO;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.TagNameSearchParams;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.TreeResultsDTO;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.TreeResultsDTO.TreeItemDTO;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.events.DAOAggregateEvent;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.events.DAOEvent;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.events.DeleteAnalysisResultEvent;
|
||||||
|
import org.sleuthkit.autopsy.mainui.datamodel.events.TreeEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for displaying analysis result types in the tree.
|
||||||
|
*/
|
||||||
|
public class TagNameFactory extends TreeChildFactory<TagNameSearchParams> {
|
||||||
|
|
||||||
|
private static final String TAG_ICON = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png";
|
||||||
|
|
||||||
|
private final Long dataSourceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*
|
||||||
|
* @param dataSourceId The data source id to filter on or null if no filter.
|
||||||
|
*/
|
||||||
|
public TagNameFactory(Long dataSourceId) {
|
||||||
|
this.dataSourceId = dataSourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TreeResultsDTO<? extends TagNameSearchParams> getChildResults() throws IllegalArgumentException, ExecutionException {
|
||||||
|
return MainDAO.getInstance().getTagsDAO().getNameCounts(dataSourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TreeNode<TagNameSearchParams> createNewNode(TreeResultsDTO.TreeItemDTO<? extends TagNameSearchParams> rowData) {
|
||||||
|
return new TagNameNode(rowData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TreeResultsDTO.TreeItemDTO<? extends TagNameSearchParams> getOrCreateRelevantChild(TreeEvent treeEvt) {
|
||||||
|
TreeResultsDTO.TreeItemDTO<TagNameSearchParams> originalTreeItem = super.getTypedTreeItem(treeEvt, TagNameSearchParams.class);
|
||||||
|
|
||||||
|
if (originalTreeItem != null
|
||||||
|
&& (this.dataSourceId == null || Objects.equals(this.dataSourceId, originalTreeItem.getSearchParams().getDataSourceId()))) {
|
||||||
|
|
||||||
|
return MainDAO.getInstance().getTagsDAO().createTagNameTreeItem(
|
||||||
|
originalTreeItem.getSearchParams().getTagName(),
|
||||||
|
dataSourceId,
|
||||||
|
originalTreeItem.getDisplayCount());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(TreeItemDTO<? extends TagNameSearchParams> o1, TreeItemDTO<? extends TagNameSearchParams> o2) {
|
||||||
|
return Comparator.comparing((TreeItemDTO<? extends TagNameSearchParams> tagTreeItem) -> tagTreeItem.getDisplayName())
|
||||||
|
.compare(o1, o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleDAOAggregateEvent(DAOAggregateEvent aggEvt) {
|
||||||
|
for (DAOEvent evt : aggEvt.getEvents()) {
|
||||||
|
if (evt instanceof DeleteAnalysisResultEvent && evt.getType() == DAOEvent.Type.TREE) {
|
||||||
|
super.update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.handleDAOAggregateEvent(aggEvt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A node for a tag name.
|
||||||
|
*/
|
||||||
|
static class TagNameNode extends TreeNode<TagNameSearchParams> {
|
||||||
|
|
||||||
|
public TagNameNode(TreeResultsDTO.TreeItemDTO<? extends TagNameSearchParams> rowData) {
|
||||||
|
super(TagNameSearchParams.getTypeId() + "_" + Objects.toString(rowData.getId()),
|
||||||
|
TAG_ICON,
|
||||||
|
rowData,
|
||||||
|
Children.create(new TagTypeFactory(rowData.getSearchParams()), false),
|
||||||
|
getDefaultLookup(rowData));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory displaying file type or result type underneath a tag name node.
|
||||||
|
*/
|
||||||
|
static class TagTypeFactory extends TreeChildFactory<TagsSearchParams> {
|
||||||
|
|
||||||
|
private final TagNameSearchParams searchParams;
|
||||||
|
|
||||||
|
TagTypeFactory(TagNameSearchParams searchParams) {
|
||||||
|
this.searchParams = searchParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TreeNode<TagsSearchParams> createNewNode(TreeItemDTO<? extends TagsSearchParams> rowData) {
|
||||||
|
return new TagsTypeNode(rowData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TreeResultsDTO<? extends TagsSearchParams> getChildResults() throws IllegalArgumentException, ExecutionException {
|
||||||
|
return MainDAO.getInstance().getTagsDAO().getTypeCounts(searchParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TreeItemDTO<? extends TagsSearchParams> getOrCreateRelevantChild(TreeEvent treeEvt) {
|
||||||
|
TreeResultsDTO.TreeItemDTO<TagsSearchParams> originalTreeItem = super.getTypedTreeItem(treeEvt, TagsSearchParams.class);
|
||||||
|
|
||||||
|
if (originalTreeItem != null
|
||||||
|
&& Objects.equals(this.searchParams.getTagName(), originalTreeItem.getSearchParams().getTagName())
|
||||||
|
&& (this.searchParams.getDataSourceId() == null || Objects.equals(this.searchParams.getDataSourceId(), originalTreeItem.getSearchParams().getDataSourceId()))) {
|
||||||
|
|
||||||
|
return MainDAO.getInstance().getTagsDAO().createTagTypeTreeItem(
|
||||||
|
searchParams.getTagName(),
|
||||||
|
originalTreeItem.getSearchParams().getTagType(),
|
||||||
|
searchParams.getDataSourceId(),
|
||||||
|
originalTreeItem.getDisplayCount());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(TreeItemDTO<? extends TagsSearchParams> o1, TreeItemDTO<? extends TagsSearchParams> o2) {
|
||||||
|
return Comparator.comparing((TreeItemDTO<? extends TagsSearchParams> rowData) -> rowData.getSearchParams().getTagType() == TagsSearchParams.TagType.FILE ? 0 : 1)
|
||||||
|
.compare(o1, o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tag type (i.e. File/Result) tree node. Clicking on this will go to
|
||||||
|
* results.
|
||||||
|
*/
|
||||||
|
static class TagsTypeNode extends TreeNode<TagsSearchParams> {
|
||||||
|
|
||||||
|
private TagsTypeNode(TreeItemDTO<? extends TagsSearchParams> rowData) {
|
||||||
|
super(TagsSearchParams.getTypeId() + "_" + Objects.toString(rowData.getId()), TAG_ICON, rowData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void respondSelection(DataResultTopComponent dataResultPanel) {
|
||||||
|
dataResultPanel.displayTags(this.getItemData().getSearchParams());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user