19 package org.sleuthkit.datamodel;
21 import com.google.common.collect.ImmutableSet;
22 import java.sql.PreparedStatement;
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.sql.Statement;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Objects;
34 import java.util.logging.Level;
35 import java.util.logging.Logger;
36 import java.util.stream.Collectors;
46 private static final Logger LOGGER = Logger.getLogger(
Blackboard.class.getName());
57 this.caseDb = Objects.requireNonNull(casedb,
"Cannot create Blackboard for null SleuthkitCase");
139 if (category == null) {
140 throw new BlackboardException(
"Category provided must be non-null");
149 throw new BlackboardException(
"Failed to get or add artifact type", ex);
152 throw new BlackboardException(
"Failed to get or add artifact type", ex);
179 String conclusion, String configuration, String justification, Collection<BlackboardAttribute> attributesList)
183 throw new BlackboardException(String.format(
"Artifact type (name = %s) is not of Analysis Result category. ", artifactType.getTypeName()));
189 conclusion, configuration, justification, attributesList, transaction);
191 return analysisResult;
196 LOGGER.log(Level.SEVERE,
"Failed to rollback transaction after exception. "
197 +
"Error invoking newAnalysisResult with dataSourceObjId: "
198 + (dataSourceObjId == null ?
"<null>" : dataSourceObjId)
199 +
", sourceObjId: " + objId, ex2);
228 String conclusion, String configuration, String justification, Collection<BlackboardAttribute> attributesList,
CaseDbTransaction transaction)
throws BlackboardException {
231 throw new BlackboardException(String.format(
"Artifact type (name = %s) is not of Analysis Result category. ", artifactType.getTypeName()));
236 AnalysisResult analysisResult = caseDb.newAnalysisResult(artifactType, objId, dataSourceObjId, score, conclusion, configuration, justification, transaction.getConnection());
239 if (attributesList != null && !attributesList.isEmpty()) {
244 Score aggregateScore = caseDb.
getScoringManager().updateAggregateScoreAfterAddition(objId, dataSourceObjId, analysisResult.
getScore(), transaction);
250 throw new BlackboardException(
"Failed to add analysis result.", ex);
278 if (transaction != null) {
299 List<AnalysisResult> analysisResults =
getAnalysisResultsWhere(
" artifacts.artifact_obj_id = " + artifactObjId, transaction.getConnection());
301 if (analysisResults.isEmpty()) {
302 throw new TskCoreException(String.format(
"Analysis Result not found for artifact obj id %d", artifactObjId));
324 CaseDbConnection connection = transaction.getConnection();
327 String deleteSQL =
"DELETE FROM blackboard_artifacts WHERE artifact_obj_id = ?";
329 PreparedStatement deleteStatement = connection.getPreparedStatement(deleteSQL, Statement.RETURN_GENERATED_KEYS);
330 deleteStatement.clearParameters();
331 deleteStatement.setLong(1, analysisResult.getId());
333 deleteStatement.executeUpdate();
336 transaction.registerDeletedAnalysisResult(analysisResult.getObjectID());
338 return caseDb.
getScoringManager().updateAggregateScoreAfterDeletion(analysisResult.getObjectID(), analysisResult.getDataSourceObjectID(), transaction);
340 }
catch (SQLException ex) {
341 throw new TskCoreException(String.format(
"Error deleting analysis result with artifact obj id %d", analysisResult.getId()), ex);
345 private final static String ANALYSIS_RESULT_QUERY_STRING =
"SELECT DISTINCT artifacts.artifact_id AS artifact_id, "
346 +
" artifacts.obj_id AS obj_id, artifacts.artifact_obj_id AS artifact_obj_id, artifacts.data_source_obj_id AS data_source_obj_id, artifacts.artifact_type_id AS artifact_type_id, "
347 +
" types.type_name AS type_name, types.display_name AS display_name, types.category_type as category_type,"
348 +
" artifacts.review_status_id AS review_status_id, "
349 +
" results.conclusion AS conclusion, results.significance AS significance, results.priority AS priority, "
350 +
" results.configuration AS configuration, results.justification AS justification "
351 +
" FROM blackboard_artifacts AS artifacts "
352 +
" JOIN blackboard_artifact_types AS types "
353 +
" ON artifacts.artifact_type_id = types.artifact_type_id"
354 +
" LEFT JOIN tsk_analysis_results AS results "
355 +
" ON artifacts.artifact_obj_id = results.artifact_obj_id "
356 +
" WHERE artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()
357 +
" AND types.category_type = " + BlackboardArtifact.Category.ANALYSIS_RESULT.getID();
385 return getAnalysisResultsWhere(
" artifacts.artifact_type_id = " + artifactTypeId +
" AND artifacts.data_source_obj_id = " + dataSourceObjId);
412 List<DataArtifact> getDataArtifactsBySource(
long sourceObjId)
throws TskCoreException {
414 try (CaseDbConnection connection = caseDb.getConnection()) {
415 return getDataArtifactsWhere(String.format(
" artifacts.obj_id = %d", sourceObjId), connection);
461 String queryString =
"SELECT COUNT(*) AS count "
462 +
" FROM blackboard_artifacts AS arts "
463 +
" JOIN blackboard_artifact_types AS types "
464 +
" ON arts.artifact_type_id = types.artifact_type_id"
465 +
" WHERE types.category_type = " + category.getID()
466 +
" AND arts.obj_id = " + sourceObjId;
470 Statement statement = connection.createStatement();
471 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
472 if (resultSet.next()) {
473 return resultSet.getLong(
"count") > 0;
476 }
catch (SQLException ex) {
477 throw new TskCoreException(
"Error getting artifact types is use for data source." + ex.getMessage(), ex);
495 List<AnalysisResult>
getAnalysisResults(
long sourceObjId, CaseDbConnection connection)
throws TskCoreException {
514 throw new TskCoreException(String.format(
"Artifact type id %d is not in analysis result catgeory.", artifactTypeId));
517 String whereClause =
" types.artifact_type_id = " + artifactTypeId
518 +
" AND artifacts.obj_id = " + sourceObjId;
535 try (CaseDbConnection connection = caseDb.getConnection()) {
556 final String queryString = ANALYSIS_RESULT_QUERY_STRING
557 +
" AND " + whereClause;
559 try (Statement statement = connection.createStatement();
560 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
562 List<AnalysisResult> analysisResults = resultSetToAnalysisResults(resultSet);
563 return analysisResults;
564 }
catch (SQLException ex) {
565 throw new TskCoreException(String.format(
"Error getting analysis results for WHERE clause = '%s'", whereClause), ex);
580 String whereClause =
" artifacts.artifact_obj_id = " + artifactObjId;
583 if (results.isEmpty()) {
584 throw new TskCoreException(String.format(
"Error getting analysis result with id = '%d'", artifactObjId));
586 if (results.size() > 1) {
587 throw new TskCoreException(String.format(
"Multiple analysis results found with id = '%d'", artifactObjId));
590 return results.get(0);
608 private List<AnalysisResult> resultSetToAnalysisResults(ResultSet resultSet)
throws SQLException,
TskCoreException {
609 ArrayList<AnalysisResult> analysisResults =
new ArrayList<>();
611 while (resultSet.next()) {
612 analysisResults.add(
new AnalysisResult(caseDb, resultSet.getLong(
"artifact_id"), resultSet.getLong(
"obj_id"),
613 resultSet.getLong(
"artifact_obj_id"),
614 resultSet.getObject(
"data_source_obj_id") != null ? resultSet.getLong(
"data_source_obj_id") : null,
615 resultSet.getInt(
"artifact_type_id"), resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
618 resultSet.getString(
"conclusion"), resultSet.getString(
"configuration"), resultSet.getString(
"justification")));
621 return analysisResults;
624 private final static String DATA_ARTIFACT_QUERY_STRING =
"SELECT DISTINCT artifacts.artifact_id AS artifact_id, "
625 +
"artifacts.obj_id AS obj_id, artifacts.artifact_obj_id AS artifact_obj_id, artifacts.data_source_obj_id AS data_source_obj_id, artifacts.artifact_type_id AS artifact_type_id, "
626 +
" types.type_name AS type_name, types.display_name AS display_name, types.category_type as category_type,"
627 +
" artifacts.review_status_id AS review_status_id, "
628 +
" data_artifacts.os_account_obj_id as os_account_obj_id "
629 +
" FROM blackboard_artifacts AS artifacts "
630 +
" JOIN blackboard_artifact_types AS types "
631 +
" ON artifacts.artifact_type_id = types.artifact_type_id"
632 +
" LEFT JOIN tsk_data_artifacts AS data_artifacts "
633 +
" ON artifacts.artifact_obj_id = data_artifacts.artifact_obj_id "
634 +
" WHERE artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()
635 +
" AND types.category_type = " + BlackboardArtifact.Category.DATA_ARTIFACT.getID();
651 try (CaseDbConnection connection = caseDb.getConnection()) {
652 String whereClause =
" artifacts.data_source_obj_id = " + dataSourceObjId;
653 if (artifactTypeID != null) {
654 whereClause +=
" AND artifacts.artifact_type_id = " + artifactTypeID;
656 return getDataArtifactsWhere(whereClause, connection);
678 throw new TskCoreException(String.format(
"Artifact type id %d is not in data artifact catgeory.", artifactTypeID));
682 try (CaseDbConnection connection = caseDb.getConnection()) {
683 String whereClause =
"artifacts.data_source_obj_id = " + dataSourceObjId
684 +
" AND artifacts.artifact_type_id = " + artifactTypeID;
686 return getDataArtifactsWhere(whereClause, connection);
706 throw new TskCoreException(String.format(
"Artifact type id %d is not in data artifact catgeory.", artifactTypeID));
710 try (CaseDbConnection connection = caseDb.getConnection()) {
711 String whereClause =
" artifacts.artifact_type_id = " + artifactTypeID;
713 return getDataArtifactsWhere(whereClause, connection);
731 try (CaseDbConnection connection = caseDb.getConnection()) {
732 String whereClause =
" artifacts.artifact_obj_id = " + artifactObjId;
734 List<DataArtifact> artifacts = getDataArtifactsWhere(whereClause, connection);
735 if (artifacts.isEmpty()) {
736 throw new TskCoreException(String.format(
"Error getting data artifact with id = '%d'", artifactObjId));
738 if (artifacts.size() > 1) {
739 throw new TskCoreException(String.format(
"Multiple data artifacts found with id = '%d'", artifactObjId));
742 return artifacts.get(0);
758 List<DataArtifact> getDataArtifactsWhere(String whereClause)
throws TskCoreException {
760 try (CaseDbConnection connection = caseDb.getConnection()) {
761 return getDataArtifactsWhere(whereClause, connection);
779 List<DataArtifact> getDataArtifactsWhere(String whereClause, CaseDbConnection connection)
throws TskCoreException {
781 final String queryString = DATA_ARTIFACT_QUERY_STRING
782 +
" AND ( " + whereClause +
" )";
784 try (Statement statement = connection.createStatement();
785 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
787 List<DataArtifact> dataArtifacts = resultSetToDataArtifacts(resultSet, connection);
788 return dataArtifacts;
789 }
catch (SQLException ex) {
790 throw new TskCoreException(String.format(
"Error getting data artifacts with queryString = %s", queryString), ex);
810 private List<DataArtifact> resultSetToDataArtifacts(ResultSet resultSet, CaseDbConnection connection)
throws SQLException, TskCoreException {
811 ArrayList<DataArtifact> dataArtifacts =
new ArrayList<>();
813 while (resultSet.next()) {
815 Long osAccountObjId = resultSet.getLong(
"os_account_obj_id");
816 if (resultSet.wasNull()) {
817 osAccountObjId = null;
820 dataArtifacts.add(
new DataArtifact(caseDb, resultSet.getLong(
"artifact_id"), resultSet.getLong(
"obj_id"),
821 resultSet.getLong(
"artifact_obj_id"),
822 resultSet.getObject(
"data_source_obj_id") != null ? resultSet.getLong(
"data_source_obj_id") : null,
823 resultSet.getInt(
"artifact_type_id"), resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
824 BlackboardArtifact.ReviewStatus.withID(resultSet.getInt(
"review_status_id")), osAccountObjId,
false));
827 return dataArtifacts;
866 throw new BlackboardException(
"Failed to get or add attribute type", ex);
869 throw new BlackboardException(
"Failed to get or add attribute type", ex);
886 final String queryString =
"SELECT DISTINCT arts.artifact_type_id AS artifact_type_id, "
887 +
"types.type_name AS type_name, "
888 +
"types.display_name AS display_name, "
889 +
"types.category_type AS category_type "
890 +
"FROM blackboard_artifact_types AS types "
891 +
"INNER JOIN blackboard_artifacts AS arts "
892 +
"ON arts.artifact_type_id = types.artifact_type_id "
893 +
"WHERE arts.data_source_obj_id = " + dataSourceObjId;
897 Statement statement = connection.createStatement();
898 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
901 while (resultSet.next()) {
903 resultSet.getString(
"type_name"), resultSet.getString(
"display_name"),
906 return uniqueArtifactTypes;
907 }
catch (SQLException ex) {
908 throw new TskCoreException(
"Error getting artifact types is use for data source." + ex.getMessage(), ex);
927 return getArtifactsCountHelper(artifactTypeID,
928 "blackboard_artifacts.data_source_obj_id = '" + dataSourceObjId +
"';");
944 String whereClause = String.format(
"artifacts.data_source_obj_id = %d", dataSourceObjId);
945 return getArtifactsWhere(caseDb.
getArtifactType(artifactTypeID), whereClause);
960 public List<BlackboardArtifact>
getArtifacts(Collection<BlackboardArtifact.Type> artifactTypes,
963 if (artifactTypes.isEmpty() || dataSourceObjIds.isEmpty()) {
964 return new ArrayList<>();
967 String analysisResultQuery =
"";
968 String dataArtifactQuery =
"";
972 if (!analysisResultQuery.isEmpty()) {
973 analysisResultQuery +=
" OR ";
975 analysisResultQuery +=
"types.artifact_type_id = " + type.getTypeID();
977 if (!dataArtifactQuery.isEmpty()) {
978 dataArtifactQuery +=
" OR ";
980 dataArtifactQuery +=
"types.artifact_type_id = " + type.getTypeID();
985 for (
long dsId : dataSourceObjIds) {
986 if (!dsQuery.isEmpty()) {
989 dsQuery +=
"artifacts.data_source_obj_id = " + dsId;
992 List<BlackboardArtifact> artifacts =
new ArrayList<>();
994 if (!analysisResultQuery.isEmpty()) {
995 String fullQuery =
"( " + analysisResultQuery +
" ) AND (" + dsQuery +
") ";
999 if (!dataArtifactQuery.isEmpty()) {
1000 String fullQuery =
"( " + dataArtifactQuery +
" ) AND (" + dsQuery +
") ";
1001 artifacts.addAll(this.getDataArtifactsWhere(fullQuery));
1019 private long getArtifactsCountHelper(
int artifactTypeID, String whereClause)
throws TskCoreException {
1020 String queryString =
"SELECT COUNT(*) AS count FROM blackboard_artifacts "
1021 +
"WHERE blackboard_artifacts.artifact_type_id = " + artifactTypeID
1023 +
" AND " + whereClause;
1027 Statement statement = connection.createStatement();
1028 ResultSet resultSet = connection.executeQuery(statement, queryString);) {
1031 if (resultSet.next()) {
1032 count = resultSet.getLong(
"count");
1035 }
catch (SQLException ex) {
1036 throw new TskCoreException(
"Error getting artifact types is use for data source." + ex.getMessage(), ex);
1058 ArrayList<BlackboardArtifact> artifactsList;
1063 artifactsList = content.getArtifacts(artifactType);
1064 if (artifactsList.isEmpty()) {
1072 if (attributesMatch(artifact.getAttributes(), attributesList)) {
1098 private boolean attributesMatch(Collection<BlackboardAttribute> fileAttributesList, Collection<BlackboardAttribute> expectedAttributesList) {
1100 boolean match =
false;
1103 if (attributeType.getTypeID() != expectedAttribute.getAttributeType().getTypeID()) {
1107 Object fileAttributeValue;
1108 Object expectedAttributeValue;
1109 switch (attributeType.getValueType()) {
1111 fileAttributeValue = fileAttribute.getValueBytes();
1112 expectedAttributeValue = expectedAttribute.getValueBytes();
1115 fileAttributeValue = fileAttribute.getValueDouble();
1116 expectedAttributeValue = expectedAttribute.getValueDouble();
1119 fileAttributeValue = fileAttribute.getValueInt();
1120 expectedAttributeValue = expectedAttribute.getValueInt();
1124 fileAttributeValue = fileAttribute.getValueLong();
1125 expectedAttributeValue = expectedAttribute.getValueLong();
1129 fileAttributeValue = fileAttribute.getValueString();
1130 expectedAttributeValue = expectedAttribute.getValueString();
1133 fileAttributeValue = fileAttribute.getDisplayString();
1134 expectedAttributeValue = expectedAttribute.getDisplayString();
1142 if (fileAttributeValue instanceof byte[]) {
1143 if (Arrays.equals((byte[]) fileAttributeValue, (byte[]) expectedAttributeValue)) {
1147 }
else if (fileAttributeValue.equals(expectedAttributeValue)) {
1171 public static final class BlackboardException
extends Exception {
1173 private static final long serialVersionUID = 1L;
1180 BlackboardException(String message) {
1191 BlackboardException(String message, Throwable cause) {
1192 super(message, cause);
1213 Collection<BlackboardAttribute> attributes, Long osAccountId)
throws TskCoreException {
1216 throw new TskCoreException(String.format(
"Artifact type (name = %s) is not of Data Artifact category. ", artifactType.getTypeName()));
1222 attributes, osAccountId, transaction);
1224 return dataArtifact;
1229 LOGGER.log(Level.SEVERE,
"Failed to rollback transaction after exception. "
1230 +
"Error invoking newDataArtifact with dataSourceObjId: " + dataSourceObjId +
", sourceObjId: " + sourceObjId, ex2);
1260 throw new TskCoreException(String.format(
"Artifact type (name = %s) is not of Data Artifact category. ", artifactType.getTypeName()));
1264 CaseDbConnection connection = transaction.getConnection();
1266 PreparedStatement statement = caseDb.createInsertArtifactStatement(artifactType.getTypeID(), sourceObjId, artifact_obj_id, dataSourceObjId, connection);
1268 connection.executeUpdate(statement);
1269 try (ResultSet resultSet = statement.getGeneratedKeys()) {
1272 sourceObjId, artifact_obj_id, dataSourceObjId, artifactType.getTypeID(),
1274 osAccountObjId,
true);
1277 if (osAccountObjId != null) {
1278 String insertDataArtifactSQL =
"INSERT INTO tsk_data_artifacts (artifact_obj_id, os_account_obj_id) VALUES (?, ?)";
1280 statement = connection.getPreparedStatement(insertDataArtifactSQL, Statement.NO_GENERATED_KEYS);
1281 statement.clearParameters();
1283 statement.setLong(1, artifact_obj_id);
1284 statement.setLong(2, osAccountObjId);
1285 connection.executeUpdate(statement);
1289 if (Objects.nonNull(attributes) && !attributes.isEmpty()) {
1293 return dataArtifact;
1295 }
catch (SQLException ex) {
1296 throw new TskCoreException(String.format(
"Error creating a data artifact with type id = %d, objId = %d, and data source oj id = %d ", artifactType.getTypeID(), sourceObjId, dataSourceObjId), ex);
1312 String whereClause = String.format(
"artifacts.obj_id = %d", sourceObjId);
1313 return getArtifactsWhere(artifactType, whereClause);
1325 List<BlackboardArtifact> getArtifactsByType(BlackboardArtifact.Type artifactType) throws TskCoreException {
1326 List<BlackboardArtifact> artifacts =
new ArrayList<>();
1327 if (artifactType.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
1352 private List<BlackboardArtifact> getArtifactsWhere(BlackboardArtifact.Type artifactType, String whereClause)
throws TskCoreException {
1353 List<BlackboardArtifact> artifacts =
new ArrayList<>();
1354 String whereWithType = whereClause +
" AND artifacts.artifact_type_id = " + artifactType.getTypeID();
1356 if (artifactType.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
1359 artifacts.addAll(getDataArtifactsWhere(whereWithType));
1372 private final String moduleName;
1374 private final ImmutableSet<BlackboardArtifact> artifacts;
1376 private ArtifactsPostedEvent(Collection<BlackboardArtifact> artifacts, String moduleName)
throws BlackboardException {
1377 Set<Integer> typeIDS = artifacts.stream()
1379 .collect(Collectors.toSet());
1381 for (Integer typeID : typeIDS) {
1384 }
catch (TskCoreException tskCoreException) {
1385 throw new BlackboardException(
"Error getting artifact type by id.", tskCoreException);
1388 artifactTypes = ImmutableSet.copyOf(types);
1389 this.artifacts = ImmutableSet.copyOf(artifacts);
1390 this.moduleName = moduleName;
1395 return ImmutableSet.copyOf(artifacts);
1399 Set<BlackboardArtifact> tempSet = artifacts.stream()
1400 .filter(artifact -> artifact.getArtifactTypeID() == artifactType.getTypeID())
1401 .collect(Collectors.toSet());
1402 return ImmutableSet.copyOf(tempSet);
1410 return ImmutableSet.copyOf(artifactTypes);
static Priority fromID(int id)
List< BlackboardArtifact > getArtifacts(Collection< BlackboardArtifact.Type > artifactTypes, Collection< Long > dataSourceObjIds)
static Significance fromID(int id)
AnalysisResult getAnalysisResultById(long artifactObjId)
void postArtifact(BlackboardArtifact artifact, String moduleName)
CaseDbTransaction beginTransaction()
List< DataArtifact > getDataArtifacts(int artifactTypeID, long dataSourceObjId)
List< DataArtifact > getDataArtifacts(long dataSourceObjId, Integer artifactTypeID)
boolean hasAnalysisResults(long sourceObjId)
void postArtifacts(Collection< BlackboardArtifact > artifacts, String moduleName)
static Category fromID(int id)
void addAttributes(Collection< BlackboardAttribute > attributes)
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, long sourceObjId, Long dataSourceObjId, Collection< BlackboardAttribute > attributes, Long osAccountId)
DataArtifact getDataArtifactById(long artifactObjId)
Collection< BlackboardArtifact > getArtifacts()
BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName, BlackboardArtifact.Category category)
Score deleteAnalysisResult(AnalysisResult analysisResult)
List< AnalysisResult > getAnalysisResults(long sourceObjId)
Collection< BlackboardArtifact > getArtifacts(BlackboardArtifact.Type artifactType)
BlackboardAttribute.Type addArtifactAttributeType(String attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName)
List< DataArtifact > getDataArtifacts(int artifactTypeID)
AnalysisResultAdded newAnalysisResult(BlackboardArtifact.Type artifactType, long objId, Long dataSourceObjId, Score score, String conclusion, String configuration, String justification, Collection< BlackboardAttribute > attributesList, CaseDbTransaction transaction)
List< AnalysisResult > getAnalysisResultsWhere(String whereClause)
BlackboardAttribute.Type getOrAddAttributeType(String typeName, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName)
List< BlackboardArtifact > getArtifacts(int artifactTypeID, long dataSourceObjId)
Score deleteAnalysisResult(long artifactObjId, CaseDbTransaction transaction)
TimelineManager getTimelineManager()
void releaseSingleUserCaseReadLock()
BlackboardAttribute.Type getAttributeType(String attrTypeName)
List< AnalysisResult > getAnalysisResults(long sourceObjId, int artifactTypeId)
BlackboardArtifact.Type getArtifactType(String artTypeName)
boolean artifactExists(Content content, BlackboardArtifact.ARTIFACT_TYPE artifactType, Collection< BlackboardAttribute > attributesList)
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, long sourceObjId, Long dataSourceObjId, Collection< BlackboardAttribute > attributes, Long osAccountObjId, final CaseDbTransaction transaction)
List< AnalysisResult > getAnalysisResultsByType(int artifactTypeId, long dataSourceObjId)
Collection< BlackboardArtifact.Type > getArtifactTypes()
AnalysisResultAdded newAnalysisResult(BlackboardArtifact.Type artifactType, long objId, Long dataSourceObjId, Score score, String conclusion, String configuration, String justification, Collection< BlackboardAttribute > attributesList)
BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName)
boolean hasDataArtifacts(long sourceObjId)
void acquireSingleUserCaseReadLock()
long getArtifactsCount(int artifactTypeID, long dataSourceObjId)
List< BlackboardArtifact.Type > getArtifactTypesInUse(long dataSourceObjId)
static ReviewStatus withID(int id)
BlackboardArtifact.Type getArtifactType(int artTypeId)
BlackboardArtifact.Type addBlackboardArtifactType(String artifactTypeName, String displayName)
List< AnalysisResult > getAnalysisResultsByType(int artifactTypeId)
ScoringManager getScoringManager()