diff --git a/bindings/java/doxygen/main.dox b/bindings/java/doxygen/main.dox
index d05b4127ecd538ea559de3406c81bfbecdb12285..4f9494280fc64bbe411e151d28c74b23dd31ada8 100644
--- a/bindings/java/doxygen/main.dox
+++ b/bindings/java/doxygen/main.dox
@@ -8,6 +8,24 @@ The Sleuth Kit is primarily a C/C++ library and set of command line tools. These
 
 Expand on this to mention what classes to use, etc.
 
+\section jni_hierarchy Class Hierarchy
+
+Flush out here on general layout. 
+
+- org.sleuthkit.datamodel.Content is top-level interface and gets more specific as it goes down.
+- Types disk and file system organization concepts (org.sleuthkit.datamodel.FileSystem, org.sleuthkit.datamodel.Image, etc. )
+- org.sleuthkit.datamodel.AbstractFile is interface for various types of files with more specific classes below it ( org.sleuthkit.datamodel.DerivedFile, org.sleuthkit.datamodel.FsContent, etc.)
+
+\section jni_blackboard The Blackboard
+
+The blackboard in the database is used to communicate with modules in The Sleuth Kit framework and in Autopsy.  The blackboard concepts are described in the framework documentation (http://sleuthkit.org/sleuthkit/docs/framework-docs/mod_bbpage.html).
+This section provides a high-level overview of the relevant topics from the Java perspective (since the previous document focuses on the C++ APIs). 
+
+To make an artifact, one first calls the org.sleuthkit.datamodel.AbstractContent.newArtifact() method for the object that the artifact is being added to.  This returns a org.sleuthkit.datamodel.BlackboardArtifact object.  Attributes of type org.sleuthkit.datamodel.BlackboardAttribute are then created and added to the artifact.  
+
+To find artifacts, you have two general options.  If you have an org.sleuthkit.datamodel.AbstractContent object or a derived object, then you can use the org.sleuthkit.datamodel.AbstractContent.getArtifacts() methods to perform various queries. If you want artifacts beyond those for a single file, then you must use the various get methods in org.sleuthkit.datamodel.SleuthkitCase. 
+
+
 */
 
 
diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java
index 0cec254f70da2e92d72b228fdd183c0bb0fe7112..9226675e91f341ecba3197b154dd34da59007c95 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java
@@ -43,10 +43,10 @@ public class BlackboardArtifact implements SleuthkitVisitableItem {
 	public enum ARTIFACT_TYPE implements SleuthkitVisitableItem {
 
 		TSK_GEN_INFO(1, "TSK_GEN_INFO", "General Info"), ///< Default type
-		TSK_WEB_BOOKMARK(2, "TSK_WEB_BOOKMARK", "Bookmarks"), ///< web bookmarks
-		TSK_WEB_COOKIE(3, "TSK_WEB_COOKIE", "Cookies"), ///< web cookies
+		TSK_WEB_BOOKMARK(2, "TSK_WEB_BOOKMARK", "Web Bookmarks"), ///< web bookmarks
+		TSK_WEB_COOKIE(3, "TSK_WEB_COOKIE", "Web Cookies"), ///< web cookies
 		TSK_WEB_HISTORY(4, "TSK_WEB_HISTORY", "Web History"), ///< web history
-		TSK_WEB_DOWNLOAD(5, "TSK_WEB_DOWNLOAD", "Downloads"), ///< web downloads
+		TSK_WEB_DOWNLOAD(5, "TSK_WEB_DOWNLOAD", "Web Downloads"), ///< web downloads
 		TSK_RECENT_OBJECT(6, "TSK_RECENT_OBJ", "Recent Documents"), ///< recent objects 
 		TSK_TRACKPOINT(7, "TSK_TRACKPOINT", "Trackpoints"), ///< trackpoint (geo location data)
 		TSK_INSTALLED_PROG(8, "TSK_INSTALLED_PROG", "Installed Programs"), ///< installed programs
@@ -56,14 +56,20 @@ public enum ARTIFACT_TYPE implements SleuthkitVisitableItem {
 		TSK_INTERESTING_FILE_HIT(12, "TSK_INTERESTING_FILE_HIT", "Interesting Files"), ///< an interesting/notable file hit
 		TSK_EMAIL_MSG(13, "TSK_EMAIL_MSG", "E-Mail Messages"), ///< email message
 		TSK_EXTRACTED_TEXT(14, "TSK_EXTRACTED_TEXT", "Extracted Text"), ///< text extracted from file
-		TSK_WEB_SEARCH_QUERY(15, "TSK_WEB_SEARCH_QUERY", "Web Search Engine Queries"), ///< web search engine query extracted from web history
+		TSK_WEB_SEARCH_QUERY(15, "TSK_WEB_SEARCH_QUERY", "Web Search"), ///< web search engine query extracted from web history
 		TSK_METADATA_EXIF(16, "TSK_METADATA_EXIF", "EXIF Metadata"), ///< EXIF Metadata
 		TSK_TAG_FILE(17, "TSK_TAG_FILE", "File Tags"), ///< tagged files
 		TSK_TAG_ARTIFACT(18, "TSK_TAG_ARTIFACT", "Result Tags"), ///< tagged results/artifacts
 		TSK_OS_INFO(19, "TSK_OS_INFO", "Operating System Information"), ///< Information pertaining to an operating system.
 		TSK_OS_ACCOUNT(20, "TSK_OS_ACCOUNT", "Operating System User Account"), ///< An operating system user account.
 		TSK_SERVICE_ACCOUNT(21, "TSK_SERVICE_ACCOUNT", "Network Service User Account"), ///< A network service user account.
-        ; 
+        TSK_TOOL_OUTPUT(22, "TSK_TOOL_OUTPUT", "Raw Tool Output"), ///< Output from an external tool or module that (raw text)
+		TSK_CONTACT(23, "TSK_CONTACT", "Contacts"), ///< A Contact extracted from a phone, or from an Addressbook/Email/Messaging Application
+		TSK_MESSAGE(24, "TSK_MESSAGE", "Messages"), ///< An SMS/MMS message extracted from phone, or from another messaging application, like IM
+		TSK_CALLLOG(25, "TSK_CALLLOG", "Call Logs"), ///< A Phone call log extracted from a phones or softphone application
+		TSK_CALENDAR_ENTRY(26, "TSK_CALENDAR_ENTRY", "Calendar Entries") ///< A Calendar entry from a phone, PIM or a Calendar application.
+		
+		; 
 		/* SEE ABOVE -- KEEP C++ CODE IN SYNC */
 		private String label;
 		private int typeID;
diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
index 8da3706764d9c516f44c95076736843c285a9c0d..2c4b07a5e131445dfb95a06dbd69bde19f4042e2 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
@@ -1,627 +1,641 @@
-/*
- * Sleuth Kit Data Model
- *
- * Copyright 2012 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.datamodel;
-
-/**
- * Represents an attribute as stored in the Blackboard. Attributes are a name
- * value pair. The name represents the type of data being stored. Attributes are
- * grouped together into an Artifact as represented by a BlackboardArtifact
- * object. This class is used to create attribute on the blackboard and is used
- * to represent attribute queried from the blackboard.
- */
-public class BlackboardAttribute {
-
-	private long artifactID;
-	private int attributeTypeID;
-	private String moduleName;
-	private String context;
-	private TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType;
-	private int valueInt;
-	private long valueLong;
-	private double valueDouble;
-	private String valueString;
-	private byte[] valueBytes;
-	private SleuthkitCase Case;
-
-	/**
-	 * Enum for the data type (int, double, etc.) of this attribute's value.
-	 */
-	public enum TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE {
-
-		STRING(0, "String"), ///< string
-		INTEGER(1, "Integer"), ///< int
-		LONG(2, "Long"), ///< long
-		DOUBLE(3, "Double"), ///< double
-		BYTE(4, "Byte");	  ///< byte
-		private long type;
-		private String label;
-
-		private TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE(long type, String label) {
-			this.type = type;
-			this.label = label;
-		}
-
-		/**
-		 * Get the type id for this attribute type enum
-		 */
-		public long getType() {
-			return type;
-		}
-
-		/**
-		 * Get the label string for this attribute type enum
-		 */
-		public String getLabel() {
-			return this.label;
-		}
-
-		/**
-		 * Get the enum type for the given type id
-		 *
-		 * @param type type id
-		 * @return enum type
-		 */
-		static public TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE fromType(long type) {
-			for (TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE v : TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.values()) {
-				if (v.type == type) {
-					return v;
-				}
-			}
-			throw new IllegalArgumentException("No TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE matching type: " + type);
-		}
-	}
-
-	/**
-	 * Standard attribute types. Refer to the C++ code for the full description
-	 * of their intended use. See
-	 * http://wiki.sleuthkit.org/index.php?title=Artifact_Examples for more
-	 * information.
-	 */
-	public enum ATTRIBUTE_TYPE {
-		/* It is very important that this list be kept up to
-		 * date and in sync with the C++ code.  Do not add
-		 * anything here unless you also add it there.
-		 * See framework/Services/TskBlackboard.* */
-
-		TSK_URL(1, "TSK_URL", "URL"),
-		TSK_DATETIME(2, "TSK_DATETIME", "Date/Time"),
-		TSK_NAME(3, "TSK_NAME", "Name"),
-		TSK_PROG_NAME(4, "TSK_PROG_NAME", "Program Name"),
-		TSK_VALUE(6, "TSK_VALUE", "Value"),
-		TSK_FLAG(7, "TSK_FLAG", "Flag"),
-		TSK_PATH(8, "TSK_PATH", "Path"),
-		TSK_KEYWORD(10, "TSK_KEYWORD", "Keyword"),
-		TSK_KEYWORD_REGEXP(11, "TSK_KEYWORD_REGEXP", "Keyword Regular Expression"),
-		TSK_KEYWORD_PREVIEW(12, "TSK_KEYWORD_PREVIEW", "Keyword Preview"),
-		TSK_KEYWORD_SET(13, "TSK_KEYWORD_SET", "Keyword Set"), // @@@ Deprecated
-		TSK_USER_NAME(14, "TSK_USER_NAME", "Username"),
-		TSK_DOMAIN(15, "TSK_DOMAIN", "Domain"),
-		TSK_PASSWORD(16, "TSK_PASSWORD", "Password"),
-		TSK_NAME_PERSON(17, "TSK_NAME_PERSON", "Person Name"),
-		TSK_DEVICE_MODEL(18, "TSK_DEVICE_MODEL", "Device Model"),
-		TSK_DEVICE_MAKE(19, "TSK_DEVICE_MAKE", "Device Make"),
-		TSK_DEVICE_ID(20, "TSK_DEVICE_ID", "Device ID"),
-		TSK_EMAIL(21, "TSK_EMAIL", "Email"),
-		TSK_HASH_MD5(22, "TSK_HASH_MD5", "MD5 Hash"),
-		TSK_HASH_SHA1(23, "TSK_HASH_SHA1", "SHA1 Hash"),
-		TSK_HASH_SHA2_256(24, "TSK_HASH_SHA2_256", "SHA2-256 Hash"),
-		TSK_HASH_SHA2_512(25, "TSK_HASH_SHA2_512", "SHA2-512 Hash"),
-		TSK_TEXT(26, "TSK_TEXT", "Text"),
-		TSK_TEXT_FILE(27, "TSK_TEXT_FILE", "Text File"),
-		TSK_TEXT_LANGUAGE(28, "TSK_TEXT_LANGUAGE", "Text Language"),
-		TSK_ENTROPY(29, "TSK_ENTROPY", "Entropy"),
-		TSK_HASHSET_NAME(30, "TSK_HASHSET_NAME", "Hashset Name"), // @@@ Deprecated
-		TSK_INTERESTING_FILE(31, "TSK_INTERESTING_FILE", "Interesting File"),
-		TSK_REFERRER(32, "TSK_REFERRER", "Referrer URL"),
-		TSK_DATETIME_ACCESSED(33, "TSK_DATETIME_ACCESSED", "Date Accessed"),
-		TSK_IP_ADDRESS(34, "TSK_IP_ADDRESS", "IP Address"),
-		TSK_PHONE_NUMBER(35, "TSK_PHONE_NUMBER", "Phone Number"),
-		TSK_PATH_ID(36, "TSK_PATH_ID", "Path ID"),
-		TSK_SET_NAME(37, "TSK_SET_NAME", "Set Name"),
-		TSK_ENCRYPTION_DETECTED(38, "TSK_ENCRYPTION_DETECTED", "Encryption Detected"),
-		TSK_MALWARE_DETECTED(39, "TSK_MALWARE_DETECTED", "Malware Detected"),
-		TSK_STEG_DETECTED(40, "TSK_STEG_DETECTED", "Steganography Detected"),
-		TSK_EMAIL_TO(41, "TSK_EMAIL_TO", "E-Mail To"),
-		TSK_EMAIL_CC(42, "TSK_EMAIL_CC", "E-Mail CC"),
-		TSK_EMAIL_BCC(43, "TSK_EMAIL_BCC", "E-Mail BCC"),
-		TSK_EMAIL_FROM(44, "TSK_EMAIL_FROM", "E-Mail From"),
-		TSK_EMAIL_CONTENT_PLAIN(45, "TSK_EMAIL_CONTENT_PLAIN", "Message (Plaintext)"),
-		TSK_EMAIL_CONTENT_HTML(46, "TSK_EMAIL_CONTENT_HTML", "Message (HTML)"),
-		TSK_EMAIL_CONTENT_RTF(47, "TSK_EMAIL_CONTENT_RTF", "Message (RTF)"),
-		TSK_MSG_ID(48, "TSK_MSG_ID", "Message ID"),
-		TSK_MSG_REPLY_ID(49, "TSK_MSG_REPLY_ID", "Message Reply ID"),
-		TSK_DATETIME_RCVD(50, "TSK_DATETIME_RCVD", "Date Received"),
-		TSK_DATETIME_SENT(51, "TSK_DATETIME_SENT", "Date Sent"),
-		TSK_SUBJECT(52, "TSK_SUBJECT", "Subject"),
-		TSK_TITLE(53, "TSK_TITLE", "Title"),
-		TSK_GEO_LATITUDE(54, "TSK_GEO_LATITUDE", "Latitude"),
-		TSK_GEO_LONGITUDE(55, "TSK_GEO_LONGITUDE", "Longitude"),
-		TSK_GEO_VELOCITY(56, "TSK_GEO_VELOCITY", "Velocity"),
-		TSK_GEO_ALTITUDE(57, "TSK_GEO_ALTITUDE", "Altitude"),
-		TSK_GEO_BEARING(58, "TSK_GEO_BEARING", "Bearing"),
-		TSK_GEO_HPRECISION(59, "TSK_GEO_HPRECISION", "Horizontal Precision"),
-		TSK_GEO_VPRECISION(60, "TSK_GEO_VPRECISION", "Vertical Precision"),
-		TSK_GEO_MAPDATUM(61, "TSK_GEO_MAPDATUM", "Map Datum"),
-		TSK_FILE_TYPE_SIG(62, "TSK_FILE_TYPE_SIG", "File Type (signature)"),
-		TSK_FILE_TYPE_EXT(63, "TSK_FILE_TYPE_EXT", "File Type (extension)"),
-		TSK_TAGGED_ARTIFACT(64, "TSK_TAGGED_ARTIFACT", "Tagged Result"),
-		TSK_TAG_NAME(65, "TSK_TAG_NAME", "Tag Name"),
-		TSK_COMMENT(66, "TSK_COMMENT", "Comment"),
-		TSK_URL_DECODED(67, "TSK_URL_DECODED", "Decoded URL"),
-		TSK_DATETIME_CREATED(68, "TSK_DATETIME_CREATED", "Date Created"),
-		TSK_DATETIME_MODIFIED(69, "TSK_DATETIME_MODIFIED", "Date Modified"),
-		TSK_PROCESSOR_ARCHITECTURE(70, "TSK_PROCESSOR_ARCHITECTURE", "Processor Architecture"),
-		TSK_VERSION(71, "TSK_VERSION", "Version"),
-		TSK_USER_ID(72, "TSK_USER_ID", "User ID"),
-		;
-		/* SEE ABOVE -- ALSO ADD TO C++ CODE */
-		private String label;
-		private int typeID;
-		private String displayName;
-
-		private ATTRIBUTE_TYPE(int typeID, String label, String displayName) {
-			this.typeID = typeID;
-			this.label = label;
-			this.displayName = displayName;
-		}
-
-		/**
-		 * Get label string of this attribute
-		 *
-		 * @return label string
-		 */
-		public String getLabel() {
-			return this.label;
-		}
-
-		/**
-		 * Get type id of this attribute
-		 *
-		 * @return type id
-		 */
-		public int getTypeID() {
-			return this.typeID;
-		}
-
-		/**
-		 * Get the attribute enum for the given label
-		 *
-		 * @param label label string
-		 * @return the enum value
-		 */
-		static public ATTRIBUTE_TYPE fromLabel(String label) {
-			for (ATTRIBUTE_TYPE v : ATTRIBUTE_TYPE.values()) {
-				if (v.label.equals(label)) {
-					return v;
-				}
-			}
-			throw new IllegalArgumentException("No ATTRIBUTE_TYPE matching type: " + label);
-		}
-
-		public String getDisplayName() {
-			return this.displayName;
-		}
-	}
-
-	/**
-	 * Constructor for a blackboard attribute. 
-	 * 
-	 * Should only be used by SleuthkitCase
-	 *
-	 * @param artifactID artifact id for this attribute
-	 * @param attributeTypeID type id
-	 * @param moduleName module that created this attribute
-	 * @param context extra information about this name value pair
-	 * @param valueType type of value to be stored
-	 * @param valueInt value if it is an int
-	 * @param valueLong value if it is a long
-	 * @param valueDouble value if it is a double
-	 * @param valueString value if it is a string
-	 * @param valueBytes value if it is a byte array
-	 * @param Case the case that can be used to make calls into the blackboard
-	 * db
-	 */
-	protected BlackboardAttribute(long artifactID, int attributeTypeID, String moduleName, String context,
-			TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, int valueInt, long valueLong, double valueDouble,
-			String valueString, byte[] valueBytes, SleuthkitCase Case) {
-
-		this.artifactID = artifactID;
-		this.attributeTypeID = attributeTypeID;
-		this.moduleName = moduleName;
-		this.context = context;
-		this.valueType = valueType;
-		this.valueInt = valueInt;
-		this.valueLong = valueLong;
-		this.valueDouble = valueDouble;
-		if (valueString == null) {
-			this.valueString = "";
-		} else {
-			this.valueString = valueString;
-		}
-		if (valueBytes == null) {
-			this.valueBytes = new byte[0];
-		} else {
-			this.valueBytes = valueBytes;
-		}
-		this.Case = Case;
-	}
-
-	/**
-	 * Create a blackboard attribute that stores an int (creates an attribute
-	 * that can be added to an artifact)
-	 *
-	 * @param attributeTypeID type of the attribute
-	 * @param moduleName name of the module that is creating the attribute
-	 * @param valueInt the value
-	 */
-	public BlackboardAttribute(int attributeTypeID, String moduleName, int valueInt) {
-		this.artifactID = 0;
-		this.attributeTypeID = attributeTypeID;
-		this.moduleName = moduleName;
-		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.INTEGER;
-		this.valueInt = valueInt;
-		this.valueLong = 0;
-		this.valueDouble = 0;
-		this.valueString = "";
-		this.valueBytes = new byte[0];
-		this.context = "";
-	}
-
-	/**
-	 * Create a blackboard attribute that stores an int (creates an attribute
-	 * that can be added to an artifact)
-	 *
-	 * @param attributeTypeID type of the attribute
-	 * @param moduleName name of the module that is creating the attribute
-	 * @param context extra information about the attribute
-	 * @param valueInt the value
-	 * @deprecated context parameter will be deprecated - in lieu of specific
-	 * blackboard attributes use the alternative constructor without context
-	 */
-	@Deprecated
-	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
-			int valueInt) {
-		this(attributeTypeID, moduleName, valueInt);
-		this.context = context;
-	}
-
-	/**
-	 * Create a blackboard attribute that stores a long (creates an attribute
-	 * that can be added to an artifact)
-	 *
-	 * @param attributeTypeID type of the attribute
-	 * @param moduleName name of the module that is creating the attribute
-	 * @param valueLong the value
-	 */
-	public BlackboardAttribute(int attributeTypeID, String moduleName,
-			long valueLong) {
-		this.artifactID = 0;
-		this.attributeTypeID = attributeTypeID;
-		this.moduleName = moduleName;
-		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG;
-		this.valueInt = 0;
-		this.valueLong = valueLong;
-		this.valueDouble = 0;
-		this.valueString = "";
-		this.valueBytes = new byte[0];
-		this.context = "";
-
-	}
-
-	/**
-	 * Create a blackboard attribute that stores a long (creates an attribute
-	 * that can be added to an artifact)
-	 *
-	 * @param attributeTypeID type of the attribute
-	 * @param moduleName name of the module that is creating the attribute
-	 * @param context extra information about the attribute
-	 * @param valueLong the value
-	 * @deprecated context parameter will be deprecated - in lieu of specific
-	 * blackboard attributes use the alternative constructor without context
-	 */
-	@Deprecated
-	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
-			long valueLong) {
-		this(attributeTypeID, moduleName, valueLong);
-		this.context = context;
-	}
-
-	/**
-	 * Create a blackboard attribute that stores a double (creates an attribute
-	 * that can be added to an artifact)
-	 *
-	 * @param attributeTypeID type of the attribute
-	 * @param moduleName name of the module that is creating the attribute
-	 * @param valueDouble the value
-	 */
-	public BlackboardAttribute(int attributeTypeID, String moduleName,
-			double valueDouble) {
-		this.artifactID = 0;
-		this.attributeTypeID = attributeTypeID;
-		this.moduleName = moduleName;
-		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE;
-		this.valueInt = 0;
-		this.valueLong = 0;
-		this.valueDouble = valueDouble;
-		this.valueString = "";
-		this.valueBytes = new byte[0];
-		this.context = "";
-	}
-
-	/**
-	 * Create a blackboard attribute that stores a double (creates an attribute
-	 * that can be added to an artifact)
-	 *
-	 * @param attributeTypeID type of the attribute
-	 * @param moduleName name of the module that is creating the attribute
-	 * @param context extra information about the attribute
-	 * @param valueDouble the value
-	 * @deprecated context parameter will be deprecated - in lieu of specific
-	 * blackboard attributes use the alternative constructor without context
-	 */
-	@Deprecated
-	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
-			double valueDouble) {
-		this(attributeTypeID, moduleName, valueDouble);
-		this.context = context;
-	}
-
-	/**
-	 * Create a blackboard attribute that stores a string (creates an attribute
-	 * that can be added to an artifact)
-	 *
-	 * @param attributeTypeID type of the attribute
-	 * @param moduleName name of the module that is creating the attribute
-	 * @param valueString the value
-	 */
-	public BlackboardAttribute(int attributeTypeID, String moduleName, String valueString) {
-		this.artifactID = 0;
-		this.attributeTypeID = attributeTypeID;
-		this.moduleName = moduleName;
-		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING;
-		this.valueInt = 0;
-		this.valueLong = 0;
-		this.valueDouble = 0;
-		if (valueString == null) {
-			this.valueString = "";
-		} else {
-			this.valueString = valueString;
-		}
-		this.valueBytes = new byte[0];
-		this.context = "";
-	}
-
-	/**
-	 * Create a blackboard attribute that stores a string (creates an attribute
-	 * that can be added to an artifact)
-	 *
-	 * @param attributeTypeID type of the attribute
-	 * @param moduleName name of the module that is creating the attribute
-	 * @param context extra information about the attribute
-	 * @param valueString the value
-	 * @deprecated context parameter will be deprecated - in lieu of specific
-	 * blackboard attributes use the alternative constructor without context
-	 */
-	@Deprecated
-	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
-			String valueString) {
-		this(attributeTypeID, moduleName, valueString);
-		this.context = context;
-	}
-
-	/**
-	 * Create a blackboard attribute that stores a byte array (creates an
-	 * attribute that can be added to an artifact)
-	 *
-	 * @param attributeTypeID type of the attribute
-	 * @param moduleName name of the module that is creating the attribute
-	 * @param context extra information about the attribute
-	 * @param valueBytes the value
-	 */
-	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
-			byte[] valueBytes) {
-		this.artifactID = 0;
-		this.attributeTypeID = attributeTypeID;
-		this.moduleName = moduleName;
-		this.context = context;
-		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE;
-		this.valueInt = 0;
-		this.valueLong = 0;
-		this.valueDouble = 0;
-		this.valueString = "";
-		if (valueBytes == null) {
-			this.valueBytes = new byte[0];
-		} else {
-			this.valueBytes = valueBytes;
-		}
-
-	}
-
-	@Override
-	public int hashCode() {
-		int hash = 5;
-		hash = 97 * hash + (int) (this.artifactID ^ (this.artifactID >>> 32));
-		return hash;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (obj == null) {
-			return false;
-		}
-		if (getClass() != obj.getClass()) {
-			return false;
-		}
-		final BlackboardAttribute other = (BlackboardAttribute) obj;
-		if (this.artifactID != other.artifactID) {
-			return false;
-		}
-		return true;
-	}
-
-	@Override
-	public String toString() {
-		return "BlackboardAttribute{" + "artifactID=" + artifactID + ", attributeTypeID=" + attributeTypeID + ", moduleName=" + moduleName + ", context=" + context + ", valueType=" + valueType + ", valueInt=" + valueInt + ", valueLong=" + valueLong + ", valueDouble=" + valueDouble + ", valueString=" + valueString + ", valueBytes=" + valueBytes + ", Case=" + Case + '}';
-	}
-
-	/**
-	 * Get the artifact id
-	 *
-	 * @return artifact id
-	 */
-	public long getArtifactID() {
-		return artifactID;
-	}
-
-	/**
-	 * Get the attribute type id
-	 *
-	 * @return type id
-	 */
-	public int getAttributeTypeID() {
-		return attributeTypeID;
-	}
-
-	/**
-	 * Get the attribute type name string
-	 *
-	 * @return type name string
-	 */
-	public String getAttributeTypeName() throws TskCoreException {
-		return Case.getAttrTypeString(attributeTypeID);
-	}
-
-	/**
-	 * Get the attribute type display name
-	 *
-	 * @return type display name
-	 */
-	public String getAttributeTypeDisplayName() throws TskCoreException {
-		return Case.getAttrTypeDisplayName(attributeTypeID);
-	}
-
-	/**
-	 * Get the value type.
-	 * 
-	 * This should be used to identify the type of value and
-	 * call the right value get method.
-	 *
-	 * @return value type
-	 */
-	public TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE getValueType() {
-		return valueType;
-	}
-
-	/**
-	 * Get the value if it is an int
-	 *
-	 * @return value
-	 */
-	public int getValueInt() {
-		return valueInt;
-	}
-
-	/**
-	 * Get value if it is a long
-	 *
-	 * @return value
-	 */
-	public long getValueLong() {
-		return valueLong;
-	}
-
-	/**
-	 * Get value if it is a double
-	 *
-	 * @return value
-	 */
-	public double getValueDouble() {
-		return valueDouble;
-	}
-
-	/**
-	 * Get value if it is a string
-	 *
-	 * @return value
-	 */
-	public String getValueString() {
-		return valueString;
-	}
-
-	/**
-	 * Get value if it is a byte array
-	 *
-	 * @return value
-	 */
-	public byte[] getValueBytes() {
-		return valueBytes;
-	}
-
-	/**
-	 * Get module name of the module that created the attribute
-	 *
-	 * @return name
-	 */
-	public String getModuleName() {
-		return moduleName;
-	}
-
-	/**
-	 * Get context of the data stored in the attribute, if set
-	 *
-	 * @return context
-	 */
-	public String getContext() {
-		return context;
-	}
-
-	/**
-	 * Get the artifact that this attribute is associated with.
-	 * 
-	 * The artifact can
-	 * be used to find the associated file and other attributes associated with
-	 * this artifact.
-	 *
-	 * @return artifact
-	 * @throws TskException exception thrown when critical error occurred within
-	 * tsk core
-	 */
-	public BlackboardArtifact getParentArtifact() throws TskCoreException {
-		return Case.getBlackboardArtifact(artifactID);
-	}
-
-	/**
-	 * Set the artifactID, this should only be used by sleuthkitCase
-	 *
-	 * @param artifactID artifactID to set on a newly created attribute
-	 */
-	protected void setArtifactID(long artifactID) {
-		this.artifactID = artifactID;
-	}
-
-	/**
-	 * Set the SleuthkitCase handle, this should only be used by SleuthkitCase
-	 * on a newly created attribute
-	 *
-	 * @param Case case handle to associated with this attribute
-	 */
-	protected void setCase(SleuthkitCase Case) {
-		this.Case = Case;
-	}
-}
+/*
+ * Sleuth Kit Data Model
+ *
+ * Copyright 2012 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.datamodel;
+
+/**
+ * Represents an attribute as stored in the Blackboard. Attributes are a name
+ * value pair. The name represents the type of data being stored. Attributes are
+ * grouped together into an Artifact as represented by a BlackboardArtifact
+ * object. This class is used to create attribute on the blackboard and is used
+ * to represent attribute queried from the blackboard.
+ */
+public class BlackboardAttribute {
+
+	private long artifactID;
+	private int attributeTypeID;
+	private String moduleName;
+	private String context;
+	private TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType;
+	private int valueInt;
+	private long valueLong;
+	private double valueDouble;
+	private String valueString;
+	private byte[] valueBytes;
+	private SleuthkitCase Case;
+
+	/**
+	 * Enum for the data type (int, double, etc.) of this attribute's value.
+	 */
+	public enum TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE {
+
+		STRING(0, "String"), ///< string
+		INTEGER(1, "Integer"), ///< int
+		LONG(2, "Long"), ///< long
+		DOUBLE(3, "Double"), ///< double
+		BYTE(4, "Byte");	  ///< byte
+		private long type;
+		private String label;
+
+		private TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE(long type, String label) {
+			this.type = type;
+			this.label = label;
+		}
+
+		/**
+		 * Get the type id for this attribute type enum
+		 */
+		public long getType() {
+			return type;
+		}
+
+		/**
+		 * Get the label string for this attribute type enum
+		 */
+		public String getLabel() {
+			return this.label;
+		}
+
+		/**
+		 * Get the enum type for the given type id
+		 *
+		 * @param type type id
+		 * @return enum type
+		 */
+		static public TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE fromType(long type) {
+			for (TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE v : TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.values()) {
+				if (v.type == type) {
+					return v;
+				}
+			}
+			throw new IllegalArgumentException("No TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE matching type: " + type);
+		}
+	}
+
+	/**
+	 * Standard attribute types. Refer to the C++ code for the full description
+	 * of their intended use. See
+	 * http://wiki.sleuthkit.org/index.php?title=Artifact_Examples for more
+	 * information.
+	 */
+	public enum ATTRIBUTE_TYPE {
+		/* It is very important that this list be kept up to
+		 * date and in sync with the C++ code.  Do not add
+		 * anything here unless you also add it there.
+		 * See framework/Services/TskBlackboard.* */
+
+		TSK_URL(1, "TSK_URL", "URL"),
+		TSK_DATETIME(2, "TSK_DATETIME", "Date/Time"),
+		TSK_NAME(3, "TSK_NAME", "Name"),
+		TSK_PROG_NAME(4, "TSK_PROG_NAME", "Program Name"),
+		TSK_VALUE(6, "TSK_VALUE", "Value"),
+		TSK_FLAG(7, "TSK_FLAG", "Flag"),
+		TSK_PATH(8, "TSK_PATH", "Path"),
+		TSK_KEYWORD(10, "TSK_KEYWORD", "Keyword"),
+		TSK_KEYWORD_REGEXP(11, "TSK_KEYWORD_REGEXP", "Keyword Regular Expression"),
+		TSK_KEYWORD_PREVIEW(12, "TSK_KEYWORD_PREVIEW", "Keyword Preview"),
+		TSK_KEYWORD_SET(13, "TSK_KEYWORD_SET", "Keyword Set"), // @@@ Deprecated
+		TSK_USER_NAME(14, "TSK_USER_NAME", "Username"),
+		TSK_DOMAIN(15, "TSK_DOMAIN", "Domain"),
+		TSK_PASSWORD(16, "TSK_PASSWORD", "Password"),
+		TSK_NAME_PERSON(17, "TSK_NAME_PERSON", "Person Name"),
+		TSK_DEVICE_MODEL(18, "TSK_DEVICE_MODEL", "Device Model"),
+		TSK_DEVICE_MAKE(19, "TSK_DEVICE_MAKE", "Device Make"),
+		TSK_DEVICE_ID(20, "TSK_DEVICE_ID", "Device ID"),
+		TSK_EMAIL(21, "TSK_EMAIL", "Email"),
+		TSK_HASH_MD5(22, "TSK_HASH_MD5", "MD5 Hash"),
+		TSK_HASH_SHA1(23, "TSK_HASH_SHA1", "SHA1 Hash"),
+		TSK_HASH_SHA2_256(24, "TSK_HASH_SHA2_256", "SHA2-256 Hash"),
+		TSK_HASH_SHA2_512(25, "TSK_HASH_SHA2_512", "SHA2-512 Hash"),
+		TSK_TEXT(26, "TSK_TEXT", "Text"),
+		TSK_TEXT_FILE(27, "TSK_TEXT_FILE", "Text File"),
+		TSK_TEXT_LANGUAGE(28, "TSK_TEXT_LANGUAGE", "Text Language"),
+		TSK_ENTROPY(29, "TSK_ENTROPY", "Entropy"),
+		TSK_HASHSET_NAME(30, "TSK_HASHSET_NAME", "Hashset Name"), // @@@ Deprecated
+		TSK_INTERESTING_FILE(31, "TSK_INTERESTING_FILE", "Interesting File"),
+		TSK_REFERRER(32, "TSK_REFERRER", "Referrer URL"),
+		TSK_DATETIME_ACCESSED(33, "TSK_DATETIME_ACCESSED", "Date Accessed"),
+		TSK_IP_ADDRESS(34, "TSK_IP_ADDRESS", "IP Address"),
+		TSK_PHONE_NUMBER(35, "TSK_PHONE_NUMBER", "Phone Number"),
+		TSK_PATH_ID(36, "TSK_PATH_ID", "Path ID"),
+		TSK_SET_NAME(37, "TSK_SET_NAME", "Set Name"),
+		TSK_ENCRYPTION_DETECTED(38, "TSK_ENCRYPTION_DETECTED", "Encryption Detected"),
+		TSK_MALWARE_DETECTED(39, "TSK_MALWARE_DETECTED", "Malware Detected"),
+		TSK_STEG_DETECTED(40, "TSK_STEG_DETECTED", "Steganography Detected"),
+		TSK_EMAIL_TO(41, "TSK_EMAIL_TO", "E-Mail To"),
+		TSK_EMAIL_CC(42, "TSK_EMAIL_CC", "E-Mail CC"),
+		TSK_EMAIL_BCC(43, "TSK_EMAIL_BCC", "E-Mail BCC"),
+		TSK_EMAIL_FROM(44, "TSK_EMAIL_FROM", "E-Mail From"),
+		TSK_EMAIL_CONTENT_PLAIN(45, "TSK_EMAIL_CONTENT_PLAIN", "Message (Plaintext)"),
+		TSK_EMAIL_CONTENT_HTML(46, "TSK_EMAIL_CONTENT_HTML", "Message (HTML)"),
+		TSK_EMAIL_CONTENT_RTF(47, "TSK_EMAIL_CONTENT_RTF", "Message (RTF)"),
+		TSK_MSG_ID(48, "TSK_MSG_ID", "Message ID"),
+		TSK_MSG_REPLY_ID(49, "TSK_MSG_REPLY_ID", "Message Reply ID"),
+		TSK_DATETIME_RCVD(50, "TSK_DATETIME_RCVD", "Date Received"),
+		TSK_DATETIME_SENT(51, "TSK_DATETIME_SENT", "Date Sent"),
+		TSK_SUBJECT(52, "TSK_SUBJECT", "Subject"),
+		TSK_TITLE(53, "TSK_TITLE", "Title"),
+		TSK_GEO_LATITUDE(54, "TSK_GEO_LATITUDE", "Latitude"),
+		TSK_GEO_LONGITUDE(55, "TSK_GEO_LONGITUDE", "Longitude"),
+		TSK_GEO_VELOCITY(56, "TSK_GEO_VELOCITY", "Velocity"),
+		TSK_GEO_ALTITUDE(57, "TSK_GEO_ALTITUDE", "Altitude"),
+		TSK_GEO_BEARING(58, "TSK_GEO_BEARING", "Bearing"),
+		TSK_GEO_HPRECISION(59, "TSK_GEO_HPRECISION", "Horizontal Precision"),
+		TSK_GEO_VPRECISION(60, "TSK_GEO_VPRECISION", "Vertical Precision"),
+		TSK_GEO_MAPDATUM(61, "TSK_GEO_MAPDATUM", "Map Datum"),
+		TSK_FILE_TYPE_SIG(62, "TSK_FILE_TYPE_SIG", "File Type (signature)"),
+		TSK_FILE_TYPE_EXT(63, "TSK_FILE_TYPE_EXT", "File Type (extension)"),
+		TSK_TAGGED_ARTIFACT(64, "TSK_TAGGED_ARTIFACT", "Tagged Result"),
+		TSK_TAG_NAME(65, "TSK_TAG_NAME", "Tag Name"),
+		TSK_COMMENT(66, "TSK_COMMENT", "Comment"),
+		TSK_URL_DECODED(67, "TSK_URL_DECODED", "Decoded URL"),
+		TSK_DATETIME_CREATED(68, "TSK_DATETIME_CREATED", "Date Created"),
+		TSK_DATETIME_MODIFIED(69, "TSK_DATETIME_MODIFIED", "Date Modified"),
+		TSK_PROCESSOR_ARCHITECTURE(70, "TSK_PROCESSOR_ARCHITECTURE", "Processor Architecture"),
+		TSK_VERSION(71, "TSK_VERSION", "Version"),
+		TSK_USER_ID(72, "TSK_USER_ID", "User ID"),
+		TSK_DESCRIPTION(73, "TSK_DESCRIPTION", "Description"),
+		TSK_MESSAGE_TYPE(74, "TSK_MESSAGE_TYPE", "Message Type"),	// SMS or MMS or IM ...
+		TSK_PHONE_NUMBER_HOME(75, "TSK_PHONE_NUMBER_HOME", "Phone Number (Home)"),
+		TSK_PHONE_NUMBER_OFFICE(76, "TSK_PHONE_NUMBER_OFFICE", "Phone Number (Office)"),
+		TSK_PHONE_NUMBER_MOBILE(77, "TSK_PHONE_NUMBER_MOBILE", "Phone Number (Mobile)"),
+		TSK_PHONE_NUMBER_FROM(78, "TSK_PHONE_NUMBER_FROM", "From Phone Number"),
+		TSK_PHONE_NUMBER_TO(79, "TSK_PHONE_NUMBER_TO", "To Phone Number"),
+		TSK_DIRECTION(80, "TSK_DIRECTION", "Direction"), // Msg/Call direction: incoming, outgoing
+		TSK_EMAIL_HOME(81, "TSK_EMAIL_HOME", "Email (Home)"),
+		TSK_EMAIL_OFFICE(82, "TSK_EMAIL_OFFICE", "Email (Office)"),
+		TSK_DATETIME_START(83, "TSK_DATETIME_START", "Start Date/Time"),	// start time of an event - call log, Calendar entry
+		TSK_DATETIME_END(84, "TSK_DATETIME_END", "End Date/Time"),	// end time of an event - call log, Calendar entry
+		TSK_CALENDAR_ENTRY_TYPE(85, "TSK_CALENDAR_ENTRY_TYPE", "Calendar Entry Type"),	// meeting, task, 
+		TSK_LOCATION(86, "TSK_LOCATION", "Location"),	// Location string associated with an event - Conf Room Name, Address ....
+		;
+		/* SEE ABOVE -- ALSO ADD TO C++ CODE */
+		private String label;
+		private int typeID;
+		private String displayName;
+
+		private ATTRIBUTE_TYPE(int typeID, String label, String displayName) {
+			this.typeID = typeID;
+			this.label = label;
+			this.displayName = displayName;
+		}
+
+		/**
+		 * Get label string of this attribute
+		 *
+		 * @return label string
+		 */
+		public String getLabel() {
+			return this.label;
+		}
+
+		/**
+		 * Get type id of this attribute
+		 *
+		 * @return type id
+		 */
+		public int getTypeID() {
+			return this.typeID;
+		}
+
+		/**
+		 * Get the attribute enum for the given label
+		 *
+		 * @param label label string
+		 * @return the enum value
+		 */
+		static public ATTRIBUTE_TYPE fromLabel(String label) {
+			for (ATTRIBUTE_TYPE v : ATTRIBUTE_TYPE.values()) {
+				if (v.label.equals(label)) {
+					return v;
+				}
+			}
+			throw new IllegalArgumentException("No ATTRIBUTE_TYPE matching type: " + label);
+		}
+
+		public String getDisplayName() {
+			return this.displayName;
+		}
+	}
+
+	/**
+	 * Constructor for a blackboard attribute. 
+	 * 
+	 * Should only be used by SleuthkitCase
+	 *
+	 * @param artifactID artifact id for this attribute
+	 * @param attributeTypeID type id
+	 * @param moduleName module that created this attribute
+	 * @param context extra information about this name value pair
+	 * @param valueType type of value to be stored
+	 * @param valueInt value if it is an int
+	 * @param valueLong value if it is a long
+	 * @param valueDouble value if it is a double
+	 * @param valueString value if it is a string
+	 * @param valueBytes value if it is a byte array
+	 * @param Case the case that can be used to make calls into the blackboard
+	 * db
+	 */
+	protected BlackboardAttribute(long artifactID, int attributeTypeID, String moduleName, String context,
+			TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, int valueInt, long valueLong, double valueDouble,
+			String valueString, byte[] valueBytes, SleuthkitCase Case) {
+
+		this.artifactID = artifactID;
+		this.attributeTypeID = attributeTypeID;
+		this.moduleName = moduleName;
+		this.context = context;
+		this.valueType = valueType;
+		this.valueInt = valueInt;
+		this.valueLong = valueLong;
+		this.valueDouble = valueDouble;
+		if (valueString == null) {
+			this.valueString = "";
+		} else {
+			this.valueString = valueString;
+		}
+		if (valueBytes == null) {
+			this.valueBytes = new byte[0];
+		} else {
+			this.valueBytes = valueBytes;
+		}
+		this.Case = Case;
+	}
+
+	/**
+	 * Create a blackboard attribute that stores an int (creates an attribute
+	 * that can be added to an artifact)
+	 *
+	 * @param attributeTypeID type of the attribute
+	 * @param moduleName name of the module that is creating the attribute
+	 * @param valueInt the value
+	 */
+	public BlackboardAttribute(int attributeTypeID, String moduleName, int valueInt) {
+		this.artifactID = 0;
+		this.attributeTypeID = attributeTypeID;
+		this.moduleName = moduleName;
+		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.INTEGER;
+		this.valueInt = valueInt;
+		this.valueLong = 0;
+		this.valueDouble = 0;
+		this.valueString = "";
+		this.valueBytes = new byte[0];
+		this.context = "";
+	}
+
+	/**
+	 * Create a blackboard attribute that stores an int (creates an attribute
+	 * that can be added to an artifact)
+	 *
+	 * @param attributeTypeID type of the attribute
+	 * @param moduleName name of the module that is creating the attribute
+	 * @param context extra information about the attribute
+	 * @param valueInt the value
+	 * @deprecated context parameter will be deprecated - in lieu of specific
+	 * blackboard attributes use the alternative constructor without context
+	 */
+	@Deprecated
+	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
+			int valueInt) {
+		this(attributeTypeID, moduleName, valueInt);
+		this.context = context;
+	}
+
+	/**
+	 * Create a blackboard attribute that stores a long (creates an attribute
+	 * that can be added to an artifact)
+	 *
+	 * @param attributeTypeID type of the attribute
+	 * @param moduleName name of the module that is creating the attribute
+	 * @param valueLong the value
+	 */
+	public BlackboardAttribute(int attributeTypeID, String moduleName,
+			long valueLong) {
+		this.artifactID = 0;
+		this.attributeTypeID = attributeTypeID;
+		this.moduleName = moduleName;
+		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG;
+		this.valueInt = 0;
+		this.valueLong = valueLong;
+		this.valueDouble = 0;
+		this.valueString = "";
+		this.valueBytes = new byte[0];
+		this.context = "";
+
+	}
+
+	/**
+	 * Create a blackboard attribute that stores a long (creates an attribute
+	 * that can be added to an artifact)
+	 *
+	 * @param attributeTypeID type of the attribute
+	 * @param moduleName name of the module that is creating the attribute
+	 * @param context extra information about the attribute
+	 * @param valueLong the value
+	 * @deprecated context parameter will be deprecated - in lieu of specific
+	 * blackboard attributes use the alternative constructor without context
+	 */
+	@Deprecated
+	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
+			long valueLong) {
+		this(attributeTypeID, moduleName, valueLong);
+		this.context = context;
+	}
+
+	/**
+	 * Create a blackboard attribute that stores a double (creates an attribute
+	 * that can be added to an artifact)
+	 *
+	 * @param attributeTypeID type of the attribute
+	 * @param moduleName name of the module that is creating the attribute
+	 * @param valueDouble the value
+	 */
+	public BlackboardAttribute(int attributeTypeID, String moduleName,
+			double valueDouble) {
+		this.artifactID = 0;
+		this.attributeTypeID = attributeTypeID;
+		this.moduleName = moduleName;
+		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE;
+		this.valueInt = 0;
+		this.valueLong = 0;
+		this.valueDouble = valueDouble;
+		this.valueString = "";
+		this.valueBytes = new byte[0];
+		this.context = "";
+	}
+
+	/**
+	 * Create a blackboard attribute that stores a double (creates an attribute
+	 * that can be added to an artifact)
+	 *
+	 * @param attributeTypeID type of the attribute
+	 * @param moduleName name of the module that is creating the attribute
+	 * @param context extra information about the attribute
+	 * @param valueDouble the value
+	 * @deprecated context parameter will be deprecated - in lieu of specific
+	 * blackboard attributes use the alternative constructor without context
+	 */
+	@Deprecated
+	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
+			double valueDouble) {
+		this(attributeTypeID, moduleName, valueDouble);
+		this.context = context;
+	}
+
+	/**
+	 * Create a blackboard attribute that stores a string (creates an attribute
+	 * that can be added to an artifact)
+	 *
+	 * @param attributeTypeID type of the attribute
+	 * @param moduleName name of the module that is creating the attribute
+	 * @param valueString the value
+	 */
+	public BlackboardAttribute(int attributeTypeID, String moduleName, String valueString) {
+		this.artifactID = 0;
+		this.attributeTypeID = attributeTypeID;
+		this.moduleName = moduleName;
+		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING;
+		this.valueInt = 0;
+		this.valueLong = 0;
+		this.valueDouble = 0;
+		if (valueString == null) {
+			this.valueString = "";
+		} else {
+			this.valueString = valueString;
+		}
+		this.valueBytes = new byte[0];
+		this.context = "";
+	}
+
+	/**
+	 * Create a blackboard attribute that stores a string (creates an attribute
+	 * that can be added to an artifact)
+	 *
+	 * @param attributeTypeID type of the attribute
+	 * @param moduleName name of the module that is creating the attribute
+	 * @param context extra information about the attribute
+	 * @param valueString the value
+	 * @deprecated context parameter will be deprecated - in lieu of specific
+	 * blackboard attributes use the alternative constructor without context
+	 */
+	@Deprecated
+	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
+			String valueString) {
+		this(attributeTypeID, moduleName, valueString);
+		this.context = context;
+	}
+
+	/**
+	 * Create a blackboard attribute that stores a byte array (creates an
+	 * attribute that can be added to an artifact)
+	 *
+	 * @param attributeTypeID type of the attribute
+	 * @param moduleName name of the module that is creating the attribute
+	 * @param context extra information about the attribute
+	 * @param valueBytes the value
+	 */
+	public BlackboardAttribute(int attributeTypeID, String moduleName, String context,
+			byte[] valueBytes) {
+		this.artifactID = 0;
+		this.attributeTypeID = attributeTypeID;
+		this.moduleName = moduleName;
+		this.context = context;
+		this.valueType = TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE;
+		this.valueInt = 0;
+		this.valueLong = 0;
+		this.valueDouble = 0;
+		this.valueString = "";
+		if (valueBytes == null) {
+			this.valueBytes = new byte[0];
+		} else {
+			this.valueBytes = valueBytes;
+		}
+
+	}
+
+	@Override
+	public int hashCode() {
+		int hash = 5;
+		hash = 97 * hash + (int) (this.artifactID ^ (this.artifactID >>> 32));
+		return hash;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj == null) {
+			return false;
+		}
+		if (getClass() != obj.getClass()) {
+			return false;
+		}
+		final BlackboardAttribute other = (BlackboardAttribute) obj;
+		if (this.artifactID != other.artifactID) {
+			return false;
+		}
+		return true;
+	}
+
+	@Override
+	public String toString() {
+		return "BlackboardAttribute{" + "artifactID=" + artifactID + ", attributeTypeID=" + attributeTypeID + ", moduleName=" + moduleName + ", context=" + context + ", valueType=" + valueType + ", valueInt=" + valueInt + ", valueLong=" + valueLong + ", valueDouble=" + valueDouble + ", valueString=" + valueString + ", valueBytes=" + valueBytes + ", Case=" + Case + '}';
+	}
+
+	/**
+	 * Get the artifact id
+	 *
+	 * @return artifact id
+	 */
+	public long getArtifactID() {
+		return artifactID;
+	}
+
+	/**
+	 * Get the attribute type id
+	 *
+	 * @return type id
+	 */
+	public int getAttributeTypeID() {
+		return attributeTypeID;
+	}
+
+	/**
+	 * Get the attribute type name string
+	 *
+	 * @return type name string
+	 */
+	public String getAttributeTypeName() throws TskCoreException {
+		return Case.getAttrTypeString(attributeTypeID);
+	}
+
+	/**
+	 * Get the attribute type display name
+	 *
+	 * @return type display name
+	 */
+	public String getAttributeTypeDisplayName() throws TskCoreException {
+		return Case.getAttrTypeDisplayName(attributeTypeID);
+	}
+
+	/**
+	 * Get the value type.
+	 * 
+	 * This should be used to identify the type of value and
+	 * call the right value get method.
+	 *
+	 * @return value type
+	 */
+	public TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE getValueType() {
+		return valueType;
+	}
+
+	/**
+	 * Get the value if it is an int
+	 *
+	 * @return value
+	 */
+	public int getValueInt() {
+		return valueInt;
+	}
+
+	/**
+	 * Get value if it is a long
+	 *
+	 * @return value
+	 */
+	public long getValueLong() {
+		return valueLong;
+	}
+
+	/**
+	 * Get value if it is a double
+	 *
+	 * @return value
+	 */
+	public double getValueDouble() {
+		return valueDouble;
+	}
+
+	/**
+	 * Get value if it is a string
+	 *
+	 * @return value
+	 */
+	public String getValueString() {
+		return valueString;
+	}
+
+	/**
+	 * Get value if it is a byte array
+	 *
+	 * @return value
+	 */
+	public byte[] getValueBytes() {
+		return valueBytes;
+	}
+
+	/**
+	 * Get module name of the module that created the attribute
+	 *
+	 * @return name
+	 */
+	public String getModuleName() {
+		return moduleName;
+	}
+
+	/**
+	 * Get context of the data stored in the attribute, if set
+	 *
+	 * @return context
+	 */
+	public String getContext() {
+		return context;
+	}
+
+	/**
+	 * Get the artifact that this attribute is associated with.
+	 * 
+	 * The artifact can
+	 * be used to find the associated file and other attributes associated with
+	 * this artifact.
+	 *
+	 * @return artifact
+	 * @throws TskException exception thrown when critical error occurred within
+	 * tsk core
+	 */
+	public BlackboardArtifact getParentArtifact() throws TskCoreException {
+		return Case.getBlackboardArtifact(artifactID);
+	}
+
+	/**
+	 * Set the artifactID, this should only be used by sleuthkitCase
+	 *
+	 * @param artifactID artifactID to set on a newly created attribute
+	 */
+	protected void setArtifactID(long artifactID) {
+		this.artifactID = artifactID;
+	}
+
+	/**
+	 * Set the SleuthkitCase handle, this should only be used by SleuthkitCase
+	 * on a newly created attribute
+	 *
+	 * @param Case case handle to associated with this attribute
+	 */
+	protected void setCase(SleuthkitCase Case) {
+		this.Case = Case;
+	}
+}
diff --git a/bindings/java/src/org/sleuthkit/datamodel/FsContent.java b/bindings/java/src/org/sleuthkit/datamodel/FsContent.java
index ac171bf826e9afaa184f2bf3b5a06cf4fd518369..c229d979cdaee343ffd76874fde7de02328ac085 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/FsContent.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/FsContent.java
@@ -18,8 +18,6 @@
  */
 package org.sleuthkit.datamodel;
 
