Package org.sleuthkit.autopsy.timeline.events

Source Code of org.sleuthkit.autopsy.timeline.events.FilteredEventsModel

/*
* Autopsy Forensic Browser
*
* Copyright 2014 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.events;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javax.annotation.concurrent.GuardedBy;
import org.joda.time.DateTimeZone;
import org.joda.time.Interval;
import org.sleuthkit.autopsy.timeline.TimeLineView;
import org.sleuthkit.autopsy.timeline.events.db.EventsRepository;
import org.sleuthkit.autopsy.timeline.events.type.EventType;
import org.sleuthkit.autopsy.timeline.filters.Filter;
import org.sleuthkit.autopsy.timeline.filters.IntersectionFilter;
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLOD;
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
import org.sleuthkit.autopsy.timeline.zooming.ZoomParams;

/**
* This class acts as the model for a {@link TimeLineView}
*
* Views can register listeners on properties returned by methods.
*
* This class is implemented as a filtered view into an underlying
* {@link EventsRepository}.
*
* TODO: as many methods as possible should cache their results so as to avoid
* unnecessary db calls through the {@link EventsRepository} -jm
*
* Concurrency Policy: repo is internally synchronized, so methods that only
* access the repo atomicaly do not need further synchronization
*
* all other member state variables should only be accessed with intrinsic lock
* of containing FilteredEventsModel held. Many methods delegate to a task
* submitted to the dbQueryThread executor. These methods should synchronize on
* this object, and the tasks should too. Since the tasks execute asynchronously
* from the invoking methods, the methods will return and release the lock for
* the tasks to obtain.
*
*/
public class FilteredEventsModel {

    /**
     * time range that spans the filtered events
     */
    //requested time range, filter, event_type zoom, and description level of detail.  if specifics are not passed to methods, the values of these members are used to query repository.
    @GuardedBy("this")
    private final ReadOnlyObjectWrapper<Interval> requestedTimeRange = new ReadOnlyObjectWrapper<>();

    @GuardedBy("this")
    private final ReadOnlyObjectWrapper<Filter> requestedFilter = new ReadOnlyObjectWrapper<>(Filter.getDefaultFilter());

    @GuardedBy("this")
    private final ReadOnlyObjectWrapper< EventTypeZoomLevel> requestedTypeZoom = new ReadOnlyObjectWrapper<>(EventTypeZoomLevel.BASE_TYPE);

    @GuardedBy("this")
    private final ReadOnlyObjectWrapper< DescriptionLOD> requestedLOD = new ReadOnlyObjectWrapper<>(DescriptionLOD.SHORT);

    @GuardedBy("this")
    private final ReadOnlyObjectWrapper<ZoomParams> requestedZoomParamters = new ReadOnlyObjectWrapper<>();

    /**
     * The underlying repo for events. Atomic access to repo is synchronized
     * internally, but compound access should be done with the intrinsic lock of
     * this FilteredEventsModel object
     */
    @GuardedBy("this")
    private final EventsRepository repo;

    public FilteredEventsModel(EventsRepository repo, ReadOnlyObjectProperty<ZoomParams> currentStateProperty) {
        this.repo = repo;
        requestedZoomParamters.addListener((Observable observable) -> {
            final ZoomParams zoomParams = requestedZoomParamters.get();

            if (zoomParams != null) {
                if (zoomParams.getTypeZoomLevel().equals(requestedTypeZoom.get()) == false
                        || zoomParams.getDescrLOD().equals(requestedLOD.get()) == false
                        || zoomParams.getFilter().equals(requestedFilter.get()) == false
                        || zoomParams.getTimeRange().equals(requestedTimeRange.get()) == false) {

                    requestedTypeZoom.set(zoomParams.getTypeZoomLevel());
                    requestedFilter.set(zoomParams.getFilter().copyOf());
                    requestedTimeRange.set(zoomParams.getTimeRange());
                    requestedLOD.set(zoomParams.getDescrLOD());
                }
            }
        });

        requestedZoomParamters.bind(currentStateProperty);
    }

    public Interval getBoundingEventsInterval() {
        return repo.getBoundingEventsInterval(getRequestedZoomParamters().get().getTimeRange(), getRequestedZoomParamters().get().getFilter());
    }

    synchronized public ReadOnlyObjectProperty<ZoomParams> getRequestedZoomParamters() {
        return requestedZoomParamters.getReadOnlyProperty();
    }

    public TimeLineEvent getEventById(Long eventID) {
        return repo.getEventById(eventID);
    }

