From f949a00093715b74e033b7920cde0430bdf40d8c Mon Sep 17 00:00:00 2001 From: jmillman Date: Thu, 10 Mar 2016 16:18:11 -0500 Subject: [PATCH] fix events tree; more cleanup --- .../timeline/datamodel/EventCluster.java | 17 +++--- .../timeline/datamodel/EventStripe.java | 38 ++++++++----- .../timeline/datamodel/MultiEvent.java | 2 +- .../autopsy/timeline/db/EventDB.java | 7 +-- .../ui/detailview/DetailViewPane.java | 2 +- .../timeline/ui/detailview/DetailsChart.java | 13 ++++- .../ui/detailview/EventClusterNode.java | 51 +++++++++-------- .../ui/detailview/EventStripeNode.java | 13 ++--- .../ui/detailview/MultiEventNodeBase.java | 20 +++---- .../detailview/PrimaryDetailsChartLane.java | 2 - .../tree/EventDescriptionTreeItem.java | 57 ++++++++----------- .../ui/detailview/tree/EventTypeTreeItem.java | 42 +++++++------- .../ui/detailview/tree/EventsTree.java | 15 ++--- .../{NavTreeItem.java => EventsTreeItem.java} | 8 ++- .../timeline/ui/detailview/tree/RootItem.java | 47 +++++++-------- 15 files changed, 162 insertions(+), 172 deletions(-) rename Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/{NavTreeItem.java => EventsTreeItem.java} (85%) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/EventCluster.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/EventCluster.java index c353979e3a..71a2d61482 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/EventCluster.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/EventCluster.java @@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Sets; import java.util.Comparator; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.SortedSet; @@ -33,9 +32,9 @@ import org.sleuthkit.autopsy.timeline.utils.IntervalUtils; import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD; /** - * Represents a set of other events clustered together. All the - * sub events should have the same type and matching descriptions at the - * designated 'zoom level', and be 'close together' in time. + * Represents a set of other events clustered together. All the sub events + * should have the same type and matching descriptions at the designated 'zoom + * level', and be 'close together' in time. */ @Immutable public class EventCluster implements MultiEvent { @@ -120,7 +119,7 @@ public class EventCluster implements MultiEvent { } @Override - public Optional getParentBundle() { + public Optional getParent() { return Optional.ofNullable(parent); } @@ -181,9 +180,6 @@ public class EventCluster implements MultiEvent { * EventBundle as the parent. */ public EventCluster withParent(EventStripe parent) { - if (Objects.nonNull(this.parent)) { - throw new IllegalStateException("Event Cluster already has a parent!"); - } return new EventCluster(span, type, eventIDs, hashHits, tagged, description, lod, parent); } @@ -192,5 +188,8 @@ public class EventCluster implements MultiEvent { return ImmutableSortedSet.orderedBy(Comparator.comparing(EventCluster::getStartMillis)).add(this).build(); } - + @Override + public String toString() { + return "EventCluster{" + "description=" + description + ", eventIDs=" + eventIDs.size() + '}'; + } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/EventStripe.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/EventStripe.java index a9d8a6870a..bd160ac624 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/EventStripe.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/EventStripe.java @@ -22,10 +22,10 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import java.util.Comparator; +import java.util.Objects; import java.util.Optional; import java.util.SortedSet; import javax.annotation.concurrent.Immutable; -import org.python.google.common.base.Objects; import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType; import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD; @@ -39,10 +39,10 @@ public final class EventStripe implements MultiEvent { public static EventStripe merge(EventStripe u, EventStripe v) { Preconditions.checkNotNull(u); Preconditions.checkNotNull(v); - Preconditions.checkArgument(Objects.equal(u.description, v.description)); - Preconditions.checkArgument(Objects.equal(u.lod, v.lod)); - Preconditions.checkArgument(Objects.equal(u.type, v.type)); - Preconditions.checkArgument(Objects.equal(u.parent, v.parent)); + Preconditions.checkArgument(Objects.equals(u.description, v.description)); + Preconditions.checkArgument(Objects.equals(u.lod, v.lod)); + Preconditions.checkArgument(Objects.equals(u.type, v.type)); + Preconditions.checkArgument(Objects.equals(u.parent, v.parent)); return new EventStripe(u, v); } @@ -82,8 +82,10 @@ public final class EventStripe implements MultiEvent { private final ImmutableSet hashHits; public EventStripe withParent(EventCluster parent) { - EventStripe eventStripe = new EventStripe(parent, this.type, this.description, this.lod, clusters, eventIDs, tagged, hashHits); - return eventStripe; + if (java.util.Objects.nonNull(this.parent)) { + throw new IllegalStateException("Event Stripe already has a parent!"); + } + return new EventStripe(parent, this.type, this.description, this.lod, clusters, eventIDs, tagged, hashHits); } private EventStripe(EventCluster parent, EventType type, String description, DescriptionLoD lod, SortedSet clusters, ImmutableSet eventIDs, ImmutableSet tagged, ImmutableSet hashHits) { @@ -98,9 +100,10 @@ public final class EventStripe implements MultiEvent { this.hashHits = hashHits; } - public EventStripe(EventCluster cluster, EventCluster parent) { + public EventStripe(EventCluster cluster) { + this.clusters = ImmutableSortedSet.orderedBy(Comparator.comparing(EventCluster::getStartMillis)) - .add(cluster).build(); + .add(cluster.withParent(this)).build(); type = cluster.getEventType(); description = cluster.getDescription(); @@ -108,7 +111,7 @@ public final class EventStripe implements MultiEvent { eventIDs = cluster.getEventIDs(); tagged = cluster.getEventIDsWithTags(); hashHits = cluster.getEventIDsWithHashHits(); - this.parent = parent; + this.parent = null; } private EventStripe(EventStripe u, EventStripe v) { @@ -132,14 +135,22 @@ public final class EventStripe implements MultiEvent { .addAll(u.getEventIDsWithHashHits()) .addAll(v.getEventIDsWithHashHits()) .build(); - parent = u.getParentBundle().orElse(v.getParentBundle().orElse(null)); + parent = u.getParent().orElse(v.getParent().orElse(null)); } @Override - public Optional getParentBundle() { + public Optional getParent() { return Optional.ofNullable(parent); } + public Optional getParentStripe() { + if (getParent().isPresent()) { + return getParent().get().getParent(); + } else { + return Optional.empty(); + } + } + @Override public String getDescription() { return description; @@ -191,8 +202,7 @@ public final class EventStripe implements MultiEvent { @Override public String toString() { - return "EventStripe{" + "description=" + description + ", eventIDs=" + eventIDs.size() + '}'; //NON-NLS + return "EventStripe{" + "description=" + description + ", eventIDs=" + (Objects.isNull(eventIDs) ? 0 : eventIDs.size()) + '}'; //NON-NLS } - } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/MultiEvent.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/MultiEvent.java index c5e17b5542..eee68eada8 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/MultiEvent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/MultiEvent.java @@ -45,7 +45,7 @@ public interface MultiEvent> extends TimeLineEv long getStartMillis(); - Optional getParentBundle(); + Optional getParent(); default int getSize() { return getEventIDs().size(); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/db/EventDB.java b/Core/src/org/sleuthkit/autopsy/timeline/db/EventDB.java index 246fee2226..996c35ef3b 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/db/EventDB.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/db/EventDB.java @@ -1050,7 +1050,7 @@ public class EventDB { switch (Version.getBuildType()) { case DEVELOPMENT: - LOGGER.log(Level.INFO, "executing timeline query: {0}", query); //NON-NLS +// LOGGER.log(Level.INFO, "executing timeline query: {0}", query); //NON-NLS break; case RELEASE: default: @@ -1097,8 +1097,7 @@ public class EventDB { Set hashHits = SQLHelper.unGroupConcat(rs.getString("hash_hits"), Long::valueOf); //NON-NLS Set tagged = SQLHelper.unGroupConcat(rs.getString("taggeds"), Long::valueOf); //NON-NLS - return new EventCluster(interval, type, eventIDs, hashHits, tagged, - description, descriptionLOD); + return new EventCluster(interval, type, eventIDs, hashHits, tagged, description, descriptionLOD); } /** @@ -1159,7 +1158,7 @@ public class EventDB { for (EventCluster eventCluster : aggEvents) { stripeDescMap.merge(ImmutablePair.of(eventCluster.getEventType(), eventCluster.getDescription()), - new EventStripe(eventCluster, null), EventStripe::merge); + new EventStripe(eventCluster), EventStripe::merge); } return stripeDescMap.values().stream().sorted(Comparator.comparing(EventStripe::getStartMillis)).collect(Collectors.toList()); 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 2363ae0b54..ca2e027b53 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java @@ -111,7 +111,7 @@ public class DetailViewPane extends AbstractVisualizationPane getEventStripes() { - return chart.getEventStripes(); + return chart.getAllNestedEventStripes(); } public void setSelectionModel(MultipleSelectionModel> selectionModel) { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailsChart.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailsChart.java index 86a5a0eb32..5af654be2b 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailsChart.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailsChart.java @@ -67,6 +67,7 @@ public final class DetailsChart extends Control implements TimeLineChart> selectedNodes; private final DetailsChartLayoutSettings layoutSettings = new DetailsChartLayoutSettings(); private final TimeLineController controller; + private ObservableList nestedEventStripes = FXCollections.observableArrayList(); DetailsChart(TimeLineController controller, DateAxis detailsChartDateAxis, DateAxis pinnedDateAxis, Axis verticalAxis, ObservableList> selectedNodes) { this.controller = controller; @@ -99,6 +100,7 @@ public final class DetailsChart extends Control implements TimeLineChart getAllNestedEventStripes() { + return nestedEventStripes; + } + + ObservableList getEventStripes() { + return eventStripes; } private static class DetailIntervalSelector extends IntervalSelector { @@ -244,7 +255,7 @@ public final class DetailsChart extends Control implements TimeLineChart getEventStripes() { + ObservableList getRootEventStripes() { return eventStripes; } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java index a67e2ddcd2..047c83a4c3 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.List; import static java.util.Objects.nonNull; import java.util.concurrent.ExecutionException; +import java.util.function.Function; import java.util.logging.Level; import java.util.stream.Collectors; import javafx.concurrent.Task; @@ -119,12 +120,11 @@ final public class EventClusterNode extends MultiEventNodeBase> loggedTask = new LoggedTask>(Bundle.EventStripeNode_loggedTask_name(), false) { + Task> loggedTask = new LoggedTask>(Bundle.EventClusterNode_loggedTask_name(), false) { private volatile DescriptionLoD loadedDescriptionLoD = getDescriptionLoD().withRelativeDetail(relativeDetail); @Override protected List call() throws Exception { - List bundles; + List stripes; DescriptionLoD next = loadedDescriptionLoD; do { loadedDescriptionLoD = next; - if (loadedDescriptionLoD == getEventBundle().getDescriptionLoD()) { + if (loadedDescriptionLoD == getEvent().getDescriptionLoD()) { return Collections.emptyList(); } - bundles = eventsModel.getEventStripes(zoomParams.withDescrLOD(loadedDescriptionLoD)); + stripes = eventsModel.getEventStripes(zoomParams.withDescrLOD(loadedDescriptionLoD)); next = loadedDescriptionLoD.withRelativeDetail(relativeDetail); - } while (bundles.size() == 1 && nonNull(next)); + } while (stripes.size() == 1 && nonNull(next)); // return list of EventStripes representing sub-bundles - return bundles.stream() - .map(eventStripe -> eventStripe.withParent(getEventCluster())) + return stripes.stream() + .map(new Function() { + + public EventStripe apply(EventStripe eventStripe) { + return eventStripe.withParent(getEvent()); + } + }) .collect(Collectors.toList()); } @Override protected void succeeded() { try { - List bundles = get(); + List newSubStripes = get(); //clear the existing subnodes - List transform = subNodes.stream().flatMap(new StripeFlattener()).collect(Collectors.toList()); -// getChartLane().getParentChart().getEventStripes().removeAll(transform); + List oldSubStripes = subNodes.stream().flatMap(new StripeFlattener()).collect(Collectors.toList()); + getChartLane().getParentChart().getAllNestedEventStripes().removeAll(oldSubStripes); subNodes.clear(); - if (bundles.isEmpty()) { + if (newSubStripes.isEmpty()) { getChildren().setAll(subNodePane, infoHBox); - setDescriptionLOD(getEventBundle().getDescriptionLoD()); + setDescriptionLOD(getEvent().getDescriptionLoD()); } else { -// getChartLane().getParentChart().getEventStripes().addAll(bundles); - subNodes.addAll(Lists.transform(bundles, EventClusterNode.this::createChildNode)); + getChartLane().getParentChart().getAllNestedEventStripes().addAll(newSubStripes); + subNodes.addAll(Lists.transform(newSubStripes, EventClusterNode.this::createChildNode)); getChildren().setAll(new VBox(infoHBox, subNodePane)); setDescriptionLOD(loadedDescriptionLoD); } @@ -202,10 +207,6 @@ final public class EventClusterNode extends MultiEventNodeBase { if (node.getDescriptionLoD().moreDetailed() != null) { - node.loadSubBundles(DescriptionLoD.RelativeDetail.MORE); + node.loadSubStripes(DescriptionLoD.RelativeDetail.MORE); } }); disabledProperty().bind(node.descriptionLoDProperty().isEqualTo(DescriptionLoD.FULL)); @@ -269,11 +270,11 @@ final public class EventClusterNode extends MultiEventNodeBase { if (node.getDescriptionLoD().lessDetailed() != null) { - node.loadSubBundles(DescriptionLoD.RelativeDetail.LESS); + node.loadSubStripes(DescriptionLoD.RelativeDetail.LESS); } }); - disabledProperty().bind(node.descriptionLoDProperty().isEqualTo(node.getEventCluster().getDescriptionLoD())); + disabledProperty().bind(node.descriptionLoDProperty().isEqualTo(node.getEvent().getDescriptionLoD())); } } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java index 8088c670bc..5da9be7912 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java @@ -57,20 +57,19 @@ final public class EventStripeNode extends MultiEventNodeBase 1) { for (EventCluster cluster : eventStripe.getClusters()) { - subNodes.add(createChildNode(cluster)); + subNodes.add(createChildNode(cluster.withParent(eventStripe))); } getChildren().addAll(new VBox(infoHBox, subNodePane)); } else { EventNodeBase childNode; - EventCluster cluster = Iterables.getOnlyElement(eventStripe.getClusters()); + EventCluster cluster = Iterables.getOnlyElement(eventStripe.getClusters()).withParent(eventStripe); if (cluster.getEventIDs().size() == 1) { - SingleEventNode singleEventNode = new SingleEventNode(getChartLane(), getChartLane().getController().getEventsModel().getEventById(Iterables.getOnlyElement(cluster.getEventIDs())), this); - childNode = singleEventNode; + childNode = createChildNode(cluster); } else { - EventClusterNode eventClusterNode = new EventClusterNode(getChartLane(), cluster, this); + EventClusterNode eventClusterNode = (EventClusterNode) createChildNode(cluster); eventClusterNode.installActionButtons(); - eventClusterNode.infoHBox.getChildren().remove(eventClusterNode.countLabel); controlsHBox.getChildren().addAll(eventClusterNode.minusButton, eventClusterNode.plusButton); + eventClusterNode.infoHBox.getChildren().remove(eventClusterNode.countLabel); childNode = eventClusterNode; } @@ -81,7 +80,7 @@ final public class EventStripeNode extends MultiEventNodeBase descLOD = new ReadOnlyObjectWrapper<>(); - MultiEventNodeBase(DetailsChartLane chartLane, BundleType eventBundle, ParentNodeType parentNode) { - super(eventBundle, parentNode, chartLane); - setDescriptionLOD(eventBundle.getDescriptionLoD()); + MultiEventNodeBase(DetailsChartLane chartLane, BundleType event, ParentNodeType parentNode) { + super(event, parentNode, chartLane); + setDescriptionLOD(event.getDescriptionLoD()); - if (eventBundle.getEventIDsWithHashHits().isEmpty()) { + if (event.getEventIDsWithHashHits().isEmpty()) { show(hashIV, false); } - if (eventBundle.getEventIDsWithTags().isEmpty()) { + if (event.getEventIDsWithTags().isEmpty()) { show(tagIV, false); } @@ -80,7 +80,7 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent chartLane.requestLayout()); Platform.runLater(() -> - setLayoutX(chartLane.getXAxis().getDisplayPosition(new DateTime(eventBundle.getStartMillis())) - getLayoutXCompensation()) + setLayoutX(chartLane.getXAxis().getDisplayPosition(new DateTime(event.getStartMillis())) - getLayoutXCompensation()) ); //initialize info hbox @@ -105,21 +105,17 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent> getSubNodes() { return subNodes; } final String getDescription() { - return getEventBundle().getDescription(); + return getEvent().getDescription(); } final Set getEventIDs() { - return getEventBundle().getEventIDs(); + return getEvent().getEventIDs(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/PrimaryDetailsChartLane.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/PrimaryDetailsChartLane.java index 69b1dcfe6b..403d30bec3 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/PrimaryDetailsChartLane.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/PrimaryDetailsChartLane.java @@ -100,8 +100,6 @@ public final class PrimaryDetailsChartLane extends DetailsChartLane }); } - - private double getParentXForEpochMillis(Long epochMillis) { return getXAxis().localToParent(getXForEpochMillis(epochMillis), 0).getX(); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventDescriptionTreeItem.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventDescriptionTreeItem.java index 85372311f7..faec34a6be 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventDescriptionTreeItem.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventDescriptionTreeItem.java @@ -24,57 +24,49 @@ import java.util.HashMap; import java.util.Map; import javafx.collections.FXCollections; import javafx.scene.control.TreeItem; +import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent; +import org.sleuthkit.autopsy.timeline.datamodel.EventStripe; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; /** * */ -class EventDescriptionTreeItem extends NavTreeItem { +class EventDescriptionTreeItem extends EventsTreeItem { /** * maps a description to the child item of this item with that description */ private final Map childMap = new HashMap<>(); - private final TimeLineEvent bundle; private Comparator> comparator = TreeComparator.Description; - public TimeLineEvent getEvent() { - return bundle; - } - - EventDescriptionTreeItem(TimeLineEvent g, Comparator> comp) { - bundle = g; + EventDescriptionTreeItem(EventStripe stripe, Comparator> comp) { comparator = comp; - setValue(g); - } - - @Override - public long getCount() { - return getValue().getSize(); + setValue(stripe); } @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - public void insert(Deque> path) { - MultiEvent head = path.removeFirst(); - EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(), description -> { - EventDescriptionTreeItem newTreeItem = new EventDescriptionTreeItem(head, comparator); - newTreeItem.setExpanded(true); - childMap.put(description, newTreeItem); - getChildren().add(newTreeItem); - resort(comparator, false); - return newTreeItem; - }); + public void insert(Deque path) { + EventStripe head = path.removeFirst(); + String substringAfter = StringUtils.substringAfter(head.getDescription(), head.getParentStripe().map(EventStripe::getDescription).orElse("")); + EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(substringAfter, + description -> { + EventDescriptionTreeItem newTreeItem = new EventDescriptionTreeItem(head, comparator); + newTreeItem.setExpanded(true); + getChildren().add(newTreeItem); + resort(comparator, false); + return newTreeItem; + }); if (path.isEmpty() == false) { treeItem.insert(path); } } - void remove(Deque> path) { - MultiEvent head = path.removeFirst(); - EventDescriptionTreeItem descTreeItem = childMap.get(head.getDescription()); + void remove(Deque path) { + EventStripe head = path.removeFirst(); + String substringAfter = StringUtils.substringAfter(head.getDescription(), head.getParentStripe().map(EventStripe::getDescription).orElse("")); + EventDescriptionTreeItem descTreeItem = childMap.get(substringAfter); if (path.isEmpty() == false) { descTreeItem.remove(path); } @@ -94,14 +86,14 @@ class EventDescriptionTreeItem extends NavTreeItem { } @Override - public NavTreeItem findTreeItemForEvent(TimeLineEvent t) { + public EventsTreeItem findTreeItemForEvent(TimeLineEvent event) { - if (getValue().getEventType() == t.getEventType() - && getValue().getDescription().equals(t.getDescription())) { + if (getValue().getEventType() == event.getEventType() + && getValue().getDescription().equals(event.getDescription())) { return this; } else { for (EventDescriptionTreeItem child : childMap.values()) { - final NavTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t); + final EventsTreeItem findTreeItemForEvent = child.findTreeItemForEvent(event); if (findTreeItemForEvent != null) { return findTreeItemForEvent; } @@ -109,5 +101,4 @@ class EventDescriptionTreeItem extends NavTreeItem { } return null; } - } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventTypeTreeItem.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventTypeTreeItem.java index 8f25e296b0..23ea3528e9 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventTypeTreeItem.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventTypeTreeItem.java @@ -25,10 +25,10 @@ import java.util.Map; import javafx.collections.FXCollections; import javafx.scene.control.TreeItem; import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent; +import org.sleuthkit.autopsy.timeline.datamodel.EventStripe; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; -class EventTypeTreeItem extends NavTreeItem { +class EventTypeTreeItem extends EventsTreeItem { /** * maps a description to the child item of this item with that description @@ -37,35 +37,31 @@ class EventTypeTreeItem extends NavTreeItem { private Comparator> comparator = TreeComparator.Description; - EventTypeTreeItem(MultiEvent g, Comparator> comp) { - setValue(g); + EventTypeTreeItem(EventStripe stripe, Comparator> comp) { + setValue(stripe); comparator = comp; } - @Override - public long getCount() { - return getValue().getSize(); - } - @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - public void insert(Deque> path) { - MultiEvent head = path.removeFirst(); - EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(), description -> { - EventDescriptionTreeItem newTreeItem = new EventDescriptionTreeItem(head, comparator); - newTreeItem.setExpanded(true); - childMap.put(head.getDescription(), newTreeItem); - getChildren().add(newTreeItem); - resort(comparator, false); - return newTreeItem; - }); + public void insert(Deque path) { + EventStripe head = path.removeFirst(); + + EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(), + description -> { + EventDescriptionTreeItem newTreeItem = new EventDescriptionTreeItem(head, comparator); + newTreeItem.setExpanded(true); + getChildren().add(newTreeItem); + resort(comparator, false); + return newTreeItem; + }); if (path.isEmpty() == false) { treeItem.insert(path); } } - void remove(Deque> path) { - MultiEvent head = path.removeFirst(); + void remove(Deque path) { + EventStripe head = path.removeFirst(); EventDescriptionTreeItem descTreeItem = childMap.get(head.getDescription()); if (descTreeItem != null) { if (path.isEmpty() == false) { @@ -79,11 +75,11 @@ class EventTypeTreeItem extends NavTreeItem { } @Override - public NavTreeItem findTreeItemForEvent(TimeLineEvent t) { + public EventsTreeItem findTreeItemForEvent(TimeLineEvent t) { if (t.getEventType().getBaseType() == getValue().getEventType().getBaseType()) { for (EventDescriptionTreeItem child : childMap.values()) { - final NavTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t); + final EventsTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t); if (findTreeItemForEvent != null) { return findTreeItemForEvent; } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventsTree.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventsTree.java index c619ee9c91..5cd9647d02 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventsTree.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventsTree.java @@ -49,6 +49,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.timeline.FXMLConstructor; import org.sleuthkit.autopsy.timeline.TimeLineController; +import org.sleuthkit.autopsy.timeline.datamodel.EventStripe; import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; import org.sleuthkit.autopsy.timeline.filters.AbstractFilter; @@ -86,15 +87,11 @@ final public class EventsTree extends BorderPane { this.detailViewPane = detailViewPane; detailViewPane.setSelectionModel(eventsTree.getSelectionModel()); - detailViewPane.getEventStripes().addListener((ListChangeListener.Change> c) -> { + detailViewPane.getEventStripes().addListener((ListChangeListener.Change c) -> { //on jfx thread while (c.next()) { - for (MultiEvent bundle : c.getAddedSubList()) { - getRoot().insert(bundle); - } - for (MultiEvent bundle : c.getRemoved()) { - getRoot().remove(bundle); - } + c.getRemoved().forEach(getRoot()::remove); + c.getAddedSubList().forEach(getRoot()::insert); } }); @@ -116,9 +113,7 @@ final public class EventsTree extends BorderPane { @ThreadConfined(type = ThreadConfined.ThreadType.JFX) private void setRoot() { RootItem root = new RootItem(TreeComparator.Type.reversed().thenComparing(sortByBox.getSelectionModel().getSelectedItem())); - for (MultiEvent bundle : detailViewPane.getEventStripes()) { - root.insert(bundle); - } + detailViewPane.getEventStripes().forEach(root::insert); eventsTree.setRoot(root); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/NavTreeItem.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventsTreeItem.java similarity index 85% rename from Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/NavTreeItem.java rename to Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventsTreeItem.java index c3fd30ff9b..b118044f14 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/NavTreeItem.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/EventsTreeItem.java @@ -28,12 +28,14 @@ import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; * {@link EventTreeCell}. Each NavTreeItem has a EventBundle which has a type, * description , count, etc. */ -abstract class NavTreeItem extends TreeItem { +abstract class EventsTreeItem extends TreeItem { - abstract long getCount(); + final long getSize() { + return getValue().getSize(); + } abstract void resort(Comparator> comp, Boolean recursive); - abstract NavTreeItem findTreeItemForEvent(TimeLineEvent t); + abstract EventsTreeItem findTreeItemForEvent(TimeLineEvent event); } 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 11cc15f11d..8b69f8b22f 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/RootItem.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/tree/RootItem.java @@ -26,14 +26,14 @@ import java.util.Map; import java.util.Optional; import javafx.scene.control.TreeItem; import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent; +import org.sleuthkit.autopsy.timeline.datamodel.EventStripe; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType; /** * */ -class RootItem extends NavTreeItem { +class RootItem extends EventsTreeItem { /** * maps a description to the child item of this item with that description @@ -49,52 +49,45 @@ class RootItem extends NavTreeItem { this.comparator = comp; } - @Override - public long getCount() { - return getValue().getSize(); - } - /** * Recursive method to add a grouping at a given path. * - * @param bundle bundle to add + * @param stripe stripe to add */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - public void insert(MultiEvent bundle) { + public void insert(EventStripe stripe) { - EventTypeTreeItem treeItem = childMap.computeIfAbsent(bundle.getEventType().getBaseType(), + EventTypeTreeItem treeItem = childMap.computeIfAbsent(stripe.getEventType().getBaseType(), baseType -> { - EventTypeTreeItem newTreeItem = new EventTypeTreeItem(bundle, comparator); + EventTypeTreeItem newTreeItem = new EventTypeTreeItem(stripe, comparator); newTreeItem.setExpanded(true); getChildren().add(newTreeItem); return newTreeItem; }); - treeItem.insert(getTreePath(bundle)); - + treeItem.insert(getTreePath(stripe)); } - void remove(MultiEvent bundle) { - EventTypeTreeItem typeTreeItem = childMap.get(bundle.getEventType().getBaseType()); + void remove(EventStripe stripe) { + EventTypeTreeItem typeTreeItem = childMap.get(stripe.getEventType().getBaseType()); if (typeTreeItem != null) { - typeTreeItem.remove(getTreePath(bundle)); + typeTreeItem.remove(getTreePath(stripe)); if (typeTreeItem.getChildren().isEmpty()) { - childMap.remove(bundle.getEventType().getBaseType()); + childMap.remove(stripe.getEventType().getBaseType()); getChildren().remove(typeTreeItem); } } } - static Deque< MultiEvent> getTreePath(MultiEvent g) { - Deque> path = new ArrayDeque<>(); - Optional> p = Optional.of(g); - - while (p.isPresent()) { - MultiEvent parent = p.get(); + static Deque< EventStripe> getTreePath(EventStripe event) { + Deque path = new ArrayDeque<>(); + path.addFirst(event); + Optional parentOptional = event.getParentStripe(); + while (parentOptional.isPresent()) { + EventStripe parent = parentOptional.get(); path.addFirst(parent); - p = parent.getParentBundle(); + parentOptional = parent.getParentStripe(); } - return path; } @@ -105,9 +98,9 @@ class RootItem extends NavTreeItem { } @Override - public NavTreeItem findTreeItemForEvent(TimeLineEvent t) { + public EventsTreeItem findTreeItemForEvent(TimeLineEvent t) { for (EventTypeTreeItem child : childMap.values()) { - final NavTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t); + final EventsTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t); if (findTreeItemForEvent != null) { return findTreeItemForEvent; }