org.sleuthkit.autopsy.imageanalyzer.gui.navpanel.NavPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.sleuthkit.autopsy.imageanalyzer.gui.navpanel.NavPanel.java

Source

/*
 * Autopsy Forensic Browser
 *
 * Copyright 2013 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.imageanalyzer.gui.navpanel;

import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.Exceptions;
import org.sleuthkit.autopsy.imageanalyzer.FXMLConstructor;
import org.sleuthkit.autopsy.imageanalyzer.ImageAnalyzerController;
import org.sleuthkit.autopsy.imageanalyzer.datamodel.DrawableAttribute;
import org.sleuthkit.autopsy.imageanalyzer.datamodel.DrawableFile;
import org.sleuthkit.autopsy.imageanalyzer.grouping.DrawableGroup;
import org.sleuthkit.autopsy.imageanalyzer.grouping.GroupKey;
import org.sleuthkit.autopsy.imageanalyzer.grouping.GroupSortBy;
import org.sleuthkit.autopsy.imageanalyzer.grouping.GroupViewState;
import org.sleuthkit.datamodel.TskCoreException;

/**
 * Display two trees. one shows all folders (groups) and calls out folders with
 * images. the user can select folders with images to see them in the main
 * GroupPane The other shows folders with hash set hits.
 */
public class NavPanel extends TabPane {

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    /**
     * TreeView for folders with hash hits
     */
    @FXML
    private TreeView<TreeNode> hashTree;

    @FXML
    private TabPane navTabPane;

    /**
     * TreeView for all folders
     */
    @FXML
    private TreeView<TreeNode> navTree;

    @FXML
    private Tab hashTab;

    @FXML
    private Tab navTab;

    @FXML
    private ComboBox<TreeNodeComparators> sortByBox;

    /**
     * contains the 'active tree'
     */
    private final SimpleObjectProperty<TreeView<TreeNode>> activeTreeProperty = new SimpleObjectProperty<>();

    private GroupTreeItem navTreeRoot;

    private GroupTreeItem hashTreeRoot;

    private final ImageAnalyzerController controller;

    public NavPanel(ImageAnalyzerController controller) {
        this.controller = controller;
        FXMLConstructor.construct(this, "NavPanel.fxml");
    }

    @FXML
    void initialize() {
        assert hashTab != null : "fx:id=\"hashTab\" was not injected: check your FXML file 'NavPanel.fxml'.";
        assert hashTree != null : "fx:id=\"hashTree\" was not injected: check your FXML file 'NavPanel.fxml'.";
        assert navTab != null : "fx:id=\"navTab\" was not injected: check your FXML file 'NavPanel.fxml'.";
        assert navTabPane != null : "fx:id=\"navTabPane\" was not injected: check your FXML file 'NavPanel.fxml'.";
        assert navTree != null : "fx:id=\"navTree\" was not injected: check your FXML file 'NavPanel.fxml'.";
        assert sortByBox != null : "fx:id=\"sortByBox\" was not injected: check your FXML file 'NavPanel.fxml'.";

        VBox.setVgrow(this, Priority.ALWAYS);

        navTree.setShowRoot(false);
        hashTree.setShowRoot(false);

        navTree.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
        hashTree.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);

        sortByBox.setCellFactory((ListView<TreeNodeComparators> p) -> new TreeNodeComparators.ComparatorListCell());

        sortByBox.setButtonCell(new TreeNodeComparators.ComparatorListCell());
        sortByBox.setItems(
                FXCollections.observableArrayList(FXCollections.observableArrayList(TreeNodeComparators.values())));
        sortByBox.getSelectionModel().select(TreeNodeComparators.HIT_COUNT);
        sortByBox.getSelectionModel().selectedItemProperty().addListener((Observable o) -> {
            resortHashTree();
        });

        navTree.setCellFactory((TreeView<TreeNode> p) -> new GroupTreeCell());

        hashTree.setCellFactory((TreeView<TreeNode> p) -> new GroupTreeCell());

        activeTreeProperty.addListener((Observable o) -> {
            updateControllersGroup();
            activeTreeProperty.get().getSelectionModel().selectedItemProperty().addListener((Observable o1) -> {
                updateControllersGroup();
            });
        });

        this.activeTreeProperty.set(navTree);

        navTabPane.getSelectionModel().selectedItemProperty()
                .addListener((ObservableValue<? extends Tab> ov, Tab t, Tab t1) -> {
                    if (t1 == hashTab) {
                        activeTreeProperty.set(hashTree);
                    } else if (t1 == navTab) {
                        activeTreeProperty.set(navTree);
                    }
                });

        initHashTree();
        initNavTree();

        controller.getGroupManager().getAnalyzedGroups()
                .addListener((ListChangeListener.Change<? extends DrawableGroup> change) -> {
                    while (change.next()) {
                        for (DrawableGroup g : change.getAddedSubList()) {
                            insertIntoNavTree(g);
                            if (g.getFilesWithHashSetHitsCount() > 0) {
                                insertIntoHashTree(g);
                            }
                        }
                        for (DrawableGroup g : change.getRemoved()) {
                            removeFromNavTree(g);
                            removeFromHashTree(g);
                        }
                    }
                });

        for (DrawableGroup g : controller.getGroupManager().getAnalyzedGroups()) {
            insertIntoNavTree(g);
            if (g.getFilesWithHashSetHitsCount() > 0) {
                insertIntoHashTree(g);
            }
        }

