mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
fix events tree; more cleanup
This commit is contained in:
parent
5ab1fc3395
commit
f949a00093
@ -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<EventStripe> {
|
||||
@ -120,7 +119,7 @@ public class EventCluster implements MultiEvent<EventStripe> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<EventStripe> getParentBundle() {
|
||||
public Optional<EventStripe> getParent() {
|
||||
return Optional.ofNullable(parent);
|
||||
}
|
||||
|
||||
@ -181,9 +180,6 @@ public class EventCluster implements MultiEvent<EventStripe> {
|
||||
* 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<EventStripe> {
|
||||
return ImmutableSortedSet.orderedBy(Comparator.comparing(EventCluster::getStartMillis)).add(this).build();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EventCluster{" + "description=" + description + ", eventIDs=" + eventIDs.size() + '}';
|
||||
}
|
||||
}
|
||||
|
@ -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<EventCluster> {
|
||||
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<EventCluster> {
|
||||
private final ImmutableSet<Long> 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<EventCluster> clusters, ImmutableSet<Long> eventIDs, ImmutableSet<Long> tagged, ImmutableSet<Long> hashHits) {
|
||||
@ -98,9 +100,10 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
||||
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<EventCluster> {
|
||||
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<EventCluster> {
|
||||
.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<EventCluster> getParentBundle() {
|
||||
public Optional<EventCluster> getParent() {
|
||||
return Optional.ofNullable(parent);
|
||||
}
|
||||
|
||||
public Optional<EventStripe> 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<EventCluster> {
|
||||
|
||||
@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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public interface MultiEvent<ParentType extends MultiEvent<?>> extends TimeLineEv
|
||||
|
||||
long getStartMillis();
|
||||
|
||||
Optional<ParentType> getParentBundle();
|
||||
Optional<ParentType> getParent();
|
||||
|
||||
default int getSize() {
|
||||
return getEventIDs().size();
|
||||
|
@ -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<Long> hashHits = SQLHelper.unGroupConcat(rs.getString("hash_hits"), Long::valueOf); //NON-NLS
|
||||
Set<Long> 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());
|
||||
|
@ -111,7 +111,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
|
||||
}
|
||||
|
||||
public ObservableList<EventStripe> getEventStripes() {
|
||||
return chart.getEventStripes();
|
||||
return chart.getAllNestedEventStripes();
|
||||
}
|
||||
|
||||
public void setSelectionModel(MultipleSelectionModel<TreeItem<TimeLineEvent>> selectionModel) {
|
||||
|
@ -67,6 +67,7 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
|
||||
private final ObservableList<EventNodeBase<?>> selectedNodes;
|
||||
private final DetailsChartLayoutSettings layoutSettings = new DetailsChartLayoutSettings();
|
||||
private final TimeLineController controller;
|
||||
private ObservableList<EventStripe> nestedEventStripes = FXCollections.observableArrayList();
|
||||
|
||||
DetailsChart(TimeLineController controller, DateAxis detailsChartDateAxis, DateAxis pinnedDateAxis, Axis<EventStripe> verticalAxis, ObservableList<EventNodeBase<?>> selectedNodes) {
|
||||
this.controller = controller;
|
||||
@ -99,6 +100,7 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
void addStripe(EventStripe stripe) {
|
||||
eventStripes.add(stripe);
|
||||
nestedEventStripes.add(stripe);
|
||||
}
|
||||
|
||||
void clearGuideLine(GuideLine guideLine) {
|
||||
@ -120,6 +122,15 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
void reset() {
|
||||
eventStripes.clear();
|
||||
nestedEventStripes.clear();
|
||||
}
|
||||
|
||||
public ObservableList<EventStripe> getAllNestedEventStripes() {
|
||||
return nestedEventStripes;
|
||||
}
|
||||
|
||||
ObservableList<EventStripe> getEventStripes() {
|
||||
return eventStripes;
|
||||
}
|
||||
|
||||
private static class DetailIntervalSelector extends IntervalSelector<DateTime> {
|
||||
@ -244,7 +255,7 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
|
||||
return new DetailsChartSkin(this);
|
||||
}
|
||||
|
||||
ObservableList<EventStripe> getEventStripes() {
|
||||
ObservableList<EventStripe> getRootEventStripes() {
|
||||
return eventStripes;
|
||||
}
|
||||
|
||||
|
@ -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<EventCluster, Eve
|
||||
* @param requestedDescrLoD
|
||||
* @param expand
|
||||
*/
|
||||
@NbBundle.Messages(value = "EventStripeNode.loggedTask.name=Load sub clusters")
|
||||
@NbBundle.Messages(value = "EventClusterNode.loggedTask.name=Load sub events")
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
private synchronized void loadSubBundles(DescriptionLoD.RelativeDetail relativeDetail) {
|
||||
private synchronized void loadSubStripes(DescriptionLoD.RelativeDetail relativeDetail) {
|
||||
getChartLane().setCursor(Cursor.WAIT);
|
||||
|
||||
|
||||
/*
|
||||
* make new ZoomParams to query with
|
||||
*
|
||||
@ -137,45 +137,50 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
final EventTypeZoomLevel eventTypeZoomLevel = eventsModel.eventTypeZoomProperty().get();
|
||||
final ZoomParams zoomParams = new ZoomParams(subClusterSpan, eventTypeZoomLevel, subClusterFilter, getDescriptionLoD());
|
||||
|
||||
Task<List<EventStripe>> loggedTask = new LoggedTask<List<EventStripe>>(Bundle.EventStripeNode_loggedTask_name(), false) {
|
||||
Task<List<EventStripe>> loggedTask = new LoggedTask<List<EventStripe>>(Bundle.EventClusterNode_loggedTask_name(), false) {
|
||||
|
||||
private volatile DescriptionLoD loadedDescriptionLoD = getDescriptionLoD().withRelativeDetail(relativeDetail);
|
||||
|
||||
@Override
|
||||
protected List<EventStripe> call() throws Exception {
|
||||
List<EventStripe> bundles;
|
||||
List<EventStripe> 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<EventStripe, EventStripe>() {
|
||||
|
||||
public EventStripe apply(EventStripe eventStripe) {
|
||||
return eventStripe.withParent(getEvent());
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void succeeded() {
|
||||
try {
|
||||
List<EventStripe> bundles = get();
|
||||
List<EventStripe> newSubStripes = get();
|
||||
|
||||
//clear the existing subnodes
|
||||
List<TimeLineEvent> transform = subNodes.stream().flatMap(new StripeFlattener()).collect(Collectors.toList());
|
||||
// getChartLane().getParentChart().getEventStripes().removeAll(transform);
|
||||
List<TimeLineEvent> 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<EventCluster, Eve
|
||||
}
|
||||
}
|
||||
|
||||
EventCluster getEventCluster() {
|
||||
return getEventBundle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void layoutChildren() {
|
||||
double chartX = getChartLane().getXAxis().getDisplayPosition(new DateTime(getStartMillis()));
|
||||
@ -222,7 +223,7 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
RootFilter getSubClusterFilter() {
|
||||
RootFilter subClusterFilter = eventsModel.filterProperty().get().copyOf();
|
||||
subClusterFilter.getSubFilters().addAll(
|
||||
new DescriptionFilter(getEventBundle().getDescriptionLoD(), getDescription(), DescriptionFilter.FilterMode.INCLUDE),
|
||||
new DescriptionFilter(getEvent().getDescriptionLoD(), getDescription(), DescriptionFilter.FilterMode.INCLUDE),
|
||||
new TypeFilter(getEventType()));
|
||||
return subClusterFilter;
|
||||
}
|
||||
@ -251,7 +252,7 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
setGraphic(new ImageView(PLUS));
|
||||
setEventHandler(actionEvent -> {
|
||||
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<EventCluster, Eve
|
||||
setGraphic(new ImageView(MINUS));
|
||||
setEventHandler(actionEvent -> {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,20 +57,19 @@ final public class EventStripeNode extends MultiEventNodeBase<EventStripe, Event
|
||||
|
||||
if (eventStripe.getClusters().size() > 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<EventStripe, Event
|
||||
}
|
||||
|
||||
public EventStripe getEventStripe() {
|
||||
return getEventBundle();
|
||||
return getEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,14 +57,14 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
||||
|
||||
private final ReadOnlyObjectWrapper<DescriptionLoD> 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<ParentTy
|
||||
*/
|
||||
heightProperty().addListener(heightProp -> 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<ParentTy
|
||||
descLOD.set(descriptionLoD);
|
||||
}
|
||||
|
||||
public final BundleType getEventBundle() {
|
||||
return getEvent();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<EventNodeBase<?>> getSubNodes() {
|
||||
return subNodes;
|
||||
}
|
||||
|
||||
final String getDescription() {
|
||||
return getEventBundle().getDescription();
|
||||
return getEvent().getDescription();
|
||||
}
|
||||
|
||||
final Set<Long> getEventIDs() {
|
||||
return getEventBundle().getEventIDs();
|
||||
return getEvent().getEventIDs();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,8 +100,6 @@ public final class PrimaryDetailsChartLane extends DetailsChartLane<EventStripe>
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
private double getParentXForEpochMillis(Long epochMillis) {
|
||||
return getXAxis().localToParent(getXForEpochMillis(epochMillis), 0).getX();
|
||||
}
|
||||
|
@ -24,44 +24,35 @@ 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<String, EventDescriptionTreeItem> childMap = new HashMap<>();
|
||||
private final TimeLineEvent bundle;
|
||||
private Comparator<TreeItem<TimeLineEvent>> comparator = TreeComparator.Description;
|
||||
|
||||
public TimeLineEvent getEvent() {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
EventDescriptionTreeItem(TimeLineEvent g, Comparator<TreeItem<TimeLineEvent>> comp) {
|
||||
bundle = g;
|
||||
EventDescriptionTreeItem(EventStripe stripe, Comparator<TreeItem<TimeLineEvent>> comp) {
|
||||
comparator = comp;
|
||||
setValue(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCount() {
|
||||
return getValue().getSize();
|
||||
setValue(stripe);
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
public void insert(Deque<MultiEvent<?>> path) {
|
||||
MultiEvent<?> head = path.removeFirst();
|
||||
EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(), description -> {
|
||||
public void insert(Deque<EventStripe> 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);
|
||||
childMap.put(description, newTreeItem);
|
||||
getChildren().add(newTreeItem);
|
||||
resort(comparator, false);
|
||||
return newTreeItem;
|
||||
@ -72,9 +63,10 @@ class EventDescriptionTreeItem extends NavTreeItem {
|
||||
}
|
||||
}
|
||||
|
||||
void remove(Deque<MultiEvent<?>> path) {
|
||||
MultiEvent<?> head = path.removeFirst();
|
||||
EventDescriptionTreeItem descTreeItem = childMap.get(head.getDescription());
|
||||
void remove(Deque<EventStripe> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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,23 +37,19 @@ class EventTypeTreeItem extends NavTreeItem {
|
||||
|
||||
private Comparator<TreeItem<TimeLineEvent>> comparator = TreeComparator.Description;
|
||||
|
||||
EventTypeTreeItem(MultiEvent<?> g, Comparator<TreeItem<TimeLineEvent>> comp) {
|
||||
setValue(g);
|
||||
EventTypeTreeItem(EventStripe stripe, Comparator<TreeItem<TimeLineEvent>> comp) {
|
||||
setValue(stripe);
|
||||
comparator = comp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCount() {
|
||||
return getValue().getSize();
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
public void insert(Deque<MultiEvent<?>> path) {
|
||||
MultiEvent<?> head = path.removeFirst();
|
||||
EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(), description -> {
|
||||
public void insert(Deque<EventStripe> path) {
|
||||
EventStripe 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;
|
||||
@ -64,8 +60,8 @@ class EventTypeTreeItem extends NavTreeItem {
|
||||
}
|
||||
}
|
||||
|
||||
void remove(Deque<MultiEvent<?>> path) {
|
||||
MultiEvent<?> head = path.removeFirst();
|
||||
void remove(Deque<EventStripe> 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;
|
||||
}
|
||||
|
@ -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<? extends MultiEvent<?>> c) -> {
|
||||
detailViewPane.getEventStripes().addListener((ListChangeListener.Change<? extends EventStripe> 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);
|
||||
|
||||
}
|
||||
|
@ -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<TimeLineEvent> {
|
||||
abstract class EventsTreeItem extends TreeItem<TimeLineEvent> {
|
||||
|
||||
abstract long getCount();
|
||||
final long getSize() {
|
||||
return getValue().getSize();
|
||||
}
|
||||
|
||||
abstract void resort(Comparator<TreeItem<TimeLineEvent>> comp, Boolean recursive);
|
||||
|
||||
abstract NavTreeItem findTreeItemForEvent(TimeLineEvent t);
|
||||
abstract EventsTreeItem findTreeItemForEvent(TimeLineEvent event);
|
||||
|
||||
}
|
@ -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<MultiEvent<?>> path = new ArrayDeque<>();
|
||||
Optional<? extends MultiEvent<?>> p = Optional.of(g);
|
||||
|
||||
while (p.isPresent()) {
|
||||
MultiEvent<?> parent = p.get();
|
||||
static Deque< EventStripe> getTreePath(EventStripe event) {
|
||||
Deque<EventStripe> path = new ArrayDeque<>();
|
||||
path.addFirst(event);
|
||||
Optional<EventStripe> 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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user