[ 
https://issues.apache.org/jira/browse/TIKA-4794?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18099732#comment-18099732
 ] 

Tim Allison commented on TIKA-4794:
-----------------------------------

Looking at this a bit more... How's this?

The key part is that we'll add a legacy key metadata mapper that should help 
people migrate. Where the underlying patterns have changed, we can't do 
anything... wordperfect->quattropro. But we can document known limitations. We 
can assess the success and find areas for improvement on our 1.2m corpus.

 
{noformat}
PR1 — metadata-key-tk-finalization (tk: consolidation)
  - Fold X-TIKA: + scattered natives (tika:chunks, imagereader:, signature:, 
rendering:, tika_pg:, hasSignature/embeddedResourceType) into one kebab tk: 
namespace
  - resourceName finished → tk:resource-name; Content-Type-* variants → 
tk:content-type-*; WordPerfect/QuattroPro prefix collision split
  - Reserved-key guard reserves both tk: and legacy X-TIKA: (drops untrusted 
String writes; filters/deserialize run trusted)
  - Human migration table shipped (metadata-changes-4x.adoc)
  - Status: swept; tika-core + tika-serialization green; full reactor build not 
re-run; not committed; awaiting review  PR2 — metadata-key-format-kebab (= PR1 
+ format-namespace kebab)
  - Kebab Tika-coined keys inside format namespaces (pdf, zip, database, pst, 
dwg, access-permission, wordperfect, quattropro, msoffice, 
extended-properties), ~78 keys;
  standard/file/schema names left verbatim
  - Status: tika-core green; built on PR1
  - Open (found this session):
    - rtf_meta: namespace missed entirely — prefix + suffixes still underscored 
→ fix to rtf-meta: + kebab
    - digest keys emit enum .name() (SHA3_256) → change DigestDef.metadataKey() 
to getJavaName() → tk:digest:SHA-256/SHA3-256 (also SHA256→SHA-256); bounded 
sweep (goldens + any reader
  of the key)  PR3 — metadata-key-registry (new module tika-metadata-schema)
  - Generated + CI-gated metadata-keys.json (634 closed keys incl. 27 digest 
cross-product); dependency-free SchemaGenerator classpath scan; 
MetadataSchemaTest diff-gate
  - Based on main; independent of PR1/PR2
  - Status: committed  PR4 — metadata-key-passthrough (open-namespace 
discoverability + lint) — stacked on PR3
  - PassthroughPrefix makes open/passthrough namespaces auto-discoverable; 6 
core holders + 22 parser files; metadata-open-namespaces.json generated + 
gated; MetadataCoverageTest
  backstop (no key-declaring module escapes the scan)
  - Status: committed/pushed (head "property prefix")
  - Staged, not yet committed on top: MetadataKeyValidator (registry-driven 
CLOSED/OPEN/TEMPLATE/UNKNOWN lint) + metadata-string-keys.json (bare-String 
closed keys:
  Content-Type/Content-*/Message-*/tika:chunks) + MetadataStringKeysTest gate + 
README  Cross-cutting / newly identified (target branch: format-kebab)
  - Rule: no underscores in Tika-coined 4.x keys; external-standard names 
verbatim. Bundle allowlist currently empty → rule = "zero underscores in the 
standard registry"
  - Add no-underscore lint to the registry gates (would have caught rtf_meta:)
  - 3.x→4.x migration bridge:
    - LegacyKeyMigrationFilter — MetadataFilter (runs trusted, so it can write 
reserved tk: keys); excludeUnmapped=false; one-line enable
    - Not a flat map: flat table (~131 enumerated) + tk:digest: prefix rule 
(exact) + tk:exception:/tk:warn: prefix+suffix (snake↔kebab) rule
    - Migration table must be generated from a ground-truth registry diff (main 
vs format-kebab). Sweep scripts proven unreliable — missed the quattropro 
prefix split, embedded_parser,
  and rtf_meta:
    - Table gated: every v4 valid via MetadataKeyValidator
  - Corpus drift-gate: run MetadataKeyValidator over real parser output, assert 
no UNKNOWN; needs a module above parsers (e.g. tika-parsers-integration-tests) 
to avoid a reactor cycle
  - Blast radius note: majority of keys unchanged (dc:, xmp*, exif:, tiff:, 
Content-* verbatim); only Tika-native + Tika-coined format keys move  

