Interface Configuration<C>

Type Parameters:
C - the configuration type
All Superinterfaces:
ConfigurationDefinition<C>

public interface Configuration<C> extends ConfigurationDefinition<C>
Main interface.

The C parameter defines the configuration interface being used. For example:

     
         interface MyConfig {
             default String helloWorld() { return "hi"; }

             default boolean enabled() { return true; }
         }

         Configuration<MyConfig> configuration;
     
 

Obtaining

The factory methods defaultBuilder provide configuration builders. The builder lets the library user add type liaisons, change the locale for error messages, add migrations, and change advanced settings. Use ConfigurationBuilder.build() to get an instance of this interface.

Usage

The main point of usage is the configureWith(Backend) method. This method performs many of the main features of this library, and it will be suitable for many users. At the same time, this method is purely implemented using library functions - meaning that any library user who wants to tweak its behavior can implement it themselves.

To add simple error handling to configureWith, see configureOrFallback(Backend, ErrorPrint).

Preservation of order

Throughout the library, order is preserved from start to finish. From the moment the data is loaded from the backend, to the moment it is written back, order stays consistent.

That said, there are three reasons why the order of entries in a data tree would appear differently:

  • 1. The Backend implementation does not preserve order. If the backend does not preserve order, then order is undefined. Callers can inquire about this behavior using Backend.Meta.preservesOrder(boolean).
  • 2. The Instantiator does not scan a configuration interface (i.e., its methods) in a consistent order. For example, the Java reflections API defines no order for Class.getDeclaredMethods()
  • 3. If the user deletes existing entries, the library may attempt to add them back. Adding back the missing entries will succeed if substitute values exist (see DefaultValues.ifMissing()), however, those missing entries will be added at the back of existing data trees.
  • Method Details

    • getLocale

      @NonNull Locale getLocale()
      Gets the locale used at the library level.

      This will be used to display error messages such as in ErrorContext.display().

      Returns:
      the locale for error messages
    • getTypeLiaisons

      @NonNull List<@NonNull TypeLiaison> getTypeLiaisons()
      Gets all type liaisons.

      The order of the list is relevant, with later values being sought to handle types before earlier values.

      Returns:
      the type liaisons, which are immutable
    • getKeyMapper

      @Nullable KeyMapper getKeyMapper()
      Gets the key mapper if one was specified during construction. Note that a specified key mapper will override the standard key mapper provided by the backend (Backend.recommendKeyMapper()
      Returns:
      the key mapper if specified
    • getMigrations

      @NonNull List<@NonNull Migration<?,C>> getMigrations()
      Gets the migrations. The order of the list is relevant, with earlier migrations being tried before later ones.
      Returns:
      the migrations, which are immutable
    • defaultBuilder

      static <C> @NonNull ConfigurationBuilder<C> defaultBuilder(@NonNull Class<C> configType)
      Convenience method for building a configuration.

      Produces a configuration builder for the supplied raw type, assuming it has no generic parameters. The type is treated as unannotated.

      Default liaisons

      This method will automaticallly add the default type liaisons to the returned builder. The default type liaisons cover primitive types, String, enums, Collection, List, and Set. Please see ConfigurationBuilder.addDefaultTypeLiaisons() for more details. Callers who do not want this behavior may either construct a builder directly or add later type liaisons (which will override earlier liaisons).

      Generic Parameters

      That the configuration type configType cannot use generic parameters. Class objects are not parameterized, meaning the type C would not be available at runtime. If you need to use a parameterized configuration type, please use defaultBuilder(TypeToken) and specify the generic arguments by creating a type token.

      Type Parameters:
      C - the config type
      Parameters:
      configType - the config class, which cannot have generic parameters
      Returns:
      a config builder, with the default type liaisons set
      Throws:
      DeveloperMistakeException - if the configuration class has generic parameters
    • defaultBuilder

      static <C> @NonNull ConfigurationBuilder<C> defaultBuilder(@NonNull TypeToken<C> configType)
      Convenience method for building a configuration that adds the default type liaisons.

      Example usage

       
       Configuration<MyConfig> config = Configuration.defaultBuilder(new TypeToken<MyConfig>() {});
       
       

      Default liaisons

      This method will automaticallly add the default type liaisons to the returned builder. The default type liaisons cover primitive types, String, enums, Collection, List, and Set. Please see ConfigurationBuilder.addDefaultTypeLiaisons() for more details. Callers who do not want this behavior may either construct a builder directly or add later type liaisons (which will override earlier liaisons).

      Type Parameters:
      C - the config type
      Parameters:
      configType - the reified type token, the runtime equivalent of C
      Returns:
      a config builder, with the default type liaisons set
    • readFrom

      @NonNull LoadResult<@NonNull C> readFrom(@NonNull DataTree dataTree)
      A simple, stateless read from a data tree.

      This function loads from the data tree without modifying it, and it does not use migrations. The configuration is instantiated and returned upon success.

      The key mapper used is either the one set during construction, or the default (no-op) key mapper.

      Parameters:
      dataTree - the data tree to read from
      Returns:
      the loaded configuration
    • readFrom

      @NonNull LoadResult<@NonNull C> readFrom(@NonNull DataTree dataTree, @NonNull UpdateListener updateListener)
      A simple, stateless read from a data tree.

      This function loads from the data tree without modifying it, and it does not use migrations. The configuration is instantiated and returned upon success.

      The key mapper used is either the one set during construction, or the default (no-op) key mapper.

      Parameters:
      dataTree - the data tree to read from
      updateListener - a listener which informs the caller if certain events happened
      Returns:
      the loaded configuration
    • writeTo

      void writeTo(@NonNull C config, @NonNull DataTree.Mut dataTree)
      Writes to the given data tree.

      The output data tree does not need to be empty, but any existing data may be overwritten or cleared. The values of the provided configuration are written to it, and it does not matter how the config parameter is implemented so long as it returns non-null values without throwing exceptions.

      The key mapper used is either the one set during construction, or the default (no-op) key mapper.

      Parameters:
      config - the configuration
      dataTree - the data tree to write to
    • configureWith

      @NonNull LoadResult<@NonNull C> configureWith(@NonNull Backend backend)
      Configures, migrates, and/or updates the backend as needed.

      This "all-in-one" function leverages multiple of this library's best features. It checks for migrations and updates the config as necessary, up to the latest version. If the config was on the latest version, loads it and substitutes missing values as necessary. Lastly, if any of these operations produced a change, writes the config back to the backend. Yields the instantiated configuration.

      Parameters:
      backend - the format backend
      Returns:
      the loaded configuration
      Throws:
      UncheckedIOException - if the backend threw this error, it is propagated
    • configureWith

      @NonNull LoadResult<@NonNull C> configureWith(@NonNull Backend backend, @NonNull ConfigureListener configureListener)
      Configures, migrates, and/or updates the backend as needed.

      This "all-in-one" function leverages multiple of this library's best features. It checks for migrations and updates the config as necessary, up to the latest version. If the config was on the latest version, loads it and substitutes missing values as necessary. Lastly, if any of these operations produced a change, writes the config back to the backend. Yields the instantiated configuration.

      Parameters:
      backend - the format backend
      configureListener - a listener which informs the caller if certain events happened
      Returns:
      the loaded configuration
      Throws:
      UncheckedIOException - if the backend threw this error, it is propagated
    • configureOrFallback

      @NonNull C configureOrFallback(@NonNull Backend backend, @NonNull ErrorPrint errorPrint)
      Configures, migrates, and/or updates the backend as needed. Falls back to the default values if an error occured and prints that error.

      This "all-in-one" function leverages multiple of this library's best features. It checks for migrations and updates the config as necessary, up to the latest version. If the config was on the latest version, loads it and substitutes missing values as necessary. Lastly, if any of these operations produced a change, writes the config back to the backend. Yields the instantiated configuration.

      This function is similar to configureWith(Backend) but with error handling layered on top. That error handling is simple: upon failure, print the error and return default configuration. The backend itself is left unchanged if an error occured (e.g., an erring file would be left on disk as-is).

      Parameters:
      backend - the format backend
      errorPrint - if an error occured, it will be printed through this argument
      Returns:
      the loaded configuration, or default configuration if an error occured
      Throws:
      UncheckedIOException - if the backend threw this error, it is propagated
    • configureOrFallback

      @NonNull C configureOrFallback(@NonNull Backend backend, @NonNull ConfigureListener configureListener, @NonNull ErrorPrint errorPrint)
      Configures, migrates, and/or updates the backend as needed. Falls back to the default values if an error occured and prints that error.

      This "all-in-one" function leverages multiple of this library's best features. It checks for migrations and updates the config as necessary, up to the latest version. If the config was on the latest version, loads it and substitutes missing values as necessary. Lastly, if any of these operations produced a change, writes the config back to the backend. Yields the instantiated configuration.

      This function is similar to configureWith(Backend) but with error handling layered on top. That error handling is simple: upon failure, print the error and return default configuration. The backend itself is left unchanged if an error occured (e.g., an erring file would be left on disk as-is).

      Parameters:
      backend - the format backend
      configureListener - a listener which informs the caller if certain events happened
      errorPrint - if an error occured, it will be printed through this argument
      Returns:
      the loaded configuration, or default configuration if an error occured
      Throws:
      UncheckedIOException - if the backend threw this error, it is propagated
    • makeReloadShell

      @NonNull ReloadShell<C> makeReloadShell(@Nullable C initialValue)
      Creates a reload shell for this configuration.

      Reloading and Passthrough

      By using ReloadShell.getShell(), the caller receives a transparent proxy C, called the "shell." All calls on this shell will be automatically passed through to the current delegate, which can be updated at any time using ReloadShell.setCurrentDelegate(Object).

      By using the shell to refer to configuration values, reloading is made easier. The caller can safely store the shell (e.g., in final fields) while retaining the ability to reload the backing values at any time. Because of the passthrough behavior of the shell, method calls to the proxy will automatically use the latest values.

      Cloaking

      While reloading is the primary purpose of this method, it can also be used to limit the type of a configuration object. For example, let's say we have some X where X extends C. While the shell generated by this method will always be exactly of type C, the backing delegate could be an X. This enables users of this method to "cloak" an instance of X as if it were an instance of C, such that other code can never cast to an X.

      Parameters:
      initialValue - the initial value of the delegate; if null, calls to the shell will generate NPE's.
      Returns:
      a reload shell
    • makeErrorSource

      @NonNull ErrorContext.Source makeErrorSource()
      Creates a convenient error source.

      This error source won't provide any additional contexts to created ErrorContexts. It is provided so that callers need not undergo the pain of implementing their own error context infrastructure.

      Returns:
      an error source