        controller.viewState().addListener((ObservableValue<? extends GroupViewState> observable,
                GroupViewState oldValue, GroupViewState newValue) -> {
            if (newValue != null && newValue.getGroup() != null) {
                setFocusedGroup(newValue.getGroup());
            }
        });
    }

    private void updateControllersGroup() {
        final TreeItem<TreeNode> selectedItem = activeTreeProperty.get().getSelectionModel().getSelectedItem();
        if (selectedItem != null && selectedItem.getValue() != null && selectedItem.getValue().getGroup() != null) {
            controller.advance(GroupViewState.tile(selectedItem.getValue().getGroup()));
        }
    }

    private void resortHashTree() {
        hashTreeRoot.resortChildren(sortByBox.getSelectionModel().getSelectedItem());
    }

    private void insertIntoHashTree(DrawableGroup g) {
        initHashTree();
        hashTreeRoot.insert(g.groupKey.getValueDisplayName(), g, false);
    }

    /**
     * Set the tree to the passed in group
     *
     * @param grouping
     */
    public void setFocusedGroup(DrawableGroup grouping) {

        List<String> path = groupingToPath(grouping);

        final GroupTreeItem treeItemForGroup = ((GroupTreeItem) activeTreeProperty.get().getRoot())
                .getTreeItemForPath(path);

        if (treeItemForGroup != null) {
            Platform.runLater(() -> {
                TreeItem<TreeNode> ti = treeItemForGroup;
                while (ti != null) {
                    ti.setExpanded(true);
                    ti = ti.getParent();
                }
                int row = activeTreeProperty.get().getRow(treeItemForGroup);
                if (row != -1) {
                    activeTreeProperty.get().getSelectionModel().select(treeItemForGroup);
                    activeTreeProperty.get().scrollTo(row);
                }
            });
        }
    }

    @SuppressWarnings("fallthrough")
    private static List<String> groupingToPath(DrawableGroup g) {

        if (g.groupKey.getAttribute() == DrawableAttribute.PATH) {
            String path = g.groupKey.getValueDisplayName();

            String cleanPath = StringUtils.stripStart(path, "/");
            String[] tokens = cleanPath.split("/");

            return Arrays.asList(tokens);
        } else {
            return Arrays.asList(g.groupKey.getValueDisplayName());
        }
    }

    private void insertIntoNavTree(DrawableGroup g) {
        initNavTree();
        List<String> path = groupingToPath(g);

        navTreeRoot.insert(path, g, true);
    }

    private void removeFromNavTree(DrawableGroup g) {
        initNavTree();
        final GroupTreeItem treeItemForGroup = GroupTreeItem.getTreeItemForGroup(navTreeRoot, g);
        if (treeItemForGroup != null) {
            treeItemForGroup.removeFromParent();
        }
    }

    private void removeFromHashTree(DrawableGroup g) {
        initHashTree();
        final GroupTreeItem treeItemForGroup = GroupTreeItem.getTreeItemForGroup(hashTreeRoot, g);
        if (treeItemForGroup != null) {
            treeItemForGroup.removeFromParent();
        }
    }

    private void initNavTree() {
        if (navTreeRoot == null) {
            navTreeRoot = new GroupTreeItem("", null, null);

            Platform.runLater(() -> {
                navTree.setRoot(navTreeRoot);
                navTreeRoot.setExpanded(true);
            });
        }
    }

    private void initHashTree() {
        if (hashTreeRoot == null) {
            hashTreeRoot = new GroupTreeItem("", null, null);

            Platform.runLater(() -> {
                hashTree.setRoot(hashTreeRoot);
                hashTreeRoot.setExpanded(true);
            });
        }
    }

    //these are not used anymore, but could be usefull at some point
    //TODO: remove them or find a use and undeprecate
    @Deprecated
    private void rebuildNavTree() {
        navTreeRoot = new GroupTreeItem("", null, sortByBox.getSelectionModel().selectedItemProperty().get());

        ObservableList<DrawableGroup> groups = controller.getGroupManager().getAnalyzedGroups();

        for (DrawableGroup g : groups) {
            insertIntoNavTree(g);
        }

        Platform.runLater(() -> {
            navTree.setRoot(navTreeRoot);
            navTreeRoot.setExpanded(true);
        });
    }

    @Deprecated
    private void rebuildHashTree() {
        hashTreeRoot = new GroupTreeItem("", null, sortByBox.getSelectionModel().getSelectedItem());
        //TODO: can we do this as db query?
        List<String> hashSetNames = controller.getGroupManager().findValuesForAttribute(DrawableAttribute.HASHSET,
                GroupSortBy.NONE);
        for (String name : hashSetNames) {
            try {
                List<Long> fileIDsInGroup = controller.getGroupManager()
                        .getFileIDsInGroup(new GroupKey<String>(DrawableAttribute.HASHSET, name));

                for (Long fileId : fileIDsInGroup) {

                    DrawableFile<?> file = controller.getFileFromId(fileId);
                    Collection<GroupKey<?>> groupKeysForFile = controller.getGroupManager()
                            .getGroupKeysForFile(file);

                    for (GroupKey<?> k : groupKeysForFile) {
                        final DrawableGroup groupForKey = controller.getGroupManager().getGroupForKey(k);
                        if (groupForKey != null) {
                            insertIntoHashTree(groupForKey);
                        }
                    }
                }
            } catch (TskCoreException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
        Platform.runLater(() -> {
            hashTree.setRoot(hashTreeRoot);
            hashTreeRoot.setExpanded(true);
        });
    }
}