Recommended sequence
  1. Rebase registry module (PR3) onto format-kebab
  2. Run SchemaGenerator → authoritative 4.x key set
  3. Add no-underscore lint → flags rtf_meta: + digest
  4. Fix rtf_meta:→rtf-meta:; DigestDef → getJavaName()
  5. Generate migration table from clean 3.x↔4.x diff
  6. Build LegacyKeyMigrationFilter (table + rules)
  7. Corpus drift-gate
 {noformat}

> Normalize/simplify metadata keys in 4.x
> ---------------------------------------
>
>                 Key: TIKA-4794
>                 URL: https://issues.apache.org/jira/browse/TIKA-4794
>             Project: Tika
>          Issue Type: Task
>            Reporter: Tim Allison
>            Priority: Major
>
> *Background*
> Tika's metadata keys are inconsistent, and 4.0.0 is the last free break until 
> 5.0 (whatever ships is frozen for the 4.x line):
>  * Tika's own keys are scattered across ~8 prefixes (X-TIKA:, tika:, 
> tika_pg:, rendering:, signature:, imagereader:, bare 
> hasSignature/embeddedResourceType), with 3+ casings inside X-TIKA: alone 
> (snake, camel, Title-Hyphen, UPPER sub-namespaces).
>  * resourceName shipped half-migrated (bare → X-TIKA:resourceName) — the 
> worst state.
>  * The metadata object is also a control plane (media type drives routing, 
> resourceName drives detection, X-TIKA:* carries provenance/digests), but the 
> boundary is convention only: a crafted file can inject or overwrite Tika's 
> own keys.
>  * Format namespaces mix casings; QuattroPro reuses WordPerfect's prefix 
> (collision); there's no rule for "is this key Tika's or the file's".
> Options
>  #  Leave as-is. Ship the inconsistency + half-migrated resourceName + 
> convention-only boundary; frozen until 5.x
>  #  tk:. Consolidate every Tika-asserted key under one kebab-cased tk: 
> prefix; finish resourceName → tk:resource-name; add a reserved-namespace 
> trust boundary. Format namespaces untouched.
>  #  tk: + kebab. Everything in (2), plus apply the casing rule inside the 
> format namespaces.
> *Guiding principles (2 and 3)*
>   1. Who asserted the key? Tika-computed → owned, normalized, trusted. 
> File/standard-authored → verbatim (the spelling/capitalization is the interop 
> contract).
>   2. Match enforcement to stakes. Control-plane / Tika-native keys → 
> reserved, writable only via a Property; cosmetic drift → convention.
>   3. Casing follows key-name authorship, not the namespace (the prefix is 
> just the domain). Tika coined the name → kebab; a standard/file authored it → 
> verbatim.
>   4. Clean 3→4 break, documented with a migration table; no auto-remap 
> machinery.
>   *2 — tk: (rationale + consistency)*
>   One prefix, one casing for everything Tika asserts, replacing the 8 
> scattered prefixes and their mixed casings; resourceName finished. tk: (and 
> legacy X-TIKA: ) become reserved: a String write to them is dropped unless 
> trusted, so a scraped file can't forge Tika's 
> routing/provenance/digest/content keys or inject fake tk:chunks embeddings — 
> enforced once in tika-core, not per-parser discipline. Consistency: any Tika 
> key is now predictable (tk: + kebab), and the trust boundary is mechanism 
> rather than convention.
>   *3 — tk: + kebab (rationale + consistency)*
>   Extends "Tika-coined → kebab" into the format namespaces (e.g. 
> pdf:hasMarkedContent → pdf:has-marked-content, zip:compressedSize → 
> zip:compressed-size, access_permission: →  access-permission: ). Names from a 
> standard stay verbatim (dc:, xmp:, EXIF/tiff:, MAPI, email headers, ECMA-376 
> OOXML props, PDF/A/X sub-namespaces) — re-casing them would break 
> round-trip/interop. Also fixes the QuattroPro/WordPerfect prefix collision. 
> Consistency: a Tika-authored key is kebab wherever it lives (under tk: or a 
> format prefix); a  standard/file key keeps its source spelling — one rule 
> answers casing everywhere.
>  
> If we did steps 2 or 3, we'd probably want to release a 4.0.0-beta-2.
>  
> Steps 2 or 3 would be fairly major changes for downstream users, but it would 
> allow us to clean up years of metadata key name bloat.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to