    public Set<Long> getEventIDs(Interval timeRange, Filter filter) {
        final Interval overlap;
        final IntersectionFilter intersect;
        synchronized (this) {
            overlap = getSpanningInterval().overlap(timeRange);
            intersect = Filter.intersect(new Filter[]{filter, requestedFilter.get()});
        }
        return repo.getEventIDs(overlap, intersect);
    }

    /**
     * return the number of events that pass the requested filter and are within
     * the given time range.
     *
     * NOTE: this method does not change the requested time range
     *
     * @param timeRange
     *
     * @return
     */
    public Map<EventType, Long> getEventCounts(Interval timeRange) {

        final Filter filter;
        final EventTypeZoomLevel typeZoom;
        synchronized (this) {
            filter = requestedFilter.get();
            typeZoom = requestedTypeZoom.get();
        }
        return repo.countEvents(new ZoomParams(timeRange, typeZoom, filter, null));
    }

    /**
     * @return a read only view of the time range requested via
     *         {@link #requestTimeRange(org.joda.time.Interval)}
     */
    synchronized public ReadOnlyObjectProperty<Interval> timeRange() {
        if (requestedTimeRange.get() == null) {
            requestedTimeRange.set(getSpanningInterval());
        }
        return requestedTimeRange.getReadOnlyProperty();
    }

    synchronized public ReadOnlyObjectProperty<DescriptionLOD> descriptionLOD() {
        return requestedLOD.getReadOnlyProperty();
    }

    synchronized public ReadOnlyObjectProperty<Filter> filter() {
        return requestedFilter.getReadOnlyProperty();
    }

    /**
     * @return the smallest interval spanning all the events from the
     *         repository, ignoring any filters or requested ranges
     */
    public final Interval getSpanningInterval() {
        return new Interval(getMinTime() * 1000, 1000 + getMaxTime() * 1000, DateTimeZone.UTC);
    }

    /**
     * @return the smallest interval spanning all the given events
     */
    public Interval getSpanningInterval(Collection<Long> eventIDs) {
        return repo.getSpanningInterval(eventIDs);
    }

    /**
     * @return the time (in seconds from unix epoch) of the absolutely first
     *         event available from the repository, ignoring any filters or requested
     *         ranges
     */
    public final Long getMinTime() {
        return repo.getMinTime();
    }

    /**
     * @return the time (in seconds from unix epoch) of the absolutely last
     *         event available from the repository, ignoring any filters or requested
     *         ranges
     */
    public final Long getMaxTime() {
        return repo.getMaxTime();
    }

    /**
     * @param aggregation
     *
     * @return a list of aggregated events that are within the requested time
     *         range and pass the requested filter, using the given aggregation to
     *         control the grouping of events
     */
    public List<AggregateEvent> getAggregatedEvents() {
        final Interval range;
        final Filter filter;
        final EventTypeZoomLevel zoom;
        final DescriptionLOD lod;
        synchronized (this) {
            range = requestedTimeRange.get();
            filter = requestedFilter.get();
            zoom = requestedTypeZoom.get();
            lod = requestedLOD.get();
        }
        return repo.getAggregatedEvents(new ZoomParams(range, zoom, filter, lod));
    }

    /**
     * @param aggregation
     *
     * @return a list of aggregated events that are within the requested time
     *         range and pass the requested filter, using the given aggregation to
     *         control the grouping of events
     */
    public List<AggregateEvent> getAggregatedEvents(ZoomParams params) {
        return repo.getAggregatedEvents(params);
    }

    synchronized public ReadOnlyObjectProperty<EventTypeZoomLevel> eventTypeZoom() {
        return requestedTypeZoom.getReadOnlyProperty();
    }

    synchronized public EventTypeZoomLevel getEventTypeZoom() {
        return requestedTypeZoom.get();
    }

//    synchronized public void requestZoomState(ZoomParams zCrumb, boolean force) {
//        if (force
//                || zCrumb.getTypeZoomLevel().equals(requestedTypeZoom.get()) == false
//                || zCrumb.getDescrLOD().equals(requestedLOD.get()) == false
//                || zCrumb.getFilter().equals(requestedFilter.get()) == false
//                || zCrumb.getTimeRange().equals(requestedTimeRange.get()) == false) {
//
//            requestedZoomParamters.set(zCrumb);
//            requestedTypeZoom.set(zCrumb.getTypeZoomLevel());
//            requestedFilter.set(zCrumb.getFilter().copyOf());
//            requestedTimeRange.set(zCrumb.getTimeRange());
//            requestedLOD.set(zCrumb.getDescrLOD());
//        }
//    }
    public DescriptionLOD getDescriptionLOD() {
        return requestedLOD.get();
    }
}
TOP

Related Classes of org.sleuthkit.autopsy.timeline.events.FilteredEventsModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.