chromium/chromeos/ash/components/file_manager/indexing/file_index.h

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_ASH_COMPONENTS_FILE_MANAGER_INDEXING_FILE_INDEX_H_
#define CHROMEOS_ASH_COMPONENTS_FILE_MANAGER_INDEXING_FILE_INDEX_H_

#include <memory>
#include <set>
#include <vector>

#include "chromeos/ash/components/file_manager/indexing/file_info.h"
#include "chromeos/ash/components/file_manager/indexing/index_storage.h"
#include "chromeos/ash/components/file_manager/indexing/query.h"
#include "chromeos/ash/components/file_manager/indexing/search_results.h"
#include "chromeos/ash/components/file_manager/indexing/term.h"
#include "url/gurl.h"

namespace ash::file_manager {

// Results of an indexing operation.
enum OpResults {
  // A value reserved for indicating lack of valid error handling.
  kUndefined = 0,
  // Successful operation. This may mean no-op operation. For example, asking
  // the index to remove a file that was never part of it, is considered a
  // success.
  kSuccess,
  // A generic error, equivalent to the "something went wrong" error.
  kGenericError,
  // An error indicating that the arguments of the method were invalid.
  kArgumentError,
  // Returned by operations called if the index was not initialized.
  kUninitialized,
  // Returned by operations that manipulate file terms if file is unknown.
  kFileMissing,
  // Returned by the move operation if the "new" file already exists.
  kFileExists,
};

// Abstract class that defines the interface of the file index. Typical index
// use:
//
//   // Fetch the index.
//   FileIndex* index = ....;
//   // Register a file that is kept in the index.
//   FileInfo info = {...};
//   index->PutFileInfo(info);
//   // Set the terms used with the file.
//   index->SetTerms({term_1, term_2}, info.file_url);
//   // Add new terms used with the file.
//   index->AddTerms({term_1, term_3}, info.file_url);
//   // Remove some terms used with the file.
//   index->RemoveTerms({term_3}, info.file_url);
//   // Search for matching files by a query.
//   SearchResults results = index->Search(Query({term_2}));
//   // Delete the file from the index.
//   index->RemoveFile(info.file_url);
class FileIndex {
 public:
  // Creates a new file index supported by the given storage.
  explicit FileIndex(std::unique_ptr<IndexStorage> storage);
  ~FileIndex();

  FileIndex(const FileIndex&) = delete;
  FileIndex& operator=(const FileIndex&) = delete;

  // Initializes this index; must be called before any index operations are
  // invoked. Returns false if the initialization failed.
  OpResults Init();

  // Stores the given `file_info` in this index. This method must be called
  // before any other methods that either set or add terms associated
  // with this file are called.
  OpResults PutFileInfo(const FileInfo& file_info);

  // Removes the file uniquely identified by the URL from this index. This is
  // preferred way of removing files over calling the SetTerms method with an
  // empty terms vector. Returns true if the file was found and removed.
  OpResults RemoveFile(const GURL& url);

  // Moves the file that was put under the `old_url` to the `new_url`.
  OpResults MoveFile(const GURL& old_url, const GURL& new_url);

  // Sets terms associated with the file. The `url` must be of a FileInfo
  // previously put in the index. Please note that only the passed terms are
  // associated with the file. Thus if you call this method first with, say
  // Term("label", "downloaded"), and then call this method with, say,
  // Term("label", "pinned") only the "pinned" label is associated with
  // the given `file_info`. If you want both terms to be associated you must
  // pass both terms in a single call or use the AddTerms() method.
  //
  // It is an error to pass an empty term vector. Use the RemoveFile() method
  // instead.
  OpResults SetTerms(const std::vector<Term>& terms, const GURL& url);

  // Adds terms associated with the file with the specified `url` with
  // the `terms` given as the first argument. Once this operation is finished,
  // the file can be retrieved by any existing terms that were associated with
  // it, or any new terms this call added. For example, if you first call the
  // SetTerms() method with Term("label", "downloaded") and then call
  // AddTerms() method with Term("label", "starred") you can retrieve the
  // file with the matching `url` (specified in both of these calls) by either
  // or both of the terms.
  OpResults AddTerms(const std::vector<Term>& terms, const GURL& url);

  // Removes the specified term from terms associated with the file with the
  // given URL.
  OpResults RemoveTerms(const std::vector<Term>& terms, const GURL& url);

  // Searches the index for file info matching the specified query.
  SearchResults Search(const Query& query);

 private:
  // Does a bulk conversion of given terms to term IDs.
  std::set<int64_t> ConvertToTermIds(const std::vector<Term>& terms);

  // Actual storage for structures needed to implement the inverted index.
  std::unique_ptr<IndexStorage> storage_;
};

}  // namespace ash::file_manager

#endif  // CHROMEOS_ASH_COMPONENTS_FILE_MANAGER_INDEXING_FILE_INDEX_H_