Skip to content

Releases: jeyben/fixedformat4j

1.7.2

20 Apr 20:55

Choose a tag to compare

See changelog for details.

1.7.1

18 Apr 18:37

Choose a tag to compare

New features

  • nullChar on @Field — opt-in sentinel to distinguish a genuinely-absent field from zero/empty. Null-aware handling is active only when nullChar differs from paddingChar. On load, an all-nullChar slice yields null; on export, a null value is emitted as length × nullChar. Works per-element for repeating fields (count > 1). (#29)

  • Record-level default alignment via @Record(align = …) — sets a default alignment for all fields in the record; individual fields may still override with an explicit @Field(align = …). (#30)

Validation improvements

  • Align.INHERIT is now rejected on @Record(align) with a clear FixedFormatException (it is a field-only sentinel).
  • nullChar is now rejected on @Field with a primitive return type (int, long, etc.) — primitives can never be null.

1.7.0

18 Apr 14:01

Choose a tag to compare

Breaking changes

  • AbstractFixedFormatter.getRemovePadding removed — deprecated in 1.6.1 and now deleted.
    Rename any override to stripPadding; the signature is identical. The call chain is now
    parse()stripPadding() directly.

    // Before (1.6.x)
    @Override
    protected String getRemovePadding(String value, FormatInstructions instructions) { … }
    
    // After (1.7.0+)
    @Override
    protected String stripPadding(String value, FormatInstructions instructions) { … }

New features

  • Enum support via @FixedFormatEnum (#67) —
    Annotate any getter that returns an enum type with @FixedFormatEnum to control how the value
    is serialised in the fixed-width record. Two modes are available through the EnumFormat enum:

    • LITERAL (default) — stores and reads the enum constant name (Enum.name() / valueOf()).
    • NUMERIC — stores and reads the ordinal as a zero-padded integer (Enum.ordinal() / index lookup).
    public enum Status { ACTIVE, INACTIVE }
    
    // LITERAL (default): stores "ACTIVE" / "INACTIVE"
    @Field(offset = 1, length = 8)
    @FixedFormatEnum
    public Status getStatus() { … }
    
    // NUMERIC: stores "0" / "1"
    @Field(offset = 1, length = 1)
    @FixedFormatEnum(EnumFormat.NUMERIC)
    public Status getStatus() { … }

Performance improvements

  • Field metadata caching (#77) —
    ClassMetadataCache precomputes and caches all field descriptors per annotated class on first
    use, eliminating repeated annotation scanning on every load() / export() call. The cache is
    process-wide and thread-safe.

  • MethodHandle dispatch (#75) —
    Getter and setter invocation now uses MethodHandle instead of Method.invoke(), reducing
    per-call overhead after JIT warmup.

  • Reduced string allocations (#76) —
    Padding and sign handling rewritten to minimise intermediate String object creation per field.

1.6.1

10 Apr 08:38

Choose a tag to compare

Bug fixes

  • DateFormatter (and LocalDateFormatter / LocalDateTimeFormatter) no longer over-strips padding characters (#33) — When the configured paddingChar happened to be a character that also appears in the formatted date string (e.g. paddingChar = '0' with a time value whose seconds component is 00), the previous stripPadding implementation removed those characters from the parsed string, leaving it too short and causing a ParseException. The fix introduces AbstractPatternFormatter, which overrides stripPadding to remove only leading/trailing padding characters rather than all occurrences of the character.

Deprecations

  • AbstractFixedFormatter.getRemovePadding deprecated — The method has been renamed to stripPadding, which better reflects its behaviour. The old name carried a misleading get prefix that implied a zero-argument accessor.

    getRemovePadding remains callable and fully functional in 1.6.1; it now delegates to stripPadding. It will be removed in 1.7.0.

    Migration: rename any override of getRemovePadding to stripPadding — the signature is identical:

    // Before (1.6.0 and earlier)
    @Override
    protected String getRemovePadding(String value, FormatInstructions instructions) { … }
    
    // After (1.6.1+)
    @Override
    protected String stripPadding(String value, FormatInstructions instructions) { … }

1.6.0

09 Apr 20:38

Choose a tag to compare

What's New

Repeating Fields

  • Added count and strictCount attributes to @Field for repeating field support — a single annotated getter can now map to multiple consecutive fixed-width slots
  • Clarified @Fields documentation: prefer @Field(count=…) for repeating fields

LocalDateTime Support

  • Added built-in formatter for java.time.LocalDateTime with type-specific default patterns
  • Eager pattern validation catches misconfigured @FixedFormatPattern at load time rather than at parse time

Mutation Testing (CI/CD)

  • Added PIT mutation testing with automated GitHub Pages report publishing
  • Nightly PIT report published to GitHub Pages with links from README and docs navigation

Documentation & Internals

  • Added fixed left-sidebar navigation to docs
  • Refactored FixedFormatManagerImpl into focused collaborators for improved maintainability
  • Added public method Javadoc across all production classes
  • Switched to SLF4J parameterized logging and String.format throughout

Maintenance

  • Issue tracker updated from Google Code to GitHub Issues
  • Removed maven-changes-plugin (changelog now maintained in CHANGELOG.md)

1.5.0

07 Apr 21:10
e0a0bec

Choose a tag to compare

1.5.0

New features

  • Field-level @Field and @Fields annotations@Field and @Fields can now be placed directly on Java fields in addition to getter methods. The manager discovers them at runtime and derives the getter/setter by the get/is naming convention. This enables clean usage with Lombok (@Getter/@Setter) and reduces boilerplate in plain POJOs.

    If both the field and its getter carry @Field, an error is logged (configuration mismatch) and the field annotation is used.

1.4.0

05 Apr 18:24

Choose a tag to compare

1.4.0 (2026-04-05)

New features

  • LocalDate supportjava.time.LocalDate is now a first-class field type handled automatically by ByTypeFormatter. No custom formatter needed. Configure the date pattern with @FixedFormatPattern (default: yyyyMMdd).

    @Field(offset = 1, length = 8)
    @FixedFormatPattern("yyyyMMdd")
    public LocalDate getEventDate() { return eventDate; }

    String "20260405" parses to LocalDate.of(2026, 4, 5); exporting writes "20260405" back.

Breaking changes

  • Java 11 minimum — Java 8 is no longer supported. The minimum required runtime is Java 11.
  • Logging: SLF4J replaces Commons Logging — The library no longer depends on Apache Commons Logging. Logging is now done via SLF4J. If your project relied on the transitive commons-logging dependency, you will need to add an SLF4J binding instead (e.g. logback-classic or slf4j-simple). See Get It for details.

Documentation

  • Added Quick Start guide, Examples page, and an enriched Annotations reference.

Fixedformat4j v1.3.7

24 Jun 07:21

Choose a tag to compare

Fixed bug in how negative decimal numbers between 0 and -1 is parsed big the decimal parser

Fixedformat4j v1.3.5

01 Oct 08:31
dbbb348

Choose a tag to compare

  • Contains a bugfix where very small decimals would not be parsed correct
  • Had to depend on java 8 as java 5 i long gone (which normally is not a bugfix thing to do)