Merge pull request #5294 from rcordovano/timeline-public-api-improvements

5413 Improve and document public API for timeline data
This commit is contained in:
Richard Cordovano 2019-10-02 17:20:18 -04:00 committed by GitHub
commit 97147f285d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 175 additions and 175 deletions

View File

@ -66,7 +66,6 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.Tag;
import org.sleuthkit.datamodel.TimelineManager;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TimelineEvent;
@ -81,6 +80,7 @@ import org.sleuthkit.datamodel.TimelineFilter.HideKnownFilter;
import org.sleuthkit.datamodel.TimelineFilter.RootFilter;
import org.sleuthkit.datamodel.TimelineFilter.TagsFilter;
import org.sleuthkit.datamodel.TimelineFilter.TextFilter;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* This class acts as the model for a TimelineView
@ -112,8 +112,8 @@ public final class FilteredEventsModel {
private final ReadOnlyObjectWrapper<RootFilterState> requestedFilter = new ReadOnlyObjectWrapper<>();
private final ReadOnlyObjectWrapper<Interval> requestedTimeRange = new ReadOnlyObjectWrapper<>();
private final ReadOnlyObjectWrapper<ZoomState> requestedZoomState = new ReadOnlyObjectWrapper<>();
private final ReadOnlyObjectWrapper< TimelineEventType.TypeLevel> requestedTypeZoom = new ReadOnlyObjectWrapper<>(TimelineEventType.TypeLevel.BASE_TYPE);
private final ReadOnlyObjectWrapper< TimelineEvent.DescriptionLevel> requestedLOD = new ReadOnlyObjectWrapper<>(TimelineEvent.DescriptionLevel.SHORT);
private final ReadOnlyObjectWrapper<TimelineEventType.HierarchyLevel> requestedTypeZoom = new ReadOnlyObjectWrapper<>(TimelineEventType.HierarchyLevel.CATEGORY);
private final ReadOnlyObjectWrapper<TimelineLevelOfDetail> requestedLOD = new ReadOnlyObjectWrapper<>(TimelineLevelOfDetail.LOW);
// end Filter and zoome state
//caches
@ -121,7 +121,9 @@ public final class FilteredEventsModel {
private final LoadingCache<Object, Long> minCache;
private final LoadingCache<Long, TimelineEvent> idToEventCache;
private final LoadingCache<ZoomState, Map<TimelineEventType, Long>> eventCountsCache;
/** Map from datasource id to datasource name. */
/**
* Map from datasource id to datasource name.
*/
private final ObservableMap<Long, String> datasourcesMap = FXCollections.observableHashMap();
// end caches
@ -152,9 +154,9 @@ public final class FilteredEventsModel {
.build(new CacheLoaderImpl<>(this::countEventsByType));
maxCache = CacheBuilder.newBuilder()
.build(new CacheLoaderImpl<>(ignored -> eventManager.getMaxTime()));
.build(new CacheLoaderImpl<>(ignored -> eventManager.getMaxEventTime()));
minCache = CacheBuilder.newBuilder()
.build(new CacheLoaderImpl<>(ignored -> eventManager.getMinTime()));
.build(new CacheLoaderImpl<>(ignored -> eventManager.getMinEventTime()));
InvalidationListener filterSyncListener = observable -> {
RootFilterState rootFilter = filterProperty().get();
@ -280,7 +282,7 @@ public final class FilteredEventsModel {
return requestedTimeRange.getReadOnlyProperty();
}
synchronized public ReadOnlyObjectProperty<TimelineEvent.DescriptionLevel> descriptionLODProperty() {
synchronized public ReadOnlyObjectProperty<TimelineLevelOfDetail> descriptionLODProperty() {
return requestedLOD.getReadOnlyProperty();
}
@ -288,7 +290,7 @@ public final class FilteredEventsModel {
return requestedFilter.getReadOnlyProperty();
}
synchronized public ReadOnlyObjectProperty<TimelineEventType.TypeLevel> eventTypeZoomProperty() {
synchronized public ReadOnlyObjectProperty<TimelineEventType.HierarchyLevel> eventTypeZoomProperty() {
return requestedTypeZoom.getReadOnlyProperty();
}
@ -301,7 +303,7 @@ public final class FilteredEventsModel {
return getZoomState().getTimeRange();
}
synchronized public TimelineEvent.DescriptionLevel getDescriptionLOD() {
synchronized public TimelineLevelOfDetail getDescriptionLOD() {
return getZoomState().getDescriptionLOD();
}
@ -309,11 +311,12 @@ public final class FilteredEventsModel {
return getZoomState().getFilterState();
}
synchronized public TimelineEventType.TypeLevel getEventTypeZoom() {
synchronized public TimelineEventType.HierarchyLevel getEventTypeZoom() {
return getZoomState().getTypeZoomLevel();
}
/** Get the default filter used at startup.
/**
* Get the default filter used at startup.
*
* @return the default filter used at startup
*/
@ -385,7 +388,7 @@ public final class FilteredEventsModel {
public Map<TimelineEventType, Long> getEventCounts(Interval timeRange) throws TskCoreException {
final RootFilterState filter;
final TimelineEventType.TypeLevel typeZoom;
final TimelineEventType.HierarchyLevel typeZoom;
synchronized (this) {
filter = getFilterState();
typeZoom = getEventTypeZoom();
@ -453,39 +456,40 @@ public final class FilteredEventsModel {
synchronized public boolean handleContentTagAdded(ContentTagAddedEvent evt) throws TskCoreException {
ContentTag contentTag = evt.getAddedTag();
Content content = contentTag.getContent();
Set<Long> updatedEventIDs = addTag(content.getId(), null, contentTag);
Set<Long> updatedEventIDs = eventManager.updateEventsForContentTagAdded(content);
if (isNotEmpty(updatedEventIDs)) {
invalidateCaches(updatedEventIDs);
}
return postTagsAdded(updatedEventIDs);
}
synchronized public boolean handleArtifactTagAdded(BlackBoardArtifactTagAddedEvent evt) throws TskCoreException {
BlackboardArtifactTag artifactTag = evt.getAddedTag();
BlackboardArtifact artifact = artifactTag.getArtifact();
Set<Long> updatedEventIDs = addTag(artifact.getObjectID(), artifact.getArtifactID(), artifactTag);
Set<Long> updatedEventIDs = eventManager.updateEventsForArtifactTagAdded(artifact);
if (isNotEmpty(updatedEventIDs)) {
invalidateCaches(updatedEventIDs);
}
return postTagsAdded(updatedEventIDs);
}
synchronized public boolean handleContentTagDeleted(ContentTagDeletedEvent evt) throws TskCoreException {
DeletedContentTagInfo deletedTagInfo = evt.getDeletedTagInfo();
Content content = autoCase.getSleuthkitCase().getContentById(deletedTagInfo.getContentID());
boolean isContentTagged = autoCase.getServices().getTagsManager().getContentTagsByContent(content).isEmpty() == false;
boolean isArtifactTagged = false;
if(content instanceof BlackboardArtifact) {
isArtifactTagged = autoCase.getServices().getTagsManager().getBlackboardArtifactTagsByArtifact((BlackboardArtifact)content).isEmpty() == false;
Set<Long> updatedEventIDs = eventManager.updateEventsForContentTagDeleted(content);
if (isNotEmpty(updatedEventIDs)) {
invalidateCaches(updatedEventIDs);
}
Set<Long> updatedEventIDs = deleteTag(content.getId(), null, deletedTagInfo.getTagID(), isArtifactTagged || isContentTagged);
return postTagsDeleted(updatedEventIDs);
}
synchronized public boolean handleArtifactTagDeleted(BlackBoardArtifactTagDeletedEvent evt) throws TskCoreException {
DeletedBlackboardArtifactTagInfo deletedTagInfo = evt.getDeletedTagInfo();
BlackboardArtifact artifact = autoCase.getSleuthkitCase().getBlackboardArtifact(deletedTagInfo.getArtifactID());
boolean isArtifactTagged = autoCase.getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact).isEmpty() == false;
boolean isContentTagged = autoCase.getServices().getTagsManager().getContentTagsByContent(artifact).isEmpty() == false;
Set<Long> updatedEventIDs = deleteTag(artifact.getObjectID(), artifact.getArtifactID(), deletedTagInfo.getTagID(), isArtifactTagged || isContentTagged);
Set<Long> updatedEventIDs = eventManager.updateEventsForArtifactTagDeleted(artifact);
if (isNotEmpty(updatedEventIDs)) {
invalidateCaches(updatedEventIDs);
}
return postTagsDeleted(updatedEventIDs);
}
@ -507,7 +511,7 @@ public final class FilteredEventsModel {
* @throws org.sleuthkit.datamodel.TskCoreException
*/
public Set<Long> getEventIDsForFile(AbstractFile file, boolean includeDerivedArtifacts) throws TskCoreException {
return eventManager.getEventIDsForFile(file, includeDerivedArtifacts);
return eventManager.getEventIDsForContent(file, includeDerivedArtifacts);
}
/**
@ -599,26 +603,11 @@ public final class FilteredEventsModel {
return eventManager.getEventTypes();
}
synchronized public Set<Long> addTag(long objID, Long artifactID, Tag tag) throws TskCoreException {
Set<Long> updatedEventIDs = eventManager.setEventsTagged(objID, artifactID, true);
if (isNotEmpty(updatedEventIDs)) {
invalidateCaches(updatedEventIDs);
}
return updatedEventIDs;
}
synchronized public Set<Long> deleteTag(long objID, Long artifactID, long tagID, boolean tagged) throws TskCoreException {
Set<Long> updatedEventIDs = eventManager.setEventsTagged(objID, artifactID, tagged);
if (isNotEmpty(updatedEventIDs)) {
invalidateCaches(updatedEventIDs);
}
return updatedEventIDs;
}
synchronized public Set<Long> setHashHit(Collection<BlackboardArtifact> artifacts, boolean hasHashHit) throws TskCoreException {
synchronized public Set<Long> setHashHit(Collection<BlackboardArtifact> artifacts) throws TskCoreException {
Set<Long> updatedEventIDs = new HashSet<>();
for (BlackboardArtifact artifact : artifacts) {
updatedEventIDs.addAll(eventManager.setEventsHashed(artifact.getObjectID(), hasHashHit));
Content content = autoCase.getSleuthkitCase().getContentById(artifact.getObjectID());
updatedEventIDs.addAll(eventManager.updateEventsForHashSetHit(content));
}
if (isNotEmpty(updatedEventIDs)) {
invalidateCaches(updatedEventIDs);

View File

@ -190,7 +190,7 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
typeColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue().getEventType()));
typeColumn.setCellFactory(param -> new TypeTableCell<>());
dateTimeColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue().getStartMillis()));
dateTimeColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue().getEventTimeInMs()));
dateTimeColumn.setCellFactory(param -> new DateTimeTableCell<>());
//add events to table
@ -307,7 +307,7 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
*/
private ViewInTimelineRequestedEvent makeEventInTimeRange(TimelineEvent selectedEvent) {
Duration selectedDuration = unitComboBox.getSelectionModel().getSelectedItem().getBaseUnit().getDuration().multipliedBy(amountSpinner.getValue());
Interval range = IntervalUtils.getIntervalAround(Instant.ofEpochMilli(selectedEvent.getStartMillis()), selectedDuration);
Interval range = IntervalUtils.getIntervalAround(Instant.ofEpochMilli(selectedEvent.getEventTimeInMs()), selectedDuration);
return new ViewInTimelineRequestedEvent(Collections.singleton(selectedEvent.getEventID()), range);
}

View File

@ -93,6 +93,7 @@ import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TimelineEventType;
import org.sleuthkit.datamodel.TimelineFilter.EventTypeFilter;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* Controller in the MVC design along with FilteredEventsModel TimeLineView.
@ -296,9 +297,9 @@ public class TimeLineController {
try {
InitialZoomState = new ZoomState(filteredEvents.getSpanningInterval(),
TimelineEventType.TypeLevel.BASE_TYPE,
TimelineEventType.HierarchyLevel.CATEGORY,
filteredEvents.filterProperty().get(),
TimelineEvent.DescriptionLevel.SHORT);
TimelineLevelOfDetail.LOW);
} catch (TskCoreException ex) {
throw new TskCoreException("Error getting spanning interval.", ex);
}
@ -492,7 +493,7 @@ public class TimeLineController {
return topComponent;
}
synchronized public void pushEventTypeZoom(TimelineEventType.TypeLevel typeZoomeLevel) {
synchronized public void pushEventTypeZoom(TimelineEventType.HierarchyLevel typeZoomeLevel) {
ZoomState currentZoom = filteredEvents.zoomStateProperty().get();
if (currentZoom == null) {
advance(InitialZoomState.withTypeZoomLevel(typeZoomeLevel));
@ -554,7 +555,7 @@ public class TimeLineController {
}
}
synchronized public void pushDescrLOD(TimelineEvent.DescriptionLevel newLOD) {
synchronized public void pushDescrLOD(TimelineLevelOfDetail newLOD) {
ZoomState currentZoom = filteredEvents.zoomStateProperty().get();
if (currentZoom == null) {
advance(InitialZoomState.withDescrLOD(newLOD));
@ -564,7 +565,7 @@ public class TimeLineController {
}
@SuppressWarnings("AssignmentToMethodParameter") //clamp timerange to case
synchronized public void pushTimeAndType(Interval timeRange, TimelineEventType.TypeLevel typeZoom) throws TskCoreException {
synchronized public void pushTimeAndType(Interval timeRange, TimelineEventType.HierarchyLevel typeZoom) throws TskCoreException {
Interval overlappingTimeRange = this.filteredEvents.getSpanningInterval().overlap(timeRange);
ZoomState currentZoom = filteredEvents.zoomStateProperty().get();
if (currentZoom == null) {
@ -745,7 +746,7 @@ public class TimeLineController {
case DATA_ADDED:
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == TSK_HASHSET_HIT.getTypeID()) {
logFutureException(executor.submit(() -> filteredEvents.setHashHit(eventData.getArtifacts(), true)),
logFutureException(executor.submit(() -> filteredEvents.setHashHit(eventData.getArtifacts())),
"Error executing task in response to DATA_ADDED event.",
"Error executing response to new data.");
}

View File

@ -57,6 +57,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TimelineEventType;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* * Explorer Node for a TimelineEvent.
@ -113,7 +114,7 @@ public class EventNode extends DisplayableItemNode {
properties.put(new NodeProperty<>("icon", Bundle.NodeProperty_displayName_icon(), "icon", true)); // NON-NLS //gets overridden with icon
properties.put(new TimeProperty("time", Bundle.NodeProperty_displayName_dateTime(), "time ", getDateTimeString()));// NON-NLS
properties.put(new NodeProperty<>("description", Bundle.NodeProperty_displayName_description(), "description", event.getFullDescription())); // NON-NLS
properties.put(new NodeProperty<>("description", Bundle.NodeProperty_displayName_description(), "description", event.getDescription(TimelineLevelOfDetail.HIGH))); // NON-NLS
properties.put(new NodeProperty<>("eventType", Bundle.NodeProperty_displayName_eventType(), "event type", event.getEventType().getDisplayName())); // NON-NLS
return sheet;
@ -127,7 +128,7 @@ public class EventNode extends DisplayableItemNode {
* controller's time zone setting.
*/
private String getDateTimeString() {
return new DateTime(event.getStartMillis(), DateTimeZone.UTC).toString(TimeLineController.getZonedFormatter());
return new DateTime(event.getEventTimeInMs(), DateTimeZone.UTC).toString(TimeLineController.getZonedFormatter());
}
@Override
@ -270,7 +271,7 @@ public class EventNode extends DisplayableItemNode {
* data in the lookup.
*/
final TimelineEvent eventById = eventsModel.getEventById(eventID);
Content file = sleuthkitCase.getContentById(eventById.getFileObjID());
Content file = sleuthkitCase.getContentById(eventById.getContentObjID());
if (eventById.getArtifactID().isPresent()) {
BlackboardArtifact blackboardArtifact = sleuthkitCase.getBlackboardArtifact(eventById.getArtifactID().get());

View File

@ -107,15 +107,15 @@ final public class EventTypeUtils {
return Color.hsb(359, .9, .9, 0);
}
TimelineEventType superType = type.getSuperType();
TimelineEventType superType = type.getParent();
Color baseColor = getColor(superType);
int siblings = superType.getSiblingTypes().stream()
.max((type1, type2) -> Integer.compare(type1.getSubTypes().size(), type2.getSubTypes().size()))
.get().getSubTypes().size() + 1;
int superSiblingsCount = superType.getSiblingTypes().size();
int siblings = superType.getSiblings().stream()
.max((type1, type2) -> Integer.compare(type1.getChildren().size(), type2.getChildren().size()))
.get().getChildren().size() + 1;
int superSiblingsCount = superType.getSiblings().size();
int ordinal = new ArrayList<>(type.getSiblingTypes()).indexOf(type);
int ordinal = new ArrayList<>(type.getSiblings()).indexOf(type);
double offset = (360.0 / superSiblingsCount) / siblings;
Color deriveColor = baseColor.deriveColor(ordinal * offset, 1, 1, 1);

View File

@ -207,7 +207,7 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
final Node node = item.getNode();
if (node != null) {
node.setStyle("-fx-border-width: 2; "
+ " -fx-border-color: " + ColorUtilities.getRGBCode(getColor(eventType.getSuperType())) + "; "
+ " -fx-border-color: " + ColorUtilities.getRGBCode(getColor(eventType.getParent())) + "; "
+ " -fx-bar-fill: " + ColorUtilities.getRGBCode(getColor(eventType))); // NON-NLS
node.setCursor(Cursor.HAND);

View File

@ -62,7 +62,7 @@ import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.DetailsViewModel;
import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.EventStripe;
import org.sleuthkit.autopsy.timeline.utils.MappedList;
import org.sleuthkit.autopsy.timeline.zooming.ZoomState;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
import org.sleuthkit.datamodel.TskCoreException;
/**
@ -192,7 +192,7 @@ final public class DetailViewPane extends AbstractTimelineChart<DateTime, EventS
*
* @return a new Action that will unhide events with the given description.
*/
public Action newUnhideDescriptionAction(String description, TimelineEvent.DescriptionLevel descriptionLoD) {
public Action newUnhideDescriptionAction(String description, TimelineLevelOfDetail descriptionLoD) {
return new UnhideDescriptionAction(description, descriptionLoD, getChart());
}
@ -204,7 +204,7 @@ final public class DetailViewPane extends AbstractTimelineChart<DateTime, EventS
*
* @return a new Action that will hide events with the given description.
*/
public Action newHideDescriptionAction(String description, TimelineEvent.DescriptionLevel descriptionLoD) {
public Action newHideDescriptionAction(String description, TimelineLevelOfDetail descriptionLoD) {
return new HideDescriptionAction(description, descriptionLoD, getChart());
}

View File

@ -59,7 +59,7 @@ import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.SqlFilterState;
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.DescriptionFilter;
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState;
import org.sleuthkit.autopsy.timeline.zooming.ZoomState;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TimelineEventType;
import org.sleuthkit.datamodel.TimelineEvent;
@ -181,7 +181,7 @@ final class EventClusterNode extends MultiEventNodeBase<EventCluster, EventStrip
.intersect(new SqlFilterState<>(
new EventTypeFilter(getEventType()), true));
final Interval subClusterSpan = new Interval(getStartMillis(), getEndMillis() + 1000);
final TimelineEventType.TypeLevel eventTypeZoomLevel = eventsModel.getEventTypeZoom();
final TimelineEventType.HierarchyLevel eventTypeZoomLevel = eventsModel.getEventTypeZoom();
final ZoomState zoom = new ZoomState(subClusterSpan, eventTypeZoomLevel, subClusterFilter, getDescriptionLevel());
DescriptionFilter descriptionFilter = new DescriptionFilter(getEvent().getDescriptionLevel(), getDescription());
@ -191,14 +191,14 @@ final class EventClusterNode extends MultiEventNodeBase<EventCluster, EventStrip
Task<List<EventStripe>> loggedTask;
loggedTask = new LoggedTask<List<EventStripe>>(Bundle.EventClusterNode_loggedTask_name(), false) {
private volatile TimelineEvent.DescriptionLevel loadedDescriptionLevel = withRelativeDetail(getDescriptionLevel(), relativeDetail);
private volatile TimelineLevelOfDetail loadedDescriptionLevel = withRelativeDetail(getDescriptionLevel(), relativeDetail);
@Override
protected List<EventStripe> call() throws Exception {
//newly loaded substripes
List<EventStripe> stripes;
//next LoD in diraction of given relativeDetail
TimelineEvent.DescriptionLevel next = loadedDescriptionLevel;
TimelineLevelOfDetail next = loadedDescriptionLevel;
do {
loadedDescriptionLevel = next;
if (loadedDescriptionLevel == getEvent().getDescriptionLevel()) {
@ -311,7 +311,7 @@ final class EventClusterNode extends MultiEventNodeBase<EventCluster, EventStrip
});
//disabled if the given node is already at full description level of detail
disabledProperty().bind(node.descriptionLoDProperty().isEqualTo(TimelineEvent.DescriptionLevel.FULL));
disabledProperty().bind(node.descriptionLoDProperty().isEqualTo(TimelineLevelOfDetail.HIGH));
}
}
@ -346,7 +346,7 @@ final class EventClusterNode extends MultiEventNodeBase<EventCluster, EventStrip
LESS;
}
private static TimelineEvent.DescriptionLevel withRelativeDetail(TimelineEvent.DescriptionLevel LoD, RelativeDetail relativeDetail) {
private static TimelineLevelOfDetail withRelativeDetail(TimelineLevelOfDetail LoD, RelativeDetail relativeDetail) {
switch (relativeDetail) {
case EQUAL:
return LoD;

View File

@ -148,10 +148,10 @@ public abstract class EventNodeBase<Type extends DetailViewEvent> extends StackP
show(tagIV, false);
}
if (chartLane.getController().getEventsModel().getEventTypeZoom() == TimelineEventType.TypeLevel.SUB_TYPE) {
if (chartLane.getController().getEventsModel().getEventTypeZoom() == TimelineEventType.HierarchyLevel.CATEGORY) {
evtColor = getColor(getEventType());
} else {
evtColor = getColor(getEventType().getBaseType());
evtColor = getColor(getEventType().getCategory());
}
SELECTION_BORDER = new Border(new BorderStroke(evtColor.darker().desaturate(), BorderStrokeStyle.SOLID, CORNER_RADII_3, new BorderWidths(2)));

View File

@ -24,7 +24,7 @@ import org.controlsfx.control.action.Action;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.DescriptionFilter;
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.DescriptionFilterState;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* An Action that hides, in the given chart, events that have the given
@ -36,7 +36,7 @@ class HideDescriptionAction extends Action {
private static final Image HIDE = new Image("/org/sleuthkit/autopsy/timeline/images/eye--minus.png"); // NON-NLS
HideDescriptionAction(String description, TimelineEvent.DescriptionLevel descriptionLoD, DetailsChart chart) {
HideDescriptionAction(String description, TimelineLevelOfDetail descriptionLoD, DetailsChart chart) {
super(Bundle.HideDescriptionAction_displayName());
setLongText(Bundle.HideDescriptionAction_displayMsg());
setGraphic(new ImageView(HIDE));

View File

@ -36,7 +36,7 @@ import javafx.scene.layout.Pane;
import org.joda.time.DateTime;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.MultiEvent;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
import org.sleuthkit.datamodel.TskCoreException;
/**
@ -52,7 +52,7 @@ abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentType>, Pa
final ObservableList<EventNodeBase<?>> subNodes = FXCollections.observableArrayList();
final Pane subNodePane = new Pane();
private final ReadOnlyObjectWrapper<TimelineEvent.DescriptionLevel> descLOD = new ReadOnlyObjectWrapper<>();
private final ReadOnlyObjectWrapper<TimelineLevelOfDetail> descLOD = new ReadOnlyObjectWrapper<>();
MultiEventNodeBase(DetailsChartLane<?> chartLane, BundleType event, ParentNodeType parentNode) {
super(event, parentNode, chartLane);
@ -80,18 +80,18 @@ abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentType>, Pa
Bindings.bindContent(subNodePane.getChildren(), subNodes);
}
public ReadOnlyObjectProperty<TimelineEvent.DescriptionLevel> descriptionLoDProperty() {
public ReadOnlyObjectProperty<TimelineLevelOfDetail> descriptionLoDProperty() {
return descLOD.getReadOnlyProperty();
}
final TimelineEvent.DescriptionLevel getDescriptionLevel() {
final TimelineLevelOfDetail getDescriptionLevel() {
return descLOD.get();
}
/**
*
*/
final void setDescriptionLOD(final TimelineEvent.DescriptionLevel descriptionLoD) {
final void setDescriptionLOD(final TimelineLevelOfDetail descriptionLoD) {
descLOD.set(descriptionLoD);
}

View File

@ -23,7 +23,7 @@ import javafx.scene.image.ImageView;
import org.controlsfx.control.action.Action;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.DescriptionFilter;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* An Action that un-hides, in the given chart, events with the given
@ -34,7 +34,7 @@ class UnhideDescriptionAction extends Action {
private static final Image SHOW = new Image("/org/sleuthkit/autopsy/timeline/images/eye--plus.png"); // NON-NLS
UnhideDescriptionAction(String description, TimelineEvent.DescriptionLevel descriptionLoD, DetailsChart chart) {
UnhideDescriptionAction(String description, TimelineLevelOfDetail descriptionLoD, DetailsChart chart) {
super(Bundle.UnhideDescriptionAction_displayName());
setGraphic(new ImageView(SHOW));

View File

@ -22,7 +22,7 @@ import java.util.Comparator;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
import org.sleuthkit.datamodel.TimelineEventType;
/**
@ -49,7 +49,7 @@ public interface DetailViewEvent {
*
* @return the description level of detail of the given events
*/
public TimelineEvent.DescriptionLevel getDescriptionLevel();
public TimelineLevelOfDetail getDescriptionLevel();
/**
* get the EventStripe (if any) that contains this event.

View File

@ -37,6 +37,7 @@ import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.ImmutablePair;
@ -57,6 +58,7 @@ import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TimelineEventType;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineFilter;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* Model for the Details View. Uses FilteredEventsModel as underlying datamodel
@ -115,18 +117,20 @@ final public class DetailsViewModel {
DateTimeZone timeZone = TimeLineController.getJodaTimeZone();
//unpack params
Interval timeRange = zoom.getTimeRange();
TimelineEvent.DescriptionLevel descriptionLOD = zoom.getDescriptionLOD();
TimelineEventType.TypeLevel typeZoomLevel = zoom.getTypeZoomLevel();
TimelineLevelOfDetail descriptionLOD = zoom.getDescriptionLOD();
//intermediate results
Map<TimelineEventType, SetMultimap< String, EventCluster>> eventClusters = new HashMap<>();
try {
eventCache.get(zoom).stream()
.filter(uiFilter)
.forEach(event -> {
TimelineEventType clusterType = event.getEventType(typeZoomLevel);
.forEach(new Consumer<TimelineEvent>() {
@Override
public void accept(TimelineEvent event) {
TimelineEventType clusterType = event.getEventType().getCategory();
eventClusters.computeIfAbsent(clusterType, eventType -> HashMultimap.create())
.put(event.getDescription(descriptionLOD), new EventCluster(event, clusterType, descriptionLOD));
}
});
//get some info about the time range requested
TimeUnits periodSize = RangeDivision.getRangeDivision(timeRange, timeZone).getPeriodSize();

View File

@ -28,9 +28,9 @@ import java.util.Set;
import java.util.SortedSet;
import org.joda.time.Interval;
import org.sleuthkit.autopsy.timeline.utils.IntervalUtils;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineEventType;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* Represents a set of other events clustered together. All the sub events
@ -59,7 +59,7 @@ public class EventCluster implements MultiEvent<EventStripe> {
/**
* the description level of detail that the events were clustered at.
*/
private final TimelineEvent.DescriptionLevel lod;
private final TimelineLevelOfDetail lod;
/**
* the set of ids of the clustered events
@ -126,7 +126,7 @@ public class EventCluster implements MultiEvent<EventStripe> {
}
private EventCluster(Interval spanningInterval, TimelineEventType type, Set<Long> eventIDs,
Set<Long> hashHits, Set<Long> tagged, String description, TimelineEvent.DescriptionLevel lod,
Set<Long> hashHits, Set<Long> tagged, String description, TimelineLevelOfDetail lod,
EventStripe parent) {
this.span = spanningInterval;
@ -141,19 +141,19 @@ public class EventCluster implements MultiEvent<EventStripe> {
}
public EventCluster(Interval spanningInterval, TimelineEventType type, Set<Long> eventIDs,
Set<Long> hashHits, Set<Long> tagged, String description, TimelineEvent.DescriptionLevel lod) {
Set<Long> hashHits, Set<Long> tagged, String description, TimelineLevelOfDetail lod) {
this(spanningInterval, type, eventIDs, hashHits, tagged, description, lod, null);
}
public EventCluster(TimelineEvent event, TimelineEventType type, TimelineEvent.DescriptionLevel lod) {
this.span = new Interval(event.getStartMillis(), event.getEndMillis());
public EventCluster(TimelineEvent event, TimelineEventType type, TimelineLevelOfDetail lod) {
this.span = new Interval(event.getEventTimeInMs(), event.getEventTimeInMs());
this.type = type;
this.eventIDs = new HashSet<>();
this.eventIDs.add(event.getEventID());
this.hashHits = event.isHashHit() ? new HashSet<>(eventIDs) : emptySet();
this.tagged = event.isTagged() ? new HashSet<>(eventIDs) : emptySet();
this.hashHits = event.eventSourceHasHashHits()? new HashSet<>(eventIDs) : emptySet();
this.tagged = event.eventSourceIsTagged()? new HashSet<>(eventIDs) : emptySet();
this.lod = lod;
this.description = event.getDescription(lod);
this.parent = null;
@ -222,7 +222,7 @@ public class EventCluster implements MultiEvent<EventStripe> {
}
@Override
public TimelineEvent.DescriptionLevel getDescriptionLevel() {
public TimelineLevelOfDetail getDescriptionLevel() {
return lod;
}

View File

@ -26,7 +26,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
import org.sleuthkit.datamodel.TimelineEventType;
/**
@ -52,7 +52,7 @@ public final class EventStripe implements MultiEvent<EventCluster> {
/**
* the description level of detail that the events were clustered at.
*/
private final TimelineEvent.DescriptionLevel lod;
private final TimelineLevelOfDetail lod;
/**
* the set of ids of the events
@ -88,7 +88,7 @@ public final class EventStripe implements MultiEvent<EventCluster> {
}
private EventStripe(EventCluster parent, TimelineEventType type, String description,
TimelineEvent.DescriptionLevel lod, SortedSet<EventCluster> clusters,
TimelineLevelOfDetail lod, SortedSet<EventCluster> clusters,
Set<Long> eventIDs, Set<Long> tagged, Set<Long> hashHits) {
this.parent = parent;
this.type = type;
@ -151,7 +151,7 @@ public final class EventStripe implements MultiEvent<EventCluster> {
}
@Override
public TimelineEvent.DescriptionLevel getDescriptionLevel() {
public TimelineLevelOfDetail getDescriptionLevel() {
return lod;
}

View File

@ -28,6 +28,7 @@ import java.util.SortedSet;
import org.joda.time.Interval;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineEventType;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* A single event.
@ -65,7 +66,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
* The three descriptions (full, med, short) stored in a map, keyed by
* DescriptionLOD (Level of Detail)
*/
private final ImmutableMap<TimelineEvent.DescriptionLevel, String> descriptions;
private final ImmutableMap<TimelineLevelOfDetail, String> descriptions;
/**
* True if the file this event is derived from hits any of the configured
@ -106,9 +107,9 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
this.artifactID = Long.valueOf(0).equals(artifactID) ? null : artifactID;
this.time = time;
this.type = type;
descriptions = ImmutableMap.<TimelineEvent.DescriptionLevel, String>of(TimelineEvent.DescriptionLevel.FULL, fullDescription,
TimelineEvent.DescriptionLevel.MEDIUM, medDescription,
TimelineEvent.DescriptionLevel.SHORT, shortDescription);
descriptions = ImmutableMap.<TimelineLevelOfDetail, String>of(TimelineLevelOfDetail.HIGH, fullDescription,
TimelineLevelOfDetail.MEDIUM, medDescription,
TimelineLevelOfDetail.LOW, shortDescription);
this.hashHit = hashHit;
this.tagged = tagged;
}
@ -116,15 +117,15 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
public SingleDetailsViewEvent(TimelineEvent singleEvent) {
this(singleEvent.getEventID(),
singleEvent.getDataSourceObjID(),
singleEvent.getFileObjID(),
singleEvent.getContentObjID(),
singleEvent.getArtifactID().orElse(null),
singleEvent.getTime(),
singleEvent.getEventType(),
singleEvent.getFullDescription(),
singleEvent.getMedDescription(),
singleEvent.getShortDescription(),
singleEvent.isHashHit(),
singleEvent.isTagged());
singleEvent.getDescription(TimelineLevelOfDetail.HIGH),
singleEvent.getDescription(TimelineLevelOfDetail.MEDIUM),
singleEvent.getDescription(TimelineLevelOfDetail.LOW),
singleEvent.eventSourceHasHashHits(),
singleEvent.eventSourceIsTagged());
}
/**
@ -137,7 +138,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
* with the given parent.
*/
public SingleDetailsViewEvent withParent(MultiEvent<?> newParent) {
SingleDetailsViewEvent singleEvent = new SingleDetailsViewEvent(eventID, dataSourceObjId, fileObjId, artifactID, time, type, descriptions.get(TimelineEvent.DescriptionLevel.FULL), descriptions.get(TimelineEvent.DescriptionLevel.MEDIUM), descriptions.get(TimelineEvent.DescriptionLevel.SHORT), hashHit, tagged);
SingleDetailsViewEvent singleEvent = new SingleDetailsViewEvent(eventID, dataSourceObjId, fileObjId, artifactID, time, type, descriptions.get(TimelineLevelOfDetail.HIGH), descriptions.get(TimelineLevelOfDetail.MEDIUM), descriptions.get(TimelineLevelOfDetail.LOW), hashHit, tagged);
singleEvent.parent = newParent;
return singleEvent;
}
@ -212,7 +213,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
* @return the full description
*/
public String getFullDescription() {
return getDescription(TimelineEvent.DescriptionLevel.FULL);
return getDescription(TimelineLevelOfDetail.HIGH);
}
/**
@ -221,7 +222,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
* @return the medium description
*/
public String getMedDescription() {
return getDescription(TimelineEvent.DescriptionLevel.MEDIUM);
return getDescription(TimelineLevelOfDetail.MEDIUM);
}
/**
@ -230,7 +231,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
* @return the short description
*/
public String getShortDescription() {
return getDescription(TimelineEvent.DescriptionLevel.SHORT);
return getDescription(TimelineLevelOfDetail.LOW);
}
/**
@ -240,7 +241,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
*
* @return The description of this event at the given level of detail.
*/
public String getDescription(TimelineEvent.DescriptionLevel lod) {
public String getDescription(TimelineLevelOfDetail lod) {
return descriptions.get(lod);
}
@ -299,7 +300,7 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
@Override
public SortedSet<EventCluster> getClusters() {
EventCluster eventCluster = new EventCluster(new Interval(time * 1000, time * 1000), type, getEventIDs(), getEventIDsWithHashHits(), getEventIDsWithTags(), getFullDescription(), TimelineEvent.DescriptionLevel.FULL);
EventCluster eventCluster = new EventCluster(new Interval(time * 1000, time * 1000), type, getEventIDs(), getEventIDsWithHashHits(), getEventIDsWithTags(), getFullDescription(), TimelineLevelOfDetail.HIGH);
return ImmutableSortedSet.orderedBy(Comparator.comparing(EventCluster::getStartMillis)).add(eventCluster).build();
}
@ -309,8 +310,8 @@ public class SingleDetailsViewEvent implements DetailViewEvent {
}
@Override
public TimelineEvent.DescriptionLevel getDescriptionLevel() {
return TimelineEvent.DescriptionLevel.FULL;
public TimelineLevelOfDetail getDescriptionLevel() {
return TimelineLevelOfDetail.HIGH;
}
/**

View File

@ -29,9 +29,9 @@ import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.DetailViewEvent;
import org.sleuthkit.datamodel.TimelineEventType;
/**
* EventTreeItem for base event types (file system, misc, web, ...)
* EventTreeItem for category event types (file system, misc, web, ...)
*/
class BaseTypeTreeItem extends EventTypeTreeItem {
class CategoryTypeTreeItem extends EventTypeTreeItem {
/**
* A map of the children TreeItems, keyed by EventTypes if the children are
@ -46,8 +46,8 @@ class BaseTypeTreeItem extends EventTypeTreeItem {
* @param comparator the initial comparator used to sort the children of
* this tree item
*/
BaseTypeTreeItem(DetailViewEvent event, Comparator<TreeItem<DetailViewEvent>> comparator) {
super(event.getEventType().getBaseType(), comparator);
CategoryTypeTreeItem(DetailViewEvent event, Comparator<TreeItem<DetailViewEvent>> comparator) {
super(event.getEventType().getCategory(), comparator);
}
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
@ -61,7 +61,7 @@ class BaseTypeTreeItem extends EventTypeTreeItem {
* if the stripe and this tree item have the same type, create a
* description tree item, else create a sub-type tree item
*/
if (head.getEventType().getTypeLevel() == TimelineEventType.TypeLevel.SUB_TYPE) {
if (head.getEventType().getTypeHierarchyLevel() == TimelineEventType.HierarchyLevel.CATEGORY) {
descriptionKey = head.getEventType().getDisplayName();
treeItemConstructor = () -> configureNewTreeItem(new SubTypeTreeItem(head, getComparator()));
} else {
@ -87,7 +87,7 @@ class BaseTypeTreeItem extends EventTypeTreeItem {
* if the stripe and this tree item have the same type, get the child
* item keyed on event type, else keyed on description.
*/
if (head.getEventType().getTypeLevel() == TimelineEventType.TypeLevel.SUB_TYPE) {
if (head.getEventType().getTypeHierarchyLevel()== TimelineEventType.HierarchyLevel.CATEGORY) {
descTreeItem = childMap.get(head.getEventType().getDisplayName());
} else {
path.remove(0); //remove head of list if we are going straight to description

View File

@ -35,7 +35,7 @@ class RootItem extends EventsTreeItem {
/**
* A map of the children BaseTypeTreeItems, keyed by EventType.
*/
private final Map<TimelineEventType, BaseTypeTreeItem> childMap = new HashMap<>();
private final Map<TimelineEventType, CategoryTypeTreeItem> childMap = new HashMap<>();
/**
* Constructor
@ -85,7 +85,7 @@ class RootItem extends EventsTreeItem {
@Override
void remove(List<DetailViewEvent> path) {
DetailViewEvent event = path.get(0);
BaseTypeTreeItem typeTreeItem = childMap.get(event.getEventType().getBaseType());
CategoryTypeTreeItem typeTreeItem = childMap.get(event.getEventType().getCategory());
//remove the path from the child
if (typeTreeItem != null) {
@ -93,7 +93,7 @@ class RootItem extends EventsTreeItem {
//if the child has no children remove it also
if (typeTreeItem.getChildren().isEmpty()) {
childMap.remove(event.getEventType().getBaseType());
childMap.remove(event.getEventType().getCategory());
getChildren().remove(typeTreeItem);
}
}
@ -102,8 +102,8 @@ class RootItem extends EventsTreeItem {
@Override
void insert(List<DetailViewEvent> path) {
DetailViewEvent event = path.get(0);
BaseTypeTreeItem treeItem = childMap.computeIfAbsent(event.getEventType().getBaseType(),
baseType -> configureNewTreeItem(new BaseTypeTreeItem(event, getComparator()))
CategoryTypeTreeItem treeItem = childMap.computeIfAbsent(event.getEventType().getCategory(),
baseType -> configureNewTreeItem(new CategoryTypeTreeItem(event, getComparator()))
);
treeItem.insert(path);
}

View File

@ -79,8 +79,8 @@ final class LegendCell extends TreeTableCell<FilterState<?>, FilterState<?>> {
setLegendColor(filter, rect, newZoomLevel);
});
HBox hBox = new HBox(new Rectangle(filter.getEventType().getTypeLevel().ordinal() * 10, 5, CLEAR),
new ImageView(EventTypeUtils.getImagePath(filter.getEventType())), rect
HBox hBox = new HBox(new Rectangle(filter.getRootEventType().getTypeHierarchyLevel().ordinal() * 10, 5, CLEAR),
new ImageView(EventTypeUtils.getImagePath(filter.getRootEventType())), rect
);
hBox.setAlignment(Pos.CENTER);
Platform.runLater(() -> {
@ -92,7 +92,7 @@ final class LegendCell extends TreeTableCell<FilterState<?>, FilterState<?>> {
TextFilter filter = (TextFilter) item.getFilter();
TextField textField = new TextField();
textField.setPromptText(Bundle.Timeline_ui_filtering_promptText());
textField.textProperty().bindBidirectional(filter.textProperty());
textField.textProperty().bindBidirectional(filter.substringProperty());
Platform.runLater(() -> setGraphic(textField));
} else {
@ -104,12 +104,12 @@ final class LegendCell extends TreeTableCell<FilterState<?>, FilterState<?>> {
}
}
private void setLegendColor(EventTypeFilter filter, Rectangle rect, TimelineEventType.TypeLevel eventTypeZoom) {
private void setLegendColor(EventTypeFilter filter, Rectangle rect, TimelineEventType.HierarchyLevel eventTypeZoom) {
//only show legend color if filter is of the same zoomlevel as requested in filteredEvents
if (eventTypeZoom.equals(filter.getEventType().getTypeLevel())) {
if (eventTypeZoom.equals(filter.getRootEventType().getTypeHierarchyLevel())) {
Platform.runLater(() -> {
rect.setStroke(EventTypeUtils.getColor(filter.getEventType().getSuperType()));
rect.setFill(EventTypeUtils.getColor(filter.getEventType()));
rect.setStroke(EventTypeUtils.getColor(filter.getRootEventType().getParent()));
rect.setFill(EventTypeUtils.getColor(filter.getRootEventType()));
});
} else {
Platform.runLater(() -> {

View File

@ -20,23 +20,23 @@ package org.sleuthkit.autopsy.timeline.ui.filtering.datamodel;
import java.util.Objects;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* Ui level filter for events that have the given description.
*/
public final class DescriptionFilter implements UIFilter {
private final TimelineEvent.DescriptionLevel descriptionLoD;
private final TimelineLevelOfDetail descriptionLoD;
private final String description;
public DescriptionFilter(TimelineEvent.DescriptionLevel descriptionLoD, String description) {
public DescriptionFilter(TimelineLevelOfDetail descriptionLoD, String description) {
super();
this.descriptionLoD = descriptionLoD;
this.description = description;
}
public TimelineEvent.DescriptionLevel getDescriptionLevel() {
public TimelineLevelOfDetail getDescriptionLevel() {
return descriptionLoD;
}

View File

@ -39,9 +39,9 @@ public class SqlFilterState<FilterType extends TimelineFilter> extends AbstractF
selectedProperty().addListener(selectedProperty -> {
if (filter instanceof TimelineFilter.TagsFilter) {
((TimelineFilter.TagsFilter)filter).setTagged(isSelected());
((TimelineFilter.TagsFilter)filter).setEventSourcesAreTagged(isSelected());
} else if (filter instanceof TimelineFilter.HashHitsFilter) {
((TimelineFilter.HashHitsFilter)filter).setTagged(isSelected());
((TimelineFilter.HashHitsFilter)filter).setEventSourcesHaveHashSetHits(isSelected());
}
});

View File

@ -98,6 +98,7 @@ import static org.sleuthkit.datamodel.TimelineEventType.FILE_CREATED;
import static org.sleuthkit.datamodel.TimelineEventType.FILE_MODIFIED;
import static org.sleuthkit.datamodel.TimelineEventType.FILE_SYSTEM;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* The inner component that makes up the List view. Manages the TableView.
@ -232,11 +233,11 @@ class ListTimeline extends BorderPane {
//// set up cell and cell-value factories for columns
dateTimeColumn.setCellValueFactory(CELL_VALUE_FACTORY);
dateTimeColumn.setCellFactory(col -> new TextEventTableCell(singleEvent
-> TimeLineController.getZonedFormatter().print(singleEvent.getStartMillis())));
-> TimeLineController.getZonedFormatter().print(singleEvent.getEventTimeInMs())));
descriptionColumn.setCellValueFactory(CELL_VALUE_FACTORY);
descriptionColumn.setCellFactory(col -> new TextEventTableCell(singleEvent
-> singleEvent.getDescription(TimelineEvent.DescriptionLevel.FULL)));
-> singleEvent.getDescription(TimelineLevelOfDetail.HIGH)));
typeColumn.setCellValueFactory(CELL_VALUE_FACTORY);
typeColumn.setCellFactory(col -> new EventTypeCell());
@ -409,11 +410,11 @@ class ListTimeline extends BorderPane {
setGraphic(null);
setTooltip(null);
} else {
if (item.getEventTypes().stream().allMatch(TimelineEventType.FILE_SYSTEM.getSubTypes()::contains)) {
if (item.getEventTypes().stream().allMatch(TimelineEventType.FILE_SYSTEM.getChildren()::contains)) {
String typeString = ""; //NON-NLS
VBox toolTipVbox = new VBox(5);
for (TimelineEventType type : TimelineEventType.FILE_SYSTEM.getSubTypes()) {
for (TimelineEventType type : TimelineEventType.FILE_SYSTEM.getChildren()) {
if (item.getEventTypes().contains(type)) {
if (type.equals(FILE_MODIFIED)) {
typeString += "M"; //NON-NLS
@ -472,7 +473,7 @@ class ListTimeline extends BorderPane {
protected void updateItem(CombinedEvent item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null || (getEvent().isTagged() == false)) {
if (empty || item == null || (getEvent().eventSourceIsTagged() == false)) {
setGraphic(null);
setTooltip(null);
} else {
@ -485,13 +486,13 @@ class ListTimeline extends BorderPane {
SortedSet<String> tagNames = new TreeSet<>();
try {
//get file tags
Content file = sleuthkitCase.getContentById(getEvent().getFileObjID());
Content file = sleuthkitCase.getContentById(getEvent().getContentObjID());
tagsManager.getContentTagsByContent(file).stream()
.map(tag -> tag.getName().getDisplayName())
.forEach(tagNames::add);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to lookup tags for obj id " + getEvent().getFileObjID(), ex); //NON-NLS
logger.log(Level.SEVERE, "Failed to lookup tags for obj id " + getEvent().getContentObjID(), ex); //NON-NLS
Platform.runLater(() -> {
Notifications.create()
.owner(getScene().getWindow())
@ -544,7 +545,7 @@ class ListTimeline extends BorderPane {
protected void updateItem(CombinedEvent item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null || (getEvent().isHashHit() == false)) {
if (empty || item == null || (getEvent().eventSourceHasHashHits()== false)) {
setGraphic(null);
setTooltip(null);
} else {
@ -555,12 +556,12 @@ class ListTimeline extends BorderPane {
*/
setGraphic(new ImageView(HASH_HIT));
try {
Set<String> hashSetNames = new TreeSet<>(sleuthkitCase.getContentById(getEvent().getFileObjID()).getHashSetNames());
Set<String> hashSetNames = new TreeSet<>(sleuthkitCase.getContentById(getEvent().getContentObjID()).getHashSetNames());
Tooltip tooltip = new Tooltip(Bundle.ListTimeline_hashHitTooltip_text(String.join("\n", hashSetNames))); //NON-NLS
tooltip.setGraphic(new ImageView(HASH_HIT));
setTooltip(tooltip);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to lookup hash set names for obj id " + getEvent().getFileObjID(), ex); //NON-NLS
logger.log(Level.SEVERE, "Failed to lookup hash set names for obj id " + getEvent().getContentObjID(), ex); //NON-NLS
Platform.runLater(() -> {
Notifications.create()
.owner(getScene().getWindow())

View File

@ -35,6 +35,7 @@ import org.sleuthkit.datamodel.TimelineManager;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineEventType;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* Model for the ListView. Uses FilteredEventsModel as underlying datamodel and
@ -88,7 +89,7 @@ public class ListViewModel {
ArrayList<CombinedEvent> combinedEvents = new ArrayList<>();
Map<CombinedEventGroup, List<TimelineEvent>> groupedEventList = events.stream().collect(groupingBy(event -> new CombinedEventGroup(event.getTime(), event.getFileObjID(), event.getFullDescription())));
Map<CombinedEventGroup, List<TimelineEvent>> groupedEventList = events.stream().collect(groupingBy(event -> new CombinedEventGroup(event.getTime(), event.getContentObjID(), event.getDescription(TimelineLevelOfDetail.HIGH))));
for(Entry<CombinedEventGroup, List<TimelineEvent>> entry: groupedEventList.entrySet()){
List<TimelineEvent> groupedEvents = entry.getValue();
@ -120,7 +121,7 @@ public class ListViewModel {
private boolean hasFileTypeEvents(Collection<TimelineEventType> eventTypes) {
for (TimelineEventType type: eventTypes) {
if (type.getBaseType() != TimelineEventType.FILE_SYSTEM) {
if (type.getCategory() != TimelineEventType.FILE_SYSTEM) {
return false;
}
}

View File

@ -41,6 +41,7 @@ import org.sleuthkit.autopsy.timeline.utils.RangeDivision;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TimelineEventType;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* A Panel that acts as a view for a given
@ -93,21 +94,21 @@ public class ZoomSettingsPane extends TitledPane {
zoomLabel.setText(Bundle.ZoomSettingsPane_zoomLabel_text());
typeZoomSlider.setMin(1); //don't show ROOT_TYPE
typeZoomSlider.setMax(TimelineEventType.TypeLevel.values().length - 1);
typeZoomSlider.setMax(TimelineEventType.HierarchyLevel.values().length - 1);
configureSliderListeners(typeZoomSlider,
controller::pushEventTypeZoom,
filteredEvents.eventTypeZoomProperty(),
TimelineEventType.TypeLevel.class,
TimelineEventType.TypeLevel::ordinal,
TimelineEventType.HierarchyLevel.class,
TimelineEventType.HierarchyLevel::ordinal,
Function.identity());
typeZoomLabel.setText(Bundle.ZoomSettingsPane_typeZoomLabel_text());
descrLODSlider.setMax(TimelineEvent.DescriptionLevel.values().length - 1);
descrLODSlider.setMax(TimelineLevelOfDetail.values().length - 1);
configureSliderListeners(descrLODSlider,
controller::pushDescrLOD,
filteredEvents.descriptionLODProperty(),
TimelineEvent.DescriptionLevel.class,
TimelineEvent.DescriptionLevel::ordinal,
TimelineLevelOfDetail.class,
TimelineLevelOfDetail::ordinal,
Function.identity());
descrLODLabel.setText(Bundle.ZoomSettingsPane_descrLODLabel_text());
//the description slider is only usefull in the detail view

View File

@ -23,6 +23,7 @@ import org.joda.time.Interval;
import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState;
import org.sleuthkit.datamodel.TimelineEvent;
import org.sleuthkit.datamodel.TimelineEventType;
import org.sleuthkit.datamodel.TimelineLevelOfDetail;
/**
* This class encapsulates all the zoom(and filter) parameters into one object
@ -32,17 +33,17 @@ final public class ZoomState {
private final Interval timeRange;
private final TimelineEventType.TypeLevel typeZoomLevel;
private final TimelineEventType.HierarchyLevel typeZoomLevel;
private final RootFilterState filter;
private final TimelineEvent.DescriptionLevel descrLOD;
private final TimelineLevelOfDetail descrLOD;
public Interval getTimeRange() {
return timeRange;
}
public TimelineEventType.TypeLevel getTypeZoomLevel() {
public TimelineEventType.HierarchyLevel getTypeZoomLevel() {
return typeZoomLevel;
}
@ -50,22 +51,22 @@ final public class ZoomState {
return filter;
}
public TimelineEvent.DescriptionLevel getDescriptionLOD() {
public TimelineLevelOfDetail getDescriptionLOD() {
return descrLOD;
}
public ZoomState(Interval timeRange, TimelineEventType.TypeLevel zoomLevel, RootFilterState filter, TimelineEvent.DescriptionLevel descrLOD) {
public ZoomState(Interval timeRange, TimelineEventType.HierarchyLevel zoomLevel, RootFilterState filter, TimelineLevelOfDetail descrLOD) {
this.timeRange = timeRange;
this.typeZoomLevel = zoomLevel;
this.filter = filter;
this.descrLOD = descrLOD;
}
public ZoomState withTimeAndType(Interval timeRange, TimelineEventType.TypeLevel zoomLevel) {
public ZoomState withTimeAndType(Interval timeRange, TimelineEventType.HierarchyLevel zoomLevel) {
return new ZoomState(timeRange, zoomLevel, filter, descrLOD);
}
public ZoomState withTypeZoomLevel(TimelineEventType.TypeLevel zoomLevel) {
public ZoomState withTypeZoomLevel(TimelineEventType.HierarchyLevel zoomLevel) {
return new ZoomState(timeRange, zoomLevel, filter, descrLOD);
}
@ -73,7 +74,7 @@ final public class ZoomState {
return new ZoomState(timeRange, typeZoomLevel, filter, descrLOD);
}
public ZoomState withDescrLOD(TimelineEvent.DescriptionLevel descrLOD) {
public ZoomState withDescrLOD(TimelineLevelOfDetail descrLOD) {
return new ZoomState(timeRange, typeZoomLevel, filter, descrLOD);
}
@ -85,7 +86,7 @@ final public class ZoomState {
return this.filter.equals(filterSet);
}
public boolean hasTypeZoomLevel(TimelineEventType.TypeLevel typeZoom) {
public boolean hasTypeZoomLevel(TimelineEventType.HierarchyLevel typeZoom) {
return this.typeZoomLevel.equals(typeZoom);
}
@ -93,7 +94,7 @@ final public class ZoomState {
return this.timeRange != null && this.timeRange.equals(timeRange);
}
public boolean hasDescrLOD(TimelineEvent.DescriptionLevel newLOD) {
public boolean hasDescrLOD(TimelineLevelOfDetail newLOD) {
return this.descrLOD.equals(newLOD);
}