fix another bug in EventsTree and make it more general (takes TimeLineEvent instead of EventStripe)

This commit is contained in:
jmillman 2016-04-13 16:43:54 -04:00
parent 2f087fb022
commit 395f248a06
14 changed files with 122 additions and 57 deletions

View File

@ -132,6 +132,11 @@ public class EventCluster implements MultiEvent<EventStripe> {
return Optional.ofNullable(parent); return Optional.ofNullable(parent);
} }
@Override
public Optional<EventStripe> getParentStripe() {
return getParent();
}
public Interval getSpan() { public Interval getSpan() {
return span; return span;
} }

View File

@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -50,10 +51,12 @@ public class SingleEvent implements TimeLineEvent {
private final boolean hashHit; private final boolean hashHit;
private final boolean tagged; private final boolean tagged;
private MultiEvent<?> parent = null;
public SingleEvent(long eventID, long dataSourceID, long objID, @Nullable Long artifactID, long time, EventType type, String fullDescription, String medDescription, String shortDescription, TskData.FileKnown known, boolean hashHit, boolean tagged) { public SingleEvent(long eventID, long dataSourceID, long objID, @Nullable Long artifactID, long time, EventType type, String fullDescription, String medDescription, String shortDescription, TskData.FileKnown known, boolean hashHit, boolean tagged) {
this.eventID = eventID; this.eventID = eventID;
this.fileID = objID; this.fileID = objID;
this.artifactID = artifactID == 0 ? null : artifactID; this.artifactID = (artifactID == null || artifactID == 0) ? null : artifactID;
this.time = time; this.time = time;
this.subType = type; this.subType = type;
descriptions = ImmutableMap.<DescriptionLoD, String>of(DescriptionLoD.FULL, fullDescription, descriptions = ImmutableMap.<DescriptionLoD, String>of(DescriptionLoD.FULL, fullDescription,
@ -66,6 +69,12 @@ public class SingleEvent implements TimeLineEvent {
this.dataSourceID = dataSourceID; this.dataSourceID = dataSourceID;
} }
public SingleEvent withParent(MultiEvent<?> newParent) {
SingleEvent singleEvent = new SingleEvent(eventID, dataSourceID, fileID, artifactID, time, subType, descriptions.get(DescriptionLoD.FULL), descriptions.get(DescriptionLoD.MEDIUM), descriptions.get(DescriptionLoD.SHORT), known, hashHit, tagged);
singleEvent.parent = newParent;
return singleEvent;
}
public boolean isTagged() { public boolean isTagged() {
return tagged; return tagged;
} }
@ -94,6 +103,7 @@ public class SingleEvent implements TimeLineEvent {
return time; return time;
} }
@Override
public EventType getEventType() { public EventType getEventType() {
return subType; return subType;
} }
@ -184,4 +194,15 @@ public class SingleEvent implements TimeLineEvent {
public DescriptionLoD getDescriptionLoD() { public DescriptionLoD getDescriptionLoD() {
return DescriptionLoD.FULL; return DescriptionLoD.FULL;
} }
@Override
public Optional<EventStripe> getParentStripe() {
if (parent == null) {
return Optional.empty();
} else if (parent instanceof EventStripe) {
return Optional.of((EventStripe) parent);
} else {
return parent.getParentStripe();
}
}
} }

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.timeline.datamodel; package org.sleuthkit.autopsy.timeline.datamodel;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType; import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
@ -32,6 +33,8 @@ public interface TimeLineEvent {
public DescriptionLoD getDescriptionLoD(); public DescriptionLoD getDescriptionLoD();
public Optional<EventStripe> getParentStripe();
Set<Long> getEventIDs(); Set<Long> getEventIDs();
Set<Long> getEventIDsWithHashHits(); Set<Long> getEventIDsWithHashHits();

View File

@ -114,8 +114,11 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
}); });
} }
public ObservableList<EventStripe> getAllEventStripes() { /*
return chart.getAllNestedEventStripes(); * gets the tree of event stripes flattened into a list
*/
public ObservableList<TimeLineEvent> getAllNestedEvents() {
return chart.getAllNestedEvents();
} }
public ObservableList<TimeLineEvent> getSelectedEvents() { public ObservableList<TimeLineEvent> getSelectedEvents() {

View File

@ -66,7 +66,7 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
private final ObservableList<EventNodeBase<?>> selectedNodes; private final ObservableList<EventNodeBase<?>> selectedNodes;
private final DetailsChartLayoutSettings layoutSettings = new DetailsChartLayoutSettings(); private final DetailsChartLayoutSettings layoutSettings = new DetailsChartLayoutSettings();
private final TimeLineController controller; private final TimeLineController controller;
private final ObservableList<EventStripe> nestedEventStripes = FXCollections.observableArrayList(); private final ObservableList<TimeLineEvent> nestedEvents = FXCollections.observableArrayList();
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private final ObservableList<EventStripe> eventStripes = FXCollections.observableArrayList(); private final ObservableList<EventStripe> eventStripes = FXCollections.observableArrayList();
@ -103,7 +103,7 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
void addStripe(EventStripe stripe) { void addStripe(EventStripe stripe) {
eventStripes.add(stripe); eventStripes.add(stripe);
nestedEventStripes.add(stripe); nestedEvents.add(stripe);
} }
void clearGuideLines() { void clearGuideLines() {
@ -129,11 +129,14 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
void reset() { void reset() {
eventStripes.clear(); eventStripes.clear();
nestedEventStripes.clear(); nestedEvents.clear();
} }
public ObservableList<EventStripe> getAllNestedEventStripes() { /*
return nestedEventStripes; * gets the tree of event stripes flattened into a list
*/
public ObservableList<TimeLineEvent> getAllNestedEvents() {
return nestedEvents;
} }
private static class DetailIntervalSelector extends IntervalSelector<DateTime> { private static class DetailIntervalSelector extends IntervalSelector<DateTime> {
@ -279,7 +282,7 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
DescriptionFilter descriptionFilter = chart.getController().getQuickHideFilters().stream() DescriptionFilter descriptionFilter = chart.getController().getQuickHideFilters().stream()
.filter(testFilter::equals) .filter(testFilter::equals)
.findFirst().orElseGet(() -> { .findFirst().orElseGet(() -> {
testFilter.selectedProperty().addListener(observable -> chart.requestLayout()); testFilter.selectedProperty().addListener(observable -> chart.requestLayout());
chart.getController().getQuickHideFilters().add(testFilter); chart.getController().getQuickHideFilters().add(testFilter);
return testFilter; return testFilter;
}); });

View File

@ -166,15 +166,16 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
List<EventStripe> newSubStripes = get(); List<EventStripe> newSubStripes = get();
//clear the existing subnodes //clear the existing subnodes
List<TimeLineEvent> oldSubStripes = subNodes.stream().flatMap(new StripeFlattener()).collect(Collectors.toList()); List<TimeLineEvent> oldSubEvents = subNodes.stream().flatMap(new StripeFlattener()).collect(Collectors.toList());
getChartLane().getParentChart().getAllNestedEventStripes().removeAll(oldSubStripes); getChartLane().getParentChart().getAllNestedEvents().removeAll(oldSubEvents);
subNodes.clear(); subNodes.clear();
if (newSubStripes.isEmpty()) { if (newSubStripes.isEmpty()) {
getChildren().setAll(subNodePane, infoHBox); getChildren().setAll(subNodePane, infoHBox);
setDescriptionLOD(getEvent().getDescriptionLoD()); setDescriptionLOD(getEvent().getDescriptionLoD());
} else { } else {
getChartLane().getParentChart().getAllNestedEventStripes().addAll(newSubStripes);
subNodes.addAll(Lists.transform(newSubStripes, EventClusterNode.this::createChildNode)); subNodes.addAll(Lists.transform(newSubStripes, EventClusterNode.this::createChildNode));
List<TimeLineEvent> newSubEvents = subNodes.stream().flatMap(new StripeFlattener()).collect(Collectors.toList());
getChartLane().getParentChart().getAllNestedEvents().addAll(newSubEvents);
getChildren().setAll(new VBox(infoHBox, subNodePane)); getChildren().setAll(new VBox(infoHBox, subNodePane));
setDescriptionLOD(loadedDescriptionLoD); setDescriptionLOD(loadedDescriptionLoD);
} }
@ -195,7 +196,7 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
@Override @Override
EventNodeBase<?> createChildNode(EventStripe stripe) { EventNodeBase<?> createChildNode(EventStripe stripe) {
if (stripe.getEventIDs().size() == 1) { if (stripe.getEventIDs().size() == 1) {
return new SingleEventNode(getChartLane(), getChartLane().getController().getEventsModel().getEventById(Iterables.getOnlyElement(stripe.getEventIDs())), this); return new SingleEventNode(getChartLane(), getChartLane().getController().getEventsModel().getEventById(Iterables.getOnlyElement(stripe.getEventIDs())).withParent(stripe), this);
} else { } else {
return new EventStripeNode(getChartLane(), stripe, this); return new EventStripeNode(getChartLane(), stripe, this);
} }

View File

@ -98,7 +98,7 @@ final public class EventStripeNode extends MultiEventNodeBase<EventStripe, Event
@Override @Override
EventNodeBase<?> createChildNode(EventCluster cluster) { EventNodeBase<?> createChildNode(EventCluster cluster) {
if (cluster.getEventIDs().size() == 1) { if (cluster.getEventIDs().size() == 1) {
return new SingleEventNode(getChartLane(), getChartLane().getController().getEventsModel().getEventById(Iterables.getOnlyElement(cluster.getEventIDs())), this); return new SingleEventNode(getChartLane(), getChartLane().getController().getEventsModel().getEventById(Iterables.getOnlyElement(cluster.getEventIDs())).withParent(cluster), this);
} else { } else {
return new EventClusterNode(getChartLane(), cluster, this); return new EventClusterNode(getChartLane(), cluster, this);
} }

View File

@ -23,7 +23,6 @@ import java.util.Deque;
import java.util.function.Supplier; import java.util.function.Supplier;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel; import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
@ -32,14 +31,14 @@ import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
*/ */
class BaseTypeTreeItem extends EventTypeTreeItem<EventsTreeItem> { class BaseTypeTreeItem extends EventTypeTreeItem<EventsTreeItem> {
BaseTypeTreeItem(EventStripe stripe, Comparator<TreeItem<TimeLineEvent>> comp) { BaseTypeTreeItem(TimeLineEvent stripe, Comparator<TreeItem<TimeLineEvent>> comp) {
super(stripe.getEventType().getBaseType(), comp); super(stripe.getEventType().getBaseType(), comp);
} }
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
@Override @Override
public void insert(Deque<EventStripe> path) { public void insert(Deque<TimeLineEvent> path) {
EventStripe peek = path.peek(); TimeLineEvent peek = path.peek();
Supplier< EventsTreeItem> treeItemConstructor; Supplier< EventsTreeItem> treeItemConstructor;
String descriptionKey; String descriptionKey;
/* /*
@ -51,7 +50,7 @@ class BaseTypeTreeItem extends EventTypeTreeItem<EventsTreeItem> {
treeItemConstructor = () -> configureNewTreeItem(new SubTypeTreeItem(peek, getComparator())); treeItemConstructor = () -> configureNewTreeItem(new SubTypeTreeItem(peek, getComparator()));
} else { } else {
descriptionKey = peek.getDescription(); descriptionKey = peek.getDescription();
EventStripe stripe = path.removeFirst(); TimeLineEvent stripe = path.removeFirst();
treeItemConstructor = () -> configureNewTreeItem(new EventDescriptionTreeItem(stripe, getComparator())); treeItemConstructor = () -> configureNewTreeItem(new EventDescriptionTreeItem(stripe, getComparator()));
} }
@ -64,9 +63,9 @@ class BaseTypeTreeItem extends EventTypeTreeItem<EventsTreeItem> {
} }
@Override @Override
void remove(Deque<EventStripe> path) { void remove(Deque<TimeLineEvent> path) {
EventStripe head = path.peek(); TimeLineEvent head = path.peek();
EventsTreeItem descTreeItem; EventsTreeItem descTreeItem;
if (head.getEventType().getZoomLevel() == EventTypeZoomLevel.SUB_TYPE) { if (head.getEventType().getZoomLevel() == EventTypeZoomLevel.SUB_TYPE) {

View File

@ -40,14 +40,14 @@ class EventDescriptionTreeItem extends EventsTreeItem {
*/ */
private final Map<String, EventDescriptionTreeItem> childMap = new HashMap<>(); private final Map<String, EventDescriptionTreeItem> childMap = new HashMap<>();
EventDescriptionTreeItem(EventStripe stripe, Comparator<TreeItem<TimeLineEvent>> comp) { EventDescriptionTreeItem(TimeLineEvent stripe, Comparator<TreeItem<TimeLineEvent>> comp) {
super(comp); super(comp);
setValue(stripe); setValue(stripe);
} }
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
public void insert(Deque<EventStripe> path) { public void insert(Deque<TimeLineEvent> path) {
EventStripe head = path.removeFirst(); TimeLineEvent head = path.removeFirst();
String substringAfter = StringUtils.substringAfter(head.getDescription(), head.getParentStripe().map(EventStripe::getDescription).orElse("")); String substringAfter = StringUtils.substringAfter(head.getDescription(), head.getParentStripe().map(EventStripe::getDescription).orElse(""));
EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(substringAfter, EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(substringAfter,
description -> configureNewTreeItem(new EventDescriptionTreeItem(head, getComparator())) description -> configureNewTreeItem(new EventDescriptionTreeItem(head, getComparator()))
@ -59,16 +59,19 @@ class EventDescriptionTreeItem extends EventsTreeItem {
} }
@Override @Override
void remove(Deque<EventStripe> path) { void remove(Deque<TimeLineEvent> path) {
EventStripe head = path.removeFirst(); TimeLineEvent head = path.removeFirst();
String substringAfter = StringUtils.substringAfter(head.getDescription(), head.getParentStripe().map(EventStripe::getDescription).orElse("")); String substringAfter = StringUtils.substringAfter(head.getDescription(), head.getParentStripe().map(EventStripe::getDescription).orElse(""));
EventDescriptionTreeItem descTreeItem = childMap.get(substringAfter); EventDescriptionTreeItem descTreeItem = childMap.get(substringAfter);
if (path.isEmpty() == false) {
descTreeItem.remove(path); if (descTreeItem != null) {
} if (path.isEmpty() == false) {
if (descTreeItem.getChildren().isEmpty()) { descTreeItem.remove(path);
childMap.remove(head.getDescription()); }
getChildren().remove(descTreeItem); if (descTreeItem.getChildren().isEmpty()) {
childMap.remove(substringAfter);
getChildren().remove(descTreeItem);
}
} }
} }

View File

@ -1,7 +1,20 @@
/* /*
* To change this license header, choose License Headers in Project Properties. * Autopsy Forensic Browser
* To change this template file, choose Tools | Templates *
* and open the template in the editor. * Copyright 2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.sleuthkit.autopsy.timeline.ui.detailview.tree; package org.sleuthkit.autopsy.timeline.ui.detailview.tree;
@ -13,7 +26,7 @@ import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType; import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
/** /**
* * EventTreeItem for event types
*/ */
abstract class EventTypeTreeItem<T extends EventsTreeItem> extends EventsTreeItem { abstract class EventTypeTreeItem<T extends EventsTreeItem> extends EventsTreeItem {

View File

@ -86,7 +86,7 @@ final public class EventsTree extends BorderPane {
public void setDetailViewPane(DetailViewPane detailViewPane) { public void setDetailViewPane(DetailViewPane detailViewPane) {
this.detailViewPane = detailViewPane; this.detailViewPane = detailViewPane;
detailViewPane.getAllEventStripes().addListener((ListChangeListener.Change<? extends EventStripe> c) -> { detailViewPane.getAllNestedEvents().addListener((ListChangeListener.Change<? extends TimeLineEvent> c) -> {
//on jfx thread //on jfx thread
while (c.next()) { while (c.next()) {
c.getRemoved().forEach(getRoot()::remove); c.getRemoved().forEach(getRoot()::remove);
@ -112,7 +112,7 @@ final public class EventsTree extends BorderPane {
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private void setRoot() { private void setRoot() {
RootItem root = new RootItem(TreeComparator.Type.reversed().thenComparing(sortByBox.getSelectionModel().getSelectedItem())); RootItem root = new RootItem(TreeComparator.Type.reversed().thenComparing(sortByBox.getSelectionModel().getSelectedItem()));
detailViewPane.getAllEventStripes().forEach(root::insert); detailViewPane.getAllNestedEvents().forEach(root::insert);
eventsTree.setRoot(root); eventsTree.setRoot(root);
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2014-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.timeline.ui.detailview.tree;
import java.util.Comparator; import java.util.Comparator;
import java.util.Deque; import java.util.Deque;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType; import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
@ -58,9 +57,9 @@ abstract class EventsTreeItem extends TreeItem<TimeLineEvent> {
abstract EventType getEventType(); abstract EventType getEventType();
abstract void remove(Deque<EventStripe> path); abstract void remove(Deque<TimeLineEvent> path);
abstract void insert(Deque<EventStripe> path); abstract void insert(Deque<TimeLineEvent> path);
<T extends EventsTreeItem> T configureNewTreeItem(T newTreeItem) { <T extends EventsTreeItem> T configureNewTreeItem(T newTreeItem) {
newTreeItem.setExpanded(true); newTreeItem.setExpanded(true);

View File

@ -50,7 +50,7 @@ class RootItem extends EventsTreeItem {
* @param stripe stripe to add * @param stripe stripe to add
*/ */
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
public void insert(EventStripe stripe) { public void insert(TimeLineEvent stripe) {
BaseTypeTreeItem treeItem = childMap.computeIfAbsent(stripe.getEventType().getBaseType(), BaseTypeTreeItem treeItem = childMap.computeIfAbsent(stripe.getEventType().getBaseType(),
baseType -> configureNewTreeItem(new BaseTypeTreeItem(stripe, getComparator())) baseType -> configureNewTreeItem(new BaseTypeTreeItem(stripe, getComparator()))
@ -58,7 +58,7 @@ class RootItem extends EventsTreeItem {
treeItem.insert(getTreePath(stripe)); treeItem.insert(getTreePath(stripe));
} }
void remove(EventStripe stripe) { void remove(TimeLineEvent stripe) {
BaseTypeTreeItem typeTreeItem = childMap.get(stripe.getEventType().getBaseType()); BaseTypeTreeItem typeTreeItem = childMap.get(stripe.getEventType().getBaseType());
if (typeTreeItem != null) { if (typeTreeItem != null) {
typeTreeItem.remove(getTreePath(stripe)); typeTreeItem.remove(getTreePath(stripe));
@ -70,8 +70,8 @@ class RootItem extends EventsTreeItem {
} }
} }
static Deque< EventStripe> getTreePath(EventStripe event) { static Deque< TimeLineEvent> getTreePath(TimeLineEvent event) {
Deque<EventStripe> path = new ArrayDeque<>(); Deque<TimeLineEvent> path = new ArrayDeque<>();
path.addFirst(event); path.addFirst(event);
Optional<EventStripe> parentOptional = event.getParentStripe(); Optional<EventStripe> parentOptional = event.getParentStripe();
while (parentOptional.isPresent()) { while (parentOptional.isPresent()) {
@ -110,12 +110,12 @@ class RootItem extends EventsTreeItem {
} }
@Override @Override
void remove(Deque<EventStripe> path) { void remove(Deque<TimeLineEvent> path) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
} }
@Override @Override
void insert(Deque<EventStripe> path) { void insert(Deque<TimeLineEvent> path) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
} }

View File

@ -1,7 +1,20 @@
/* /*
* To change this license header, choose License Headers in Project Properties. * Autopsy Forensic Browser
* To change this template file, choose Tools | Templates *
* and open the template in the editor. * Copyright 2013-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.sleuthkit.autopsy.timeline.ui.detailview.tree; package org.sleuthkit.autopsy.timeline.ui.detailview.tree;
@ -9,18 +22,20 @@ import java.util.Comparator;
import java.util.Deque; import java.util.Deque;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
/**
* EventTreeItem for sub event types
*/
public class SubTypeTreeItem extends EventTypeTreeItem<EventDescriptionTreeItem> { public class SubTypeTreeItem extends EventTypeTreeItem<EventDescriptionTreeItem> {
SubTypeTreeItem(EventStripe stripe, Comparator<TreeItem<TimeLineEvent>> comp) { SubTypeTreeItem(TimeLineEvent stripe, Comparator<TreeItem<TimeLineEvent>> comp) {
super(stripe.getEventType(), comp); super(stripe.getEventType(), comp);
} }
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
public void insert(Deque<EventStripe> path) { public void insert(Deque<TimeLineEvent> path) {
EventStripe head = path.removeFirst(); TimeLineEvent head = path.removeFirst();
EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(), EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(),
description -> configureNewTreeItem(new EventDescriptionTreeItem(head, getComparator())) description -> configureNewTreeItem(new EventDescriptionTreeItem(head, getComparator()))
); );
@ -31,8 +46,8 @@ public class SubTypeTreeItem extends EventTypeTreeItem<EventDescriptionTreeItem>
} }
@Override @Override
void remove(Deque<EventStripe> path) { void remove(Deque<TimeLineEvent> path) {
EventStripe head = path.removeFirst(); TimeLineEvent head = path.removeFirst();
EventsTreeItem descTreeItem = childMap.get(head.getDescription()); EventsTreeItem descTreeItem = childMap.get(head.getDescription());
if (descTreeItem != null) { if (descTreeItem != null) {
if (path.isEmpty() == false) { if (path.isEmpty() == false) {