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

Java tutorial

Introduction

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

Source

/*
 * Autopsy Forensic Browser
 *
 * Copyright 2013-14 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.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.scene.control.TreeItem;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.imageanalyzer.grouping.DrawableGroup;

/**
 * A node in the nav/hash tree. Manages inserts and removals. Has parents and
 * children. Does not have graphical properties these are configured in
 * {@link GroupTreeCell}. Each GroupTreeItem has a TreeNode which has a path
 * segment and may or may not have a group
 */
class GroupTreeItem extends TreeItem<TreeNode> implements Comparable<GroupTreeItem> {

    /**
     * maps a path segment to the child item of this item with that path segment
     */
    private Map<String, GroupTreeItem> childMap = new HashMap<>();
    /**
     * the comparator if any used to sort the children of this item
     */
    private TreeNodeComparators comp;

    public GroupTreeItem(String t, DrawableGroup g, TreeNodeComparators comp) {
        super(new TreeNode(t, g));
        this.comp = comp;
    }

    /**
     * Returns the full absolute path of this level in the tree
     *
     * @return the full absolute path of this level in the tree
     */
    public String getAbsolutePath() {
        if (getParent() != null) {
            return ((GroupTreeItem) getParent()).getAbsolutePath() + getValue().getPath() + "/";
        } else {
            return getValue().getPath() + "/";
        }
    }

    /**
     * Recursive method to add a grouping at a given path.
     *
     * @param path Full path (or subset not yet added) to add
     * @param g Group to add
     * @param tree True if it is part of a tree (versus a list)
     */
    void insert(String path, DrawableGroup g, Boolean tree) {
        if (tree) {
            String cleanPath = StringUtils.stripStart(path, "/");

            // get the first token
            String prefix = StringUtils.substringBefore(cleanPath, "/");

            // Are we at the end of the recursion?
            if ("".equals(prefix)) {
                getValue().setGroup(g);
            } else {
                GroupTreeItem prefixTreeItem = childMap.get(prefix);
                if (prefixTreeItem == null) {
                    final GroupTreeItem newTreeItem = new GroupTreeItem(prefix, null, comp);

                    prefixTreeItem = newTreeItem;
                    childMap.put(prefix, prefixTreeItem);
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            synchronized (getChildren()) {
                                getChildren().add(newTreeItem);
                            }
                        }
                    });

                }

                // recursively go into the path
                prefixTreeItem.insert(StringUtils.stripStart(cleanPath, prefix), g, tree);
            }
        } else {
            GroupTreeItem treeItem = childMap.get(path);
            if (treeItem == null) {
                final GroupTreeItem newTreeItem = new GroupTreeItem(path, g, comp);
                newTreeItem.setExpanded(true);
                childMap.put(path, newTreeItem);

                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        synchronized (getChildren()) {
                            getChildren().add(newTreeItem);
                            if (comp != null) {
                                FXCollections.sort(getChildren(), comp);
                            }
                        }
                    }
                });

            }
        }
    }

    /**
     * Recursive method to add a grouping at a given path.
     *
     * @param path Full path (or subset not yet added) to add
     * @param g Group to add
     * @param tree True if it is part of a tree (versus a list)
     */
    void insert(List<String> path, DrawableGroup g, Boolean tree) {
        if (tree) {
            // Are we at the end of the recursion?
            if (path.isEmpty()) {
                getValue().setGroup(g);
            } else {
                String prefix = path.get(0);

                GroupTreeItem prefixTreeItem = childMap.get(prefix);
                if (prefixTreeItem == null) {
                    final GroupTreeItem newTreeItem = new GroupTreeItem(prefix, null, comp);

                    prefixTreeItem = newTreeItem;
                    childMap.put(prefix, prefixTreeItem);

                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            synchronized (getChildren()) {
                                getChildren().add(newTreeItem);
                            }
                        }
                    });

                }

                // recursively go into the path
                prefixTreeItem.insert(path.subList(1, path.size()), g, tree);
            }
        } else {
            //flat list
            GroupTreeItem treeItem = childMap.get(StringUtils.join(path, "/"));
            if (treeItem == null) {
                final GroupTreeItem newTreeItem = new GroupTreeItem(StringUtils.join(path, "/"), g, comp);
                newTreeItem.setExpanded(true);
                childMap.put(path.get(0), newTreeItem);

                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        synchronized (getChildren()) {
                            getChildren().add(newTreeItem);
                            if (comp != null) {
                                FXCollections.sort(getChildren(), comp);
                            }
                        }
                    }
                });
            }
        }
    }

    @Override
    public int compareTo(GroupTreeItem o) {
        return comp.compare(this, o);
    }

    static GroupTreeItem getTreeItemForGroup(GroupTreeItem root, DrawableGroup grouping) {
        if (Objects.equals(root.getValue().getGroup(), grouping)) {
            return root;
        } else {
            synchronized (root.getChildren()) {
                for (TreeItem<TreeNode> child : root.getChildren()) {
                    final GroupTreeItem childGTI = (GroupTreeItem) child;

                    GroupTreeItem val = getTreeItemForGroup(childGTI, grouping);
                    if (val != null) {
                        return val;
                    }
                }
            }
        }
        return null;
    }

    GroupTreeItem getTreeItemForPath(List<String> path) {
        // end of recursion
        if (path.isEmpty()) {
            return this;
        } else {
            synchronized (getChildren()) {
                String prefix = path.get(0);

                GroupTreeItem prefixTreeItem = childMap.get(prefix);
                if (prefixTreeItem == null) {
                    // @@@ ERROR;
                    return null;
                }

                // recursively go into the path
                return prefixTreeItem.getTreeItemForPath(path.subList(1, path.size()));
            }
        }
    }

    void removeFromParent() {
        final GroupTreeItem parent = (GroupTreeItem) getParent();
        if (parent != null) {
            parent.childMap.remove(getValue().getPath());

            Platform.runLater(() -> {
                synchronized (parent.getChildren()) {
                    parent.getChildren().removeAll(Collections.singleton(GroupTreeItem.this));
                }
            });

            if (parent.childMap.isEmpty()) {
                parent.removeFromParent();
            }
        }
    }

    void resortChildren(TreeNodeComparators newComp) {
        this.comp = newComp;
        synchronized (getChildren()) {
            FXCollections.sort(getChildren(), comp);
        }
        for (GroupTreeItem ti : childMap.values()) {
            ti.resortChildren(comp);
        }
    }
}