Interface Backend


public interface Backend
Configuration backend for reading and writing data trees.

Configuration formats and options

A backend typically represents a configuration format, such as YAML or Json, using another library to handle parsing syntax. Some formats will expose the capability to behave differently - whether to change printing style, support commenting workarounds, or accept escape sequences. Backends can provide such options through constructor parameters.

Null values

Some configuration formats define null values. If a backend discovers a null value, it is recommended that the backend act in a user-friendly manner, either by substituting the literal string "null", or by behaving as if the referring key-value pair or list element did not exist.

A null value caused by the user string null should be replaced by the literal value "null". However, a null value which is the implicit result of user omission (e.g., a key-value pair but missing the value), might cause the backend to omit the containing entry (whether a key-value pair or list element).

Comments

Backends are not required to support comments, but it is strongly preferred if they do. If comments are supported, the backend is required to report it in Backend.Meta.supportsComments(boolean, boolean, CommentLocation), and comments (where supported) must be read and written alongside data.

Data roots

A backend will typically require some DataRoot (or subclass thereof) as the raw source. This requirement is often expressed by a constructor parameter.

  • Method Details

    • read

      @NonNull LoadResult<@Nullable Backend.Document> read(@NonNull ErrorContext.Source errorSource)
      Reads data. Upon full success, the backend returns a nonnull document.

      Emptiness

      If no data exists at the source, a null value should be returned. An example of this would be if the backend were using a PathRoot and the file in question did not exist: the implementor of this method would check DataRoot.dataExists() in this case.

      In other cases, data might exist but be blank. Here, Backends should behave in a manner appropriate to the validity of blank data in their schema. Either null or an error should be returned depending on whether blank data is a syntax exception. For example, a blank file is a valid document in YAML, and the implementor of this method would return a null document. A blank file is not valid in JSON, so a parse error might be triggered instead.

      Syntax errors

      If the loading failed because the data is malformatted, an error result should be returned. The error message can be given as ErrorContext.BACKEND_MESSAGE. Additionally, backends can recommend a syntax linter by using ErrorContext.SYNTAX_LINTER.

      IO errors

      A backend is permitted to throw UncheckedIOException to handle I/O errors coming from the data root.

      Parameters:
      errorSource - a factory for the backend to produce errors
      Returns:
      a load result of the data
      Throws:
      UncheckedIOException - upon I/O failure
    • write

      void write(@NonNull Backend.Document document)
      Writes the provided data tree to the source.

      Comments

      If the comment header is non-empty, some of it may need to be written before the rest of the data, and some of it may need to be written after the data. If not supported by this backend, this comment header may be ignored.

      Unsupported Data

      Not all configuration formats follow a data structure that aligns with DataTree's key/value model with nestable trees. For example, .properties files don't provide nested sections, and HOCON supports only string-valued keys (integer keys are impossible).

      When unsupported data structure is encountered, the implementor should throw DeveloperMistakeException. Throwing an exception is the appropriate way to signal an incompatible configuration structure. While this makes some configuration definitions constricted to compatible formats, such fail-fast behavior follows this library's culture. If need be, library users can always write migrations to change their configuration definition.

      Parameters:
      document - the document to write
      Throws:
      UncheckedIOException - upon I/O failure
      DeveloperMistakeException - if some aspects of the data structure are not supported by this backend
    • recommendKeyMapper

      @NonNull KeyMapper recommendKeyMapper()
      Recommends a KeyMapper appropriate to the backend format.

      When loading a config with Configuration.configureWith(Backend), the recommended key mapper will be selected from this method, unless the Configuration already declares its own key mapper.

      Returns:
      the recommended key mapper
    • meta

      @NonNull Backend.Meta meta()
      Gets information about this backend itself.

      The returned meta should behave consistently if invoked on identical backends. It should not be affected by the state of this Backend (or data contained in it), but only by its properties and capabilities.

      Returns:
      meta information about the backend