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) {
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@ -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.
|
||||
*
|
||||
|
@ -319,7 +319,7 @@ public class TagsManager implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
for(TagName tagName: caseDb.getAllTagNames()) {
|
||||
for (TagName tagName : caseDb.getAllTagNames()) {
|
||||
allTagNameMap.put(tagName.getDisplayName(), tagName);
|
||||
}
|
||||
|
||||
@ -636,14 +636,6 @@ public class TagsManager implements Closeable {
|
||||
*/
|
||||
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);
|
||||
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();
|
||||
}
|
||||
|
||||
@ -657,11 +649,6 @@ public class TagsManager implements Closeable {
|
||||
*/
|
||||
public void deleteContentTag(ContentTag tag) throws TskCoreException {
|
||||
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 {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -876,11 +857,6 @@ public class TagsManager implements Closeable {
|
||||
*/
|
||||
public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
|
||||
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.TagNameNode node);
|
||||
|
||||
T visit(Tags.ContentTagTypeNode node);
|
||||
|
||||
T visit(Tags.BlackboardArtifactTagTypeNode node);
|
||||
|
||||
|
||||
/*
|
||||
* Reports
|
||||
@ -270,21 +264,6 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
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
|
||||
public T visit(Reports.ReportsListNode node) {
|
||||
return defaultVisit(node);
|
||||
|
@ -97,7 +97,7 @@ public class RootContentChildren extends Children.Keys<Object> {
|
||||
public static Node createNode(Object key) {
|
||||
if (key instanceof Tags) {
|
||||
Tags tagsNodeKey = (Tags) key;
|
||||
return tagsNodeKey.new RootNode(tagsNodeKey.filteringDataSourceObjId());
|
||||
return new Tags.RootNode(tagsNodeKey.filteringDataSourceObjId());
|
||||
} else if (key instanceof DataSources) {
|
||||
DataSources dataSourcesKey = (DataSources) key;
|
||||
return new DataSourceFilesNode(dataSourcesKey.filteringDataSourceObjId());
|
||||
|
@ -18,39 +18,12 @@
|
||||
*/
|
||||
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.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
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;
|
||||
import org.sleuthkit.autopsy.mainui.nodes.TagNameFactory;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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 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
|
||||
|
||||
Tags() {
|
||||
@ -91,34 +55,23 @@ public class Tags {
|
||||
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
|
||||
* 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 RootNode extends DisplayableItemNode {
|
||||
public static class RootNode extends DisplayableItemNode {
|
||||
|
||||
public RootNode(long objId) {
|
||||
super(Children.create(new TagNameNodeFactory(objId), true), Lookups.singleton(DISPLAY_NAME));
|
||||
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 dsId) {
|
||||
super(Children.create(new TagNameFactory(dsId != null && dsId> 0 ? dsId : null), true), Lookups.singleton(DISPLAY_NAME));
|
||||
super.setName(DISPLAY_NAME);
|
||||
super.setDisplayName(DISPLAY_NAME);
|
||||
this.setIconBaseWithExtension(ICON_PATH);
|
||||
this.dataSourceObjId = dsId != null && dsId> 0 ? dsId : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,422 +102,15 @@ public class Tags {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
public Node clone() {
|
||||
return new RootNode(dataSourceObjId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cause the contents of the RootNode and its children to be updated.
|
||||
*/
|
||||
public void refresh() {
|
||||
tagResults.update();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
|
||||
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
|
||||
import org.sleuthkit.autopsy.datamodel.LocalDirectoryNode;
|
||||
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.autopsy.datamodel.ViewsNode;
|
||||
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
||||
import org.sleuthkit.autopsy.datamodel.VolumeNode;
|
||||
@ -92,6 +93,9 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
|
||||
} else if (origNode instanceof AnalysisResults.RootNode) {
|
||||
Node cloned = ((AnalysisResults.RootNode) origNode).clone();
|
||||
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) {
|
||||
Node cloned = ((ViewsNode) origNode).clone();
|
||||
return new Node[]{cloned};
|
||||
|
@ -327,7 +327,7 @@ public class ExtractActionHelper {
|
||||
|
||||
@Override
|
||||
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.typeColLbl=Result Type
|
||||
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.CacheBuilder;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.sql.SQLException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
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.ContentTagAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
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_UNITS;
|
||||
import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_SIZE;
|
||||
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.events.TagsEvent;
|
||||
import org.sleuthkit.autopsy.mainui.datamodel.events.TreeCounts;
|
||||
import org.sleuthkit.autopsy.mainui.datamodel.events.TreeEvent;
|
||||
import org.sleuthkit.autopsy.mainui.nodes.DAOFetcher;
|
||||
import org.sleuthkit.autopsy.tags.TagUtils;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.CaseDbAccessManager;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@ -85,6 +98,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
"TagsDAO.tagColumns.userNameColLbl=User Name"})
|
||||
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 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());
|
||||
}
|
||||
|
||||
private final Cache<SearchParams<TagsSearchParams>, SearchResultsDTO> searchParamsCache =
|
||||
CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).expireAfterAccess(CACHE_DURATION, CACHE_DURATION_UNITS).build();
|
||||
private final Cache<SearchParams<TagsSearchParams>, SearchResultsDTO> searchParamsCache
|
||||
= CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).expireAfterAccess(CACHE_DURATION, CACHE_DURATION_UNITS).build();
|
||||
private final TreeCounts<TagsEvent> treeCounts = new TreeCounts<>();
|
||||
|
||||
public SearchResultsDTO getTags(TagsSearchParams key, long startItem, Long maxCount) throws ExecutionException, IllegalArgumentException {
|
||||
if (key.getTagName() == null) {
|
||||
throw new IllegalArgumentException("Must have non-null tag name");
|
||||
} else if (key.getDataSourceId() != null && key.getDataSourceId() <= 0) {
|
||||
if (key.getDataSourceId() != null && key.getDataSourceId() <= 0) {
|
||||
throw new IllegalArgumentException("Data source id must be greater than 0 or null");
|
||||
} else if (key.getTagType() == null) {
|
||||
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 {
|
||||
|
||||
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
|
||||
List<BlackboardArtifactTag> allTags = new ArrayList<>();
|
||||
List<BlackboardArtifactTag> artifactTags = (dataSourceId != null && dataSourceId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, dataSourceId)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName);
|
||||
? tm.getBlackboardArtifactTagsByTagName(tagNameId, dataSourceId)
|
||||
: tm.getBlackboardArtifactTagsByTagName(tagNameId);
|
||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||
for (BlackboardArtifactTag tag : artifactTags) {
|
||||
@ -233,13 +247,15 @@ public class TagsDAO extends AbstractDAO {
|
||||
private SearchResultsDTO fetchFileTags(SearchParams<TagsSearchParams> cacheKey) throws NoCurrentCaseException, TskCoreException {
|
||||
|
||||
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
|
||||
List<ContentTag> allTags = new ArrayList<>();
|
||||
List<ContentTag> contentTags = (dataSourceId != null && dataSourceId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, dataSourceId)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName);
|
||||
? tm.getContentTagsByTagName(tagNameId, dataSourceId)
|
||||
: tm.getContentTagsByTagName(tagNameId);
|
||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||
for (ContentTag tag : contentTags) {
|
||||
@ -345,9 +361,9 @@ public class TagsDAO extends AbstractDAO {
|
||||
|
||||
Collection<TagsEvent> daoEvents = Collections.singletonList(data);
|
||||
|
||||
Collection<TreeEvent> treeEvents = this.treeCounts.enqueueAll(daoEvents).stream()
|
||||
.map(arEvt -> new TreeEvent(getTreeItem(arEvt, TreeResultsDTO.TreeDisplayCount.INDETERMINATE), false))
|
||||
.collect(Collectors.toList());
|
||||
Collection<TreeEvent> treeEvents = daoEvents.stream()
|
||||
.map(arEvt -> new TreeEvent(getTreeItem(arEvt, TreeResultsDTO.TreeDisplayCount.UNSPECIFIED), true))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return Stream.of(daoEvents, treeEvents)
|
||||
.flatMap(lst -> lst.stream())
|
||||
@ -398,6 +414,208 @@ public class TagsDAO extends AbstractDAO {
|
||||
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.
|
||||
*/
|
||||
|
@ -19,12 +19,13 @@
|
||||
package org.sleuthkit.autopsy.mainui.datamodel;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
|
||||
/**
|
||||
* Key for accessing data about tags from the DAO.
|
||||
*/
|
||||
public class TagsSearchParams {
|
||||
public class TagsSearchParams extends TagNameSearchParams {
|
||||
|
||||
private static final String TYPE_ID = "TAG";
|
||||
|
||||
@ -35,39 +36,40 @@ public class TagsSearchParams {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"TagType_File_displayName=File Tags",
|
||||
"TagType_Result_displayName=Result Tags",})
|
||||
public enum TagType {
|
||||
FILE,
|
||||
RESULT;
|
||||
FILE(Bundle.TagType_File_displayName()),
|
||||
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 TagName tagName;
|
||||
private final Long dataSourceId;
|
||||
|
||||
public TagsSearchParams(TagName tagName, TagType type, Long dataSourceId) {
|
||||
this.tagName = tagName;
|
||||
super(tagName, dataSourceId);
|
||||
this.type = type;
|
||||
this.dataSourceId = dataSourceId;
|
||||
}
|
||||
|
||||
public TagName getTagName() {
|
||||
return tagName;
|
||||
}
|
||||
|
||||
public TagType getTagType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Long getDataSourceId() {
|
||||
return dataSourceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 23 * hash + Objects.hashCode(this.tagName);
|
||||
hash = 23 * hash + Objects.hashCode(this.type);
|
||||
hash = 23 * hash + Objects.hashCode(this.dataSourceId);
|
||||
int hash = 3;
|
||||
hash = 97 * hash + Objects.hashCode(this.type);
|
||||
hash = 97 * hash + super.hashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -83,16 +85,10 @@ public class TagsSearchParams {
|
||||
return false;
|
||||
}
|
||||
final TagsSearchParams other = (TagsSearchParams) obj;
|
||||
if (!Objects.equals(this.tagName, other.tagName)) {
|
||||
if (this.type != other.type) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.dataSourceId, other.dataSourceId)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.type, other.type)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
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