Sleuth Kit Java Bindings (JNI)  4.11.0
Java bindings for using The Sleuth Kit
TaggingManager.java
Go to the documentation of this file.
1 /*
2  * Sleuth Kit Data Model
3  *
4  * Copyright 2020-2021 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.datamodel;
20 
21 import java.sql.PreparedStatement;
22 import java.sql.ResultSet;
23 import java.sql.SQLException;
24 import java.sql.Statement;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Optional;
37 
41 public class TaggingManager {
42 
43  private final SleuthkitCase skCase;
44 
51  this.skCase = skCase;
52  }
53 
61  public List<TagSet> getTagSets() throws TskCoreException {
62  List<TagSet> tagSetList = new ArrayList<>();
63 
65  String getAllTagSetsQuery = "SELECT * FROM tsk_tag_sets";
66  try (CaseDbConnection connection = skCase.getConnection(); Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(getAllTagSetsQuery);) {
67  while (resultSet.next()) {
68  int setID = resultSet.getInt("tag_set_id");
69  String setName = resultSet.getString("name");
70  TagSet set = new TagSet(setID, setName, getTagNamesByTagSetID(setID));
71  tagSetList.add(set);
72  }
73  } catch (SQLException ex) {
74  throw new TskCoreException("Error occurred getting TagSet list.", ex);
75  } finally {
77  }
78  return tagSetList;
79  }
80 
91  public TagSet addTagSet(String name, List<TagName> tagNames) throws TskCoreException {
92  if (name == null || name.isEmpty()) {
93  throw new IllegalArgumentException("Error adding TagSet, TagSet name must be non-empty string.");
94  }
95 
96  TagSet tagSet = null;
97 
98  CaseDbTransaction trans = skCase.beginTransaction();
99  try (Statement stmt = trans.getConnection().createStatement()) {
100  String query = String.format("INSERT INTO tsk_tag_sets (name) VALUES('%s')", name);
101 
102  if (skCase.getDatabaseType() == POSTGRESQL) {
103  stmt.execute(query, Statement.RETURN_GENERATED_KEYS);
104  } else {
105  stmt.execute(query);
106  }
107 
108  try (ResultSet resultSet = stmt.getGeneratedKeys()) {
109 
110  resultSet.next();
111  int setID = resultSet.getInt(1);
112 
113  List<TagName> updatedTags = new ArrayList<>();
114  if (tagNames != null) {
115  // Get all of the TagName ids they can be updated in one
116  // SQL call.
117  for (int index = 0; index < tagNames.size(); index++) {
118  TagName tagName = tagNames.get(index);
119  stmt.executeUpdate(String.format("UPDATE tag_names SET tag_set_id = %d, rank = %d WHERE tag_name_id = %d", setID, index, tagName.getId()));
120  updatedTags.add(new TagName(tagName.getId(),
121  tagName.getDisplayName(),
122  tagName.getDescription(),
123  tagName.getColor(),
124  tagName.getKnownStatus(),
125  setID,
126  index));
127  }
128  }
129  tagSet = new TagSet(setID, name, updatedTags);
130  skCase.fireTSKEvent(new TagSetsAddedTskEvent(Collections.singletonList(tagSet)));
131  skCase.fireTSKEvent(new TagNamesUpdatedTskEvent(updatedTags));
132  }
133  trans.commit();
134  } catch (SQLException ex) {
135  trans.rollback();
136  throw new TskCoreException(String.format("Error adding tag set %s", name), ex);
137  }
138 
139  return tagSet;
140  }
141 
152  public void deleteTagSet(TagSet tagSet) throws TskCoreException {
153  if (tagSet == null) {
154  throw new IllegalArgumentException("Error adding deleting TagSet, TagSet object was null");
155  }
156 
157  if (isTagSetInUse(tagSet)) {
158  throw new TskCoreException("Unable to delete TagSet (%d). TagSet TagName list contains TagNames that are currently in use.");
159  }
160 
161  CaseDbTransaction trans = skCase.beginTransaction();
162  try (Statement stmt = trans.getConnection().createStatement()) {
163  String queryTemplate = "DELETE FROM tag_names WHERE tag_name_id IN (SELECT tag_name_id FROM tag_names WHERE tag_set_id = %d)";
164  stmt.execute(String.format(queryTemplate, tagSet.getId()));
165 
166  queryTemplate = "DELETE FROM tsk_tag_sets WHERE tag_set_id = '%d'";
167  stmt.execute(String.format(queryTemplate, tagSet.getId()));
168  trans.commit();
169 
170  List<Long> tagNameIds = new ArrayList<>();
171  for (TagName tagName : tagSet.getTagNames()) {
172  tagNameIds.add(tagName.getId());
173  }
174 
175  skCase.fireTSKEvent(new TagSetsDeletedTskEvent(Collections.singletonList(tagSet.getId())));
176  skCase.fireTSKEvent(new TagNamesDeletedTskEvent(tagNameIds));
177  } catch (SQLException ex) {
178  trans.rollback();
179  throw new TskCoreException(String.format("Error deleting tag set where id = %d.", tagSet.getId()), ex);
180  }
181  }
182 
192  public TagSet getTagSet(TagName tagName) throws TskCoreException {
193  if (tagName == null) {
194  throw new IllegalArgumentException("Null tagName argument");
195  }
196 
197  if (tagName.getTagSetId() <= 0) {
198  return null;
199  }
200 
202  TagSet tagSet = null;
203  String sqlQuery = String.format("SELECT * FROM tsk_tag_sets WHERE tag_set_id = %d", tagName.getTagSetId());
204  try (CaseDbConnection connection = skCase.getConnection(); Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(sqlQuery);) {
205  if (resultSet.next()) {
206  int setID = resultSet.getInt("tag_set_id");
207  String setName = resultSet.getString("name");
208  tagSet = new TagSet(setID, setName, getTagNamesByTagSetID(setID));
209  }
210  return tagSet;
211  } catch (SQLException ex) {
212  throw new TskCoreException(String.format("Error occurred getting TagSet for TagName '%s' (ID=%d)", tagName.getDisplayName(), tagName.getId()), ex);
213  } finally {
215  }
216  }
217 
228  public TagSet getTagSet(long id) throws TskCoreException {
229  TagSet tagSet = null;
230  String preparedQuery = "Select * FROM tsk_tag_sets WHERE tag_set_id = ?";
232  try (CaseDbConnection connection = skCase.getConnection(); PreparedStatement statement = connection.getPreparedStatement(preparedQuery, Statement.NO_GENERATED_KEYS)) {
233  statement.setLong(1, id);
234  try (ResultSet resultSet = statement.executeQuery()) {
235  if (resultSet.next()) {
236  int setID = resultSet.getInt("tag_set_id");
237  String setName = resultSet.getString("name");
238  tagSet = new TagSet(setID, setName, getTagNamesByTagSetID(setID));
239  }
240  }
241 
242  } catch (SQLException ex) {
243  throw new TskCoreException(String.format("Error occurred getting TagSet (ID=%d)", id), ex);
244  } finally {
246  }
247 
248  return tagSet;
249  }
250 
264  public BlackboardArtifactTagChange addArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
265  if (artifact == null || tagName == null) {
266  throw new IllegalArgumentException("NULL argument passed to addArtifactTag");
267  }
268 
269  List<BlackboardArtifactTag> removedTags = new ArrayList<>();
270  List<String> removedTagIds = new ArrayList<>();
271  CaseDbTransaction trans = null;
272  try {
273  // If a TagName is part of a TagSet remove any existing tags from the
274  // set that are currenctly on the artifact
275  long tagSetId = tagName.getTagSetId();
276  if (tagSetId > 0) {
277  // Get the list of all of the blackboardArtifactTags that use
278  // TagName for the given artifact.
279  String selectQuery = String.format("SELECT * from blackboard_artifact_tags JOIN tag_names ON tag_names.tag_name_id = blackboard_artifact_tags.tag_name_id JOIN tsk_examiners on tsk_examiners.examiner_id = blackboard_artifact_tags.examiner_id WHERE artifact_id = %d AND tag_names.tag_set_id = %d", artifact.getArtifactID(), tagSetId);
280  TagName removedTag;
281  try (Statement stmt = skCase.getConnection().createStatement(); ResultSet resultSet = stmt.executeQuery(selectQuery)) {
282  while (resultSet.next()) {
283  removedTag = new TagName(
284  resultSet.getLong("tag_name_id"),
285  resultSet.getString("display_name"),
286  resultSet.getString("description"),
287  TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
288  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")),
289  tagSetId,
290  resultSet.getInt("rank")
291  );
292 
294  = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
295  artifact,
296  skCase.getContentById(artifact.getObjectID()),
297  removedTag,
298  resultSet.getString("comment"),
299  resultSet.getString("login_name"));
300 
301  removedTags.add(bat);
302  removedTagIds.add(Long.toString(bat.getId()));
303  }
304  }
305 
306  }
307 
308  Content content = skCase.getContentById(artifact.getObjectID());
309  Examiner currentExaminer = skCase.getCurrentExaminer();
310 
311  trans = skCase.beginTransaction();
312  CaseDbConnection connection = trans.getConnection();
313 
314  if (!removedTags.isEmpty()) {
315  // Remove the tags.
316  String removeQuery = String.format("DELETE FROM blackboard_artifact_tags WHERE tag_id IN (%s)", String.join(",", removedTagIds));
317  try (Statement stmt = connection.createStatement()) {
318  stmt.executeUpdate(removeQuery);
319  }
320  }
321 
322  // Add the new Tag.
323  BlackboardArtifactTag artifactTag;
324  try (Statement stmt = connection.createStatement()) {
325 
326  String query = String.format(
327  "INSERT INTO blackboard_artifact_tags (artifact_id, tag_name_id, comment, examiner_id) VALUES (%d, %d, '%s', %d)",
328  artifact.getArtifactID(),
329  tagName.getId(),
330  comment,
331  currentExaminer.getId());
332 
333  if (skCase.getDatabaseType() == POSTGRESQL) {
334  stmt.execute(query, Statement.RETURN_GENERATED_KEYS);
335  } else {
336  stmt.execute(query);
337  }
338 
339  try (ResultSet resultSet = stmt.getGeneratedKeys()) {
340  resultSet.next();
341  artifactTag = new BlackboardArtifactTag(resultSet.getLong(1), //last_insert_rowid()
342  artifact, content, tagName, comment, currentExaminer.getLoginName());
343  }
344  }
345 
346  skCase.getScoringManager().updateAggregateScoreAfterAddition(
347  artifact.getId(), artifact.getDataSourceObjectID(), getTagScore(tagName.getKnownStatus()), trans);
348 
349  trans.commit();
350 
351  return new BlackboardArtifactTagChange(artifactTag, removedTags);
352  } catch (SQLException ex) {
353  if (trans != null) {
354  trans.rollback();
355  }
356  throw new TskCoreException("Error adding row to blackboard_artifact_tags table (obj_id = " + artifact.getArtifactID() + ", tag_name_id = " + tagName.getId() + ")", ex);
357  }
358  }
359 
368  static Score getTagScore(TskData.FileKnown knownStatus) {
369  switch (knownStatus) {
370  case BAD:
371  /*
372  * The "bad" known status is used to define tags that are
373  * "notable." An item tagged with a "notable" tag is scored as
374  * notable.
375  */
376  return Score.SCORE_NOTABLE;
377  case UNKNOWN:
378  case KNOWN:
379  default: // N/A
380  /*
381  * All other known status values have no special significance in
382  * a tag definition. However, if an item has been tagged at all
383  * by a user, the item is scored as likely notable.
384  */
386  }
387  }
388 
400  Optional<TskData.FileKnown> getMaxTagKnownStatus(long objectId, CaseDbTransaction transaction) throws TskCoreException {
401  // query content tags and blackboard artifact tags for highest
402  // known status associated with a tag associated with this object id
403  String queryString = "SELECT tag_names.knownStatus AS knownStatus\n"
404  + " FROM (\n"
405  + " SELECT ctags.tag_name_id AS tag_name_id FROM content_tags ctags WHERE ctags.obj_id = " + objectId + "\n"
406  + " UNION\n"
407  + " SELECT btags.tag_name_id AS tag_name_id FROM blackboard_artifact_tags btags \n"
408  + " INNER JOIN blackboard_artifacts ba ON btags.artifact_id = ba.artifact_id\n"
409  + " WHERE ba.artifact_obj_id = " + objectId + "\n"
410  + " ) tag_name_ids\n"
411  + " INNER JOIN tag_names ON tag_name_ids.tag_name_id = tag_names.tag_name_id\n"
412  + " ORDER BY tag_names.knownStatus DESC\n"
413  + " LIMIT 1";
414 
415  try (Statement statement = transaction.getConnection().createStatement();
416  ResultSet resultSet = transaction.getConnection().executeQuery(statement, queryString);) {
417 
418  if (resultSet.next()) {
419  return Optional.ofNullable(TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")));
420  } else {
421  return Optional.empty();
422  }
423 
424  } catch (SQLException ex) {
425  throw new TskCoreException("Error getting content tag FileKnown status for content with id: " + objectId);
426  }
427  }
428 
442  public ContentTagChange addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException {
443  List<ContentTag> removedTags = new ArrayList<>();
444  List<String> removedTagIds = new ArrayList<>();
445  Examiner currentExaminer = skCase.getCurrentExaminer();
446  CaseDbTransaction trans = skCase.beginTransaction();
447  CaseDbConnection connection = trans.getConnection();
448 
449  try {
450  long tagSetId = tagName.getTagSetId();
451 
452  if (tagSetId > 0) {
453  String selectQuery = String.format("SELECT * from content_tags JOIN tag_names ON tag_names.tag_name_id = content_tags.tag_name_id JOIN tsk_examiners on tsk_examiners.examiner_id = content_tags.examiner_id WHERE obj_id = %d AND tag_names.tag_set_id = %d", content.getId(), tagSetId);
454 
455  try (Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(selectQuery)) {
456  while (resultSet.next()) {
457  TagName removedTag = new TagName(
458  resultSet.getLong("tag_name_id"),
459  resultSet.getString("display_name"),
460  resultSet.getString("description"),
461  TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
462  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")),
463  tagSetId,
464  resultSet.getInt("rank")
465  );
466 
467  ContentTag bat
468  = new ContentTag(resultSet.getLong("tag_id"),
469  content,
470  removedTag,
471  resultSet.getString("comment"),
472  resultSet.getLong("begin_byte_offset"),
473  resultSet.getLong("end_byte_offset"),
474  resultSet.getString("login_name"));
475 
476  removedTagIds.add(Long.toString(bat.getId()));
477  removedTags.add(bat);
478  }
479  }
480 
481  if (!removedTags.isEmpty()) {
482  String removeQuery = String.format("DELETE FROM content_tags WHERE tag_id IN (%s)", String.join(",", removedTagIds));
483  try (Statement stmt = connection.createStatement()) {
484  stmt.executeUpdate(removeQuery);
485  }
486  }
487  }
488 
489  String queryTemplate = "INSERT INTO content_tags (obj_id, tag_name_id, comment, begin_byte_offset, end_byte_offset, examiner_id) VALUES (%d, %d, '%s', %d, %d, %d)";
490  ContentTag contentTag = null;
491  try (Statement stmt = connection.createStatement()) {
492 
493  String query = String.format(queryTemplate,
494  content.getId(),
495  tagName.getId(),
496  comment,
497  beginByteOffset,
498  endByteOffset,
499  currentExaminer.getId());
500 
501  if (skCase.getDatabaseType() == POSTGRESQL) {
502  stmt.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
503  } else {
504  stmt.executeUpdate(query);
505  }
506 
507  try (ResultSet resultSet = stmt.getGeneratedKeys()) {
508  resultSet.next();
509  contentTag = new ContentTag(resultSet.getLong(1), //last_insert_rowid()
510  content, tagName, comment, beginByteOffset, endByteOffset, currentExaminer.getLoginName());
511  }
512  }
513 
514  Long dataSourceId = content.getDataSource() != null ? content.getDataSource().getId() : null;
515  skCase.getScoringManager().updateAggregateScoreAfterAddition(
516  content.getId(), dataSourceId, getTagScore(tagName.getKnownStatus()), trans);
517 
518  trans.commit();
519  return new ContentTagChange(contentTag, removedTags);
520  } catch (SQLException ex) {
521  trans.rollback();
522  throw new TskCoreException("Error adding row to content_tags table (obj_id = " + content.getId() + ", tag_name_id = " + tagName.getId() + ")", ex);
523  }
524  }
525 
540  public TagName addOrUpdateTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TskCoreException {
541  String insertQuery = "INSERT INTO tag_names (display_name, description, color, knownStatus) VALUES (?, ?, ?, ?) ON CONFLICT (display_name) DO UPDATE SET description = ?, color = ?, knownStatus = ?";
542  boolean isUpdated = false;
544  try (CaseDbConnection connection = skCase.getConnection()) {
545  try (PreparedStatement statement = connection.getPreparedStatement("SELECT * FROM tag_names WHERE display_name = ?", Statement.NO_GENERATED_KEYS)) {
546  statement.setString(1, displayName);
547  try (ResultSet resultSet = statement.executeQuery()) {
548  isUpdated = resultSet.next();
549  }
550  }
551 
552  try (PreparedStatement statement = connection.getPreparedStatement(insertQuery, Statement.RETURN_GENERATED_KEYS);) {
553  statement.clearParameters();
554  statement.setString(5, description);
555  statement.setString(6, color.getName());
556  statement.setByte(7, knownStatus.getFileKnownValue());
557  statement.setString(1, displayName);
558  statement.setString(2, description);
559  statement.setString(3, color.getName());
560  statement.setByte(4, knownStatus.getFileKnownValue());
561  statement.executeUpdate();
562  }
563 
564  try (PreparedStatement statement = connection.getPreparedStatement("SELECT * FROM tag_names where display_name = ?", Statement.NO_GENERATED_KEYS)) {
565  statement.setString(1, displayName);
566  try (ResultSet resultSet = connection.executeQuery(statement)) {
567  resultSet.next();
568  TagName newTag = new TagName(resultSet.getLong("tag_name_id"), displayName, description, color, knownStatus, resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
569 
570  if (!isUpdated) {
571  skCase.fireTSKEvent(new TagNamesAddedTskEvent(Collections.singletonList(newTag)));
572  } else {
573  skCase.fireTSKEvent(new TagNamesUpdatedTskEvent(Collections.singletonList(newTag)));
574  }
575 
576  return newTag;
577  }
578  }
579  } catch (SQLException ex) {
580  throw new TskCoreException("Error adding row for " + displayName + " tag name to tag_names table", ex);
581  } finally {
583  }
584  }
585 
595  public TagName getTagName(long id) throws TskCoreException {
596  String preparedQuery = "SELECT * FROM tag_names where tag_name_id = ?";
597 
599  try (CaseDbConnection connection = skCase.getConnection()) {
600  try (PreparedStatement statement = connection.getPreparedStatement(preparedQuery, Statement.NO_GENERATED_KEYS)) {
601  statement.clearParameters();
602  statement.setLong(1, id);
603  try (ResultSet resultSet = statement.executeQuery()) {
604  if (resultSet.next()) {
605  return new TagName(resultSet.getLong("tag_name_id"),
606  resultSet.getString("display_name"),
607  resultSet.getString("description"),
608  TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
609  TskData.FileKnown.valueOf(resultSet.getByte("knowStatus")),
610  resultSet.getLong("tag_set_id"),
611  resultSet.getInt("rank"));
612  }
613  }
614  }
615  } catch (SQLException ex) {
616  throw new TskCoreException("", ex);
617  } finally {
619  }
620 
621  return null;
622  }
623 
634  private boolean isTagSetInUse(TagSet tagSet) throws TskCoreException {
636  try (CaseDbConnection connection = skCase.getConnection()) {
637  List<TagName> tagNameList = tagSet.getTagNames();
638  if (tagNameList != null && !tagNameList.isEmpty()) {
639  String statement = String.format("SELECT tag_id FROM content_tags WHERE tag_name_id IN (SELECT tag_name_id FROM tag_names WHERE tag_set_id = %d)", tagSet.getId());
640  try (Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(statement)) {
641  if (resultSet.next()) {
642  return true;
643  }
644  } catch (SQLException ex) {
645  throw new TskCoreException(String.format("Failed to determine if TagSet is in use (%s)", tagSet.getId()), ex);
646  }
647 
648  statement = String.format("SELECT tag_id FROM blackboard_artifact_tags WHERE tag_name_id IN (SELECT tag_name_id FROM tag_names WHERE tag_set_id = %d)", tagSet.getId());
649  try (Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(statement)) {
650  if (resultSet.next()) {
651  return true;
652  }
653  } catch (SQLException ex) {
654  throw new TskCoreException(String.format("Failed to determine if TagSet is in use (%s)", tagSet.getId()), ex);
655  }
656  }
657  } finally {
659  }
660 
661  return false;
662  }
663 
673  private List<TagName> getTagNamesByTagSetID(int tagSetId) throws TskCoreException {
674 
675  if (tagSetId <= 0) {
676  throw new IllegalArgumentException("Invalid tagSetID passed to getTagNameByTagSetID");
677  }
678 
679  List<TagName> tagNameList = new ArrayList<>();
680 
682  String query = String.format("SELECT * FROM tag_names WHERE tag_set_id = %d", tagSetId);
683  try (CaseDbConnection connection = skCase.getConnection(); Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(query)) {
684  while (resultSet.next()) {
685  tagNameList.add(new TagName(resultSet.getLong("tag_name_id"),
686  resultSet.getString("display_name"),
687  resultSet.getString("description"),
688  TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
689  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")),
690  tagSetId,
691  resultSet.getInt("rank")));
692  }
693  } catch (SQLException ex) {
694  throw new TskCoreException(String.format("Error getting tag names for tag set (%d)", tagSetId), ex);
695  } finally {
697  }
698 
699  return tagNameList;
700  }
701 
705  public static class BlackboardArtifactTagChange {
706 
707  private final BlackboardArtifactTag addedTag;
708  private final List<BlackboardArtifactTag> removedTagList;
709 
716  BlackboardArtifactTagChange(BlackboardArtifactTag added, List<BlackboardArtifactTag> removed) {
717  this.addedTag = added;
718  this.removedTagList = removed;
719  }
720 
727  return addedTag;
728  }
729 
735  public List<BlackboardArtifactTag> getRemovedTags() {
736  return Collections.unmodifiableList(removedTagList);
737  }
738  }
739 
743  public static class ContentTagChange {
744 
745  private final ContentTag addedTag;
746  private final List<ContentTag> removedTagList;
747 
754  ContentTagChange(ContentTag added, List<ContentTag> removed) {
755  this.addedTag = added;
756  this.removedTagList = removed;
757  }
758 
765  return addedTag;
766  }
767 
773  public List<ContentTag> getRemovedTags() {
774  return Collections.unmodifiableList(removedTagList);
775  }
776  }
777 }
static FileKnown valueOf(byte known)
Definition: TskData.java:810
TagName addOrUpdateTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus)
static final Score SCORE_NOTABLE
Definition: Score.java:208
BlackboardArtifactTagChange addArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment)
TskData.FileKnown getKnownStatus()
Definition: TagName.java:119
static HTML_COLOR getColorByName(String colorName)
Definition: TagName.java:76
ContentTagChange addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset)
static final Score SCORE_LIKELY_NOTABLE
Definition: Score.java:209
TagSet addTagSet(String name, List< TagName > tagNames)

Copyright © 2011-2021 Brian Carrier. (carrier -at- sleuthkit -dot- org)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.