From b5216cc87b0cd8afe9c4ffd0728bb8d2ced1e752 Mon Sep 17 00:00:00 2001 From: jmillman Date: Fri, 19 Jun 2015 13:53:53 -0400 Subject: [PATCH] use new Autopsy Tag events, don't fire extra events from ig, but listen to events from autopsy --- .../casemodule/services/TagsManager.java | 1 - .../imagegallery/DrawableTagsManager.java | 82 ++++++++----------- .../imagegallery/ImageGalleryController.java | 30 +++---- .../autopsy/imagegallery/TagsChangeEvent.java | 41 ---------- .../actions/AddDrawableTagAction.java | 9 +- .../imagegallery/actions/AddTagAction.java | 9 +- .../actions/CategorizeAction.java | 27 +++--- .../actions/DeleteFollowUpTagAction.java | 7 +- .../imagegallery/datamodel/Category.java | 12 --- .../datamodel/CategoryChangeEvent.java | 14 +++- .../datamodel/CategoryManager.java | 69 +++++++++++++++- .../imagegallery/datamodel/DrawableFile.java | 2 +- .../imagegallery/grouping/GroupManager.java | 64 +++++++++------ .../imagegallery/gui/DrawableView.java | 8 +- .../imagegallery/gui/DrawableViewBase.java | 18 ++-- .../imagegallery/gui/MetaDataPane.java | 18 ++-- 16 files changed, 208 insertions(+), 203 deletions(-) delete mode 100644 ImageGallery/src/org/sleuthkit/autopsy/imagegallery/TagsChangeEvent.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 5a52cefde9..72fdf22ca4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -250,7 +250,6 @@ public class TagsManager implements Closeable { final ContentTag newContentTag = tskCase.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset); Case.getCurrentCase().notifyContentTagAdded(newContentTag); return newContentTag; - return newContentTag; } /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/DrawableTagsManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/DrawableTagsManager.java index 13455d2fb1..0bbc4b9d5a 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/DrawableTagsManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/DrawableTagsManager.java @@ -27,11 +27,11 @@ import java.util.logging.Level; import java.util.stream.Collectors; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.events.ContentTagAddedEvent; +import org.sleuthkit.autopsy.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; -import org.sleuthkit.autopsy.ingest.IngestServices; -import org.sleuthkit.autopsy.ingest.ModuleDataEvent; -import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; @@ -59,6 +59,32 @@ public class DrawableTagsManager { } + /** + * register an object to receive CategoryChangeEvents + * + * @param listner + */ + public void registerListener(Object listner) { + tagsEventBus.register(listner); + } + + /** + * unregister an object from receiving CategoryChangeEvents + * + * @param listener + */ + public void unregisterListener(Object listener) { + tagsEventBus.unregister(listener); + } + + public void fireTagAddedEvent(ContentTagAddedEvent event) { + tagsEventBus.post(event); + } + + public void fireTagDeletedEvent(ContentTagDeletedEvent event) { + tagsEventBus.post(event); + } + /** * assign a new TagsManager to back this one, ie when the current case * changes @@ -82,24 +108,6 @@ public class DrawableTagsManager { } } - /** - * register an object to receive CategoryChangeEvents - * - * @param listner - */ - public void registerListener(Object listner) { - tagsEventBus.register(listner); - } - - /** - * unregister an object from receiving CategoryChangeEvents - * - * @param listener - */ - public void unregisterListener(Object listener) { - tagsEventBus.unregister(listener); - } - /** * get the (cached) follow up TagName * @@ -120,7 +128,7 @@ public class DrawableTagsManager { synchronized (autopsyTagsManagerLock) { try { return autopsyTagsManager.getAllTagNames().stream() - .filter(Category::isCategoryTagName) + .filter(CategoryManager::isCategoryTagName) .collect(Collectors.toSet()); } catch (TskCoreException | IllegalStateException ex) { Logger.getLogger(DrawableTagsManager.class.getName()).log(Level.WARNING, "couldn't access case", ex); @@ -173,12 +181,10 @@ public class DrawableTagsManager { } } - public void addContentTag(DrawableFile file, TagName tagName, String comment) throws TskCoreException { - ContentTag addContentTag; + public ContentTag addContentTag(DrawableFile file, TagName tagName, String comment) throws TskCoreException { synchronized (autopsyTagsManagerLock) { - addContentTag = autopsyTagsManager.addContentTag(file, tagName, comment); + return autopsyTagsManager.addContentTag(file, tagName, comment); } - fireTagAdded(addContentTag); } public List getContentTagsByTagName(TagName t) throws TskCoreException { @@ -187,21 +193,6 @@ public class DrawableTagsManager { } } - /** - * Fire the ModuleDataEvent that we use as a place holder for a real Tag - * Event. This is used to refresh the autopsy tag tree and the ui in - * ImageGallery - * - * - * Note: this is a hack. In an ideal world, TagsManager would fire - * events so that the directory tree would refresh. But, we haven't - * had a chance to add that so, we fire these events and the tree - * refreshes based on them. - */ - static public void refreshTagsInAutopsy() { - IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent("TagAction", BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE)); //NON-NLS - } - public List getAllTagNames() throws TskCoreException { synchronized (autopsyTagsManagerLock) { return autopsyTagsManager.getAllTagNames(); @@ -214,18 +205,9 @@ public class DrawableTagsManager { } } - public void fireTagAdded(ContentTag newTag) { - tagsEventBus.post(new TagsChangeEvent(Collections.singleton(newTag.getContent().getId()))); - } - - public void fireTagDeleted(ContentTag oldTag) { - tagsEventBus.post(new TagsChangeEvent(Collections.singleton(oldTag.getContent().getId()))); - } - public void deleteContentTag(ContentTag ct) throws TskCoreException { synchronized (autopsyTagsManagerLock) { autopsyTagsManager.deleteContentTag(ct); } - fireTagDeleted(ct); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 046c88bc7a..6c6bd7c789 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.imagegallery; import java.beans.PropertyChangeEvent; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.concurrent.BlockingQueue; @@ -58,10 +57,9 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.History; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.autopsy.imagegallery.actions.CategorizeAction; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.events.ContentTagAddedEvent; +import org.sleuthkit.autopsy.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; -import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.HashSetManager; @@ -74,7 +72,6 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.FileSystem; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitCase; @@ -366,6 +363,8 @@ public final class ImageGalleryController { categoryManager.setDb(db); tagsManager.setAutopsyTagsManager(theNewCase.getServices().getTagsManager()); tagsManager.registerListener(groupManager); + tagsManager.registerListener(categoryManager); + } else { reset(); } @@ -384,6 +383,7 @@ public final class ImageGalleryController { }); tagsManager.clearFollowUpTagName(); tagsManager.unregisterListener(groupManager); + tagsManager.unregisterListener(categoryManager); Toolbar.getDefault(this).reset(); groupManager.clear(); @@ -490,23 +490,15 @@ public final class ImageGalleryController { } break; case CONTENT_TAG_ADDED: - ContentTag newTag = (ContentTag) evt.getNewValue(); - if (Category.isCategoryTagName(newTag.getName())) { - new CategorizeAction(ImageGalleryController.this).addTag(newTag.getName(), ""); - } else { - getTagsManager().fireTagAdded(newTag); + final ContentTagAddedEvent tagAddedEvent = (ContentTagAddedEvent) evt; + if (getDatabase().isInDB((tagAddedEvent).getAddedTag().getContent().getId())) { + getTagsManager().fireTagAddedEvent(tagAddedEvent); } break; case CONTENT_TAG_DELETED: - ContentTag oldTag = (ContentTag) evt.getOldValue(); - final long fileID = oldTag.getContent().getId(); - if (getDatabase().isInDB(fileID)) { - if (Category.isCategoryTagName(oldTag.getName())) { - getCategoryManager().decrementCategoryCount(Category.fromTagName(oldTag.getName())); - getGroupManager().handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.CATEGORY)); - } else { - getTagsManager().fireTagDeleted(oldTag); - } + final ContentTagDeletedEvent tagDeletedEvent = (ContentTagDeletedEvent) evt; + if (getDatabase().isInDB((tagDeletedEvent).getDeletedTag().getContent().getId())) { + getTagsManager().fireTagDeletedEvent(tagDeletedEvent); } break; } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/TagsChangeEvent.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/TagsChangeEvent.java deleted file mode 100644 index 0647a18456..0000000000 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/TagsChangeEvent.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit 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.imagegallery; - -import java.util.Collection; -import java.util.Collections; -import javax.annotation.concurrent.Immutable; - -/** - * - */ -@Immutable -public class TagsChangeEvent { - - private final Collection fileIDs; - - public Collection getFileIDs() { - return Collections.unmodifiableCollection(fileIDs); - } - - public TagsChangeEvent(Collection fileIDs) { - this.fileIDs = fileIDs; - } - -} diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddDrawableTagAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddDrawableTagAction.java index e88c51f12b..be9343f4de 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddDrawableTagAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddDrawableTagAction.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.imagegallery.actions; -import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -28,11 +27,8 @@ import javax.swing.JOptionPane; import javax.swing.SwingWorker; import org.openide.util.Utilities; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager; import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel; -import org.sleuthkit.autopsy.imagegallery.FileUpdateEvent; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.TagName; @@ -87,10 +83,9 @@ public class AddDrawableTagAction extends AddTagAction { JOptionPane.showMessageDialog(null, "Unable to tag " + fileID + ".", "Tagging Error", JOptionPane.ERROR_MESSAGE); } - //make sure rest of ui hears category change. - controller.getGroupManager().handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.TAGS)); +// //make sure rest of ui hears category change. +// controller.getGroupManager().handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.TAGS)); } - DrawableTagsManager.refreshTagsInAutopsy(); return null; } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddTagAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddTagAction.java index a82244d368..f20fccfcfd 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddTagAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddTagAction.java @@ -31,7 +31,7 @@ import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; @@ -95,11 +95,10 @@ abstract class AddTagAction { // a tag with the associated tag name. if (null != tagNames && !tagNames.isEmpty()) { for (final TagName tagName : tagNames) { - if (Category.isNotCategoryTagName(tagName)) { + if (CategoryManager.isNotCategoryTagName(tagName)) { MenuItem tagNameItem = new MenuItem(tagName.getDisplayName()); tagNameItem.setOnAction((ActionEvent t) -> { addTag(tagName, NO_COMMENT); - DrawableTagsManager.refreshTagsInAutopsy(); }); quickTagMenu.getItems().add(tagNameItem); } @@ -120,7 +119,6 @@ abstract class AddTagAction { TagName tagName = GetTagNameDialog.doDialog(); if (tagName != null) { addTag(tagName, NO_COMMENT); - } }); }); @@ -134,12 +132,11 @@ abstract class AddTagAction { SwingUtilities.invokeLater(() -> { GetTagNameAndCommentDialog.TagNameAndComment tagNameAndComment = GetTagNameAndCommentDialog.doDialog(); if (null != tagNameAndComment) { - if (Category.isCategoryTagName(tagNameAndComment.getTagName())) { + if (CategoryManager.isCategoryTagName(tagNameAndComment.getTagName())) { new CategorizeAction(controller).addTag(tagNameAndComment.getTagName(), tagNameAndComment.getComment()); } else { new AddDrawableTagAction(controller).addTag(tagNameAndComment.getTagName(), tagNameAndComment.getComment()); } - } }); }); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java index 8918934a6e..067a5cf967 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.imagegallery.actions; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -32,7 +31,6 @@ import javax.swing.JOptionPane; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager; import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel; -import org.sleuthkit.autopsy.imagegallery.FileUpdateEvent; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; @@ -41,7 +39,6 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.grouping.GroupKey; import org.sleuthkit.autopsy.imagegallery.grouping.GroupManager; import org.sleuthkit.datamodel.ContentTag; -import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; @@ -87,6 +84,10 @@ public class CategorizeAction extends AddTagAction { } } + public void enforceOneCat(TagName name, String string) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + /** * Instances of this class implement a context menu user interface for * selecting a category @@ -127,8 +128,8 @@ public class CategorizeAction extends AddTagAction { @Override public void run() { final GroupManager groupManager = controller.getGroupManager(); - final SleuthkitCase sleuthKitCase = controller.getSleuthKitCase(); final CategoryManager categoryManager = controller.getCategoryManager(); + final DrawableTagsManager tagsManager = controller.getTagsManager(); try { DrawableFile file = controller.getFileFromId(fileID); //drawable db @@ -138,27 +139,27 @@ public class CategorizeAction extends AddTagAction { groupManager.removeFromGroup(new GroupKey(DrawableAttribute.CATEGORY, oldCat), fileID); //memory //remove old category tag if necessary - List allContentTags = sleuthKitCase.getContentTagsByContent(file); //tsk db + List allContentTags = tagsManager.getContentTagsByContent(file); //tsk db + //JMTODO: move this to CategoryManager for (ContentTag ct : allContentTags) { - if (Category.isCategoryTagName(ct.getName())) { - sleuthKitCase.deleteContentTag(ct); //tsk db - categoryManager.decrementCategoryCount(Category.fromDisplayName(ct.getName().getDisplayName())); //memory/drawable db + if (CategoryManager.isCategoryTagName(ct.getName())) { + tagsManager.deleteContentTag(ct); //tsk db +// categoryManager.decrementCategoryCount(Category.fromDisplayName(ct.getName().getDisplayName())); //memory/drawable db } } - categoryManager.incrementCategoryCount(Category.fromDisplayName(tagName.getDisplayName())); //memory/drawable db +// categoryManager.incrementCategoryCount(Category.fromDisplayName(tagName.getDisplayName())); //memory/drawable db if (tagName != categoryManager.getTagName(Category.ZERO)) { // no tags for cat-0 - controller.getTagsManager().addContentTag(file, tagName, comment); //tsk db + tagsManager.addContentTag(file, tagName, comment); //tsk db } - //make sure rest of ui hears category change. - groupManager.handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.CATEGORY)); //memory/ui +// //make sure rest of ui hears category change. +// groupManager.handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.CATEGORY)); //memory/ui } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error categorizing result", ex); JOptionPane.showMessageDialog(null, "Unable to categorize " + fileID + ".", "Categorizing Error", JOptionPane.ERROR_MESSAGE); } - DrawableTagsManager.refreshTagsInAutopsy(); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteFollowUpTagAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteFollowUpTagAction.java index 98fdc316ad..aab8a9c827 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteFollowUpTagAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteFollowUpTagAction.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.imagegallery.actions; -import java.util.Collections; import java.util.List; import java.util.logging.Level; import javafx.event.ActionEvent; @@ -26,14 +25,12 @@ import javax.swing.SwingWorker; import org.controlsfx.control.action.Action; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager; -import org.sleuthkit.autopsy.imagegallery.FileUpdateEvent; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.grouping.GroupKey; import org.sleuthkit.autopsy.imagegallery.grouping.GroupManager; import org.sleuthkit.datamodel.ContentTag; -import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; @@ -53,7 +50,6 @@ public class DeleteFollowUpTagAction extends Action { @Override protected Void doInBackground() throws Exception { - final SleuthkitCase sleuthKitCase = controller.getSleuthKitCase(); final GroupManager groupManager = controller.getGroupManager(); final DrawableTagsManager tagsManager = controller.getTagsManager(); @@ -69,9 +65,8 @@ public class DeleteFollowUpTagAction extends Action { } } - DrawableTagsManager.refreshTagsInAutopsy(); //make sure rest of ui hears category change. - groupManager.handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.TAGS)); +// groupManager.handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.TAGS)); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to delete follow up tag.", ex); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java index 00750c4ba9..8999fff2f1 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java @@ -23,7 +23,6 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import javafx.scene.paint.Color; -import org.sleuthkit.datamodel.TagName; /** * Enum to represent the six categories in the DHs image categorization scheme. @@ -49,17 +48,6 @@ public enum Category { public static Category fromDisplayName(String displayName) { return nameMap.get(displayName); } - public static Category fromTagName(TagName tagName) { - return nameMap.get(tagName.getDisplayName()); - } - - public static boolean isCategoryTagName(TagName tName) { - return isCategoryName(tName.getDisplayName()); - } - - public static boolean isNotCategoryTagName(TagName tName) { - return isNotCategoryName(tName.getDisplayName()); - } public static boolean isCategoryName(String tName) { return nameMap.containsKey(tName); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryChangeEvent.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryChangeEvent.java index 9896325e09..3868864737 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryChangeEvent.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryChangeEvent.java @@ -30,6 +30,16 @@ import javax.annotation.concurrent.Immutable; public class CategoryChangeEvent { private final Collection fileIDs; + private final Category newCategory; + + public CategoryChangeEvent(Collection fileIDs, Category newCategory) { + this.fileIDs = fileIDs; + this.newCategory = newCategory; + } + + public Category getNewCategory() { + return newCategory; + } /** * @return the fileIDs of the files whose categories have changed @@ -37,8 +47,4 @@ public class CategoryChangeEvent { public Collection getFileIDs() { return Collections.unmodifiableCollection(fileIDs); } - - public CategoryChangeEvent(Collection fileIDs) { - this.fileIDs = fileIDs; - } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java index f8b0e6beb1..b6a11d2b25 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java @@ -24,11 +24,17 @@ import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.concurrent.atomic.LongAdder; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.events.ContentTagAddedEvent; +import org.sleuthkit.autopsy.events.ContentTagDeletedEvent; +import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; +import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TskCoreException; /** * Provides a cached view of the number of files per category, and fires @@ -94,13 +100,13 @@ public class CategoryManager { this.db = db; categoryCounts.invalidateAll(); catTagNameMap.invalidateAll(); - fireChange(Collections.singleton(-1L)); + fireChange(Collections.emptyList(), null); } synchronized public void invalidateCaches() { categoryCounts.invalidateAll(); catTagNameMap.invalidateAll(); - fireChange(Collections.singleton(-1L)); + fireChange(Collections.emptyList(), null); } /** @@ -173,8 +179,8 @@ public class CategoryManager { * * @param fileIDs */ - public void fireChange(Collection fileIDs) { - categoryEventBus.post(new CategoryChangeEvent(fileIDs)); + public void fireChange(Collection fileIDs, Category newCategory) { + categoryEventBus.post(new CategoryChangeEvent(fileIDs, newCategory)); } /** @@ -204,4 +210,59 @@ public class CategoryManager { return catTagNameMap.getUnchecked(cat); } + + public static Category fromTagName(TagName tagName) { + return Category.fromDisplayName(tagName.getDisplayName()); + } + + public static boolean isCategoryTagName(TagName tName) { + return Category.isCategoryName(tName.getDisplayName()); + } + + public static boolean isNotCategoryTagName(TagName tName) { + return Category.isNotCategoryName(tName.getDisplayName()); + + } + + public void handleTagAdded(ContentTagAddedEvent event) { + ContentTag addedTag = event.getAddedTag(); + if (isCategoryTagName(addedTag.getName())) { + final DrawableTagsManager tagsManager = controller.getTagsManager(); + try { + //remove old category tag(s) if necessary + List allContentTags = tagsManager.getContentTagsByContent(addedTag.getContent()); + + for (ContentTag ct : allContentTags) { + if (ct.getId() != addedTag.getId() + && CategoryManager.isCategoryTagName(ct.getName())) { + try { + tagsManager.deleteContentTag(ct); + } catch (TskCoreException tskException) { + LOGGER.log(Level.SEVERE, "Failed to delete content tag. Unable to maintain categories in a consistent state.", tskException); + } + } + } + } catch (TskCoreException tskException) { + LOGGER.log(Level.SEVERE, "Failed to get content tags for content. Unable to maintain category in a consistent state.", tskException); + } + Category newCat = CategoryManager.fromTagName(addedTag.getName()); + if (newCat != Category.ZERO) { + incrementCategoryCount(newCat); + } + + fireChange(Collections.singleton(addedTag.getId()), newCat); + } + } + + public void handleTagDeleted(ContentTagDeletedEvent event) { + ContentTag deleted = event.getDeletedTag(); + if (isCategoryTagName(deleted.getName())) { + + Category deletedCat = CategoryManager.fromTagName(deleted.getName()); + if (deletedCat != Category.ZERO) { + decrementCategoryCount(deletedCat); + } + fireChange(Collections.singleton(deleted.getId()), null); + } + } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index 3890ca577a..79ea49f879 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -272,7 +272,7 @@ public abstract class DrawableFile extends AbstractFile private void updateCategory() { try { category.set(getSleuthkitCase().getContentTagsByContent(this).stream() - .map(Tag::getName).filter(Category::isCategoryTagName) + .map(Tag::getName).filter(CategoryManager::isCategoryTagName) .map(TagName::getDisplayName) .map(Category::fromDisplayName) .sorted().findFirst() //sort by severity and take the first diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java index 51a99bd5f7..733baf2813 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java @@ -60,12 +60,14 @@ import org.sleuthkit.autopsy.coreutils.LoggedTask; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; +import org.sleuthkit.autopsy.events.ContentTagAddedEvent; +import org.sleuthkit.autopsy.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager; import org.sleuthkit.autopsy.imagegallery.FileUpdateEvent; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule; -import org.sleuthkit.autopsy.imagegallery.TagsChangeEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; @@ -161,7 +163,7 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener { Set> resultSet = new HashSet<>(); for (Comparable val : groupBy.getValue(file)) { if (groupBy == DrawableAttribute.TAGS) { - if (Category.isNotCategoryTagName((TagName) val)) { + if (CategoryManager.isNotCategoryTagName((TagName) val)) { resultSet.add(new GroupKey(groupBy, val)); } } else { @@ -282,6 +284,10 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener { }); } } + } else { //group == null + // It may be that this was the last unanalyzed file in the group, so test + // whether the group is now fully analyzed. + popuplateIfAnalyzed(groupKey, null); } return group; @@ -360,7 +366,7 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener { break; case TAGS: values = (List) controller.getTagsManager().getTagNamesInUse().stream() - .filter(Category::isNotCategoryTagName) + .filter(CategoryManager::isNotCategoryTagName) .collect(Collectors.toList()); break; case ANALYZED: @@ -528,14 +534,31 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener { } @Subscribe - public void handleAutopsyTagChange(TagsChangeEvent evt) { - if (groupBy == DrawableAttribute.TAGS - && evt.getFileIDs().size() == 1 - && evt.getFileIDs().contains(-1L)) { - regroup(groupBy, sortBy, sortOrder, Boolean.TRUE); + public void handleTagAdded(ContentTagAddedEvent evt) { + final GroupKey groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getAddedTag().getName()); + final long fileID = evt.getAddedTag().getContent().getId(); + DrawableGroup g = getGroupForKey(groupKey); + addFileToGroup(g, groupKey, fileID); + + } + + private void addFileToGroup(DrawableGroup g, final GroupKey groupKey, final long fileID) { + if (g == null) { + //if there wasn't already a group check if there should be one now + popuplateIfAnalyzed(groupKey, null); + } else { + //if there is aleady a group that was previously deemed fully analyzed, then add this newly analyzed file to it. + g.addFile(fileID); } } + @Subscribe + public void handleTagDeleted(ContentTagDeletedEvent evt) { + final GroupKey groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getDeletedTag().getName()); + final long fileID = evt.getDeletedTag().getContent().getId(); + DrawableGroup g = removeFromGroup(groupKey, fileID); + } + @Override synchronized public void handleFileRemoved(FileUpdateEvent evt) { Validate.isTrue(evt.getUpdateType() == FileUpdateEvent.UpdateType.REMOVE); @@ -545,13 +568,7 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener { Set> groupsForFile = getGroupKeysForFileID(fileId); for (GroupKey gk : groupsForFile) { - DrawableGroup g = removeFromGroup(gk, fileId); - - if (g == null) { - // It may be that this was the last unanalyzed file in the group, so test - // whether the group is now fully analyzed. - popuplateIfAnalyzed(gk, null); - } + removeFromGroup(gk, fileId); } } } @@ -578,29 +595,21 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener { //get grouping(s) this file would be in Set> groupsForFile = getGroupKeysForFileID(fileId); - for (GroupKey gk : groupsForFile) { DrawableGroup g = getGroupForKey(gk); - - if (g == null) { - //if there wasn't already a group check if there should be one now - popuplateIfAnalyzed(gk, null); - } else { - //if there is aleady a group that was previously deemed fully analyzed, then add this newly analyzed file to it. - g.addFile(fileId); - } + addFileToGroup(g, gk, fileId); } } //we fire this event for all files so that the category counts get updated during initial db population - controller.getCategoryManager().fireChange(fileIDs); + controller.getCategoryManager().fireChange(fileIDs, null); // if (evt.getChangedAttribute() == DrawableAttribute.TAGS) { // controller.getTagsManager().fireChange(fileIDs); // } } - private void popuplateIfAnalyzed(GroupKey groupKey, ReGroupTask task) { + private DrawableGroup popuplateIfAnalyzed(GroupKey groupKey, ReGroupTask task) { if (Objects.nonNull(task) && (task.isCancelled())) { /* if this method call is part of a ReGroupTask and that task is @@ -609,6 +618,7 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener { * this allows us to stop if a regroup task has been cancelled (e.g. * the user picked a different group by attribute, while the * current task was still running) */ + } else { // no task or un-cancelled task if ((groupKey.getAttribute() != DrawableAttribute.PATH) || db.isGroupAnalyzed(groupKey)) { /* for attributes other than path we can't be sure a group is @@ -639,12 +649,14 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener { } markGroupSeen(group, groupSeen); }); + return group; } } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "failed to get files for group: " + groupKey.getAttribute().attrName.toString() + " = " + groupKey.getValue(), ex); } } } + return null; } /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java index 99d8671a63..9b442273d1 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java @@ -12,8 +12,9 @@ import javafx.scene.layout.Region; import javafx.scene.paint.Color; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; +import org.sleuthkit.autopsy.events.ContentTagAddedEvent; +import org.sleuthkit.autopsy.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.TagsChangeEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryChangeEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; @@ -68,7 +69,10 @@ public interface DrawableView { void handleCategoryChanged(CategoryChangeEvent evt); @Subscribe - void handleTagsChanged(TagsChangeEvent evt); + void handleTagAdded(ContentTagAddedEvent evt); + + @Subscribe + void handleTagDeleted(ContentTagDeletedEvent evt); ImageGalleryController getController(); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableViewBase.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableViewBase.java index 93026d688d..ea88d2dfbb 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableViewBase.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableViewBase.java @@ -61,10 +61,11 @@ import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; +import org.sleuthkit.autopsy.events.ContentTagAddedEvent; +import org.sleuthkit.autopsy.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryTopComponent; -import org.sleuthkit.autopsy.imagegallery.TagsChangeEvent; import org.sleuthkit.autopsy.imagegallery.actions.AddDrawableTagAction; import org.sleuthkit.autopsy.imagegallery.actions.CategorizeAction; import org.sleuthkit.autopsy.imagegallery.actions.DeleteFollowUpTagAction; @@ -378,16 +379,21 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie @Subscribe @Override - synchronized public void handleTagsChanged(TagsChangeEvent evnt) { - if (fileID != null && (evnt.getFileIDs().contains(fileID) || evnt.getFileIDs().contains(-1L))) { - updateFollowUpIcon(); - } + public void handleTagAdded(ContentTagAddedEvent evt) { + + updateFollowUpIcon(); + } + + @Subscribe + @Override + public void handleTagDeleted(ContentTagDeletedEvent evt) { + updateFollowUpIcon(); } @Subscribe @Override synchronized public void handleCategoryChanged(CategoryChangeEvent evt) { - if (evt.getFileIDs().contains(getFileID()) || evt.getFileIDs().contains(-1L)) { + if (fileID != null && evt.getFileIDs().contains(getFileID())) { updateCategoryBorder(); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/MetaDataPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/MetaDataPane.java index 4f4cace550..0681d29eb9 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/MetaDataPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/MetaDataPane.java @@ -44,8 +44,9 @@ import javafx.scene.text.Text; import javafx.util.Pair; import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.events.ContentTagAddedEvent; +import org.sleuthkit.autopsy.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.TagsChangeEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryChangeEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; @@ -225,16 +226,23 @@ public class MetaDataPane extends AnchorPane implements DrawableView { @Subscribe @Override public void handleCategoryChanged(CategoryChangeEvent evt) { - if (getFile() != null && (evt.getFileIDs().contains(-1L) || evt.getFileIDs().contains(getFileID()))) { + if (getFile() != null && evt.getFileIDs().contains(getFileID())) { updateUI(); } } @Override - @Subscribe - public void handleTagsChanged(TagsChangeEvent evt) { - if (getFile() != null && (evt.getFileIDs().contains(-1L) || evt.getFileIDs().contains(getFileID()))) { + public void handleTagAdded(ContentTagAddedEvent evt) { + if (getFile() != null && evt.getAddedTag().getContent().getId() == getFileID()) { updateUI(); } } + + @Override + public void handleTagDeleted(ContentTagDeletedEvent evt) { + if (getFile() != null && evt.getDeletedTag().getContent().getId() == getFileID()) { + updateUI(); + } + } + }