-import java.util.Collections;
-import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.sleuthkit.datamodel.TskData.FileKnown;
@@ -42,6 +40,8 @@ public abstract class FsContent extends AbstractFile {
 	protected final long fsObjId;
 	private String uniquePath;
 	///read-write database tsk_files fields
+	private final SleuthkitCase tskCase;
+	
 	/**
 	 * parent file system
 	 */
@@ -84,6 +84,7 @@ public abstract class FsContent extends AbstractFile {
 			long size, long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, FileKnown knownState,
 			String parentPath) {
 		super(db, objId, attrType, attrId, name, TskData.TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, knownState, parentPath);
+		this.tskCase = db;
 		this.fsObjId = fsObjId;
 	}
 
@@ -123,18 +124,26 @@ public FileSystem getFileSystem() throws TskCoreException {
 
 	@Override
 	protected int readInt(byte[] buf, long offset, long len) throws TskCoreException {
-		if (offset == 0 && size == 0) {
-			//special case for 0-size file
-			return 0;
-		}
-		if (fileHandle == 0) {
-			synchronized (this) {
-				if (fileHandle == 0) {
-					fileHandle = SleuthkitJNI.openFile(getFileSystem().getFileSystemHandle(), metaAddr, attrType, attrId);
+		try {
+			if (offset == 0 && size == 0) {
+				//special case for 0-size file
+				return 0;
+			}
+			if (fileHandle == 0) {
+				synchronized (this) {
+					if (fileHandle == 0) {
+						fileHandle = SleuthkitJNI.openFile(getFileSystem().getFileSystemHandle(), metaAddr, attrType, attrId);
+					}
 				}
 			}
+			return SleuthkitJNI.readFile(fileHandle, buf, offset, len);
+		}
+		catch (TskCoreException ex) {
+			if (!getImage().imageFileExists()) {
+				tskCase.submitError("Image File Read Error", "Image file is does not exist or is inaccessible.");
+			}
+			throw ex;
 		}
-		return SleuthkitJNI.readFile(fileHandle, buf, offset, len);
 	}
 
 	@Override
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Image.java b/bindings/java/src/org/sleuthkit/datamodel/Image.java
index 3c025b5e44e9a5a9fa89f432774546b957a6e0ea..83b66817b6a6c7c8b3d6fe94545dbc172128ca9f 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/Image.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/Image.java
@@ -23,6 +23,7 @@
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.io.File;
 
 /**
  * Represents a disk image file, stored in tsk_image_info. Populated based on
@@ -315,4 +316,13 @@ public List<Long> getChildrenIds() throws TskCoreException {
 	public String toString(boolean preserveState){
 		return super.toString(preserveState) + "Image [\t" + "\t" + "paths " + Arrays.toString(paths) + "\t" + "size " + size + "\t" + "ssize " + ssize + "\t" + "timezone " + timezone + "\t" + "type " + type + "]\t";
 	}
+	
+	public Boolean imageFileExists() {
+		if (paths.length > 0) {
+			File imageFile = new File(paths[0]);
+			return imageFile.exists();
+		}
+		
+		return false;
+	}
 }
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index 0bbec519a298b55658f586e1de8c7f72b9f702f7..5fc5b0ce1dd318a0246612680887aeb76485fbd0 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -35,8 +35,8 @@
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.logging.Level;
-import org.sleuthkit.datamodel.TskData.ObjectType;
 import java.util.logging.Logger;
+import org.sleuthkit.datamodel.TskData.ObjectType;
 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
 import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
@@ -112,6 +112,8 @@ public class SleuthkitCase {
 	private PreparedStatement getFsIdForFileIdSt;
 	private static final Logger logger = Logger.getLogger(SleuthkitCase.class.getName());
 
+	private ArrayList<ErrorObserver> errorObservers = new ArrayList<ErrorObserver>();
+	
 	/**
 	 * constructor (private) - client uses openCase() and newCase() instead
 	 *
@@ -1021,6 +1023,26 @@ public ArrayList<BlackboardArtifact.ARTIFACT_TYPE> getBlackboardArtifactTypes()
 		}
 
 	}
+	
+	/**
+	 * Get all of the blackboard artifact types that are in use in the blackboard. 
+	 * 
+	 * @return List of blackboard artifact types
+	 * @throws TskCoreException 
+	 */
+	public ArrayList<BlackboardArtifact.ARTIFACT_TYPE> getBlackboardArtifactTypesInUse() throws TskCoreException {
+		// @@@ TODO: This should be rewritten as a single query. 
+		
+		ArrayList<BlackboardArtifact.ARTIFACT_TYPE> allArts = getBlackboardArtifactTypes();
+		ArrayList<BlackboardArtifact.ARTIFACT_TYPE> usedArts = new ArrayList<BlackboardArtifact.ARTIFACT_TYPE>();
+		
+		for (BlackboardArtifact.ARTIFACT_TYPE art : allArts) {
+			if (getBlackboardArtifactsTypeCount(art.getTypeID()) > 0) {
+				usedArts.add(art);
+			}
+		}
+		return usedArts;
+	}
 
 	/**
 	 * Get all blackboard attribute types
@@ -4994,4 +5016,45 @@ public int countFilesMd5Hashed() {
 		}
 		return count;
 	}
+	
+	/**
+	 * This is a temporary workaround to avoid an API change.
+	 * @deprecated
+	 */
+	@Deprecated
+	public interface ErrorObserver {
+		void receiveError(String context, String errorMessage);
+	}
+	
+	/**
+	 * This is a temporary workaround to avoid an API change.
+	 * @deprecated
+	 */
+	@Deprecated
+	public void addErrorObserver(ErrorObserver observer) {
+		errorObservers.add(observer);
+	}
+	
+	/**
+	 * This is a temporary workaround to avoid an API change.
+	 * @deprecated
+	 */
+	@Deprecated
+	public void removerErrorObserver(ErrorObserver observer) {
+		int i = errorObservers.indexOf(observer);
+		if (i >= 0) {
+			errorObservers.remove(i);
+		}
+	}
+	
+	/**
+	 * This is a temporary workaround to avoid an API change.
+	 * @deprecated
+	 */
+	@Deprecated
+	public void submitError(String context, String errorMessage) {
+		for (ErrorObserver observer : errorObservers) {
+			observer.receiveError(context, errorMessage);
+		}
+	}
 }
diff --git a/framework/tsk/framework/services/TskBlackboard.cpp b/framework/tsk/framework/services/TskBlackboard.cpp
index e056a0fd9082f3276e22827eee174a7cf3b8e25e..45826bd6a32d9c0a42893646c67f58aa21796f51 100755
--- a/framework/tsk/framework/services/TskBlackboard.cpp
+++ b/framework/tsk/framework/services/TskBlackboard.cpp
@@ -33,7 +33,13 @@ map<int, TskArtifactNames> initializeArtifactTypeMap(){
     retval.insert(pair<int, TskArtifactNames>(TSK_OS_INFO, TskArtifactNames("TSK_OS_INFO", "Operating System Information")));
     retval.insert(pair<int, TskArtifactNames>(TSK_OS_ACCOUNT, TskArtifactNames("TSK_OS_ACCOUNT", "Operating System User Account")));
     retval.insert(pair<int, TskArtifactNames>(TSK_SERVICE_ACCOUNT, TskArtifactNames("TSK_SERVICE_ACCOUNT", "Network Service User Account")));
+    retval.insert(pair<int, TskArtifactNames>(TSK_TOOL_OUTPUT, TskArtifactNames("TSK_TOOL_OUTPUT", "Raw Tool Output")));
+	retval.insert(pair<int, TskArtifactNames>(TSK_CONTACT, TskArtifactNames("TSK_CONTACT", "Contacts")));
+	retval.insert(pair<int, TskArtifactNames>(TSK_MESSAGE, TskArtifactNames("TSK_MESSAGE", "Messages")));
+	retval.insert(pair<int, TskArtifactNames>(TSK_CALLLOG, TskArtifactNames("TSK_CALLLOG", "Call Logs")));
+	retval.insert(pair<int, TskArtifactNames>(TSK_CALENDAR_ENTRY, TskArtifactNames("TSK_CALENDAR_ENTRY", "Calendar Entries")));
 
+	
     return retval;
 }
 
@@ -108,6 +114,22 @@ map<int, TskAttributeNames> initializeAttributeTypeMap(){
     retval.insert(pair<int, TskAttributeNames>(TSK_PROCESSOR_ARCHITECTURE, TskAttributeNames("TSK_PROCESSOR_ARCHITECTURE", "Processor Architecture")));
     retval.insert(pair<int, TskAttributeNames>(TSK_VERSION, TskAttributeNames("TSK_VERSION", "Version")));
     retval.insert(pair<int, TskAttributeNames>(TSK_USER_ID, TskAttributeNames("TSK_USER_ID", "User ID")));
+    retval.insert(pair<int, TskAttributeNames>(TSK_DESCRIPTION, TskAttributeNames("TSK_DESCRIPTION", "Description")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_MESSAGE_TYPE, TskAttributeNames("TSK_MESSAGE_TYPE",  "Message Type")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_PHONE_NUMBER_HOME, TskAttributeNames("TSK_PHONE_NUMBER_HOME",  "Phone Number (Home)")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_PHONE_NUMBER_OFFICE, TskAttributeNames("TSK_PHONE_NUMBER_OFFICE",  "Phone Number (Office)")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_PHONE_NUMBER_MOBILE, TskAttributeNames("TSK_PHONE_NUMBER_MOBILE",  "Phone Number (Mobile)")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_PHONE_NUMBER_FROM, TskAttributeNames("TSK_PHONE_NUMBER_FROM",  "From Phone Number")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_PHONE_NUMBER_TO, TskAttributeNames("TSK_PHONE_NUMBER_TO",  "To Phone Number")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_DIRECTION, TskAttributeNames("TSK_DIRECTION",  "Direction")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_EMAIL_HOME, TskAttributeNames("TSK_EMAIL_HOME",  "Email (Home)")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_EMAIL_OFFICE, TskAttributeNames("TSK_EMAIL_OFFICE", "Email (Office)")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_DATETIME_START, TskAttributeNames("TSK_DATETIME_START",  "Start Date/Time")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_DATETIME_END, TskAttributeNames("TSK_DATETIME_END",  "End Date/Time")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_CALENDAR_ENTRY_TYPE, TskAttributeNames("TSK_CALENDAR_ENTRY_TYPE", "Calendar Entry Type")));
+	retval.insert(pair<int, TskAttributeNames>(TSK_LOCATION, TskAttributeNames("TSK_LOCATION", "Location")));
+
+
 
     return retval;
 }
diff --git a/framework/tsk/framework/services/TskBlackboard.h b/framework/tsk/framework/services/TskBlackboard.h
index fe30305a33565fc3559ed8917cafe540a1a3292b..ee4d72bf9e477460ab0495f16b3cf9bf1e32c024 100755
--- a/framework/tsk/framework/services/TskBlackboard.h
+++ b/framework/tsk/framework/services/TskBlackboard.h
@@ -65,8 +65,14 @@ enum TSK_ARTIFACT_TYPE {
     TSK_TAG_FILE = 17, ///< File tags.
     TSK_TAG_ARTIFACT = 18, ///< Result tags.
     TSK_OS_INFO = 19, ///< Information pertaining to an operating system.
-    TSK_OS_ACCOUNT, ///< An operating system user account.
-    TSK_SERVICE_ACCOUNT, ///< A network service user account.
+    TSK_OS_ACCOUNT = 20, ///< An operating system user account.
+    TSK_SERVICE_ACCOUNT = 21, ///< A network service user account.
+    TSK_TOOL_OUTPUT = 22,  ///< Output from an external tool or module (raw text)
+	TSK_CONTACT = 23, ///< A Contact extracted from a phone, or from an Addressbook/Email/Messaging Application
+	TSK_MESSAGE = 24, ///< An SMS/MMS message extracted from phone, or from another messaging application, like IM
+	TSK_CALLLOG = 25, ///< A Phone call log extracted from a phones or softphone application
+	TSK_CALENDAR_ENTRY = 26, ///< A Calendar entry from a phone, PIM or a Calendar application.
+		
     /* SEE ABOVE:
     * - KEEP JAVA CODE IN SYNC 
     * - UPDATE map in TskBlackboard.cpp
@@ -155,7 +161,21 @@ enum TSK_ATTRIBUTE_TYPE {
     TSK_DATETIME_MODIFIED = 69,///< Time in Unix epoch that something was modified
     TSK_PROCESSOR_ARCHITECTURE = 70,///< String of processor architecture.  Naming convention from http://en.wikipedia.org/wiki/Comparison_of_CPU_architectures.  So far, we've used x86, x86-64, and IA64.
     TSK_VERSION = 71,///< String for a software version 
-    TSK_USER_ID,///< User IDfor a user account, e.g., a Windows SID or Linux UID.
+    TSK_USER_ID = 72,///< User IDfor a user account, e.g., a Windows SID or Linux UID.
+    TSK_DESCRIPTION = 73, ///< String for a description associated with an artifact.
+	TSK_MESSAGE_TYPE =74, ///< SMS or MMS or IM ...
+	TSK_PHONE_NUMBER_HOME = 75, ///< Phone number (Home)
+	TSK_PHONE_NUMBER_OFFICE = 76, ///< Phone number (Office)
+	TSK_PHONE_NUMBER_MOBILE = 77, ///< Phone Number (Mobile)
+	TSK_PHONE_NUMBER_FROM = 78, ///<  Source Phone Number, originating a call or message
+	TSK_PHONE_NUMBER_TO = 79, /// < Destination Phone Number, receiving a call or message
+	TSK_DIRECTION = 80,  ///< Msg/Call direction: incoming, outgoing
+	TSK_EMAIL_HOME = 81, ///< Email (Home)"),
+	TSK_EMAIL_OFFICE = 82, ///< Email (Office)
+	TSK_DATETIME_START = 83, ///< start time of an event - call log, Calendar entry
+	TSK_DATETIME_END = 84, ///< end time of an event - call log, Calendar entry
+	TSK_CALENDAR_ENTRY_TYPE = 85, ///< calendar entry type: meeting, task, 
+	TSK_LOCATION = 86, 	// Location string associated with an event - Conf Room Name, Address ....
 
     /* SEE ABOVE: 
     * - KEEP JAVA CODE IN SYNC 
diff --git a/framework/tsk/framework/services/TskImgDBPostgreSQL.cpp b/framework/tsk/framework/services/TskImgDBPostgreSQL.cpp
index 6098bf2d1ddc5207cc3475aeed97541db0392ddf..c85384d82f3aa0cb8694a1de9afec3b06eea3726 100755
--- a/framework/tsk/framework/services/TskImgDBPostgreSQL.cpp
+++ b/framework/tsk/framework/services/TskImgDBPostgreSQL.cpp
@@ -3323,7 +3323,6 @@ int TskImgDBPostgreSQL::addUnusedSector(uint64_t sectStart, uint64_t sectEnd, in
 {
     assert(sectEnd > sectStart);
     int rc = -1;
-    unusedSectorsList.clear();
     if (!initialized())
         return rc;
 
diff --git a/tools/autotools/tsk_gettimes.cpp b/tools/autotools/tsk_gettimes.cpp
index de388a3c0733727f94125a6fd900e95da241c419..1f8f169e96a569b2389e9ed199ea4dfa2e8480c1 100644
--- a/tools/autotools/tsk_gettimes.cpp
+++ b/tools/autotools/tsk_gettimes.cpp
@@ -21,12 +21,13 @@ usage()
 {
     TFPRINTF(stderr,
         _TSK_T
-        ("usage: %s [-vV] [-i imgtype] [-b dev_sector_size] [-z zone] [-s seconds] image [image]\n"),
+        ("usage: %s [-vVm] [-i imgtype] [-b dev_sector_size] [-z zone] [-s seconds] image [image]\n"),
         progname);
     tsk_fprintf(stderr,
         "\t-i imgtype: The format of the image file (use '-i list' for supported types)\n");
     tsk_fprintf(stderr,
         "\t-b dev_sector_size: The size (in bytes) of the device sectors\n");
+	tsk_fprintf(stderr, "\t-m: Calculate MD5 hash in output (slow)\n");
     tsk_fprintf(stderr, "\t-v: verbose output to stderr\n");
     tsk_fprintf(stderr, "\t-V: Print version\n");
     tsk_fprintf(stderr,
@@ -42,6 +43,7 @@ usage()
 class TskGetTimes:public TskAuto {
 public:
     TskGetTimes(int32_t);
+	TskGetTimes(int32_t, bool);
     virtual TSK_RETVAL_ENUM processFile(TSK_FS_FILE * fs_file, const char *path);
     virtual TSK_FILTER_ENUM filterVol(const TSK_VS_PART_INFO * vs_part);
     virtual TSK_FILTER_ENUM filterFs(TSK_FS_INFO * fs_info);
@@ -50,6 +52,7 @@ class TskGetTimes:public TskAuto {
 private:
     int m_curVolAddr;
     int32_t m_secSkew;
+	bool m_compute_hash;
 };
 
 
@@ -57,6 +60,14 @@ TskGetTimes::TskGetTimes(int32_t a_secSkew)
 {
     m_curVolAddr = -1;
     m_secSkew = a_secSkew;
+	m_compute_hash = false;
+}
+
+TskGetTimes::TskGetTimes(int32_t a_secSkew, bool a_compute_hash)
+{
+    m_curVolAddr = -1;
+    m_secSkew = a_secSkew;
+	m_compute_hash = a_compute_hash;
 }
 
 // Print errors as they are encountered
@@ -82,10 +93,16 @@ TskGetTimes::filterFs(TSK_FS_INFO * fs_info)
     else 
         volName[0] = '\0';
 
-    if (tsk_fs_fls(fs_info, (TSK_FS_FLS_FLAG_ENUM)(TSK_FS_FLS_MAC | TSK_FS_FLS_DIR | TSK_FS_FLS_FILE | TSK_FS_FLS_FULL),
-       fs_info->root_inum, (TSK_FS_DIR_WALK_FLAG_ENUM)(TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC | TSK_FS_DIR_WALK_FLAG_RECURSE), volName, m_secSkew)) {
-        
-    }
+	TSK_FS_FLS_FLAG_ENUM fls_flags = (TSK_FS_FLS_FLAG_ENUM)(TSK_FS_FLS_MAC | TSK_FS_FLS_DIR | TSK_FS_FLS_FILE | TSK_FS_FLS_FULL);
+	if(m_compute_hash){
+		fls_flags = (TSK_FS_FLS_FLAG_ENUM)(fls_flags | TSK_FS_FLS_HASH);
+	}
+
+	if (tsk_fs_fls(fs_info, (TSK_FS_FLS_FLAG_ENUM)(fls_flags),
+		fs_info->root_inum, (TSK_FS_DIR_WALK_FLAG_ENUM)(TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC | TSK_FS_DIR_WALK_FLAG_RECURSE), volName, m_secSkew)) {
+	}
+
+
     return TSK_FILTER_SKIP;
 }
 
@@ -107,6 +124,7 @@ main(int argc, char **argv1)
     unsigned int ssize = 0;
     TSK_TCHAR *cp;
     int32_t sec_skew = 0;
+	bool do_hash = false;
 
 #ifdef TSK_WIN32
     // On Windows, get the wide arguments (mingw doesn't support wmain)
@@ -122,7 +140,7 @@ main(int argc, char **argv1)
     progname = argv[0];
     setlocale(LC_ALL, "");
 
-    while ((ch = GETOPT(argc, argv, _TSK_T("b:i:s:vVz:"))) > 0) {
+    while ((ch = GETOPT(argc, argv, _TSK_T("b:i:s:mvVz:"))) > 0) {
         switch (ch) {
         case _TSK_T('?'):
         default:
@@ -161,6 +179,9 @@ main(int argc, char **argv1)
             sec_skew = TATOI(OPTARG);
             break;
 
+        case _TSK_T('m'):
+            do_hash = true;
+            break;
 
         case _TSK_T('v'):
             tsk_verbose++;
@@ -194,7 +215,7 @@ main(int argc, char **argv1)
         usage();
     }
 
-    TskGetTimes tskGetTimes(sec_skew);
+    TskGetTimes tskGetTimes(sec_skew, do_hash);
     if (tskGetTimes.openImage(argc - OPTIND, &argv[OPTIND], imgtype,
             ssize)) {
         tsk_error_print(stderr);
diff --git a/tools/srchtools/srch_strings.c b/tools/srchtools/srch_strings.c
index 2028835c896456c5ac0afdbad920f89682924047..35fd29c810c0fa45a82f1f340841a3ba7b54d406 100644
--- a/tools/srchtools/srch_strings.c
+++ b/tools/srchtools/srch_strings.c
@@ -1,6 +1,6 @@
-/* From binutils-2.15 
+/* From binutils-2.15
  * removed getopt_long stuff
- *  
+ *
  */
 
 /* strings -- print the strings of printable characters in files
@@ -98,7 +98,7 @@
 
 /* The following were taken from other files in binutils */
 // from include/libiberty.h
-enum { 
+enum {
   /* In C99 */
   _sch_isblank  = 0x0001,       /* space \t */
   _sch_iscntrl  = 0x0002,       /* nonprinting characters */
@@ -142,7 +142,7 @@ enum {
 #define vs _sch_isvsp
 #define xd _sch_isxdigit
 
-/* Masks.  */ 
+/* Masks.  */
 #define L  (const unsigned short) (lo|is   |pr) /* lower case letter */
 #define XL (const unsigned short) (lo|is|xd|pr) /* lowercase hex digit */
 #define U  (const unsigned short) (up|is   |pr) /* upper case letter */
@@ -283,7 +283,7 @@ main (int argc, char **argv)
 	case 'n':
 	  string_min = integer_arg (optarg);
 	  if (string_min < 1) {
-	    fprintf (stderr, "invalid number %s", optarg);
+	    fprintf (stderr, "invalid number %s\n", optarg);
 	  }
 	  break;
 
@@ -401,13 +401,13 @@ get_file_size (const char * file_name)
   if (stat (file_name, &statbuf) < 0)
     {
       if (errno == ENOENT)
-        fprintf (stderr, "'%s': No such file", file_name);
+        fprintf (stderr, "'%s': No such file\n", file_name);
       else
-        fprintf (stderr, "Warning: could not locate '%s'.  reason: %s",
+        fprintf (stderr, "Warning: could not locate '%s'.  reason: %s\n",
                    file_name, strerror (errno));
     }
   else if (! S_ISREG (statbuf.st_mode)) {
-    fprintf(stderr, "Warning: '%s' is not an ordinary file", file_name);
+    fprintf(stderr, "Warning: '%s' is not an ordinary file\n", file_name);
   }
   else
     return statbuf.st_size;
@@ -600,7 +600,7 @@ print_strings (const char *filename, FILE *stream, uint64_t address,
 }
 
 /* Parse string S as an integer, using decimal radix by default,
-   but allowing octal and hex numbers as in C.  
+   but allowing octal and hex numbers as in C.
 
    Return 0 on error
  */
@@ -642,7 +642,7 @@ integer_arg (char *s)
     p--;
 
   if (*p) {
-      fprintf(stderr, "invalid integer argument %s", s);
+      fprintf(stderr, "invalid integer argument %s\n", s);
       return 0;
   }
 
diff --git a/tsk/base/tsk_base.h b/tsk/base/tsk_base.h
index 3de0c9b7403c0f720ee224597076d1c2031df041..9caa4404e4586b57f877e40aa96d49fae45830b5 100644
--- a/tsk/base/tsk_base.h
+++ b/tsk/base/tsk_base.h
@@ -473,6 +473,16 @@ documentation and/or software.
     void TSK_SHA_Init(TSK_SHA_CTX *);
     void TSK_SHA_Update(TSK_SHA_CTX *, BYTE * buffer, int count);
     void TSK_SHA_Final(BYTE * output, TSK_SHA_CTX *);
+
+/* Flags for which type of hash(es) to run */
+	typedef enum{
+		TSK_HASH_INVALID_ID = 0,
+		TSK_HASH_MD5 = 0x01,
+		TSK_HASH_SHA1 = 0x02
+		//TSK_HASH_SHA256 = 0x04,
+	} TSK_HASH_ENUM;
+
+
 //@}
 
 #ifdef __cplusplus
diff --git a/tsk/fs/fls_lib.c b/tsk/fs/fls_lib.c
index 169b3ec4ce104aa6a5bcec7833f2adf8f008f4b5..48a1d51266af0e8a5049b4e1e259844e04bc4412 100644
--- a/tsk/fs/fls_lib.c
+++ b/tsk/fs/fls_lib.c
@@ -50,6 +50,7 @@ static void
 printit(TSK_FS_FILE * fs_file, const char *a_path,
     const TSK_FS_ATTR * fs_attr, const FLS_DATA * fls_data)
 {
+	TSK_HASH_RESULTS hash_results;
     unsigned int i;
 
     if ((!(fls_data->flags & TSK_FS_FLS_FULL)) && (a_path)) {
@@ -66,10 +67,18 @@ printit(TSK_FS_FILE * fs_file, const char *a_path,
     }
 
 
-    if (fls_data->flags & TSK_FS_FLS_MAC) {
-        tsk_fs_name_print_mac(stdout, fs_file, a_path,
-            fs_attr, fls_data->macpre, fls_data->sec_skew);
-    }
+	if(fls_data->flags & TSK_FS_FLS_MAC){
+		if(fls_data->flags & TSK_FS_FLS_HASH){
+			tsk_fs_file_hash_calc(fs_file, &hash_results, TSK_HASH_MD5);
+			tsk_fs_name_print_mac_md5(stdout, fs_file, a_path,
+				fs_attr, fls_data->macpre, fls_data->sec_skew,
+				hash_results.md5_digest);
+		}
+		else{
+			tsk_fs_name_print_mac(stdout, fs_file, a_path,
+				fs_attr, fls_data->macpre, fls_data->sec_skew);
+		}
+	}
     else if (fls_data->flags & TSK_FS_FLS_LONG) {
         tsk_fs_name_print_long(stdout, fs_file, a_path, fs_file->fs_info,
             fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0,
@@ -192,7 +201,6 @@ tsk_fs_fls(TSK_FS_INFO * fs, TSK_FS_FLS_FLAG_ENUM lclflags,
 
 #ifdef TSK_WIN32
     {
-        char *cpre;
         size_t clen;
         UTF8 *ptr8;
         UTF16 *ptr16;
@@ -200,11 +208,11 @@ tsk_fs_fls(TSK_FS_INFO * fs, TSK_FS_FLS_FLAG_ENUM lclflags,
 
         if ((tpre != NULL) && (TSTRLEN(tpre) > 0)) {
             clen = TSTRLEN(tpre) * 4;
-            cpre = (char *) tsk_malloc(clen);
-            if (cpre == NULL) {
+            data.macpre = (char *) tsk_malloc(clen);
+            if (data.macpre == NULL) {
                 return 1;
             }
-            ptr8 = (UTF8 *) cpre;
+            ptr8 = (UTF8 *) data.macpre;
             ptr16 = (UTF16 *) tpre;
 
             retval =
@@ -219,18 +227,19 @@ tsk_fs_fls(TSK_FS_INFO * fs, TSK_FS_FLS_FLAG_ENUM lclflags,
                     retval);
                 return 1;
             }
-            data.macpre = cpre;
         }
         else {
-            data.macpre = NULL;
-            cpre = NULL;
+            data.macpre = (char *) tsk_malloc(1);
+            if (data.macpre == NULL) {
+                return 1;
+            }
+            data.macpre[0] = '\0';
         }
 
         retval = tsk_fs_dir_walk(fs, inode, flags, print_dent_act, &data);
 
-        if (cpre)
-            free(cpre);
-
+        free(data.macpre);
+        data.macpre = NULL;
         return retval;
     }
 #else
diff --git a/tsk/fs/fs_file.c b/tsk/fs/fs_file.c
index b4e0d31517e2f062b874dca09ef99ff1d1478832..74417d832a99308e7fa89162d04b827e6ea44232 100644
--- a/tsk/fs/fs_file.c
+++ b/tsk/fs/fs_file.c
@@ -563,3 +563,88 @@ tsk_fs_file_get_owner_sid(TSK_FS_FILE * a_fs_file, char **sid_str)
 
     return a_fs_file->fs_info->fread_owner_sid(a_fs_file, sid_str);
 }
+
+
+/**
+ * Internal struct used for hash calculations
+ */
+typedef struct {
+	TSK_HASH_ENUM flags;
+	TSK_MD5_CTX md5_context;
+	TSK_SHA_CTX sha1_context;
+} TSK_HASH_DATA;
+
+/**
+ * Helper function for tsk_fs_file_get_md5
+ */
+TSK_WALK_RET_ENUM
+tsk_fs_file_hash_calc_callback(TSK_FS_FILE * file, TSK_OFF_T offset,
+    TSK_DADDR_T addr, char *buf, size_t size,
+    TSK_FS_BLOCK_FLAG_ENUM a_flags, void *ptr)
+{
+    TSK_HASH_DATA * hash_data = (TSK_HASH_DATA *) ptr;
+    if (hash_data == NULL)
+        return TSK_WALK_CONT;
+
+	if(hash_data->flags & TSK_HASH_MD5){
+		TSK_MD5_Update(&(hash_data->md5_context), (unsigned char *) buf, (unsigned int) size);
+	}
+
+	if(hash_data->flags & TSK_HASH_SHA1){
+		TSK_SHA_Update(&(hash_data->sha1_context), (unsigned char *) buf, (unsigned int) size);
+	}
+
+
+    return TSK_WALK_CONT;
+}
+
+/**
+ * Returns a string containing the md5 hash of the given file
+ *
+ * @param a_fs_file The file to calculate the hash of
+ * @param a_hash_results The results will be stored here (must be allocated beforehand)
+ * @param a_flags Indicates which hash algorithm(s) to use
+ * @returns 0 on success or 1 on error
+ */
+extern uint8_t tsk_fs_file_hash_calc(TSK_FS_FILE * a_fs_file, TSK_HASH_RESULTS * a_hash_results, TSK_HASH_ENUM a_flags){
+	TSK_HASH_DATA hash_data;
+	int i;
+
+    if ((a_fs_file == NULL) || (a_fs_file->fs_info == NULL)
+        || (a_fs_file->meta == NULL)) {
+        tsk_error_set_errno(TSK_ERR_FS_ARG);
+        tsk_error_set_errstr("tsk_fs_file_hash_calc: fs_info is NULL");
+        return 1;
+    }
+
+	if(a_hash_results == NULL){
+        tsk_error_set_errno(TSK_ERR_FS_ARG);
+        tsk_error_set_errstr("tsk_fs_file_hash_calc: hash_results is NULL");
+        return 1;
+    }
+
+	if(a_flags & TSK_HASH_MD5){
+		TSK_MD5_Init(&(hash_data.md5_context));
+	}
+	if(a_flags & TSK_HASH_SHA1){
+		TSK_SHA_Init(&(hash_data.sha1_context));
+	}
+
+	hash_data.flags = a_flags;
+	if(tsk_fs_file_walk(a_fs_file, TSK_FS_FILE_WALK_FLAG_NONE,
+            tsk_fs_file_hash_calc_callback, (void *) &hash_data)) {
+        tsk_error_set_errno(TSK_ERR_FS_ARG);
+        tsk_error_set_errstr("tsk_fs_file_hash_calc: error in file walk");     
+        return 1;
+    }
+
+	a_hash_results->flags = a_flags;
+	if(a_flags & TSK_HASH_MD5){
+		TSK_MD5_Final(a_hash_results->md5_digest, &(hash_data.md5_context));
+	}
+	if(a_flags & TSK_HASH_MD5){
+		TSK_SHA_Final(a_hash_results->sha1_digest, &(hash_data.sha1_context));
+	}
+
+	return 0;
+}
diff --git a/tsk/fs/fs_name.c b/tsk/fs/fs_name.c
index aaa12c495da7b19bb0d7a7c15339d3e852884035..189ab8292044e2511db4d551597795aacdae3c21 100644
--- a/tsk/fs/fs_name.c
+++ b/tsk/fs/fs_name.c
@@ -582,6 +582,33 @@ void
 tsk_fs_name_print_mac(FILE * hFile, const TSK_FS_FILE * fs_file,
     const char *a_path, const TSK_FS_ATTR * fs_attr,
     const char *prefix, int32_t time_skew)
+{
+	tsk_fs_name_print_mac_md5(hFile, fs_file, a_path, fs_attr, prefix, time_skew, NULL);
+}
+
+/**
+ * \internal
+ *
+** Print output in the format that mactime reads.
+**
+** If the flags in the fs_file->meta structure are set to FS_FLAG_ALLOC
+** then it is assumed that the inode has been reallocated and the
+** contents are not displayed
+**
+** fs is not required (only used for block size).
+ * @param hFile handle to print results to
+ * @param fs_file File to print details about
+ * @param a_path Parent directory of file (needs to end with "/")
+ * @param fs_attr Attribute in file that is being called for (NULL for non-NTFS)
+ * @param prefix Path of mounting point for image
+ * @param time_skew number of seconds skew to adjust time
+ * @param hash_results Holds the calculated md5 hash
+*/
+void
+tsk_fs_name_print_mac_md5(FILE * hFile, const TSK_FS_FILE * fs_file,
+    const char *a_path, const TSK_FS_ATTR * fs_attr,
+    const char *prefix, int32_t time_skew,
+	const unsigned char * hash_results)
 {
     char ls[12];
     size_t i;
@@ -600,8 +627,18 @@ tsk_fs_name_print_mac(FILE * hFile, const TSK_FS_FILE * fs_file,
         isADS = 1;
     }
 
-    /* md5 */
-    tsk_fprintf(hFile, "0|");
+    /* hash
+	 * Print out the hash buffer (if not null)
+	 */
+	if(hash_results == NULL){
+		tsk_fprintf(hFile, "0|");
+	}
+	else{
+		for(i = 0;i < 16;i++){
+			tsk_fprintf(hFile, "%02x", hash_results[i]);
+		}
+		tsk_fprintf(hFile, "|");
+	}
 
     /* file name */
     tsk_fprintf(hFile, "%s", prefix);
diff --git a/tsk/fs/tsk_fs.h b/tsk/fs/tsk_fs.h
index 2814434832abe172432abd9ede450b92dcb30d76..936d4ee8c3c219c465ff8172431acc4a3c7fa397 100644
--- a/tsk/fs/tsk_fs.h
+++ b/tsk/fs/tsk_fs.h
@@ -722,6 +722,14 @@ extern "C" {
 
     extern uint8_t tsk_fs_file_get_owner_sid(TSK_FS_FILE *, char **);
 
+	typedef struct {
+		TSK_HASH_ENUM flags;
+		unsigned char md5_digest[16];
+		unsigned char sha1_digest[20];
+	} TSK_HASH_RESULTS;
+
+	extern uint8_t tsk_fs_file_hash_calc(TSK_FS_FILE *, TSK_HASH_RESULTS *, TSK_HASH_ENUM);
+
     //@}
 
 
@@ -1043,6 +1051,7 @@ extern "C" {
         TSK_FS_FLS_DIR = 0x08,
         TSK_FS_FLS_FULL = 0x10,
         TSK_FS_FLS_MAC = 0x20,
+		TSK_FS_FLS_HASH = 0x40
     };
     typedef enum TSK_FS_FLS_FLAG_ENUM TSK_FS_FLS_FLAG_ENUM;
     extern uint8_t tsk_fs_fls(TSK_FS_INFO * fs,
diff --git a/tsk/fs/tsk_fs_i.h b/tsk/fs/tsk_fs_i.h
index 27538e28de4e49c4039f9adf942957cbe15a56b7..944f2818d24eacc29df7ab03768372f497127703 100644
--- a/tsk/fs/tsk_fs_i.h
+++ b/tsk/fs/tsk_fs_i.h
@@ -162,6 +162,9 @@ extern "C" {
         int32_t);
     extern void tsk_fs_name_print_mac(FILE *, const TSK_FS_FILE *,
         const char *, const TSK_FS_ATTR * fs_attr, const char *, int32_t);
+    extern void tsk_fs_name_print_mac_md5(FILE *, const TSK_FS_FILE *,
+        const char *, const TSK_FS_ATTR * fs_attr, const char *, int32_t,
+		const unsigned char *);
     extern uint8_t tsk_fs_name_copy(TSK_FS_NAME * a_fs_name_to,
         const TSK_FS_NAME * a_fs_name_from);
     extern void tsk_fs_name_reset(TSK_FS_NAME * a_fs_name);