Class ContentHasher

java.lang.Object
org.egothor.methodatlas.command.ContentHasher

public final class ContentHasher extends Object
Pure utility helpers for content fingerprints and scan-root path prefixes.

Two unrelated-but-small concerns live here because both are stateless, dependency-free, and named-focused. Pulling them into one single-responsibility utility class keeps each concern visible without the cost of constructor injection — both methods are pure functions mandated by their specifications (SHA-256 for hashing, OS-native relativisation for the prefix), so there is nothing to substitute:

  • hashClass(String) — computes a SHA-256 fingerprint of the canonical pretty-printed AST text of a class. This is the value exposed as content_hash in CSV / SARIF output and used as the cache key by AiResultCache.
  • filePrefix(List) — derives the forward-slashed path prefix used in GitHub Actions workflow annotations and SARIF location URIs, relativised to the current working directory so that paths resolve to inline positions in PR diffs.

Both methods are pure functions and therefore exposed as static. Test code calls them directly with handcrafted inputs; no dependency injection is needed because there is nothing to substitute — the SHA-256 implementation is mandated by the Java SE specification and the path relativisation has only one correct answer.

Since:
1.0.0
See Also:
  • Method Details

    • hashClass

      public static String hashClass(String classSource)
      Computes a SHA-256 content fingerprint of a class source string.

      The input is expected to be the canonical AST text of the class — for Java this is the JavaParser pretty-printed form, which normalises whitespace and comments so that semantically equivalent classes that differ only in formatting produce identical hashes. The output is suitable for incremental scanning, AI-cache lookups, and audit traceability across two pipeline stages.

      Algorithm: SHA-256 (FIPS 180-4) applied to the UTF-8 bytes of classSource. Time complexity is O(n) in the source size. The result is a 64-character lowercase hexadecimal string.

      Parameters:
      classSource - canonical pretty-printed form of the class declaration; must not be null
      Returns:
      64-character lowercase hexadecimal SHA-256 digest; never null, never empty
      Throws:
      IllegalStateException - if SHA-256 is unavailable — never in practice, because SHA-256 is mandated by the Java SE specification
    • filePrefix

      public static String filePrefix(List<Path> roots)
      Derives the forward-slashed path prefix used in GitHub Actions workflow annotations and SARIF location URIs.

      The first configured scan root is relativised against the current working directory and converted to forward slashes. A trailing slash is appended unless the prefix is empty. The resulting string is concatenated with the per-method relative path to produce annotation paths that GitHub resolves to inline positions in the PR diff (for example src/test/java/com/acme/AuthTest.java).

      When roots is empty the returned prefix is the empty string, which produces unprefixed annotation paths — appropriate when no scan root was configured because the caller is operating on the current directory directly.

      On Windows, scan roots that resolve to a different drive than the current working directory cannot be relativised. The method falls back to the absolute path of the root in that case rather than throwing.

      Parameters:
      roots - configured scan roots; must not be null; may be empty
      Returns:
      forward-slash path ending with /, or the empty string when roots is empty