Class Db<T extends DbData<?>>

java.lang.Object
com.renomad.minum.database.Db<T>
Type Parameters:
T - the type of data we'll be persisting (must extend from DbData

public final class Db<T extends DbData<?>> extends Object
a memory-based disk-persisted database class.
  • Constructor Details

    • Db

      public Db(Path dbDirectory, Context context, T instance)
      Constructs an in-memory disk-persisted database. Loading of data from disk happens at the first invocation of any command changing or requesting data, such as write(DbData), delete(DbData), or values(). See the private method loadData() for details.
      Parameters:
      dbDirectory - this uniquely names your database, and also sets the directory name for this data. The expected use case is to name this after the data in question. For example, "users", or "accounts".
      context - used to provide important state data to several components
      instance - an instance of the DbData object relevant for use in this database. Note that each database (that is, each instance of this class), focuses on just one data, which must be an implementation of DbData.
  • Method Details

    • stop

      public void stop()
      This function will stop the minum.database persistence cleanly.

      In order to do this, we need to wait for our threads to finish their work. In particular, we have offloaded our file writes to [actionQueue], which has an internal thread for serializing all actions on our minum.database

    • stop

      public void stop(int count, int sleepTime)
      Similar to stop() but gives more control over how long we'll wait before crashing it closed. See ActionQueue.stop(int, int)
    • write

      public T write(T newData)
      Write data to the database. Use an index of 0 to store new data, and a positive non-zero value to update data.

      Example of adding new data to the database:

               final var newSalt = StringUtils.generateSecureRandomString(10);
               final var hashedPassword = CryptoUtils.createPasswordHash(newPassword, newSalt);
               final var newUser = new User(0L, newUsername, hashedPassword, newSalt);
               userDb.write(newUser);
      

      Example of updating data:

              // write the updated salted password to the database
              final var updatedUser = new User(
                      user().getIndex(),
                      user().getUsername(),
                      hashedPassword,
                      newSalt);
              userDb.write(updatedUser);
      
      Parameters:
      newData - the data we are writing
    • delete

      public void delete(T dataToDelete)
      Delete data

      Example:

           userDb.delete(user);
      
      Parameters:
      dataToDelete - the data we are serializing and writing
    • values

      public Collection<T> values()
      This method provides read capability for the values of a database.
      The returned collection is a read-only view over the data, through Collections.unmodifiableCollection(Collection)

      Example:

      boolean doesUserAlreadyExist(String username) {
          return userDb.values().stream().anyMatch(x -> x.getUsername().equals(username));
      }
      
    • registerIndex

      public boolean registerIndex(String indexName, Function<T,String> keyObtainingFunction)
      Register an index in the database for higher performance data access
      Parameters:
      indexName - a string used to distinguish this index. This string will be used again when requesting data in a method like getIndexedData(java.lang.String, java.lang.String) or findExactlyOne(java.lang.String, java.lang.String)
      keyObtainingFunction - a function which obtains data from the data in this database, used to partition the data into groups (potentially up to a 1-to-1 correspondence between id and object)
      Returns:
      true if the registration succeeded
    • getIndexedData

      public Collection<T> getIndexedData(String indexName, String key)
      Given the name of a registered index (see registerIndex(String, Function)), use the key to find the collection of data that matches it.
      Parameters:
      indexName - the name of an index
      key - a string value that matches a partition calculated from the partition function provided to registerIndex(String, Function)
      Returns:
      a collection of data, an empty collection if nothing found
    • getSetOfIndexes

      public Set<String> getSetOfIndexes()
      Get a set of the currently-registered indexes on this database, useful for debugging.
    • findExactlyOne

      public T findExactlyOne(String indexName, String indexKey)
      A utility to find exactly one item from the database.
      This utility will search the indexes for a particular data by indexName and indexKey. If not found, it will return null. If found, it will be returned. If more than one are found, an exception will be thrown. Use this tool when the data has been uniquely indexed, like for example when setting a unique identifier into each data.
      Parameters:
      indexName - the name of the index, an arbitrary value set by the user to help distinguish among potentially many indexes set on this data
      indexKey - the key for this particular value, such as a UUID or a name or any other way to partition the data
      See Also:
    • findExactlyOne

      public T findExactlyOne(String indexName, String indexKey, Callable<T> alternate)
      Find one item, with an alternate value if null
      This utility will search the indexes for a particular data by indexName and indexKey. If not found, it will return null. If found, it will be returned. If more than one are found, an exception will be thrown. Use this tool when the data has been uniquely indexed, like for example when setting a unique identifier into each data.
      Parameters:
      indexName - the name of the index, an arbitrary value set by the user to help distinguish among potentially many indexes set on this data
      indexKey - the key for this particular value, such as a UUID or a name or any other way to partition the data
      alternate - a functional interface that will be run if the result would have been null, useful for situations where you don't want the output to be null when nothing is found.
      See Also: