diff --git a/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java b/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java index 6a9253043a..483172844f 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java @@ -66,7 +66,6 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TimelineManager; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TimelineEvent; @@ -81,6 +80,7 @@ import org.sleuthkit.datamodel.TimelineFilter.HideKnownFilter; import org.sleuthkit.datamodel.TimelineFilter.RootFilter; import org.sleuthkit.datamodel.TimelineFilter.TagsFilter; import org.sleuthkit.datamodel.TimelineFilter.TextFilter; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * This class acts as the model for a TimelineView @@ -112,8 +112,8 @@ public final class FilteredEventsModel { private final ReadOnlyObjectWrapper requestedFilter = new ReadOnlyObjectWrapper<>(); private final ReadOnlyObjectWrapper requestedTimeRange = new ReadOnlyObjectWrapper<>(); private final ReadOnlyObjectWrapper requestedZoomState = new ReadOnlyObjectWrapper<>(); - private final ReadOnlyObjectWrapper< TimelineEventType.TypeLevel> requestedTypeZoom = new ReadOnlyObjectWrapper<>(TimelineEventType.TypeLevel.BASE_TYPE); - private final ReadOnlyObjectWrapper< TimelineEvent.DescriptionLevel> requestedLOD = new ReadOnlyObjectWrapper<>(TimelineEvent.DescriptionLevel.SHORT); + private final ReadOnlyObjectWrapper requestedTypeZoom = new ReadOnlyObjectWrapper<>(TimelineEventType.HierarchyLevel.CATEGORY); + private final ReadOnlyObjectWrapper requestedLOD = new ReadOnlyObjectWrapper<>(TimelineLevelOfDetail.LOW); // end Filter and zoome state //caches @@ -121,7 +121,9 @@ public final class FilteredEventsModel { private final LoadingCache minCache; private final LoadingCache idToEventCache; private final LoadingCache> eventCountsCache; - /** Map from datasource id to datasource name. */ + /** + * Map from datasource id to datasource name. + */ private final ObservableMap datasourcesMap = FXCollections.observableHashMap(); // end caches @@ -152,9 +154,9 @@ public final class FilteredEventsModel { .build(new CacheLoaderImpl<>(this::countEventsByType)); maxCache = CacheBuilder.newBuilder() - .build(new CacheLoaderImpl<>(ignored -> eventManager.getMaxTime())); + .build(new CacheLoaderImpl<>(ignored -> eventManager.getMaxEventTime())); minCache = CacheBuilder.newBuilder() - .build(new CacheLoaderImpl<>(ignored -> eventManager.getMinTime())); + .build(new CacheLoaderImpl<>(ignored -> eventManager.getMinEventTime())); InvalidationListener filterSyncListener = observable -> { RootFilterState rootFilter = filterProperty().get(); @@ -280,7 +282,7 @@ public final class FilteredEventsModel { return requestedTimeRange.getReadOnlyProperty(); } - synchronized public ReadOnlyObjectProperty descriptionLODProperty() { + synchronized public ReadOnlyObjectProperty descriptionLODProperty() { return requestedLOD.getReadOnlyProperty(); } @@ -288,7 +290,7 @@ public final class FilteredEventsModel { return requestedFilter.getReadOnlyProperty(); } - synchronized public ReadOnlyObjectProperty eventTypeZoomProperty() { + synchronized public ReadOnlyObjectProperty eventTypeZoomProperty() { return requestedTypeZoom.getReadOnlyProperty(); } @@ -301,7 +303,7 @@ public final class FilteredEventsModel { return getZoomState().getTimeRange(); } - synchronized public TimelineEvent.DescriptionLevel getDescriptionLOD() { + synchronized public TimelineLevelOfDetail getDescriptionLOD() { return getZoomState().getDescriptionLOD(); } @@ -309,11 +311,12 @@ public final class FilteredEventsModel { return getZoomState().getFilterState(); } - synchronized public TimelineEventType.TypeLevel getEventTypeZoom() { + synchronized public TimelineEventType.HierarchyLevel getEventTypeZoom() { return getZoomState().getTypeZoomLevel(); } - /** Get the default filter used at startup. + /** + * Get the default filter used at startup. * * @return the default filter used at startup */ @@ -385,7 +388,7 @@ public final class FilteredEventsModel { public Map getEventCounts(Interval timeRange) throws TskCoreException { final RootFilterState filter; - final TimelineEventType.TypeLevel typeZoom; + final TimelineEventType.HierarchyLevel typeZoom; synchronized (this) { filter = getFilterState(); typeZoom = getEventTypeZoom(); @@ -453,39 +456,40 @@ public final class FilteredEventsModel { synchronized public boolean handleContentTagAdded(ContentTagAddedEvent evt) throws TskCoreException { ContentTag contentTag = evt.getAddedTag(); Content content = contentTag.getContent(); - Set updatedEventIDs = addTag(content.getId(), null, contentTag); + Set updatedEventIDs = eventManager.updateEventsForContentTagAdded(content); + if (isNotEmpty(updatedEventIDs)) { + invalidateCaches(updatedEventIDs); + } return postTagsAdded(updatedEventIDs); } synchronized public boolean handleArtifactTagAdded(BlackBoardArtifactTagAddedEvent evt) throws TskCoreException { BlackboardArtifactTag artifactTag = evt.getAddedTag(); BlackboardArtifact artifact = artifactTag.getArtifact(); - Set updatedEventIDs = addTag(artifact.getObjectID(), artifact.getArtifactID(), artifactTag); + Set updatedEventIDs = eventManager.updateEventsForArtifactTagAdded(artifact); + if (isNotEmpty(updatedEventIDs)) { + invalidateCaches(updatedEventIDs); + } return postTagsAdded(updatedEventIDs); } synchronized public boolean handleContentTagDeleted(ContentTagDeletedEvent evt) throws TskCoreException { DeletedContentTagInfo deletedTagInfo = evt.getDeletedTagInfo(); - Content content = autoCase.getSleuthkitCase().getContentById(deletedTagInfo.getContentID()); - boolean isContentTagged = autoCase.getServices().getTagsManager().getContentTagsByContent(content).isEmpty() == false; - boolean isArtifactTagged = false; - - if(content instanceof BlackboardArtifact) { - isArtifactTagged = autoCase.getServices().getTagsManager().getBlackboardArtifactTagsByArtifact((BlackboardArtifact)content).isEmpty() == false; + Set updatedEventIDs = eventManager.updateEventsForContentTagDeleted(content); + if (isNotEmpty(updatedEventIDs)) { + invalidateCaches(updatedEventIDs); } - - Set updatedEventIDs = deleteTag(content.getId(), null, deletedTagInfo.getTagID(), isArtifactTagged || isContentTagged); return postTagsDeleted(updatedEventIDs); } synchronized public boolean handleArtifactTagDeleted(BlackBoardArtifactTagDeletedEvent evt) throws TskCoreException { DeletedBlackboardArtifactTagInfo deletedTagInfo = evt.getDeletedTagInfo(); - BlackboardArtifact artifact = autoCase.getSleuthkitCase().getBlackboardArtifact(deletedTagInfo.getArtifactID()); - boolean isArtifactTagged = autoCase.getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact).isEmpty() == false; - boolean isContentTagged = autoCase.getServices().getTagsManager().getContentTagsByContent(artifact).isEmpty() == false; - Set updatedEventIDs = deleteTag(artifact.getObjectID(), artifact.getArtifactID(), deletedTagInfo.getTagID(), isArtifactTagged || isContentTagged); + Set updatedEventIDs = eventManager.updateEventsForArtifactTagDeleted(artifact); + if (isNotEmpty(updatedEventIDs)) { + invalidateCaches(updatedEventIDs); + } return postTagsDeleted(updatedEventIDs); } @@ -507,7 +511,7 @@ public final class FilteredEventsModel { * @throws org.sleuthkit.datamodel.TskCoreException */ public Set getEventIDsForFile(AbstractFile file, boolean includeDerivedArtifacts) throws TskCoreException { - return eventManager.getEventIDsForFile(file, includeDerivedArtifacts); + return eventManager.getEventIDsForContent(file, includeDerivedArtifacts); } /** @@ -599,26 +603,11 @@ public final class FilteredEventsModel { return eventManager.getEventTypes(); } - synchronized public Set addTag(long objID, Long artifactID, Tag tag) throws TskCoreException { - Set updatedEventIDs = eventManager.setEventsTagged(objID, artifactID, true); - if (isNotEmpty(updatedEventIDs)) { - invalidateCaches(updatedEventIDs); - } - return updatedEventIDs; - } - - synchronized public Set deleteTag(long objID, Long artifactID, long tagID, boolean tagged) throws TskCoreException { - Set updatedEventIDs = eventManager.setEventsTagged(objID, artifactID, tagged); - if (isNotEmpty(updatedEventIDs)) { - invalidateCaches(updatedEventIDs); - } - return updatedEventIDs; - } - - synchronized public Set setHashHit(Collection artifacts, boolean hasHashHit) throws TskCoreException { + synchronized public Set setHashHit(Collection artifacts) throws TskCoreException { Set updatedEventIDs = new HashSet<>(); for (BlackboardArtifact artifact : artifacts) { - updatedEventIDs.addAll(eventManager.setEventsHashed(artifact.getObjectID(), hasHashHit)); + Content content = autoCase.getSleuthkitCase().getContentById(artifact.getObjectID()); + updatedEventIDs.addAll(eventManager.updateEventsForHashSetHit(content)); } if (isNotEmpty(updatedEventIDs)) { invalidateCaches(updatedEventIDs); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ShowInTimelineDialog.java b/Core/src/org/sleuthkit/autopsy/timeline/ShowInTimelineDialog.java index b99ac2c6fb..1c1dae4165 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ShowInTimelineDialog.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ShowInTimelineDialog.java @@ -190,7 +190,7 @@ final class ShowInTimelineDialog extends Dialog { typeColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue().getEventType())); typeColumn.setCellFactory(param -> new TypeTableCell<>()); - dateTimeColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue().getStartMillis())); + dateTimeColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue().getEventTimeInMs())); dateTimeColumn.setCellFactory(param -> new DateTimeTableCell<>()); //add events to table @@ -307,7 +307,7 @@ final class ShowInTimelineDialog extends Dialog { */ private ViewInTimelineRequestedEvent makeEventInTimeRange(TimelineEvent selectedEvent) { Duration selectedDuration = unitComboBox.getSelectionModel().getSelectedItem().getBaseUnit().getDuration().multipliedBy(amountSpinner.getValue()); - Interval range = IntervalUtils.getIntervalAround(Instant.ofEpochMilli(selectedEvent.getStartMillis()), selectedDuration); + Interval range = IntervalUtils.getIntervalAround(Instant.ofEpochMilli(selectedEvent.getEventTimeInMs()), selectedDuration); return new ViewInTimelineRequestedEvent(Collections.singleton(selectedEvent.getEventID()), range); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index 01aaaf34d0..8235fb79f3 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -93,6 +93,7 @@ import org.sleuthkit.datamodel.TimelineEvent; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TimelineEventType; import org.sleuthkit.datamodel.TimelineFilter.EventTypeFilter; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * Controller in the MVC design along with FilteredEventsModel TimeLineView. @@ -296,9 +297,9 @@ public class TimeLineController { try { InitialZoomState = new ZoomState(filteredEvents.getSpanningInterval(), - TimelineEventType.TypeLevel.BASE_TYPE, + TimelineEventType.HierarchyLevel.CATEGORY, filteredEvents.filterProperty().get(), - TimelineEvent.DescriptionLevel.SHORT); + TimelineLevelOfDetail.LOW); } catch (TskCoreException ex) { throw new TskCoreException("Error getting spanning interval.", ex); } @@ -492,7 +493,7 @@ public class TimeLineController { return topComponent; } - synchronized public void pushEventTypeZoom(TimelineEventType.TypeLevel typeZoomeLevel) { + synchronized public void pushEventTypeZoom(TimelineEventType.HierarchyLevel typeZoomeLevel) { ZoomState currentZoom = filteredEvents.zoomStateProperty().get(); if (currentZoom == null) { advance(InitialZoomState.withTypeZoomLevel(typeZoomeLevel)); @@ -554,7 +555,7 @@ public class TimeLineController { } } - synchronized public void pushDescrLOD(TimelineEvent.DescriptionLevel newLOD) { + synchronized public void pushDescrLOD(TimelineLevelOfDetail newLOD) { ZoomState currentZoom = filteredEvents.zoomStateProperty().get(); if (currentZoom == null) { advance(InitialZoomState.withDescrLOD(newLOD)); @@ -564,7 +565,7 @@ public class TimeLineController { } @SuppressWarnings("AssignmentToMethodParameter") //clamp timerange to case - synchronized public void pushTimeAndType(Interval timeRange, TimelineEventType.TypeLevel typeZoom) throws TskCoreException { + synchronized public void pushTimeAndType(Interval timeRange, TimelineEventType.HierarchyLevel typeZoom) throws TskCoreException { Interval overlappingTimeRange = this.filteredEvents.getSpanningInterval().overlap(timeRange); ZoomState currentZoom = filteredEvents.zoomStateProperty().get(); if (currentZoom == null) { @@ -745,7 +746,7 @@ public class TimeLineController { case DATA_ADDED: ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == TSK_HASHSET_HIT.getTypeID()) { - logFutureException(executor.submit(() -> filteredEvents.setHashHit(eventData.getArtifacts(), true)), + logFutureException(executor.submit(() -> filteredEvents.setHashHit(eventData.getArtifacts())), "Error executing task in response to DATA_ADDED event.", "Error executing response to new data."); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/EventNode.java b/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/EventNode.java index be05c59b67..56dc02daed 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/EventNode.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/EventNode.java @@ -57,6 +57,7 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TimelineEventType; import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * * Explorer Node for a TimelineEvent. @@ -113,7 +114,7 @@ public class EventNode extends DisplayableItemNode { properties.put(new NodeProperty<>("icon", Bundle.NodeProperty_displayName_icon(), "icon", true)); // NON-NLS //gets overridden with icon properties.put(new TimeProperty("time", Bundle.NodeProperty_displayName_dateTime(), "time ", getDateTimeString()));// NON-NLS - properties.put(new NodeProperty<>("description", Bundle.NodeProperty_displayName_description(), "description", event.getFullDescription())); // NON-NLS + properties.put(new NodeProperty<>("description", Bundle.NodeProperty_displayName_description(), "description", event.getDescription(TimelineLevelOfDetail.HIGH))); // NON-NLS properties.put(new NodeProperty<>("eventType", Bundle.NodeProperty_displayName_eventType(), "event type", event.getEventType().getDisplayName())); // NON-NLS return sheet; @@ -127,7 +128,7 @@ public class EventNode extends DisplayableItemNode { * controller's time zone setting. */ private String getDateTimeString() { - return new DateTime(event.getStartMillis(), DateTimeZone.UTC).toString(TimeLineController.getZonedFormatter()); + return new DateTime(event.getEventTimeInMs(), DateTimeZone.UTC).toString(TimeLineController.getZonedFormatter()); } @Override @@ -270,7 +271,7 @@ public class EventNode extends DisplayableItemNode { * data in the lookup. */ final TimelineEvent eventById = eventsModel.getEventById(eventID); - Content file = sleuthkitCase.getContentById(eventById.getFileObjID()); + Content file = sleuthkitCase.getContentById(eventById.getContentObjID()); if (eventById.getArtifactID().isPresent()) { BlackboardArtifact blackboardArtifact = sleuthkitCase.getBlackboardArtifact(eventById.getArtifactID().get()); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/EventTypeUtils.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/EventTypeUtils.java index 9a698699ee..85b900a5e6 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/EventTypeUtils.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/EventTypeUtils.java @@ -107,15 +107,15 @@ final public class EventTypeUtils { return Color.hsb(359, .9, .9, 0); } - TimelineEventType superType = type.getSuperType(); + TimelineEventType superType = type.getParent(); Color baseColor = getColor(superType); - int siblings = superType.getSiblingTypes().stream() - .max((type1, type2) -> Integer.compare(type1.getSubTypes().size(), type2.getSubTypes().size())) - .get().getSubTypes().size() + 1; - int superSiblingsCount = superType.getSiblingTypes().size(); + int siblings = superType.getSiblings().stream() + .max((type1, type2) -> Integer.compare(type1.getChildren().size(), type2.getChildren().size())) + .get().getChildren().size() + 1; + int superSiblingsCount = superType.getSiblings().size(); - int ordinal = new ArrayList<>(type.getSiblingTypes()).indexOf(type); + int ordinal = new ArrayList<>(type.getSiblings()).indexOf(type); double offset = (360.0 / superSiblingsCount) / siblings; Color deriveColor = baseColor.deriveColor(ordinal * offset, 1, 1, 1); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/countsview/EventCountsChart.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/countsview/EventCountsChart.java index 25297a321a..e7c44b3a27 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/countsview/EventCountsChart.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/countsview/EventCountsChart.java @@ -207,7 +207,7 @@ final class EventCountsChart extends StackedBarChart implements final Node node = item.getNode(); if (node != null) { node.setStyle("-fx-border-width: 2; " - + " -fx-border-color: " + ColorUtilities.getRGBCode(getColor(eventType.getSuperType())) + "; " + + " -fx-border-color: " + ColorUtilities.getRGBCode(getColor(eventType.getParent())) + "; " + " -fx-bar-fill: " + ColorUtilities.getRGBCode(getColor(eventType))); // NON-NLS node.setCursor(Cursor.HAND); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java index 7f7e986e1f..8736c46103 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java @@ -62,7 +62,7 @@ import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.DetailsViewModel; import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.EventStripe; import org.sleuthkit.autopsy.timeline.utils.MappedList; import org.sleuthkit.autopsy.timeline.zooming.ZoomState; -import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; import org.sleuthkit.datamodel.TskCoreException; /** @@ -192,7 +192,7 @@ final public class DetailViewPane extends AbstractTimelineChart( new EventTypeFilter(getEventType()), true)); final Interval subClusterSpan = new Interval(getStartMillis(), getEndMillis() + 1000); - final TimelineEventType.TypeLevel eventTypeZoomLevel = eventsModel.getEventTypeZoom(); + final TimelineEventType.HierarchyLevel eventTypeZoomLevel = eventsModel.getEventTypeZoom(); final ZoomState zoom = new ZoomState(subClusterSpan, eventTypeZoomLevel, subClusterFilter, getDescriptionLevel()); DescriptionFilter descriptionFilter = new DescriptionFilter(getEvent().getDescriptionLevel(), getDescription()); @@ -191,14 +191,14 @@ final class EventClusterNode extends MultiEventNodeBase> loggedTask; loggedTask = new LoggedTask>(Bundle.EventClusterNode_loggedTask_name(), false) { - private volatile TimelineEvent.DescriptionLevel loadedDescriptionLevel = withRelativeDetail(getDescriptionLevel(), relativeDetail); + private volatile TimelineLevelOfDetail loadedDescriptionLevel = withRelativeDetail(getDescriptionLevel(), relativeDetail); @Override protected List call() throws Exception { //newly loaded substripes List stripes; //next LoD in diraction of given relativeDetail - TimelineEvent.DescriptionLevel next = loadedDescriptionLevel; + TimelineLevelOfDetail next = loadedDescriptionLevel; do { loadedDescriptionLevel = next; if (loadedDescriptionLevel == getEvent().getDescriptionLevel()) { @@ -311,7 +311,7 @@ final class EventClusterNode extends MultiEventNodeBase extends StackP show(tagIV, false); } - if (chartLane.getController().getEventsModel().getEventTypeZoom() == TimelineEventType.TypeLevel.SUB_TYPE) { + if (chartLane.getController().getEventsModel().getEventTypeZoom() == TimelineEventType.HierarchyLevel.CATEGORY) { evtColor = getColor(getEventType()); } else { - evtColor = getColor(getEventType().getBaseType()); + evtColor = getColor(getEventType().getCategory()); } SELECTION_BORDER = new Border(new BorderStroke(evtColor.darker().desaturate(), BorderStrokeStyle.SOLID, CORNER_RADII_3, new BorderWidths(2))); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/HideDescriptionAction.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/HideDescriptionAction.java index 5fcdee723f..7abfd6a12c 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/HideDescriptionAction.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/HideDescriptionAction.java @@ -24,7 +24,7 @@ import org.controlsfx.control.action.Action; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.DescriptionFilter; import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.DescriptionFilterState; -import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * An Action that hides, in the given chart, events that have the given @@ -36,7 +36,7 @@ class HideDescriptionAction extends Action { private static final Image HIDE = new Image("/org/sleuthkit/autopsy/timeline/images/eye--minus.png"); // NON-NLS - HideDescriptionAction(String description, TimelineEvent.DescriptionLevel descriptionLoD, DetailsChart chart) { + HideDescriptionAction(String description, TimelineLevelOfDetail descriptionLoD, DetailsChart chart) { super(Bundle.HideDescriptionAction_displayName()); setLongText(Bundle.HideDescriptionAction_displayMsg()); setGraphic(new ImageView(HIDE)); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/MultiEventNodeBase.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/MultiEventNodeBase.java index ddc56b0752..da1d1df704 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/MultiEventNodeBase.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/MultiEventNodeBase.java @@ -36,7 +36,7 @@ import javafx.scene.layout.Pane; import org.joda.time.DateTime; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.MultiEvent; -import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; import org.sleuthkit.datamodel.TskCoreException; /** @@ -52,7 +52,7 @@ abstract class MultiEventNodeBase< BundleType extends MultiEvent, Pa final ObservableList> subNodes = FXCollections.observableArrayList(); final Pane subNodePane = new Pane(); - private final ReadOnlyObjectWrapper descLOD = new ReadOnlyObjectWrapper<>(); + private final ReadOnlyObjectWrapper descLOD = new ReadOnlyObjectWrapper<>(); MultiEventNodeBase(DetailsChartLane chartLane, BundleType event, ParentNodeType parentNode) { super(event, parentNode, chartLane); @@ -80,18 +80,18 @@ abstract class MultiEventNodeBase< BundleType extends MultiEvent, Pa Bindings.bindContent(subNodePane.getChildren(), subNodes); } - public ReadOnlyObjectProperty descriptionLoDProperty() { + public ReadOnlyObjectProperty descriptionLoDProperty() { return descLOD.getReadOnlyProperty(); } - final TimelineEvent.DescriptionLevel getDescriptionLevel() { + final TimelineLevelOfDetail getDescriptionLevel() { return descLOD.get(); } /** * */ - final void setDescriptionLOD(final TimelineEvent.DescriptionLevel descriptionLoD) { + final void setDescriptionLOD(final TimelineLevelOfDetail descriptionLoD) { descLOD.set(descriptionLoD); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/UnhideDescriptionAction.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/UnhideDescriptionAction.java index 7d9e779909..8afd63fc1c 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/UnhideDescriptionAction.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/UnhideDescriptionAction.java @@ -23,7 +23,7 @@ import javafx.scene.image.ImageView; import org.controlsfx.control.action.Action; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.DescriptionFilter; -import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * An Action that un-hides, in the given chart, events with the given @@ -34,7 +34,7 @@ class UnhideDescriptionAction extends Action { private static final Image SHOW = new Image("/org/sleuthkit/autopsy/timeline/images/eye--plus.png"); // NON-NLS - UnhideDescriptionAction(String description, TimelineEvent.DescriptionLevel descriptionLoD, DetailsChart chart) { + UnhideDescriptionAction(String description, TimelineLevelOfDetail descriptionLoD, DetailsChart chart) { super(Bundle.UnhideDescriptionAction_displayName()); setGraphic(new ImageView(SHOW)); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/DetailViewEvent.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/DetailViewEvent.java index 4da970e8ed..d1b01fb0d4 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/DetailViewEvent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/DetailViewEvent.java @@ -22,7 +22,7 @@ import java.util.Comparator; import java.util.Optional; import java.util.Set; import java.util.SortedSet; -import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; import org.sleuthkit.datamodel.TimelineEventType; /** @@ -49,7 +49,7 @@ public interface DetailViewEvent { * * @return the description level of detail of the given events */ - public TimelineEvent.DescriptionLevel getDescriptionLevel(); + public TimelineLevelOfDetail getDescriptionLevel(); /** * get the EventStripe (if any) that contains this event. diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/DetailsViewModel.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/DetailsViewModel.java index f37cce6035..ff0b77d49c 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/DetailsViewModel.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/DetailsViewModel.java @@ -37,6 +37,7 @@ import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; import java.util.logging.Level; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -57,6 +58,7 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TimelineEventType; import org.sleuthkit.datamodel.TimelineEvent; import org.sleuthkit.datamodel.TimelineFilter; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * Model for the Details View. Uses FilteredEventsModel as underlying datamodel @@ -115,19 +117,21 @@ final public class DetailsViewModel { DateTimeZone timeZone = TimeLineController.getJodaTimeZone(); //unpack params Interval timeRange = zoom.getTimeRange(); - TimelineEvent.DescriptionLevel descriptionLOD = zoom.getDescriptionLOD(); - TimelineEventType.TypeLevel typeZoomLevel = zoom.getTypeZoomLevel(); + TimelineLevelOfDetail descriptionLOD = zoom.getDescriptionLOD(); //intermediate results Map> eventClusters = new HashMap<>(); try { eventCache.get(zoom).stream() .filter(uiFilter) - .forEach(event -> { - TimelineEventType clusterType = event.getEventType(typeZoomLevel); - eventClusters.computeIfAbsent(clusterType, eventType -> HashMultimap.create()) - .put(event.getDescription(descriptionLOD), new EventCluster(event, clusterType, descriptionLOD)); - }); + .forEach(new Consumer() { + @Override + public void accept(TimelineEvent event) { + TimelineEventType clusterType = event.getEventType().getCategory(); + eventClusters.computeIfAbsent(clusterType, eventType -> HashMultimap.create()) + .put(event.getDescription(descriptionLOD), new EventCluster(event, clusterType, descriptionLOD)); + } + }); //get some info about the time range requested TimeUnits periodSize = RangeDivision.getRangeDivision(timeRange, timeZone).getPeriodSize(); return mergeClustersToStripes(periodSize.toUnitPeriod(), eventClusters); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventCluster.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventCluster.java index a4bc8a86a2..4ecdd40d91 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventCluster.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventCluster.java @@ -28,9 +28,9 @@ import java.util.Set; import java.util.SortedSet; import org.joda.time.Interval; import org.sleuthkit.autopsy.timeline.utils.IntervalUtils; -import org.sleuthkit.datamodel.TimelineEvent; import org.sleuthkit.datamodel.TimelineEventType; import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * Represents a set of other events clustered together. All the sub events @@ -59,7 +59,7 @@ public class EventCluster implements MultiEvent { /** * the description level of detail that the events were clustered at. */ - private final TimelineEvent.DescriptionLevel lod; + private final TimelineLevelOfDetail lod; /** * the set of ids of the clustered events @@ -126,7 +126,7 @@ public class EventCluster implements MultiEvent { } private EventCluster(Interval spanningInterval, TimelineEventType type, Set eventIDs, - Set hashHits, Set tagged, String description, TimelineEvent.DescriptionLevel lod, + Set hashHits, Set tagged, String description, TimelineLevelOfDetail lod, EventStripe parent) { this.span = spanningInterval; @@ -141,19 +141,19 @@ public class EventCluster implements MultiEvent { } public EventCluster(Interval spanningInterval, TimelineEventType type, Set eventIDs, - Set hashHits, Set tagged, String description, TimelineEvent.DescriptionLevel lod) { + Set hashHits, Set tagged, String description, TimelineLevelOfDetail lod) { this(spanningInterval, type, eventIDs, hashHits, tagged, description, lod, null); } - public EventCluster(TimelineEvent event, TimelineEventType type, TimelineEvent.DescriptionLevel lod) { - this.span = new Interval(event.getStartMillis(), event.getEndMillis()); + public EventCluster(TimelineEvent event, TimelineEventType type, TimelineLevelOfDetail lod) { + this.span = new Interval(event.getEventTimeInMs(), event.getEventTimeInMs()); this.type = type; this.eventIDs = new HashSet<>(); this.eventIDs.add(event.getEventID()); - this.hashHits = event.isHashHit() ? new HashSet<>(eventIDs) : emptySet(); - this.tagged = event.isTagged() ? new HashSet<>(eventIDs) : emptySet(); + this.hashHits = event.eventSourceHasHashHits()? new HashSet<>(eventIDs) : emptySet(); + this.tagged = event.eventSourceIsTagged()? new HashSet<>(eventIDs) : emptySet(); this.lod = lod; this.description = event.getDescription(lod); this.parent = null; @@ -222,7 +222,7 @@ public class EventCluster implements MultiEvent { } @Override - public TimelineEvent.DescriptionLevel getDescriptionLevel() { + public TimelineLevelOfDetail getDescriptionLevel() { return lod; } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventStripe.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventStripe.java index 9403844c5f..748d0bb1f2 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventStripe.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/EventStripe.java @@ -26,7 +26,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.SortedSet; -import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; import org.sleuthkit.datamodel.TimelineEventType; /** @@ -52,7 +52,7 @@ public final class EventStripe implements MultiEvent { /** * the description level of detail that the events were clustered at. */ - private final TimelineEvent.DescriptionLevel lod; + private final TimelineLevelOfDetail lod; /** * the set of ids of the events @@ -88,7 +88,7 @@ public final class EventStripe implements MultiEvent { } private EventStripe(EventCluster parent, TimelineEventType type, String description, - TimelineEvent.DescriptionLevel lod, SortedSet clusters, + TimelineLevelOfDetail lod, SortedSet clusters, Set eventIDs, Set tagged, Set hashHits) { this.parent = parent; this.type = type; @@ -151,7 +151,7 @@ public final class EventStripe implements MultiEvent { } @Override - public TimelineEvent.DescriptionLevel getDescriptionLevel() { + public TimelineLevelOfDetail getDescriptionLevel() { return lod; } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/SingleDetailsViewEvent.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/SingleDetailsViewEvent.java index 69bbf12af5..f71a298128 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/SingleDetailsViewEvent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/datamodel/SingleDetailsViewEvent.java @@ -28,6 +28,7 @@ import java.util.SortedSet; import org.joda.time.Interval; import org.sleuthkit.datamodel.TimelineEvent; import org.sleuthkit.datamodel.TimelineEventType; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * A single event. @@ -65,7 +66,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent { * The three descriptions (full, med, short) stored in a map, keyed by * DescriptionLOD (Level of Detail) */ - private final ImmutableMap descriptions; + private final ImmutableMap descriptions; /** * True if the file this event is derived from hits any of the configured @@ -106,9 +107,9 @@ public class SingleDetailsViewEvent implements DetailViewEvent { this.artifactID = Long.valueOf(0).equals(artifactID) ? null : artifactID; this.time = time; this.type = type; - descriptions = ImmutableMap.of(TimelineEvent.DescriptionLevel.FULL, fullDescription, - TimelineEvent.DescriptionLevel.MEDIUM, medDescription, - TimelineEvent.DescriptionLevel.SHORT, shortDescription); + descriptions = ImmutableMap.of(TimelineLevelOfDetail.HIGH, fullDescription, + TimelineLevelOfDetail.MEDIUM, medDescription, + TimelineLevelOfDetail.LOW, shortDescription); this.hashHit = hashHit; this.tagged = tagged; } @@ -116,15 +117,15 @@ public class SingleDetailsViewEvent implements DetailViewEvent { public SingleDetailsViewEvent(TimelineEvent singleEvent) { this(singleEvent.getEventID(), singleEvent.getDataSourceObjID(), - singleEvent.getFileObjID(), + singleEvent.getContentObjID(), singleEvent.getArtifactID().orElse(null), singleEvent.getTime(), singleEvent.getEventType(), - singleEvent.getFullDescription(), - singleEvent.getMedDescription(), - singleEvent.getShortDescription(), - singleEvent.isHashHit(), - singleEvent.isTagged()); + singleEvent.getDescription(TimelineLevelOfDetail.HIGH), + singleEvent.getDescription(TimelineLevelOfDetail.MEDIUM), + singleEvent.getDescription(TimelineLevelOfDetail.LOW), + singleEvent.eventSourceHasHashHits(), + singleEvent.eventSourceIsTagged()); } /** @@ -137,7 +138,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent { * with the given parent. */ public SingleDetailsViewEvent withParent(MultiEvent newParent) { - SingleDetailsViewEvent singleEvent = new SingleDetailsViewEvent(eventID, dataSourceObjId, fileObjId, artifactID, time, type, descriptions.get(TimelineEvent.DescriptionLevel.FULL), descriptions.get(TimelineEvent.DescriptionLevel.MEDIUM), descriptions.get(TimelineEvent.DescriptionLevel.SHORT), hashHit, tagged); + SingleDetailsViewEvent singleEvent = new SingleDetailsViewEvent(eventID, dataSourceObjId, fileObjId, artifactID, time, type, descriptions.get(TimelineLevelOfDetail.HIGH), descriptions.get(TimelineLevelOfDetail.MEDIUM), descriptions.get(TimelineLevelOfDetail.LOW), hashHit, tagged); singleEvent.parent = newParent; return singleEvent; } @@ -212,7 +213,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent { * @return the full description */ public String getFullDescription() { - return getDescription(TimelineEvent.DescriptionLevel.FULL); + return getDescription(TimelineLevelOfDetail.HIGH); } /** @@ -221,7 +222,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent { * @return the medium description */ public String getMedDescription() { - return getDescription(TimelineEvent.DescriptionLevel.MEDIUM); + return getDescription(TimelineLevelOfDetail.MEDIUM); } /** @@ -230,7 +231,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent { * @return the short description */ public String getShortDescription() { - return getDescription(TimelineEvent.DescriptionLevel.SHORT); + return getDescription(TimelineLevelOfDetail.LOW); } /** @@ -240,7 +241,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent { * * @return The description of this event at the given level of detail. */ - public String getDescription(TimelineEvent.DescriptionLevel lod) { + public String getDescription(TimelineLevelOfDetail lod) { return descriptions.get(lod); } @@ -299,7 +300,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent { @Override public SortedSet getClusters() { - EventCluster eventCluster = new EventCluster(new Interval(time * 1000, time * 1000), type, getEventIDs(), getEventIDsWithHashHits(), getEventIDsWithTags(), getFullDescription(), TimelineEvent.DescriptionLevel.FULL); + EventCluster eventCluster = new EventCluster(new Interval(time * 1000, time * 1000), type, getEventIDs(), getEventIDsWithHashHits(), getEventIDsWithTags(), getFullDescription(), TimelineLevelOfDetail.HIGH); return ImmutableSortedSet.orderedBy(Comparator.comparing(EventCluster::getStartMillis)).add(eventCluster).build(); } @@ -309,8 +310,8 @@ public class SingleDetailsViewEvent implements DetailViewEvent { } @Override - public TimelineEvent.DescriptionLevel getDescriptionLevel() { - return TimelineEvent.DescriptionLevel.FULL; + public TimelineLevelOfDetail getDescriptionLevel() { + return TimelineLevelOfDetail.HIGH; } /** diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/BaseTypeTreeItem.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/CategoryTypeTreeItem.java similarity index 88% rename from Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/BaseTypeTreeItem.java rename to Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/CategoryTypeTreeItem.java index a4b7c25770..c397ecf2f1 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/BaseTypeTreeItem.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/CategoryTypeTreeItem.java @@ -29,9 +29,9 @@ import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.DetailViewEvent; import org.sleuthkit.datamodel.TimelineEventType; /** - * EventTreeItem for base event types (file system, misc, web, ...) + * EventTreeItem for category event types (file system, misc, web, ...) */ -class BaseTypeTreeItem extends EventTypeTreeItem { +class CategoryTypeTreeItem extends EventTypeTreeItem { /** * A map of the children TreeItems, keyed by EventTypes if the children are @@ -46,8 +46,8 @@ class BaseTypeTreeItem extends EventTypeTreeItem { * @param comparator the initial comparator used to sort the children of * this tree item */ - BaseTypeTreeItem(DetailViewEvent event, Comparator> comparator) { - super(event.getEventType().getBaseType(), comparator); + CategoryTypeTreeItem(DetailViewEvent event, Comparator> comparator) { + super(event.getEventType().getCategory(), comparator); } @ThreadConfined(type = ThreadConfined.ThreadType.JFX) @@ -61,7 +61,7 @@ class BaseTypeTreeItem extends EventTypeTreeItem { * if the stripe and this tree item have the same type, create a * description tree item, else create a sub-type tree item */ - if (head.getEventType().getTypeLevel() == TimelineEventType.TypeLevel.SUB_TYPE) { + if (head.getEventType().getTypeHierarchyLevel() == TimelineEventType.HierarchyLevel.CATEGORY) { descriptionKey = head.getEventType().getDisplayName(); treeItemConstructor = () -> configureNewTreeItem(new SubTypeTreeItem(head, getComparator())); } else { @@ -87,7 +87,7 @@ class BaseTypeTreeItem extends EventTypeTreeItem { * if the stripe and this tree item have the same type, get the child * item keyed on event type, else keyed on description. */ - if (head.getEventType().getTypeLevel() == TimelineEventType.TypeLevel.SUB_TYPE) { + if (head.getEventType().getTypeHierarchyLevel()== TimelineEventType.HierarchyLevel.CATEGORY) { descTreeItem = childMap.get(head.getEventType().getDisplayName()); } else { path.remove(0); //remove head of list if we are going straight to description diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/RootItem.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/RootItem.java index 9c57815c3f..8b5efbba48 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/RootItem.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/RootItem.java @@ -35,7 +35,7 @@ class RootItem extends EventsTreeItem { /** * A map of the children BaseTypeTreeItems, keyed by EventType. */ - private final Map childMap = new HashMap<>(); + private final Map childMap = new HashMap<>(); /** * Constructor @@ -85,7 +85,7 @@ class RootItem extends EventsTreeItem { @Override void remove(List path) { DetailViewEvent event = path.get(0); - BaseTypeTreeItem typeTreeItem = childMap.get(event.getEventType().getBaseType()); + CategoryTypeTreeItem typeTreeItem = childMap.get(event.getEventType().getCategory()); //remove the path from the child if (typeTreeItem != null) { @@ -93,7 +93,7 @@ class RootItem extends EventsTreeItem { //if the child has no children remove it also if (typeTreeItem.getChildren().isEmpty()) { - childMap.remove(event.getEventType().getBaseType()); + childMap.remove(event.getEventType().getCategory()); getChildren().remove(typeTreeItem); } } @@ -102,8 +102,8 @@ class RootItem extends EventsTreeItem { @Override void insert(List path) { DetailViewEvent event = path.get(0); - BaseTypeTreeItem treeItem = childMap.computeIfAbsent(event.getEventType().getBaseType(), - baseType -> configureNewTreeItem(new BaseTypeTreeItem(event, getComparator())) + CategoryTypeTreeItem treeItem = childMap.computeIfAbsent(event.getEventType().getCategory(), + baseType -> configureNewTreeItem(new CategoryTypeTreeItem(event, getComparator())) ); treeItem.insert(path); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/LegendCell.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/LegendCell.java index 8d12377d0f..53ffec84a6 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/LegendCell.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/LegendCell.java @@ -79,8 +79,8 @@ final class LegendCell extends TreeTableCell, FilterState> { setLegendColor(filter, rect, newZoomLevel); }); - HBox hBox = new HBox(new Rectangle(filter.getEventType().getTypeLevel().ordinal() * 10, 5, CLEAR), - new ImageView(EventTypeUtils.getImagePath(filter.getEventType())), rect + HBox hBox = new HBox(new Rectangle(filter.getRootEventType().getTypeHierarchyLevel().ordinal() * 10, 5, CLEAR), + new ImageView(EventTypeUtils.getImagePath(filter.getRootEventType())), rect ); hBox.setAlignment(Pos.CENTER); Platform.runLater(() -> { @@ -92,7 +92,7 @@ final class LegendCell extends TreeTableCell, FilterState> { TextFilter filter = (TextFilter) item.getFilter(); TextField textField = new TextField(); textField.setPromptText(Bundle.Timeline_ui_filtering_promptText()); - textField.textProperty().bindBidirectional(filter.textProperty()); + textField.textProperty().bindBidirectional(filter.substringProperty()); Platform.runLater(() -> setGraphic(textField)); } else { @@ -104,12 +104,12 @@ final class LegendCell extends TreeTableCell, FilterState> { } } - private void setLegendColor(EventTypeFilter filter, Rectangle rect, TimelineEventType.TypeLevel eventTypeZoom) { + private void setLegendColor(EventTypeFilter filter, Rectangle rect, TimelineEventType.HierarchyLevel eventTypeZoom) { //only show legend color if filter is of the same zoomlevel as requested in filteredEvents - if (eventTypeZoom.equals(filter.getEventType().getTypeLevel())) { + if (eventTypeZoom.equals(filter.getRootEventType().getTypeHierarchyLevel())) { Platform.runLater(() -> { - rect.setStroke(EventTypeUtils.getColor(filter.getEventType().getSuperType())); - rect.setFill(EventTypeUtils.getColor(filter.getEventType())); + rect.setStroke(EventTypeUtils.getColor(filter.getRootEventType().getParent())); + rect.setFill(EventTypeUtils.getColor(filter.getRootEventType())); }); } else { Platform.runLater(() -> { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/DescriptionFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/DescriptionFilter.java index 6fb03776bd..01287bd79f 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/DescriptionFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/DescriptionFilter.java @@ -20,23 +20,23 @@ package org.sleuthkit.autopsy.timeline.ui.filtering.datamodel; import java.util.Objects; import org.sleuthkit.datamodel.TimelineEvent; -import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * Ui level filter for events that have the given description. */ public final class DescriptionFilter implements UIFilter { - private final TimelineEvent.DescriptionLevel descriptionLoD; + private final TimelineLevelOfDetail descriptionLoD; private final String description; - public DescriptionFilter(TimelineEvent.DescriptionLevel descriptionLoD, String description) { + public DescriptionFilter(TimelineLevelOfDetail descriptionLoD, String description) { super(); this.descriptionLoD = descriptionLoD; this.description = description; } - public TimelineEvent.DescriptionLevel getDescriptionLevel() { + public TimelineLevelOfDetail getDescriptionLevel() { return descriptionLoD; } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/SqlFilterState.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/SqlFilterState.java index 2f33ebec61..195637c4b3 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/SqlFilterState.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/SqlFilterState.java @@ -39,9 +39,9 @@ public class SqlFilterState extends AbstractF selectedProperty().addListener(selectedProperty -> { if (filter instanceof TimelineFilter.TagsFilter) { - ((TimelineFilter.TagsFilter)filter).setTagged(isSelected()); + ((TimelineFilter.TagsFilter)filter).setEventSourcesAreTagged(isSelected()); } else if (filter instanceof TimelineFilter.HashHitsFilter) { - ((TimelineFilter.HashHitsFilter)filter).setTagged(isSelected()); + ((TimelineFilter.HashHitsFilter)filter).setEventSourcesHaveHashSetHits(isSelected()); } }); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java index 8f4f1b2477..0f068b8a8d 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java @@ -98,6 +98,7 @@ import static org.sleuthkit.datamodel.TimelineEventType.FILE_CREATED; import static org.sleuthkit.datamodel.TimelineEventType.FILE_MODIFIED; import static org.sleuthkit.datamodel.TimelineEventType.FILE_SYSTEM; import org.sleuthkit.datamodel.TimelineEvent; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * The inner component that makes up the List view. Manages the TableView. @@ -232,11 +233,11 @@ class ListTimeline extends BorderPane { //// set up cell and cell-value factories for columns dateTimeColumn.setCellValueFactory(CELL_VALUE_FACTORY); dateTimeColumn.setCellFactory(col -> new TextEventTableCell(singleEvent - -> TimeLineController.getZonedFormatter().print(singleEvent.getStartMillis()))); + -> TimeLineController.getZonedFormatter().print(singleEvent.getEventTimeInMs()))); descriptionColumn.setCellValueFactory(CELL_VALUE_FACTORY); descriptionColumn.setCellFactory(col -> new TextEventTableCell(singleEvent - -> singleEvent.getDescription(TimelineEvent.DescriptionLevel.FULL))); + -> singleEvent.getDescription(TimelineLevelOfDetail.HIGH))); typeColumn.setCellValueFactory(CELL_VALUE_FACTORY); typeColumn.setCellFactory(col -> new EventTypeCell()); @@ -409,11 +410,11 @@ class ListTimeline extends BorderPane { setGraphic(null); setTooltip(null); } else { - if (item.getEventTypes().stream().allMatch(TimelineEventType.FILE_SYSTEM.getSubTypes()::contains)) { + if (item.getEventTypes().stream().allMatch(TimelineEventType.FILE_SYSTEM.getChildren()::contains)) { String typeString = ""; //NON-NLS VBox toolTipVbox = new VBox(5); - for (TimelineEventType type : TimelineEventType.FILE_SYSTEM.getSubTypes()) { + for (TimelineEventType type : TimelineEventType.FILE_SYSTEM.getChildren()) { if (item.getEventTypes().contains(type)) { if (type.equals(FILE_MODIFIED)) { typeString += "M"; //NON-NLS @@ -472,7 +473,7 @@ class ListTimeline extends BorderPane { protected void updateItem(CombinedEvent item, boolean empty) { super.updateItem(item, empty); - if (empty || item == null || (getEvent().isTagged() == false)) { + if (empty || item == null || (getEvent().eventSourceIsTagged() == false)) { setGraphic(null); setTooltip(null); } else { @@ -485,13 +486,13 @@ class ListTimeline extends BorderPane { SortedSet tagNames = new TreeSet<>(); try { //get file tags - Content file = sleuthkitCase.getContentById(getEvent().getFileObjID()); + Content file = sleuthkitCase.getContentById(getEvent().getContentObjID()); tagsManager.getContentTagsByContent(file).stream() .map(tag -> tag.getName().getDisplayName()) .forEach(tagNames::add); } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Failed to lookup tags for obj id " + getEvent().getFileObjID(), ex); //NON-NLS + logger.log(Level.SEVERE, "Failed to lookup tags for obj id " + getEvent().getContentObjID(), ex); //NON-NLS Platform.runLater(() -> { Notifications.create() .owner(getScene().getWindow()) @@ -544,7 +545,7 @@ class ListTimeline extends BorderPane { protected void updateItem(CombinedEvent item, boolean empty) { super.updateItem(item, empty); - if (empty || item == null || (getEvent().isHashHit() == false)) { + if (empty || item == null || (getEvent().eventSourceHasHashHits()== false)) { setGraphic(null); setTooltip(null); } else { @@ -555,12 +556,12 @@ class ListTimeline extends BorderPane { */ setGraphic(new ImageView(HASH_HIT)); try { - Set hashSetNames = new TreeSet<>(sleuthkitCase.getContentById(getEvent().getFileObjID()).getHashSetNames()); + Set hashSetNames = new TreeSet<>(sleuthkitCase.getContentById(getEvent().getContentObjID()).getHashSetNames()); Tooltip tooltip = new Tooltip(Bundle.ListTimeline_hashHitTooltip_text(String.join("\n", hashSetNames))); //NON-NLS tooltip.setGraphic(new ImageView(HASH_HIT)); setTooltip(tooltip); } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Failed to lookup hash set names for obj id " + getEvent().getFileObjID(), ex); //NON-NLS + logger.log(Level.SEVERE, "Failed to lookup hash set names for obj id " + getEvent().getContentObjID(), ex); //NON-NLS Platform.runLater(() -> { Notifications.create() .owner(getScene().getWindow()) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/datamodel/ListViewModel.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/datamodel/ListViewModel.java index 4103e736fe..957b17265c 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/datamodel/ListViewModel.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/datamodel/ListViewModel.java @@ -35,6 +35,7 @@ import org.sleuthkit.datamodel.TimelineManager; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TimelineEvent; import org.sleuthkit.datamodel.TimelineEventType; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * Model for the ListView. Uses FilteredEventsModel as underlying datamodel and @@ -88,7 +89,7 @@ public class ListViewModel { ArrayList combinedEvents = new ArrayList<>(); - Map> groupedEventList = events.stream().collect(groupingBy(event -> new CombinedEventGroup(event.getTime(), event.getFileObjID(), event.getFullDescription()))); + Map> groupedEventList = events.stream().collect(groupingBy(event -> new CombinedEventGroup(event.getTime(), event.getContentObjID(), event.getDescription(TimelineLevelOfDetail.HIGH)))); for(Entry> entry: groupedEventList.entrySet()){ List groupedEvents = entry.getValue(); @@ -120,7 +121,7 @@ public class ListViewModel { private boolean hasFileTypeEvents(Collection eventTypes) { for (TimelineEventType type: eventTypes) { - if (type.getBaseType() != TimelineEventType.FILE_SYSTEM) { + if (type.getCategory() != TimelineEventType.FILE_SYSTEM) { return false; } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/zooming/ZoomSettingsPane.java b/Core/src/org/sleuthkit/autopsy/timeline/zooming/ZoomSettingsPane.java index 9558157094..0d832e0108 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/zooming/ZoomSettingsPane.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/zooming/ZoomSettingsPane.java @@ -41,6 +41,7 @@ import org.sleuthkit.autopsy.timeline.utils.RangeDivision; import org.sleuthkit.datamodel.TimelineEvent; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TimelineEventType; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * A Panel that acts as a view for a given @@ -93,21 +94,21 @@ public class ZoomSettingsPane extends TitledPane { zoomLabel.setText(Bundle.ZoomSettingsPane_zoomLabel_text()); typeZoomSlider.setMin(1); //don't show ROOT_TYPE - typeZoomSlider.setMax(TimelineEventType.TypeLevel.values().length - 1); + typeZoomSlider.setMax(TimelineEventType.HierarchyLevel.values().length - 1); configureSliderListeners(typeZoomSlider, controller::pushEventTypeZoom, filteredEvents.eventTypeZoomProperty(), - TimelineEventType.TypeLevel.class, - TimelineEventType.TypeLevel::ordinal, + TimelineEventType.HierarchyLevel.class, + TimelineEventType.HierarchyLevel::ordinal, Function.identity()); typeZoomLabel.setText(Bundle.ZoomSettingsPane_typeZoomLabel_text()); - descrLODSlider.setMax(TimelineEvent.DescriptionLevel.values().length - 1); + descrLODSlider.setMax(TimelineLevelOfDetail.values().length - 1); configureSliderListeners(descrLODSlider, controller::pushDescrLOD, filteredEvents.descriptionLODProperty(), - TimelineEvent.DescriptionLevel.class, - TimelineEvent.DescriptionLevel::ordinal, + TimelineLevelOfDetail.class, + TimelineLevelOfDetail::ordinal, Function.identity()); descrLODLabel.setText(Bundle.ZoomSettingsPane_descrLODLabel_text()); //the description slider is only usefull in the detail view diff --git a/Core/src/org/sleuthkit/autopsy/timeline/zooming/ZoomState.java b/Core/src/org/sleuthkit/autopsy/timeline/zooming/ZoomState.java index 4484169138..2588a32cf7 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/zooming/ZoomState.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/zooming/ZoomState.java @@ -23,6 +23,7 @@ import org.joda.time.Interval; import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState; import org.sleuthkit.datamodel.TimelineEvent; import org.sleuthkit.datamodel.TimelineEventType; +import org.sleuthkit.datamodel.TimelineLevelOfDetail; /** * This class encapsulates all the zoom(and filter) parameters into one object @@ -32,17 +33,17 @@ final public class ZoomState { private final Interval timeRange; - private final TimelineEventType.TypeLevel typeZoomLevel; + private final TimelineEventType.HierarchyLevel typeZoomLevel; private final RootFilterState filter; - private final TimelineEvent.DescriptionLevel descrLOD; + private final TimelineLevelOfDetail descrLOD; public Interval getTimeRange() { return timeRange; } - public TimelineEventType.TypeLevel getTypeZoomLevel() { + public TimelineEventType.HierarchyLevel getTypeZoomLevel() { return typeZoomLevel; } @@ -50,22 +51,22 @@ final public class ZoomState { return filter; } - public TimelineEvent.DescriptionLevel getDescriptionLOD() { + public TimelineLevelOfDetail getDescriptionLOD() { return descrLOD; } - public ZoomState(Interval timeRange, TimelineEventType.TypeLevel zoomLevel, RootFilterState filter, TimelineEvent.DescriptionLevel descrLOD) { + public ZoomState(Interval timeRange, TimelineEventType.HierarchyLevel zoomLevel, RootFilterState filter, TimelineLevelOfDetail descrLOD) { this.timeRange = timeRange; this.typeZoomLevel = zoomLevel; this.filter = filter; this.descrLOD = descrLOD; } - public ZoomState withTimeAndType(Interval timeRange, TimelineEventType.TypeLevel zoomLevel) { + public ZoomState withTimeAndType(Interval timeRange, TimelineEventType.HierarchyLevel zoomLevel) { return new ZoomState(timeRange, zoomLevel, filter, descrLOD); } - public ZoomState withTypeZoomLevel(TimelineEventType.TypeLevel zoomLevel) { + public ZoomState withTypeZoomLevel(TimelineEventType.HierarchyLevel zoomLevel) { return new ZoomState(timeRange, zoomLevel, filter, descrLOD); } @@ -73,7 +74,7 @@ final public class ZoomState { return new ZoomState(timeRange, typeZoomLevel, filter, descrLOD); } - public ZoomState withDescrLOD(TimelineEvent.DescriptionLevel descrLOD) { + public ZoomState withDescrLOD(TimelineLevelOfDetail descrLOD) { return new ZoomState(timeRange, typeZoomLevel, filter, descrLOD); } @@ -85,7 +86,7 @@ final public class ZoomState { return this.filter.equals(filterSet); } - public boolean hasTypeZoomLevel(TimelineEventType.TypeLevel typeZoom) { + public boolean hasTypeZoomLevel(TimelineEventType.HierarchyLevel typeZoom) { return this.typeZoomLevel.equals(typeZoom); } @@ -93,7 +94,7 @@ final public class ZoomState { return this.timeRange != null && this.timeRange.equals(timeRange); } - public boolean hasDescrLOD(TimelineEvent.DescriptionLevel newLOD) { + public boolean hasDescrLOD(TimelineLevelOfDetail newLOD) { return this.descrLOD.equals(newLOD); }