/*
* Autopsy Forensic Browser
*
* Copyright 2013-16 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.imagegallery.datamodel;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.StringProperty;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.datamodel.TagName;
/**
* psuedo-enum of attributes to filter, sort, and group on. They mostly
* correspond to the columns in the db.
*
* TODO: Review and refactor DrawableAttribute related code with an eye to usage
* of type paramaters and multivalued attributes
*/
@NbBundle.Messages({"DrawableAttribute.md5hash=MD5 Hash",
"DrawableAttribute.name=Name",
"DrawableAttribute.analyzed=Analyzed",
"DrawableAttribute.category=Category",
"DrawableAttribute.tags=Tags",
"DrawableAttribute.path=Path",
"DrawableAttribute.createdTime=Created Time",
"DrawableAttribute.modifiedTime=Modified Time",
"DrawableAttribute.cameraMake=Camera Make",
"DrawableAttribute.cameraModel=Camera Model",
"DrawableAttribute.hashSet=Hashset",
"DrawableAttribute.intObjID=Internal Object ID",
"DrawableAttribute.width=Width",
"DrawableAttribute.height=Height",
"DrawableAttribute.mimeType=MIME type"})
public class DrawableAttribute<T extends Comparable<T>> {
public final static DrawableAttribute<String> MD5_HASH =
new DrawableAttribute<>(AttributeName.MD5_HASH, Bundle.DrawableAttribute_md5hash(),
false,
"icon-hashtag.png", // NON-NLS
f -> Collections.singleton(f.getMd5Hash()));
public final static DrawableAttribute<String> NAME =
new DrawableAttribute<>(AttributeName.NAME, Bundle.DrawableAttribute_name(),
true,
"folder-rename.png", //NON-NLS
f -> Collections.singleton(f.getName()));
public final static DrawableAttribute<Boolean> ANALYZED =
new DrawableAttribute<>(AttributeName.ANALYZED, Bundle.DrawableAttribute_analyzed(),
true,
"",
f -> Collections.singleton(f.isAnalyzed()));
/**
* since categories are really just tags in autopsy, they are not dealt with
* in the DrawableDB. they have special code in various places to make this
* transparent.
*
* //TODO: this has lead to awkward hard to maintain code, and little
* advantage. move categories into DrawableDB?
*/
public final static DrawableAttribute<Category> CATEGORY =
new DrawableAttribute<Category>(AttributeName.CATEGORY, Bundle.DrawableAttribute_category(),
false,
"category-icon.png", //NON-NLS
f -> Collections.singleton(f.getCategory())) {
@Override
public Node getGraphicForValue(Category val) {
return val.getGraphic();
}
};
public final static DrawableAttribute<TagName> TAGS =
new DrawableAttribute<>(AttributeName.TAGS, Bundle.DrawableAttribute_tags(),
false,
"tag_red.png", //NON-NLS
DrawableFile::getTagNames);
public final static DrawableAttribute<String> PATH =
new DrawableAttribute<>(AttributeName.PATH, Bundle.DrawableAttribute_path(),
true,
"folder_picture.png", //NON-NLS
f -> Collections.singleton(f.getDrawablePath()));
public final static DrawableAttribute<String> CREATED_TIME =
new DrawableAttribute<>(AttributeName.CREATED_TIME, Bundle.DrawableAttribute_createdTime(),
true,
"clock--plus.png", //NON-NLS
f -> Collections.singleton(ContentUtils.getStringTime(f.getCrtime(), f.getAbstractFile())));
public final static DrawableAttribute<String> MODIFIED_TIME =
new DrawableAttribute<>(AttributeName.MODIFIED_TIME, Bundle.DrawableAttribute_modifiedTime(),
true,
"clock--pencil.png", //NON-NLS
f -> Collections.singleton(ContentUtils.getStringTime(f.getMtime(), f.getAbstractFile())));
public final static DrawableAttribute<String> MAKE =
new DrawableAttribute<>(AttributeName.MAKE, Bundle.DrawableAttribute_cameraMake(),
true,
"camera.png", //NON-NLS
f -> Collections.singleton(f.getMake()));
public final static DrawableAttribute<String> MODEL =
new DrawableAttribute<>(AttributeName.MODEL, Bundle.DrawableAttribute_cameraModel(),
true,
"camera.png", //NON-NLS
f -> Collections.singleton(f.getModel()));
public final static DrawableAttribute<String> HASHSET =
new DrawableAttribute<>(AttributeName.HASHSET, Bundle.DrawableAttribute_hashSet(),
true,
"hashset_hits.png", //NON-NLS
DrawableFile::getHashSetNamesUnchecked);
public final static DrawableAttribute<Long> OBJ_ID =
new DrawableAttribute<>(AttributeName.OBJ_ID, Bundle.DrawableAttribute_intObjID(),
true,
"",
f -> Collections.singleton(f.getId()));
public final static DrawableAttribute<Double> WIDTH =
new DrawableAttribute<>(AttributeName.WIDTH, Bundle.DrawableAttribute_width(),
false,
"arrow-resize.png", //NON-NLS
f -> Collections.singleton(f.getWidth()));
public final static DrawableAttribute<Double> HEIGHT =
new DrawableAttribute<>(AttributeName.HEIGHT, Bundle.DrawableAttribute_height(),
false,
"arrow-resize-090.png", //NON-NLS
f -> Collections.singleton(f.getHeight()));
public final static DrawableAttribute<String> MIME_TYPE =
new DrawableAttribute<>(AttributeName.MIME_TYPE, Bundle.DrawableAttribute_mimeType(),
false,
"mime_types.png", //NON-NLS
f -> Collections.singleton(f.getMIMEType()));
final private static List< DrawableAttribute<?>> groupables =
Arrays.asList(PATH, HASHSET, CATEGORY, TAGS, MAKE, MODEL, MIME_TYPE);
final private static List<DrawableAttribute<?>> values =
Arrays.asList(NAME, ANALYZED, CATEGORY, TAGS, PATH, CREATED_TIME,
MODIFIED_TIME, MD5_HASH, HASHSET, MAKE, MODEL, OBJ_ID, WIDTH, HEIGHT, MIME_TYPE);
private final Function<DrawableFile, Collection<T>> extractor;
private DrawableAttribute(AttributeName name, String displayName, Boolean isDBColumn, String imageName, Function<DrawableFile, Collection<T>> extractor) {
this.attrName = name;
this.displayName = new ReadOnlyStringWrapper(displayName);
this.isDBColumn = isDBColumn;
this.extractor = extractor;
this.imageName = imageName;
}
private final String imageName;
private Image icon;
public final boolean isDBColumn;
public final AttributeName attrName;
private final StringProperty displayName;
public Image getIcon() {
/*
* There is some issue with loading this in the constructor which gets
* called at class load time, so instead we load them lazily the first
* time they are needed
*/
if (null == icon && StringUtils.isNotBlank(imageName)) {
this.icon = new Image("org/sleuthkit/autopsy/imagegallery/images/" + imageName, true); //NON-NLS
}
return icon;
}
/**
* TODO: override this to load per value icons form some attributes like
* mime-type and category
*/
public Node getGraphicForValue(T val) {
return new ImageView(getIcon());
}
public static List<DrawableAttribute<?>> getGroupableAttrs() {
return Collections.unmodifiableList(groupables);
}
public static List<DrawableAttribute<?>> getValues() {
return Collections.unmodifiableList(values);
}
public StringProperty displayName() {
return displayName;
}
public String getDisplayName() {
return displayName.get();
}
public Collection<T> getValue(DrawableFile f) {
return extractor.apply(f);
}
public static enum AttributeName {
NAME,
ANALYZED,
CATEGORY,
TAGS,
PATH,
CREATED_TIME,
MODIFIED_TIME,
MAKE,
MODEL,
HASHSET,
OBJ_ID,
WIDTH,
HEIGHT,
MD5_HASH,
MIME_TYPE;
}
}