/* * Autopsy Forensic Browser * * Copyright 2011-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.datamodel; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Set; import org.python.google.common.collect.ImmutableSet; import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType; /** * A container for several events that have the same timestamp and description * and are backed by the same file. Used in the ListView to coalesce the file * system events for a file when they have the same timestamp. */ public class CombinedEvent { private final long fileID; private final long epochMillis; private final String description; /** * A map from EventType to event ID. */ private final Map<EventType, Long> eventTypeMap = new HashMap<>(); /** * Constructor * * @param epochMillis The timestamp for this event, in millis from the Unix * epoch. * @param description The full description shared by all the combined events * @param fileID The ID of the file shared by all the combined events. * @param eventMap A map from EventType to event ID. */ public CombinedEvent(long epochMillis, String description, long fileID, Map<EventType, Long> eventMap) { this.epochMillis = epochMillis; this.description = description; eventTypeMap.putAll(eventMap); this.fileID = fileID; } /** * Get the timestamp of this event as millis from the Unix epoch. * * @return The timestamp of this event as millis from the Unix epoch. */ public long getStartMillis() { return epochMillis; } /** * Get the full description shared by all the combined events. * * @return The full description shared by all the combined events. */ public String getDescription() { return description; } /** * Get the obj ID of the file shared by the combined events. * * @return The obj ID of the file shared by the combined events. */ public long getFileID() { return fileID; } /** * Get the types of the combined events. * * @return The types of the combined events. */ public Set<EventType> getEventTypes() { return eventTypeMap.keySet(); } /** * Get the event IDs of the combined events. * * @return The event IDs of the combined events. */ public ImmutableSet<Long> getEventIDs() { return ImmutableSet.copyOf(eventTypeMap.values()); } /** * Get the event ID of one event that is representative of all the combined * events. It can be used to look up a SingleEvent with more details, for * example. * * @return An arbitrary representative event ID for the combined events. */ public Long getRepresentativeEventID() { return eventTypeMap.values().stream().findFirst().get(); } @Override public int hashCode() { int hash = 3; hash = 53 * hash + (int) (this.fileID ^ (this.fileID >>> 32)); hash = 53 * hash + (int) (this.epochMillis ^ (this.epochMillis >>> 32)); hash = 53 * hash + Objects.hashCode(this.description); hash = 53 * hash + Objects.hashCode(this.eventTypeMap); return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final CombinedEvent other = (CombinedEvent) obj; if (this.fileID != other.fileID) { return false; } if (this.epochMillis != other.epochMillis) { return false; } if (!Objects.equals(this.description, other.description)) { return false; } if (!Objects.equals(this.eventTypeMap, other.eventTypeMap)) { return false; } return true; } }