You are currently viewing Designing Source-Aware Claim Models in Java

Designing Source-Aware Claim Models in Java

A boolean such as licensed = true cannot tell a Java program who holds a licence, which identifier was reported, whether the status is current, or where the information came from. If a second source disagrees with the first, that single value becomes impossible to audit without reconstructing context the model has already discarded.

A safer design treats each statement as a claim backed by evidence. It preserves the reported value, its provenance, and its verification state instead of forcing several independent facts into one convenient flag. The pattern suits compliance data, software inventories, vulnerability reports, supplier records, and other domains where sources carry different levels of authority.

Start With the Questions the Model Must Answer

Before creating classes, list the questions that a future developer or reviewer may need to answer. A useful claim model should normally cover the following:

  • What exact value was reported?
  • Which source supplied that value?
  • When was the source checked or retrieved?
  • Was the value verified, disputed, or left unverified?
  • Does another source report a different value for the same subject?
  • Can the original evidence be located without relying on mutable display text?

These questions show why a domain object and its evidence should not be flattened into a few strings and booleans. A field can contain a value that remains unverified. A source can be identified while its statement is still ambiguous. Two records may also be accurate representations of what separate sources said, even when their values conflict.

Developer mapping typed claims and evidence

Separate the Subject, Claim, and Evidence

A practical design starts with three concepts. The subject is the entity being described. A claim is a specific assertion about that subject. Evidence records where the assertion came from and how it was assessed.

For example, a generic Java record might contain subjectId, claimType, value, provenance, and assessment. That is safer than attaching a free-form notes field to the subject, but one universal value type can still cause problems. Licence identifiers, organization names, dates, and legal jurisdictions do not share the same validation rules.

Prefer Typed Values Over a Universal String

Use dedicated records for values with distinct meanings. An OrganizationName might reject blank text while preserving punctuation. A LicenceIdentifier might retain the source’s original representation rather than assuming that every identifier follows one global format. A GoverningLawClaim may need both the reported text and a normalized internal code when reliable normalization is possible.

Do not normalize away evidence. If a source reports an identifier with spaces or a particular letter case, keep that raw value even if the application also stores a canonical form for searching. Canonicalization helps with matching; it should not silently rewrite the source’s statement.

Model Status as More Than True or False

Binary status fields conceal materially different states. Consider replacing a boolean with an enum such as:

  • REPORTED_VALID — the source explicitly reports a valid status.
  • REPORTED_INVALID — the source explicitly reports an invalid status.
  • REPORTED_EXPIRED — expiry is stated rather than inferred from missing data.
  • NOT_STATED — the source provides no status.
  • UNVERIFIED — the application has captured the claim but has not assessed it.
  • DISPUTED — available sources conflict or an authorized reviewer has challenged the claim.

The names should reflect both the domain and the evidence the application can support. Avoid an enum member such as VALID when the program knows only that a page reported validity. REPORTED_VALID describes the stored fact without turning a source statement into an independent legal conclusion.

A Source-Specific Boundary for the Model

External records can expose distinctions that a class design must preserve. The records distinguished by the Seven Casino online-casino review show why licensee, licence identifier, validity status, governing law, and source provenance need separate data fields. The important modeling decision is that none of these values should stand in for another: matching identifiers do not establish matching status, and a reported status does not identify the licensee or its legal context.

This page-specific observation does not establish a universal legal scheme or an industry-wide requirement. Its effect on the Java model is narrower: avoid one licenceDetails string, and do not treat a reported status as a substitute for identity, legal context, or provenance. Each item can change independently, so each should remain independently inspectable. Check any legal interpretation against applicable official guidance and authoritative records.

Represent Provenance as Structured Data

A plain sourceUrl field is rarely sufficient. Provenance should capture enough detail to understand and reproduce the collection process without storing credentials, session tokens, or other secrets.

A Provenance record can include:

  • a stable internal source identifier;
  • the source category, such as official register, vendor statement, or third-party review;
  • the retrieval timestamp as an Instant;
  • the relevant page or document reference;
  • an optional evidence hash for an authorized, lawfully retained snapshot;
  • the collection method, such as manual review or approved API import.

Keep source category and verification status separate. The category describes the origin; the status describes what the application has established about a particular claim. Hard-coding trust based only on a hostname or category turns an implementation shortcut into an unsupported factual assumption.

Evidence paths connect claims to their origins

Keep Collection and Assessment Independent

Capturing what a source says is one operation. Deciding whether that statement is reliable is another. Combining both in the same setter encourages code that marks data as verified simply because parsing succeeded.

A clean application-side workflow can use separate services:

  1. ClaimCollector converts permitted input into source-scoped claims.
  2. ClaimValidator checks syntax, required fields, and basic invariants.
  3. ClaimAssessor records a verification outcome according to an explicit policy.
  4. ClaimRepository stores claims without overwriting conflicting evidence.

This order is a design recommendation for the application, not a sequence attributed to an external source. The separation also simplifies authorization: an importer may be allowed to add claims, while only designated reviewers can change assessment records.

Preserve Disagreement Instead of Overwriting It

Suppose source A reports one organization name and source B reports another. A conventional entity table may overwrite the first value when the second import runs. A claim-oriented design stores both statements under the same subject identifier, each with its own provenance and assessment data.

The application can calculate a display value through an explicit resolution policy. That policy might prefer an authorized official source, select the most recently verified claim, or present the conflict to a human reviewer. The original records remain available regardless of which value the interface currently shows.

Avoid Accidental Ordering Assumptions

Timestamps describe retrieval and assessment, but they do not prove that a newer claim is more accurate. List position does not imply authority either. If priority matters, encode it in a named policy or field rather than relying on insertion order, enum ordinals, or whatever order a database query happens to return.

Use Immutability and Explicit Invariants

Java records work well for small immutable value objects when their compact constructors enforce meaningful invariants. Reject blank subject identifiers, missing provenance, and impossible timestamp combinations at construction time. When a record contains multiple evidence references, return immutable collections with List.copyOf or Set.copyOf.

Some rules belong outside constructors. Whether a source is authoritative may depend on configuration, jurisdiction, or a policy version. Keep those changing decisions in services instead of embedding them permanently in value objects.

Concern Suitable Java representation Common mistake
Claim category Stable enum or sealed hierarchy Unvalidated free-form strings
Reported value Dedicated immutable value type One Object or String field
Assessment Enum plus assessor and timestamp verified boolean
Provenance Structured record URL hidden in notes
Conflicts Multiple retained claims Last import wins

Test Meaning, Not Just Getters

Unit tests should target the distinctions the model promises to preserve. Verify that two conflicting claims can coexist, that a missing status becomes NOT_STATED rather than false, and that parsing success does not set verification automatically. Test that raw and normalized identifiers stay associated and that serialization does not discard provenance.

Add round-trip tests when claims cross JSON or database boundaries. Serialize a record, read it back, and compare every evidence-bearing field. For database-backed enums, persist stable string names rather than ordinal numbers so that adding a member does not reinterpret existing rows.

One focused test can create two claims for subject S-104 with the same licence identifier but different reported validity states and provenance records. Retrieve them from the repository and assert that both still exist and that neither status has overwritten the other. That test directly protects the central promise of a source-aware model: disagreement remains visible and auditable.