Class AbstractPersistenceDelegate<T>

java.lang.Object
de.bsommerfeld.jshepherd.core.AbstractPersistenceDelegate<T>
All Implemented Interfaces:
PersistenceDelegate<T>

public abstract class AbstractPersistenceDelegate<T> extends Object implements PersistenceDelegate<T>
Abstract base class for all persistence delegates. Provides common functionality for file operations, type conversion, comment writing, and reflection-based data mapping.
  • Field Details

    • MAX_SECTION_DEPTH

      protected static final int MAX_SECTION_DEPTH
      Safety cap for recursive @Section nesting, protecting against accidental cycles in section POJO graphs.
      See Also:
    • filePath

      protected final Path filePath
    • useComplexSaveWithComments

      protected final boolean useComplexSaveWithComments
  • Constructor Details

    • AbstractPersistenceDelegate

      protected AbstractPersistenceDelegate(Path filePath, boolean useComplexSaveWithComments)
  • Method Details

    • loadInitial

      public final T loadInitial(Supplier<T> defaultPojoSupplier)
      Description copied from interface: PersistenceDelegate
      Loads the initial POJO instance from the persistent store, or creates and saves a default if the store is new or empty.
      Specified by:
      loadInitial in interface PersistenceDelegate<T>
      Parameters:
      defaultPojoSupplier - Supplier for creating a default POJO instance.
      Returns:
      The loaded or newly created default POJO instance.
    • save

      public final void save(T pojoInstance)
      Description copied from interface: PersistenceDelegate
      Saves the provided POJO instance to the persistent store.
      Specified by:
      save in interface PersistenceDelegate<T>
      Parameters:
      pojoInstance - The POJO instance to save.
    • reload

      public final void reload(T pojoInstanceToUpdate)
      Description copied from interface: PersistenceDelegate
      Reloads data from the persistent store into the provided POJO instance, updating its fields.
      Specified by:
      reload in interface PersistenceDelegate<T>
      Parameters:
      pojoInstanceToUpdate - The POJO instance whose fields should be updated.
    • getLastLoadIssues

      public final List<LoadIssue> getLastLoadIssues()
      Description copied from interface: PersistenceDelegate
      Returns the per-key issues recorded during the last load or reload.
      Specified by:
      getLastLoadIssues in interface PersistenceDelegate<T>
      Returns:
      an immutable list; empty if the last load was clean
    • convertNumericIfNeeded

      protected final Object convertNumericIfNeeded(Object value, Class<?> targetType)
      Converts values to match the target type. Handles numeric widening/narrowing and String-to-Enum conversion.
    • isEnumType

      protected final boolean isEnumType(Class<?> type)
      Checks if the given type is an enum type.
    • serializeEnumValue

      protected final String serializeEnumValue(Object enumValue)
      Returns the constant name of an enum value for format-agnostic serialization.
    • applyDataToInstance

      protected final void applyDataToInstance(T target, AbstractPersistenceDelegate.DataExtractor extractor)
      Applies data from parsed format to POJO instance using reflection.
    • convertValueForField

      protected final Object convertValueForField(Object value, Field field)
      Converts a raw parsed value to the field's type, including element-wise conversion for typed lists and maps (e.g. TOML integers arrive as Long and must be narrowed for a List<Integer> field).
    • resolveGenericClass

      protected final Class<?> resolveGenericClass(Field field, int index)
      Resolves the class of a field's generic type argument (e.g. the element type of a List<Integer>), or null if not determinable.
    • recordLoadIssue

      protected final void recordLoadIssue(String key, Object rawValue, Class<?> targetType, Exception cause)
      Records a value that could not be applied to its field. The issue is logged and made available to the user via ConfigurablePojo.getLastLoadIssues() after the load completes, so it can be validated in @PostInject methods.
    • shouldSkipField

      protected final boolean shouldSkipField(Field field)
      Checks if a field should be skipped during persistence operations. Skips static and transient fields.
    • writeClassComments

      protected final void writeClassComments(PrintWriter writer, T pojoInstance)
      Writes class-level comments (file header) from @Comment annotation on the POJO class.
    • writeFieldComments

      protected final void writeFieldComments(PrintWriter writer, Field field)
      Writes field-level comments from @Comment annotation.
    • resolveKey

      protected final String resolveKey(Field field)
      Resolves the configuration key for a field, using @Key annotation value or field name.
    • isSection

      protected final boolean isSection(Field field)
      Checks if a field is annotated with @Section.
    • resolveSectionName

      protected final String resolveSectionName(Field field)
      Resolves the section name from @Section annotation, falling back to @Key or field name.
    • getNonSectionFields

      protected final List<Field> getNonSectionFields(Class<?> clazz, Class<?> stopClass)
      Gets all non-section fields (regular @Key fields) from a class. These should be written first, before any sections.
    • getSectionFields

      protected final List<Field> getSectionFields(Class<?> clazz, Class<?> stopClass)
      Gets all section fields from a class. These should be written after regular fields.
    • getSectionPojoFields

      protected final List<Field> getSectionPojoFields(Object sectionPojo)
      Gets all fields from a nested section POJO that have @Key annotation. Section POJOs don't extend ConfigurablePojo, so we use Object as stop class.
    • getSectionPojoSubsectionFields

      protected final List<Field> getSectionPojoSubsectionFields(Object sectionPojo)
      Gets all nested @Section fields of a section POJO, enabling recursive section nesting. Guard recursion with MAX_SECTION_DEPTH.
    • tryLoadFromFile

      protected abstract boolean tryLoadFromFile(T instance) throws Exception
      Format-specific loading implementation.
      Returns:
      true if data was loaded successfully, false if file was empty
      Throws:
      Exception
    • saveSimple

      protected abstract void saveSimple(T pojoInstance, Path targetPath) throws IOException
      Format-specific simple save implementation.
      Throws:
      IOException
    • saveWithComments

      protected abstract void saveWithComments(T pojoInstance, Path targetPath) throws IOException
      Format-specific save with comments implementation.
      Throws:
      IOException