Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
EventCluster.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2018-2019 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.timeline.ui.detailview.datamodel;
20
21import static java.util.Collections.emptySet;
22import static java.util.Collections.singleton;
23import java.util.Comparator;
24import java.util.HashSet;
25import java.util.Objects;
26import java.util.Optional;
27import java.util.Set;
28import java.util.SortedSet;
29import org.joda.time.Interval;
30import org.sleuthkit.autopsy.timeline.utils.IntervalUtils;
31import org.sleuthkit.datamodel.TimelineEventType;
32import org.sleuthkit.datamodel.TimelineEvent;
33import org.sleuthkit.datamodel.TimelineLevelOfDetail;
34
40public class EventCluster implements MultiEvent<EventStripe> {
41
42 final private EventStripe parent;
43
47 final private Interval span;
48
52 final private TimelineEventType type;
53
57 final private String description;
58
62 private final TimelineLevelOfDetail lod;
63
67 final private Set<Long> eventIDs;
68
73 private final Set<Long> tagged;
74
79 private final Set<Long> hashHits;
80
90 public static EventCluster merge(EventCluster cluster1, EventCluster cluster2) {
91
92 if (cluster1.getEventType() != cluster2.getEventType()) {
93 throw new IllegalArgumentException("event clusters are not compatible: they have different types");
94 }
95
96 if (!cluster1.getDescription().equals(cluster2.getDescription())) {
97 throw new IllegalArgumentException("event clusters are not compatible: they have different descriptions");
98 }
99
100 Interval spanningInterval = IntervalUtils.span(cluster1.span, cluster2.span);
101
102 Set<Long> idsUnion = cluster1.getEventIDs();
103 if(!idsUnion.isEmpty()) {
104 idsUnion.addAll(cluster2.getEventIDs());
105 } else {
106 idsUnion = cluster2.getEventIDs();
107 }
108
109 Set<Long> hashHitsUnion = cluster1.getEventIDsWithHashHits();
110 if(!hashHitsUnion.isEmpty()) {
111 hashHitsUnion.addAll(cluster2.getEventIDsWithHashHits());
112 } else {
113 hashHitsUnion = cluster2.getEventIDsWithHashHits();
114 }
115
116 Set<Long> taggedUnion = cluster1.getEventIDsWithTags();
117 if(!taggedUnion.isEmpty()) {
118 taggedUnion.addAll(cluster2.getEventIDsWithTags());
119 } else {
120 taggedUnion = cluster2.getEventIDsWithTags();
121 }
122
123 return new EventCluster(spanningInterval,
124 cluster1.getEventType(), idsUnion, hashHitsUnion, taggedUnion,
125 cluster1.getDescription(), cluster1.lod);
126 }
127
128 private EventCluster(Interval spanningInterval, TimelineEventType type, Set<Long> eventIDs,
129 Set<Long> hashHits, Set<Long> tagged, String description, TimelineLevelOfDetail lod,
131
132 this.span = spanningInterval;
133
134 this.type = type;
135 this.hashHits = hashHits;
136 this.tagged = tagged;
137 this.description = description;
138 this.eventIDs = eventIDs;
139 this.lod = lod;
140 this.parent = parent;
141 }
142
143 public EventCluster(Interval spanningInterval, TimelineEventType type, Set<Long> eventIDs,
144 Set<Long> hashHits, Set<Long> tagged, String description, TimelineLevelOfDetail lod) {
145 this(spanningInterval, type, eventIDs, hashHits, tagged, description, lod, null);
146 }
147
148
149 public EventCluster(TimelineEvent event, TimelineEventType type, TimelineLevelOfDetail lod) {
150 this.span = new Interval(event.getEventTimeInMs(), event.getEventTimeInMs());
151 this.type = type;
152
153 this.eventIDs = new HashSet<>();
154 this.eventIDs.add(event.getEventID());
155 this.hashHits = event.eventSourceHasHashHits()? new HashSet<>(eventIDs) : emptySet();
156 this.tagged = event.eventSourceIsTagged()? new HashSet<>(eventIDs) : emptySet();
157 this.lod = lod;
158 this.description = event.getDescription(lod);
159 this.parent = null;
160 }
161
168 @Override
169 public Optional<EventStripe> getParent() {
170 return Optional.ofNullable(parent);
171 }
172
179 @Override
180 public Optional<EventStripe> getParentStripe() {
181 //since this clusters parent must be an event stripe just delegate to getParent();
182 return getParent();
183 }
184
185 public Interval getSpan() {
186 return span;
187 }
188
189 @Override
190 public long getStartMillis() {
191 return span.getStartMillis();
192 }
193
194 @Override
195 public long getEndMillis() {
196 return span.getEndMillis();
197 }
198
199 @Override
200 public Set<Long> getEventIDs() {
201 return eventIDs;
202 }
203
204 @Override
205 public Set<Long> getEventIDsWithHashHits() {
206 return hashHits;
207 }
208
209 @Override
210 public Set<Long> getEventIDsWithTags() {
211 return tagged;
212 }
213
214 @Override
215 public String getDescription() {
216 return description;
217 }
218
219 @Override
220 public TimelineEventType getEventType() {
221 return type;
222 }
223
224 @Override
225 public TimelineLevelOfDetail getDescriptionLevel() {
226 return lod;
227 }
228
242
243 @Override
244 public SortedSet<EventCluster> getClusters() {
245 return DetailsViewModel.copyAsSortedSet(singleton(this), Comparator.comparing(cluster -> true));
246 }
247
248 @Override
249 public String toString() {
250 return "EventCluster{" + "description=" + description + ", eventIDs=" + eventIDs.size() + '}';
251 }
252
253 @Override
254 public int hashCode() {
255 int hash = 7;
256 hash = 23 * hash + Objects.hashCode(this.type);
257 hash = 23 * hash + Objects.hashCode(this.description);
258 hash = 23 * hash + Objects.hashCode(this.lod);
259 hash = 23 * hash + Objects.hashCode(this.eventIDs);
260 return hash;
261 }
262
263 @Override
264 public boolean equals(Object obj) {
265 if (this == obj) {
266 return true;
267 }
268 if (obj == null) {
269 return false;
270 }
271 if (getClass() != obj.getClass()) {
272 return false;
273 }
274 final EventCluster other = (EventCluster) obj;
275 if (!Objects.equals(this.description, other.description)) {
276 return false;
277 }
278 if (!Objects.equals(this.type, other.type)) {
279 return false;
280 }
281 if (this.lod != other.lod) {
282 return false;
283 }
284 return Objects.equals(this.eventIDs, other.eventIDs);
285 }
286}
EventCluster(Interval spanningInterval, TimelineEventType type, Set< Long > eventIDs, Set< Long > hashHits, Set< Long > tagged, String description, TimelineLevelOfDetail lod, EventStripe parent)
EventCluster(Interval spanningInterval, TimelineEventType type, Set< Long > eventIDs, Set< Long > hashHits, Set< Long > tagged, String description, TimelineLevelOfDetail lod)
static EventCluster merge(EventCluster cluster1, EventCluster cluster2)
EventCluster(TimelineEvent event, TimelineEventType type, TimelineLevelOfDetail lod)
static Interval span(Interval range, final Interval range2)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.