This is an automated email from the ASF dual-hosted git repository. tballison pushed a commit to branch TIKA-4797-migration-table in repository https://gitbox.apache.org/repos/asf/tika.git
commit e3542384af21fbd030487459fb990f9fa9cbc8c0 Author: tallison <[email protected]> AuthorDate: Wed Jul 29 21:27:26 2026 -0400 add migration table --- .../pages/migration-to-4x/metadata-changes-4x.adoc | 13 + tika-core/pom.xml | 1 + .../metadata/filter/LegacyKeyMigrationFilter.java | 185 +++++++ .../tika/metadata/metadata-migration-3x-4x.json | 137 +++++ .../filter/LegacyKeyMigrationFilterTest.java | 148 ++++++ .../metadata/schema/MigrationTableGenerator.java | 122 +++++ .../schema/MetadataMigrationTableTest.java | 55 +++ .../org/apache/tika/metadata/metadata-keys-3x.json | 550 +++++++++++++++++++++ .../org/apache/tika/metadata/migration-overlay.tsv | 43 ++ 9 files changed, 1254 insertions(+) diff --git a/docs/modules/ROOT/pages/migration-to-4x/metadata-changes-4x.adoc b/docs/modules/ROOT/pages/migration-to-4x/metadata-changes-4x.adoc index 7cfcb1387e..454287d602 100644 --- a/docs/modules/ROOT/pages/migration-to-4x/metadata-changes-4x.adoc +++ b/docs/modules/ROOT/pages/migration-to-4x/metadata-changes-4x.adoc @@ -307,6 +307,19 @@ String value = metadata.get("mapi:some-property"); String value = metadata.get("mapi:some-property"); ---- +[CAUTION] +==== +Two 3.x keys do not migrate one-to-one, and the opt-in `LegacyKeyMigrationFilter` cannot restore +them cleanly: + +* `pst:folderPath` is *dropped*, not renamed. In 4.x the Outlook PST parser folds the folder path +into `tk:internal-path` (`<folder>/<item-name>`, a superset), so there is no folder-only value to +map back to. +* `mapi:msg-client-submit-time` is *consolidated* into `mapi:msg-submission-accepted-at-time`: 4.x +removed the distinct client-submit key and repoints PST's client-submit value onto +submission-accepted. The value carries over, but these are distinct MAPI properties. +==== + === Resource Name [source,java] diff --git a/tika-core/pom.xml b/tika-core/pom.xml index 030ad95c01..dfc9088516 100644 --- a/tika-core/pom.xml +++ b/tika-core/pom.xml @@ -207,6 +207,7 @@ <inputExclude>src/test/resources/test-documents/file-list.txt</inputExclude> <inputExclude>src/test/resources/test-documents/ang20150420t182050_corr_v1e_img.hdr</inputExclude> <inputExclude>src/test/resources/test-documents/*.pdf</inputExclude> + <inputExclude>src/main/resources/org/apache/tika/metadata/metadata-migration-3x-4x.json</inputExclude> </inputExcludes> </configuration> </plugin> diff --git a/tika-core/src/main/java/org/apache/tika/metadata/filter/LegacyKeyMigrationFilter.java b/tika-core/src/main/java/org/apache/tika/metadata/filter/LegacyKeyMigrationFilter.java new file mode 100644 index 0000000000..02d38f7ce8 --- /dev/null +++ b/tika-core/src/main/java/org/apache/tika/metadata/filter/LegacyKeyMigrationFilter.java @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tika.metadata.filter; + +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.UnaryOperator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.tika.annotation.TikaComponent; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.TikaCoreProperties; + +/** + * Rewrites 4.x metadata keys back to their 3.x spellings (or vice versa) so consumers pinned to 3.x + * key names keep working after the 4.0 rename break. Opt-in; enable it in the metadata-filter chain + * and it rewrites at the emit edge. Because it runs inside the {@link MetadataFilter} trusted bracket, + * it may write reserved (e.g. {@code X-TIKA:}/{@code tk:}) keys that a plain String write couldn't. + * + * <p><b>Data-driven, not hand-coded.</b> The renames come from the committed migration table + * (generated by joining the 3.x and 4.x field-attributed key tables — TIKA-4797). Three tiers: + * <ul> + * <li><b>flat renames</b> — the enumerated key-for-key changes (the bulk);</li> + * <li><b>drops</b> — 3.x keys 4.x no longer emits (only relevant on ingest);</li> + * <li><b>prefix rules</b> — the open families whose suffix also transforms + * ({@code tk:exception:}/{@code tk:warn:} snake↔kebab, {@code tk:digest:} algorithm names).</li> + * </ul> + * Unmapped keys pass through unchanged (this is a compatibility bridge, not an allow-list). + * + * <p><b>Skeleton status (TIKA-4799):</b> the flat/drop/passthrough mechanism is complete; the + * bundled table and the concrete prefix rules land with the rename PRs (the table resource is absent + * until then, so the default filter is a safe no-op). See {@link #prefixRules} for where the + * digest/exception rules slot in. + */ +@TikaComponent +public class LegacyKeyMigrationFilter extends MetadataFilterBase { + + /** V4_TO_V3 = egress (4.x output rewritten to 3.x keys, the BWC case); V3_TO_V4 = ingest. */ + public enum Direction { V4_TO_V3, V3_TO_V4 } + + /** Generated by the TIKA-4797 migration join; deposited into tika-core resources when renames land. */ + static final String DEFAULT_TABLE = "/org/apache/tika/metadata/metadata-migration-3x-4x.json"; + + // {"v3":"...","v4":"..."} ; v4 == "DROPPED" marks a 3.x key with no 4.x successor. + private static final Pattern ROW = + Pattern.compile("\\{\"v3\":\"(.*?)\",\"v4\":\"(.*?)\"}"); + + // 4.x digest keys use the JCA name (DigestDef.getJavaName); 3.x used the enum name. MD2/MD5 match. + private static final Map<String, String> DIGEST_ALG_V4_TO_V3 = Map.of( + "SHA-1", "SHA1", "SHA-256", "SHA256", "SHA-384", "SHA384", "SHA-512", "SHA512", + "SHA3-256", "SHA3_256", "SHA3-384", "SHA3_384", "SHA3-512", "SHA3_512"); + private static final String V4_DIGEST = TikaCoreProperties.TIKA_META_PREFIX + "digest:"; + private static final String V3_DIGEST = TikaCoreProperties.LEGACY_TIKA_META_PREFIX + "digest:"; + + public static class Config { + public Direction direction = Direction.V4_TO_V3; + public String table = DEFAULT_TABLE; + } + + private final Map<String, String> renames; // source key -> target key (direction applied) + private final Set<String> drops; // source keys to remove (ingest only) + private final List<UnaryOperator<String>> prefixRules; + + public LegacyKeyMigrationFilter() { + this(new Config()); + } + + public LegacyKeyMigrationFilter(Config config) { + this(loadTable(config.table), config.direction); + } + + /** Test/explicit hook. {@code table} is v3->v4 (with {@code null}/"DROPPED" = dropped). */ + LegacyKeyMigrationFilter(Map<String, String> table, Direction direction) { + this.renames = new HashMap<>(); + this.drops = new HashSet<>(); + for (Map.Entry<String, String> e : table.entrySet()) { + String v3 = e.getKey(); + String v4 = e.getValue(); + boolean dropped = v4 == null || "DROPPED".equals(v4); + if (direction == Direction.V4_TO_V3) { + if (!dropped) { + renames.put(v4, v3); // 4.x key -> 3.x key + } + } else { // V3_TO_V4 + if (dropped) { + drops.add(v3); + } else { + renames.put(v3, v4); + } + } + } + // Digest keys have no declaring field, so they aren't in the flat table -- rewrite them by + // prefix rule instead. (Exception/warn keys ARE enumerated in the table.) + this.prefixRules = new ArrayList<>(); + this.prefixRules.add(digestRule(direction)); + } + + @Override + protected void filter(Metadata metadata) { + for (String name : metadata.names()) { // names() returns a snapshot copy + if (drops.contains(name)) { + metadata.remove(name); + continue; + } + String mapped = renames.get(name); + if (mapped == null) { + for (UnaryOperator<String> rule : prefixRules) { + String r = rule.apply(name); + if (r != null) { + mapped = r; + break; + } + } + } + if (mapped != null && !mapped.equals(name)) { + String[] values = metadata.getValues(name); + metadata.remove(name); + for (String v : values) { + metadata.add(mapped, v); // trusted context: reserved keys allowed + } + } + // unmapped -> pass through unchanged + } + } + + private static Map<String, String> loadTable(String resource) { + Map<String, String> table = new HashMap<>(); + try (InputStream in = LegacyKeyMigrationFilter.class.getResourceAsStream(resource)) { + if (in == null) { + return table; // not bundled yet -> no-op bridge + } + Matcher m = ROW.matcher(new String(in.readAllBytes(), StandardCharsets.UTF_8)); + while (m.find()) { + table.put(unescape(m.group(1)), unescape(m.group(2))); + } + } catch (Exception e) { + throw new IllegalStateException("could not read migration table " + resource, e); + } + return table; + } + + private static String unescape(String s) { + return s.replace("\\\"", "\"").replace("\\\\", "\\"); + } + + /** {@code tk:digest:<jca-alg>[:enc]} ↔ {@code X-TIKA:digest:<enum-alg>[:enc]} (encoding kept). */ + private static UnaryOperator<String> digestRule(Direction direction) { + boolean egress = direction == Direction.V4_TO_V3; + String fromPrefix = egress ? V4_DIGEST : V3_DIGEST; + String toPrefix = egress ? V3_DIGEST : V4_DIGEST; + Map<String, String> alg = new HashMap<>(); + DIGEST_ALG_V4_TO_V3.forEach((v4, v3) -> alg.put(egress ? v4 : v3, egress ? v3 : v4)); + return name -> { + if (!name.startsWith(fromPrefix)) { + return null; + } + String rest = name.substring(fromPrefix.length()); // <alg> or <alg>:<enc> + int c = rest.indexOf(':'); + String a = c < 0 ? rest : rest.substring(0, c); + String enc = c < 0 ? "" : rest.substring(c); + return toPrefix + alg.getOrDefault(a, a) + enc; + }; + } +} diff --git a/tika-core/src/main/resources/org/apache/tika/metadata/metadata-migration-3x-4x.json b/tika-core/src/main/resources/org/apache/tika/metadata/metadata-migration-3x-4x.json new file mode 100644 index 0000000000..f8c8fc1133 --- /dev/null +++ b/tika-core/src/main/resources/org/apache/tika/metadata/metadata-migration-3x-4x.json @@ -0,0 +1,137 @@ +[ +{"v3":"Content-Type-Hint","v4":"tk:content-type-hint"}, +{"v3":"Content-Type-Override","v4":"tk:content-type-override"}, +{"v3":"Content-Type-Parser-Override","v4":"tk:content-type-parser-override"}, +{"v3":"Message:BCC-Display-Name","v4":"message:bcc-display-name"}, +{"v3":"Message:BCC-Email","v4":"message:bcc-email"}, +{"v3":"Message:BCC-Name","v4":"message:bcc-name"}, +{"v3":"Message:CC-Display-Name","v4":"message:cc-display-name"}, +{"v3":"Message:CC-Email","v4":"message:cc-email"}, +{"v3":"Message:CC-Name","v4":"message:cc-name"}, +{"v3":"Message:From-Email","v4":"message:from-email"}, +{"v3":"Message:From-Name","v4":"message:from-name"}, +{"v3":"Message:To-Display-Name","v4":"message:to-display-name"}, +{"v3":"Message:To-Email","v4":"message:to-email"}, +{"v3":"Message:To-Name","v4":"message:to-name"}, +{"v3":"X-TIKA:EXCEPTION:container_exception","v4":"tk:exception:container-exception"}, +{"v3":"X-TIKA:EXCEPTION:embedded_bytes_exception","v4":"tk:exception:embedded-bytes-exception"}, +{"v3":"X-TIKA:EXCEPTION:embedded_exception","v4":"tk:exception:embedded-exception"}, +{"v3":"X-TIKA:EXCEPTION:embedded_stream_exception","v4":"tk:exception:embedded-stream-exception"}, +{"v3":"X-TIKA:EXCEPTION:embedded_warning","v4":"tk:exception:embedded-warning"}, +{"v3":"X-TIKA:EXCEPTION:warn","v4":"tk:exception:warn"}, +{"v3":"X-TIKA:EXCEPTION:write_limit_reached","v4":"tk:exception:write-limit-reached"}, +{"v3":"X-TIKA:Parsed-By","v4":"tk:parsed-by"}, +{"v3":"X-TIKA:Parsed-By-Full-Set","v4":"tk:parsed-by-full-set"}, +{"v3":"X-TIKA:WARN:truncated_metadata","v4":"tk:warn:truncated-metadata"}, +{"v3":"X-TIKA:content","v4":"tk:content"}, +{"v3":"X-TIKA:content_handler","v4":"tk:content-handler"}, +{"v3":"X-TIKA:detectedEncoding","v4":"tk:detected-encoding"}, +{"v3":"X-TIKA:detected_language","v4":"tk:detected-language"}, +{"v3":"X-TIKA:detected_language_confidence","v4":"tk:detected-language-confidence"}, +{"v3":"X-TIKA:detected_language_confidence_raw","v4":"tk:detected-language-confidence-raw"}, +{"v3":"X-TIKA:embedded_depth","v4":"tk:embedded-depth"}, +{"v3":"X-TIKA:embedded_id","v4":"tk:embedded-id"}, +{"v3":"X-TIKA:embedded_id_path","v4":"tk:embedded-id-path"}, +{"v3":"X-TIKA:embedded_resource_path","v4":"tk:embedded-resource-path"}, +{"v3":"X-TIKA:encodingDetector","v4":"tk:encoding-detector"}, +{"v3":"X-TIKA:encrypted","v4":"tk:encrypted"}, +{"v3":"X-TIKA:final_embedded_resource_path","v4":"tk:final-embedded-resource-path"}, +{"v3":"X-TIKA:internalPath","v4":"tk:internal-path"}, +{"v3":"X-TIKA:origResourceName","v4":"tk:orig-resource-name"}, +{"v3":"X-TIKA:parse_time_millis","v4":"tk:parse-time-millis"}, +{"v3":"X-TIKA:pipes_result","v4":"tk:pipes-result"}, +{"v3":"X-TIKA:sourcePath","v4":"tk:source-path"}, +{"v3":"X-TIKA:versionCount","v4":"tk:version-count"}, +{"v3":"X-TIKA:versionNumber","v4":"tk:version-number"}, +{"v3":"access_permission:assemble_document","v4":"access-permission:assemble-document"}, +{"v3":"access_permission:can_modify","v4":"access-permission:can-modify"}, +{"v3":"access_permission:can_print","v4":"access-permission:can-print"}, +{"v3":"access_permission:can_print_faithful","v4":"access-permission:can-print-faithful"}, +{"v3":"access_permission:extract_content","v4":"access-permission:extract-content"}, +{"v3":"access_permission:extract_for_accessibility","v4":"access-permission:extract-for-accessibility"}, +{"v3":"access_permission:fill_in_form","v4":"access-permission:fill-in-form"}, +{"v3":"access_permission:modify_annotations","v4":"access-permission:modify-annotations"}, +{"v3":"database:column_count","v4":"database:column-count"}, +{"v3":"database:column_name","v4":"database:column-name"}, +{"v3":"database:row_count","v4":"database:row-count"}, +{"v3":"database:table_name","v4":"database:table-name"}, +{"v3":"embeddedResourceType","v4":"tk:embedded-resource-type"}, +{"v3":"extended-properties:DocSecurityString","v4":"extended-properties:doc-security-string"}, +{"v3":"extended-properties:HiddedSlides","v4":"extended-properties:HiddenSlides"}, +{"v3":"hasSignature","v4":"tk:has-signature"}, +{"v3":"html_meta:scriptSrc","v4":"html:scriptSrc"}, +{"v3":"imagereader:NumImages","v4":"tk:num-images"}, +{"v3":"meta:mapi-from-representing-email","v4":"mapi:from-representing-email"}, +{"v3":"meta:mapi-from-representing-name","v4":"mapi:from-representing-name"}, +{"v3":"meta:mapi-importance","v4":"mapi:importance"}, +{"v3":"meta:mapi-is-flagged","v4":"mapi:is-flagged"}, +{"v3":"meta:mapi-message-class","v4":"mapi:message-class"}, +{"v3":"meta:mapi-msg-client-submit-time","v4":"mapi:msg-submission-accepted-at-time"}, +{"v3":"meta:mapi-recipients-string","v4":"mapi:recipients-string"}, +{"v3":"meta:mapi-sent-by-server-type","v4":"mapi:sent-by-server-type"}, +{"v3":"msoffice:ocxName","v4":"msoffice:ocx-name"}, +{"v3":"msoffice:progID","v4":"msoffice:prog-id"}, +{"v3":"pdf:PDFExtensionVersion","v4":"pdf:pdf-extension-version"}, +{"v3":"pdf:PDFVersion","v4":"pdf:pdf-version"}, +{"v3":"pdf:actionTrigger","v4":"pdf:action-trigger"}, +{"v3":"pdf:actionTriggers","v4":"pdf:action-triggers"}, +{"v3":"pdf:actionTypes","v4":"pdf:action-types"}, +{"v3":"pdf:annotationSubtypes","v4":"pdf:annotation-subtypes"}, +{"v3":"pdf:annotationTypes","v4":"pdf:annotation-types"}, +{"v3":"pdf:associatedFileRelationship","v4":"pdf:associated-file-relationship"}, +{"v3":"pdf:charsPerPage","v4":"pdf:chars-per-page"}, +{"v3":"pdf:containsDamagedFont","v4":"pdf:contains-damaged-font"}, +{"v3":"pdf:containsNonEmbeddedFont","v4":"pdf:contains-non-embedded-font"}, +{"v3":"pdf:docinfo:creator_tool","v4":"pdf:docinfo:creator-tool"}, +{"v3":"pdf:embeddedFileAnnotationType","v4":"pdf:embedded-file-annotation-type"}, +{"v3":"pdf:embeddedFileDescription","v4":"pdf:embedded-file-description"}, +{"v3":"pdf:embeddedFileSubtype","v4":"pdf:embedded-file-subtype"}, +{"v3":"pdf:eofOffsets","v4":"pdf:eof-offsets"}, +{"v3":"pdf:has3D","v4":"pdf:has-3d"}, +{"v3":"pdf:hasAcroFormFields","v4":"pdf:has-acro-form-fields"}, +{"v3":"pdf:hasCollection","v4":"pdf:has-collection"}, +{"v3":"pdf:hasMarkedContent","v4":"pdf:has-marked-content"}, +{"v3":"pdf:hasSignatureFields","v4":"pdf:has-signature-fields"}, +{"v3":"pdf:hasXFA","v4":"pdf:has-xfa"}, +{"v3":"pdf:hasXMP","v4":"pdf:has-xmp"}, +{"v3":"pdf:incrementalUpdateCount","v4":"pdf:incremental-update-count"}, +{"v3":"pdf:incrementalUpdateNumber","v4":"pdf:incremental-update-number"}, +{"v3":"pdf:jsName","v4":"pdf:js-name"}, +{"v3":"pdf:num3DAnnotations","v4":"pdf:num-3d-annotations"}, +{"v3":"pdf:ocrPageCount","v4":"pdf:ocr-page-count"}, +{"v3":"pdf:overallPercentageUnmappedUnicodeChars","v4":"pdf:overall-percentage-unmapped-unicode-chars"}, +{"v3":"pdf:totalUnmappedUnicodeChars","v4":"pdf:total-unmapped-unicode-chars"}, +{"v3":"pdf:unmappedUnicodeCharsPerPage","v4":"pdf:unmapped-unicode-chars-per-page"}, +{"v3":"pdf:xmpLocation","v4":"pdf:xmp-location"}, +{"v3":"pdfa:PDFVersion","v4":"pdfa:pdf-version"}, +{"v3":"pst:discriptorNodeId","v4":"pst:discriptor-node-id"}, +{"v3":"pst:folderPath","v4":"DROPPED"}, +{"v3":"pst:isValid","v4":"pst:is-valid"}, +{"v3":"rendering:Rendered-By","v4":"tk:rendering:rendered-by"}, +{"v3":"rendering:rendering-time-ms","v4":"tk:rendering:rendering-time-ms"}, +{"v3":"rtf_meta:contains_encapsulated_html","v4":"rtf:contains-encapsulated-html"}, +{"v3":"rtf_meta:emb_app_version","v4":"rtf:embedded-app-version"}, +{"v3":"rtf_meta:emb_class","v4":"rtf:embedded-class"}, +{"v3":"rtf_meta:emb_item","v4":"rtf:embedded-item"}, +{"v3":"rtf_meta:emb_topic","v4":"rtf:embedded-topic"}, +{"v3":"rtf_meta:thumbnail","v4":"rtf:thumbnail"}, +{"v3":"signature:contact-info","v4":"tk:signature:contact-info"}, +{"v3":"signature:date","v4":"tk:signature:date"}, +{"v3":"signature:filter","v4":"tk:signature:filter"}, +{"v3":"signature:location","v4":"tk:signature:location"}, +{"v3":"signature:name","v4":"tk:signature:name"}, +{"v3":"signature:reason","v4":"tk:signature:reason"}, +{"v3":"tika_pg:page_number","v4":"tk:page:number"}, +{"v3":"tika_pg:page_rotation","v4":"tk:page:rotation"}, +{"v3":"wordperfect:Build","v4":"quattropro:build"}, +{"v3":"wordperfect:Encrypted","v4":"wordperfect:encrypted"}, +{"v3":"wordperfect:FileId","v4":"wordperfect:file-id"}, +{"v3":"wordperfect:FileSize","v4":"wordperfect:file-size"}, +{"v3":"wordperfect:FileType","v4":"wordperfect:file-type"}, +{"v3":"wordperfect:Id","v4":"quattropro:id"}, +{"v3":"wordperfect:LowestVersion","v4":"quattropro:lowest-version"}, +{"v3":"wordperfect:MajorVersion","v4":"wordperfect:major-version"}, +{"v3":"wordperfect:MinorVersion","v4":"wordperfect:minor-version"}, +{"v3":"wordperfect:ProductType","v4":"wordperfect:product-type"}, +{"v3":"wordperfect:Version","v4":"quattropro:version"} +] diff --git a/tika-core/src/test/java/org/apache/tika/metadata/filter/LegacyKeyMigrationFilterTest.java b/tika-core/src/test/java/org/apache/tika/metadata/filter/LegacyKeyMigrationFilterTest.java new file mode 100644 index 0000000000..d1ca09c3d8 --- /dev/null +++ b/tika-core/src/test/java/org/apache/tika/metadata/filter/LegacyKeyMigrationFilterTest.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tika.metadata.filter; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.filter.LegacyKeyMigrationFilter.Direction; + +public class LegacyKeyMigrationFilterTest { + + private static List<Metadata> apply(LegacyKeyMigrationFilter f, Metadata m) throws Exception { + List<Metadata> list = new ArrayList<>(); + list.add(m); + f.filter(list); // public entry sets the trusted bracket + return list; + } + + @Test + public void egressRenamesAndPassesThrough() throws Exception { + // table is v3 -> v4; egress rewrites 4.x output back to 3.x keys. + var f = new LegacyKeyMigrationFilter( + Map.of("pdf:hasMarkedContent", "pdf:has-marked-content"), Direction.V4_TO_V3); + Metadata m = new Metadata(); + m.set("pdf:has-marked-content", "true"); // 4.x key + m.set("dc:title", "Hello"); // unmapped -> passthrough + apply(f, m); + assertEquals("true", m.get("pdf:hasMarkedContent")); + assertNull(m.get("pdf:has-marked-content")); + assertEquals("Hello", m.get("dc:title")); + } + + @Test + public void egressWritesReservedTarget() throws Exception { + // Proves the trusted bracket: the 3.x target is a reserved (X-TIKA:) key a plain String + // write would be dropped for. + var f = new LegacyKeyMigrationFilter( + Map.of("X-TIKA:Parsed-By", "tk:parsed-by"), Direction.V4_TO_V3); + Metadata m = new Metadata(); + // Post-4.0 tk: is reserved too, so seed it the trusted way a parse would (a raw String set + // to a reserved key is dropped by the guard); the point of the test is the X-TIKA: target. + m.setTrusted(true); + m.set("tk:parsed-by", "org.apache.tika.parser.DefaultParser"); + m.setTrusted(false); + apply(f, m); + assertEquals("org.apache.tika.parser.DefaultParser", m.get("X-TIKA:Parsed-By")); + assertNull(m.get("tk:parsed-by")); + } + + @Test + public void ingestDropsRemovedKeysAndRenames() throws Exception { + var f = new LegacyKeyMigrationFilter(Map.of( + "pst:folderPath", "DROPPED", + "pdf:hasMarkedContent", "pdf:has-marked-content"), Direction.V3_TO_V4); + Metadata m = new Metadata(); + m.set("pst:folderPath", "/Inbox/Sub"); // 3.x key with no 4.x successor + m.set("pdf:hasMarkedContent", "true"); // 3.x key -> 4.x + apply(f, m); + assertNull(m.get("pst:folderPath")); // dropped + assertEquals("true", m.get("pdf:has-marked-content")); + } + + @Test + public void multiValuedKeysArePreserved() throws Exception { + var f = new LegacyKeyMigrationFilter( + Map.of("meta:mapi-importance", "mapi:importance"), Direction.V4_TO_V3); + Metadata m = new Metadata(); + m.add("mapi:importance", "1"); + m.add("mapi:importance", "2"); + apply(f, m); + assertArrayEquals(new String[]{"1", "2"}, m.getValues("meta:mapi-importance")); + } + + @Test + public void emptyTableIsNoOp() throws Exception { + var f = new LegacyKeyMigrationFilter(Map.of(), Direction.V4_TO_V3); + Metadata m = new Metadata(); + m.set("dc:title", "Hello"); + apply(f, m); + assertEquals("Hello", m.get("dc:title")); + } + + @Test + public void loadsBundledTableAndRewritesRealKeys() throws Exception { + // default ctor loads the committed metadata-migration-3x-4x.json; egress (V4_TO_V3). + LegacyKeyMigrationFilter f = new LegacyKeyMigrationFilter(); + Metadata m = new Metadata(); + m.setTrusted(true); + m.set("tk:content", "hello"); // reserved 4.x key -> X-TIKA:content + m.setTrusted(false); + m.set("message:from-email", "[email protected]"); // non-reserved 4.x key -> Message:From-Email + apply(f, m); + assertEquals("hello", m.get("X-TIKA:content")); + assertNull(m.get("tk:content")); + assertEquals("[email protected]", m.get("Message:From-Email")); + } + + @Test + public void digestPrefixRuleEgress() throws Exception { + // digest keys have no declaring field, so not in the flat table -> handled by the prefix rule. + var f = new LegacyKeyMigrationFilter(Map.of(), Direction.V4_TO_V3); + Metadata m = new Metadata(); + m.setTrusted(true); + m.set("tk:digest:SHA-256", "abc"); + m.set("tk:digest:SHA-256:BASE32", "def"); // encoding suffix preserved + m.set("tk:digest:MD5", "ghi"); // MD5 unchanged between 3.x/4.x + m.setTrusted(false); + apply(f, m); + assertEquals("abc", m.get("X-TIKA:digest:SHA256")); + assertEquals("def", m.get("X-TIKA:digest:SHA256:BASE32")); + assertEquals("ghi", m.get("X-TIKA:digest:MD5")); + assertNull(m.get("tk:digest:SHA-256")); + } + + @Test + public void digestPrefixRuleIngest() throws Exception { + var f = new LegacyKeyMigrationFilter(Map.of(), Direction.V3_TO_V4); + Metadata m = new Metadata(); + m.setTrusted(true); + m.set("X-TIKA:digest:SHA3_512", "z"); + m.setTrusted(false); + apply(f, m); + assertEquals("z", m.get("tk:digest:SHA3-512")); + assertNull(m.get("X-TIKA:digest:SHA3_512")); + } +} diff --git a/tika-metadata-schema/src/main/java/org/apache/tika/metadata/schema/MigrationTableGenerator.java b/tika-metadata-schema/src/main/java/org/apache/tika/metadata/schema/MigrationTableGenerator.java new file mode 100644 index 0000000000..28159524f0 --- /dev/null +++ b/tika-metadata-schema/src/main/java/org/apache/tika/metadata/schema/MigrationTableGenerator.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tika.metadata.schema; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * TIKA-4797 / TIKA-4799. Produces the 3.x->4.x metadata-key migration table + * ({@code metadata-migration-3x-4x.json}) that {@code LegacyKeyMigrationFilter} loads, by joining the + * committed 3.x and 4.x {@code {class, field, key}} field tables on field identity (Class#field): + * <ul> + * <li>same field, changed key -> a RENAME (auto);</li> + * <li>fields the join can't bridge (moves/drops, or fields renamed on both sides) -> taken from the + * adjudicated {@code migration-overlay.tsv} ({@code v4 == DROPPED} = 4.x no longer emits it).</li> + * </ul> + * Core scope only ({@code org.apache.tika.metadata.*}) until the 3.x table is widened past its v1. + * + * <p>Dependency-free by design: tika-core carries the filter and must stay Jackson-free, so both this + * generator and the filter emit/parse the flat JSON by hand. {@code MetadataMigrationTableTest} + * regenerates in-memory and asserts the committed tika-core copy has not drifted. + * + * <pre> + * java ... MigrationTableGenerator <3x-fields.json> <4x-fields.json> <overlay.tsv> <out.json> + * </pre> + */ +public final class MigrationTableGenerator { + + private static final Pattern ROW = Pattern.compile( + "\\{\"class\":\"(.*?)\",\"field\":\"(.*?)\",\"key\":\"((?:[^\"\\\\]|\\\\.)*)\"}"); + private static final String CORE = "org.apache.tika.metadata."; + + private MigrationTableGenerator() { + } + + /** Build the sorted {@code v3 -> v4} migration JSON from the three input contents. */ + public static String generate(String threeFieldsJson, String fourFieldsJson, String overlayTsv) { + Map<String, String> three = readFields(threeFieldsJson); // class#field -> key + Map<String, String> four = readFields(fourFieldsJson); + Set<String> v4keys = new HashSet<>(four.values()); + + TreeMap<String, String> table = new TreeMap<>(); // v3 -> v4 (or "DROPPED") + for (Map.Entry<String, String> e : three.entrySet()) { // auto-renames by field identity + String key4 = four.get(e.getKey()); + if (key4 != null && !e.getValue().equals(key4)) { + table.put(e.getValue(), key4); + } + } + for (String line : overlayTsv.split("\n")) { // adjudicated moves/drops; overlay wins + String t = line.strip(); + int tab = t.indexOf('\t'); + if (t.isEmpty() || t.startsWith("#") || tab < 0) { + continue; + } + table.put(t.substring(0, tab).strip(), t.substring(tab + 1).strip()); + } + for (Map.Entry<String, String> e : table.entrySet()) { // every target must be a real 4.x key + if (!"DROPPED".equals(e.getValue()) && !v4keys.contains(e.getValue())) { + throw new IllegalStateException( + "migration target is not a 4.x key: " + e.getKey() + " -> " + e.getValue()); + } + } + StringBuilder sb = new StringBuilder("[\n"); + int i = 0; + int n = table.size(); + for (Map.Entry<String, String> e : table.entrySet()) { + sb.append("{\"v3\":\"").append(esc(e.getKey())) + .append("\",\"v4\":\"").append(esc(e.getValue())).append("\"}") + .append(++i < n ? "," : "").append('\n'); + } + return sb.append("]\n").toString(); + } + + /** Core-scoped {@code class#field -> key} from a {class,field,key} table. */ + private static Map<String, String> readFields(String json) { + Map<String, String> m = new LinkedHashMap<>(); + Matcher mt = ROW.matcher(json); + while (mt.find()) { + if (mt.group(1).startsWith(CORE)) { + m.put(mt.group(1) + "#" + mt.group(2), unescape(mt.group(3))); + } + } + return m; + } + + private static String esc(String s) { + return s.replace("\\", "\\\\").replace("\"", "\\\""); + } + + private static String unescape(String s) { + return s.replace("\\\"", "\"").replace("\\\\", "\\"); + } + + public static void main(String[] args) throws Exception { + String json = generate(Files.readString(Path.of(args[0])), Files.readString(Path.of(args[1])), + Files.readString(Path.of(args[2]))); + Files.writeString(Path.of(args[3]), json); + System.out.println("wrote " + args[3] + " rows=" + + json.lines().filter(l -> l.startsWith("{\"v3\"")).count()); + } +} diff --git a/tika-metadata-schema/src/test/java/org/apache/tika/metadata/schema/MetadataMigrationTableTest.java b/tika-metadata-schema/src/test/java/org/apache/tika/metadata/schema/MetadataMigrationTableTest.java new file mode 100644 index 0000000000..0bd7c384e1 --- /dev/null +++ b/tika-metadata-schema/src/test/java/org/apache/tika/metadata/schema/MetadataMigrationTableTest.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tika.metadata.schema; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import org.junit.jupiter.api.Test; + +/** + * The CI gate for the 3.x->4.x migration table (TIKA-4797 / TIKA-4799): regenerates it from the + * committed field tables + overlay and asserts tika-core's bundled {@code metadata-migration-3x-4x.json} + * has not drifted. The migration table is committed in tika-core (where the filter lives, and which is + * Jackson-free); the inputs and this gate live here, alongside the other schema registries. + */ +public class MetadataMigrationTableTest { + + private static final String THREE_X = "/org/apache/tika/metadata/metadata-keys-3x.json"; + private static final String FOUR_X = "/org/apache/tika/metadata/metadata-key-fields.json"; + private static final String OVERLAY = "/org/apache/tika/metadata/migration-overlay.tsv"; + private static final String COMMITTED = "/org/apache/tika/metadata/metadata-migration-3x-4x.json"; + + @Test + public void committedMigrationTableMatchesRegeneration() throws Exception { + String regenerated = MigrationTableGenerator.generate(read(THREE_X), read(FOUR_X), read(OVERLAY)); + assertEquals(read(COMMITTED), regenerated, + "metadata-migration-3x-4x.json (in tika-core) is stale. Regenerate with " + + "MigrationTableGenerator and commit the result."); + } + + private static String read(String resource) throws Exception { + try (InputStream in = MetadataMigrationTableTest.class.getResourceAsStream(resource)) { + if (in == null) { + throw new IllegalStateException("missing resource on the test classpath: " + resource); + } + return new String(in.readAllBytes(), StandardCharsets.UTF_8); + } + } +} diff --git a/tika-metadata-schema/src/test/resources/org/apache/tika/metadata/metadata-keys-3x.json b/tika-metadata-schema/src/test/resources/org/apache/tika/metadata/metadata-keys-3x.json new file mode 100644 index 0000000000..78de3ef835 --- /dev/null +++ b/tika-metadata-schema/src/test/resources/org/apache/tika/metadata/metadata-keys-3x.json @@ -0,0 +1,550 @@ +[ + {"class":"org.apache.tika.detect.FileCommandDetector","field":"FILE_MIME","key":"file:mime"}, + {"class":"org.apache.tika.metadata.AccessPermissions","field":"ASSEMBLE_DOCUMENT","key":"access_permission:assemble_document"}, + {"class":"org.apache.tika.metadata.AccessPermissions","field":"CAN_MODIFY","key":"access_permission:can_modify"}, + {"class":"org.apache.tika.metadata.AccessPermissions","field":"CAN_MODIFY_ANNOTATIONS","key":"access_permission:modify_annotations"}, + {"class":"org.apache.tika.metadata.AccessPermissions","field":"CAN_PRINT","key":"access_permission:can_print"}, + {"class":"org.apache.tika.metadata.AccessPermissions","field":"CAN_PRINT_FAITHFUL","key":"access_permission:can_print_faithful"}, + {"class":"org.apache.tika.metadata.AccessPermissions","field":"EXTRACT_CONTENT","key":"access_permission:extract_content"}, + {"class":"org.apache.tika.metadata.AccessPermissions","field":"EXTRACT_FOR_ACCESSIBILITY","key":"access_permission:extract_for_accessibility"}, + {"class":"org.apache.tika.metadata.AccessPermissions","field":"FILL_IN_FORM","key":"access_permission:fill_in_form"}, + {"class":"org.apache.tika.metadata.Database","field":"COLUMN_COUNT","key":"database:column_count"}, + {"class":"org.apache.tika.metadata.Database","field":"COLUMN_NAME","key":"database:column_name"}, + {"class":"org.apache.tika.metadata.Database","field":"ROW_COUNT","key":"database:row_count"}, + {"class":"org.apache.tika.metadata.Database","field":"TABLE_NAME","key":"database:table_name"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"CONTRIBUTOR","key":"dc:contributor"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"COVERAGE","key":"dc:coverage"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"CREATED","key":"dcterms:created"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"CREATOR","key":"dc:creator"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"DATE","key":"dc:date"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"DESCRIPTION","key":"dc:description"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"FORMAT","key":"dc:format"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"IDENTIFIER","key":"dc:identifier"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"LANGUAGE","key":"dc:language"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"MODIFIED","key":"dcterms:modified"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"PUBLISHER","key":"dc:publisher"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"RELATION","key":"dc:relation"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"RIGHTS","key":"dc:rights"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"SOURCE","key":"dc:source"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"SUBJECT","key":"dc:subject"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"TITLE","key":"dc:title"}, + {"class":"org.apache.tika.metadata.DublinCore","field":"TYPE","key":"dc:type"}, + {"class":"org.apache.tika.metadata.Epub","field":"RENDITION_LAYOUT","key":"epub:rendition:layout"}, + {"class":"org.apache.tika.metadata.Epub","field":"VERSION","key":"epub:version"}, + {"class":"org.apache.tika.metadata.ExternalProcess","field":"EXIT_VALUE","key":"external-process:exit-value"}, + {"class":"org.apache.tika.metadata.ExternalProcess","field":"IS_TIMEOUT","key":"external-process:timeout"}, + {"class":"org.apache.tika.metadata.ExternalProcess","field":"STD_ERR","key":"external-process:stderr"}, + {"class":"org.apache.tika.metadata.ExternalProcess","field":"STD_ERR_IS_TRUNCATED","key":"external-process:stderr-truncated"}, + {"class":"org.apache.tika.metadata.ExternalProcess","field":"STD_ERR_LENGTH","key":"external-process:stderr-length"}, + {"class":"org.apache.tika.metadata.ExternalProcess","field":"STD_OUT","key":"external-process:stdout"}, + {"class":"org.apache.tika.metadata.ExternalProcess","field":"STD_OUT_IS_TRUNCATED","key":"external-process:stdout-truncated"}, + {"class":"org.apache.tika.metadata.ExternalProcess","field":"STD_OUT_LENGTH","key":"external-process:stdout-length"}, + {"class":"org.apache.tika.metadata.FileSystem","field":"ACCESSED","key":"fs:accessed"}, + {"class":"org.apache.tika.metadata.FileSystem","field":"CREATED","key":"fs:created"}, + {"class":"org.apache.tika.metadata.FileSystem","field":"MODIFIED","key":"fs:modified"}, + {"class":"org.apache.tika.metadata.Font","field":"FONT_NAME","key":"font:name"}, + {"class":"org.apache.tika.metadata.Geographic","field":"ALTITUDE","key":"geo:alt"}, + {"class":"org.apache.tika.metadata.Geographic","field":"LATITUDE","key":"geo:lat"}, + {"class":"org.apache.tika.metadata.Geographic","field":"LONGITUDE","key":"geo:long"}, + {"class":"org.apache.tika.metadata.Geographic","field":"TIMESTAMP","key":"geo:timestamp"}, + {"class":"org.apache.tika.metadata.HTML","field":"SCRIPT_SOURCE","key":"html_meta:scriptSrc"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ADDITIONAL_MODEL_INFO","key":"Iptc4xmpExt:AddlModelInfo"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ARTWORK_OR_OBJECT","key":"Iptc4xmpExt:ArtworkOrObject"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ARTWORK_OR_OBJECT_DETAIL_COPYRIGHT_NOTICE","key":"Iptc4xmpExt:AOCopyrightNotice"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ARTWORK_OR_OBJECT_DETAIL_CREATOR","key":"Iptc4xmpExt:AOCreator"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ARTWORK_OR_OBJECT_DETAIL_DATE_CREATED","key":"Iptc4xmpExt:AODateCreated"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ARTWORK_OR_OBJECT_DETAIL_SOURCE","key":"Iptc4xmpExt:AOSource"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ARTWORK_OR_OBJECT_DETAIL_SOURCE_INVENTORY_NUMBER","key":"Iptc4xmpExt:AOSourceInvNo"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ARTWORK_OR_OBJECT_DETAIL_TITLE","key":"Iptc4xmpExt:AOTitle"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CATEGORY","key":"photoshop:Category"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CITY","key":"photoshop:City"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CONTACT_INFO_ADDRESS","key":"Iptc4xmpCore:CiAdrExtadr"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CONTACT_INFO_CITY","key":"Iptc4xmpCore:CiAdrCity"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CONTACT_INFO_COUNTRY","key":"Iptc4xmpCore:CiAdrCtry"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CONTACT_INFO_EMAIL","key":"Iptc4xmpCore:CiEmailWork"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CONTACT_INFO_PHONE","key":"Iptc4xmpCore:CiTelWork"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CONTACT_INFO_POSTAL_CODE","key":"Iptc4xmpCore:CiAdrPcode"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CONTACT_INFO_STATE_PROVINCE","key":"Iptc4xmpCore:CiAdrRegion"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CONTACT_INFO_WEB_URL","key":"Iptc4xmpCore:CiUrlWork"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CONTROLLED_VOCABULARY_TERM","key":"Iptc4xmpExt:CVterm"}, + {"class":"org.apache.tika.metadata.IPTC","field":"COPYRIGHT_NOTICE","key":"dc:rights"}, + {"class":"org.apache.tika.metadata.IPTC","field":"COPYRIGHT_OWNER","key":"plus:CopyrightOwner"}, + {"class":"org.apache.tika.metadata.IPTC","field":"COPYRIGHT_OWNER_ID","key":"plus:CopyrightOwnerID"}, + {"class":"org.apache.tika.metadata.IPTC","field":"COPYRIGHT_OWNER_NAME","key":"plus:CopyrightOwnerName"}, + {"class":"org.apache.tika.metadata.IPTC","field":"COUNTRY","key":"photoshop:Country"}, + {"class":"org.apache.tika.metadata.IPTC","field":"COUNTRY_CODE","key":"Iptc4xmpCore:CountryCode"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CREATOR","key":"dc:creator"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CREATORS_CONTACT_INFO","key":"Iptc4xmpCore:CreatorContactInfo"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CREATORS_JOB_TITLE","key":"photoshop:AuthorsPosition"}, + {"class":"org.apache.tika.metadata.IPTC","field":"CREDIT_LINE","key":"photoshop:Credit"}, + {"class":"org.apache.tika.metadata.IPTC","field":"DATE_CREATED","key":"photoshop:DateCreated"}, + {"class":"org.apache.tika.metadata.IPTC","field":"DESCRIPTION","key":"dc:description"}, + {"class":"org.apache.tika.metadata.IPTC","field":"DESCRIPTION_WRITER","key":"photoshop:CaptionWriter"}, + {"class":"org.apache.tika.metadata.IPTC","field":"DIGITAL_IMAGE_GUID","key":"Iptc4xmpExt:DigImageGUID"}, + {"class":"org.apache.tika.metadata.IPTC","field":"DIGITAL_SOURCE_FILE_TYPE","key":"Iptc4xmpExt:DigitalSourcefileType"}, + {"class":"org.apache.tika.metadata.IPTC","field":"DIGITAL_SOURCE_TYPE","key":"Iptc4xmpExt:DigitalSourceType"}, + {"class":"org.apache.tika.metadata.IPTC","field":"EVENT","key":"Iptc4xmpExt:Event"}, + {"class":"org.apache.tika.metadata.IPTC","field":"HEADLINE","key":"photoshop:Headline"}, + {"class":"org.apache.tika.metadata.IPTC","field":"IMAGE_CREATOR","key":"plus:ImageCreator"}, + {"class":"org.apache.tika.metadata.IPTC","field":"IMAGE_CREATOR_ID","key":"plus:ImageCreatorID"}, + {"class":"org.apache.tika.metadata.IPTC","field":"IMAGE_CREATOR_NAME","key":"plus:ImageCreatorName"}, + {"class":"org.apache.tika.metadata.IPTC","field":"IMAGE_REGISTRY_ENTRY","key":"Iptc4xmpExt:RegistryId"}, + {"class":"org.apache.tika.metadata.IPTC","field":"IMAGE_SUPPLIER","key":"plus:ImageSupplier"}, + {"class":"org.apache.tika.metadata.IPTC","field":"IMAGE_SUPPLIER_ID","key":"plus:ImageSupplierID"}, + {"class":"org.apache.tika.metadata.IPTC","field":"IMAGE_SUPPLIER_IMAGE_ID","key":"plus:ImageSupplierImageID"}, + {"class":"org.apache.tika.metadata.IPTC","field":"IMAGE_SUPPLIER_NAME","key":"plus:ImageSupplierName"}, + {"class":"org.apache.tika.metadata.IPTC","field":"INSTRUCTIONS","key":"photoshop:Instructions"}, + {"class":"org.apache.tika.metadata.IPTC","field":"INTELLECTUAL_GENRE","key":"Iptc4xmpCore:IntellectualGenre"}, + {"class":"org.apache.tika.metadata.IPTC","field":"IPTC_LAST_EDITED","key":"Iptc4xmpExt:IptcLastEdited"}, + {"class":"org.apache.tika.metadata.IPTC","field":"JOB_ID","key":"photoshop:TransmissionReference"}, + {"class":"org.apache.tika.metadata.IPTC","field":"KEYWORDS","key":"dc:subject"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR","key":"plus:Licensor"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_CITY","key":"plus:LicensorCity"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_COUNTRY","key":"plus:LicensorCountry"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_EMAIL","key":"plus:LicensorEmail"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_EXTENDED_ADDRESS","key":"plus:LicensorExtendedAddress"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_ID","key":"plus:LicensorID"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_NAME","key":"plus:LicensorName"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_POSTAL_CODE","key":"plus:LicensorPostalCode"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_REGION","key":"plus:LicensorRegion"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_STREET_ADDRESS","key":"plus:LicensorStreetAddress"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_TELEPHONE_1","key":"plus:LicensorTelephone1"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_TELEPHONE_2","key":"plus:LicensorTelephone2"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LICENSOR_URL","key":"plus:LicensorURL"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_CREATED","key":"Iptc4xmpExt:LocationCreated"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_CREATED_CITY","key":"Iptc4xmpExt:LocationCreatedCity"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_CREATED_COUNTRY_CODE","key":"Iptc4xmpExt:LocationCreatedCountryCode"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_CREATED_COUNTRY_NAME","key":"Iptc4xmpExt:LocationCreatedCountryName"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_CREATED_PROVINCE_OR_STATE","key":"Iptc4xmpExt:LocationCreatedProvinceState"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_CREATED_SUBLOCATION","key":"Iptc4xmpExt:LocationCreatedSublocation"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_CREATED_WORLD_REGION","key":"Iptc4xmpExt:LocationCreatedWorldRegion"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_SHOWN","key":"Iptc4xmpExt:LocationShown"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_SHOWN_CITY","key":"Iptc4xmpExt:LocationShownCity"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_SHOWN_COUNTRY_CODE","key":"Iptc4xmpExt:LocationShownCountryCode"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_SHOWN_COUNTRY_NAME","key":"Iptc4xmpExt:LocationShownCountryName"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_SHOWN_PROVINCE_OR_STATE","key":"Iptc4xmpExt:LocationShownProvinceState"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_SHOWN_SUBLOCATION","key":"Iptc4xmpExt:LocationShownSublocation"}, + {"class":"org.apache.tika.metadata.IPTC","field":"LOCATION_SHOWN_WORLD_REGION","key":"Iptc4xmpExt:LocationShownWorldRegion"}, + {"class":"org.apache.tika.metadata.IPTC","field":"MAX_AVAIL_HEIGHT","key":"Iptc4xmpExt:MaxAvailHeight"}, + {"class":"org.apache.tika.metadata.IPTC","field":"MAX_AVAIL_WIDTH","key":"Iptc4xmpExt:MaxAvailWidth"}, + {"class":"org.apache.tika.metadata.IPTC","field":"MINOR_MODEL_AGE_DISCLOSURE","key":"plus:MinorModelAgeDisclosure"}, + {"class":"org.apache.tika.metadata.IPTC","field":"MODEL_AGE","key":"Iptc4xmpExt:ModelAge"}, + {"class":"org.apache.tika.metadata.IPTC","field":"MODEL_RELEASE_ID","key":"plus:ModelReleaseID"}, + {"class":"org.apache.tika.metadata.IPTC","field":"MODEL_RELEASE_STATUS","key":"plus:ModelReleaseStatus"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ORGANISATION_CODE","key":"Iptc4xmpExt:OrganisationInImageCode"}, + {"class":"org.apache.tika.metadata.IPTC","field":"ORGANISATION_NAME","key":"Iptc4xmpExt:OrganisationInImageName"}, + {"class":"org.apache.tika.metadata.IPTC","field":"PERSON","key":"Iptc4xmpExt:PersonInImage"}, + {"class":"org.apache.tika.metadata.IPTC","field":"PLUS_VERSION","key":"plus:Version"}, + {"class":"org.apache.tika.metadata.IPTC","field":"PROPERTY_RELEASE_ID","key":"plus:PropertyReleaseID"}, + {"class":"org.apache.tika.metadata.IPTC","field":"PROPERTY_RELEASE_STATUS","key":"plus:PropertyReleaseStatus"}, + {"class":"org.apache.tika.metadata.IPTC","field":"PROVINCE_OR_STATE","key":"photoshop:State"}, + {"class":"org.apache.tika.metadata.IPTC","field":"REGISTRY_ENTRY_CREATED_ITEM_ID","key":"Iptc4xmpExt:RegItemId"}, + {"class":"org.apache.tika.metadata.IPTC","field":"REGISTRY_ENTRY_CREATED_ORGANISATION_ID","key":"Iptc4xmpExt:RegOrgId"}, + {"class":"org.apache.tika.metadata.IPTC","field":"RIGHTS_USAGE_TERMS","key":"xmpRights:UsageTerms"}, + {"class":"org.apache.tika.metadata.IPTC","field":"SCENE_CODE","key":"Iptc4xmpCore:Scene"}, + {"class":"org.apache.tika.metadata.IPTC","field":"SOURCE","key":"photoshop:Source"}, + {"class":"org.apache.tika.metadata.IPTC","field":"SUBJECT_CODE","key":"Iptc4xmpCore:SubjectCode"}, + {"class":"org.apache.tika.metadata.IPTC","field":"SUBLOCATION","key":"Iptc4xmpCore:Location"}, + {"class":"org.apache.tika.metadata.IPTC","field":"SUPPLEMENTAL_CATEGORIES","key":"photoshop:SupplementalCategories"}, + {"class":"org.apache.tika.metadata.IPTC","field":"TITLE","key":"dc:title"}, + {"class":"org.apache.tika.metadata.IPTC","field":"URGENCY","key":"photoshop:Urgency"}, + {"class":"org.apache.tika.metadata.MAPI","field":"ATTACH_CONTENT_ID","key":"mapi:attach:content-id"}, + {"class":"org.apache.tika.metadata.MAPI","field":"ATTACH_CONTENT_LOCATION","key":"mapi:attach:content-location"}, + {"class":"org.apache.tika.metadata.MAPI","field":"ATTACH_DISPLAY_NAME","key":"mapi:attach:display-name"}, + {"class":"org.apache.tika.metadata.MAPI","field":"ATTACH_EXTENSION","key":"mapi:attach:extension"}, + {"class":"org.apache.tika.metadata.MAPI","field":"ATTACH_FILE_NAME","key":"mapi:attach:file-name"}, + {"class":"org.apache.tika.metadata.MAPI","field":"ATTACH_LANGUAGE","key":"mapi:attach:language"}, + {"class":"org.apache.tika.metadata.MAPI","field":"ATTACH_LONG_FILE_NAME","key":"mapi:attach:long-file-name"}, + {"class":"org.apache.tika.metadata.MAPI","field":"ATTACH_LONG_PATH_NAME","key":"mapi:attach:long-path-name"}, + {"class":"org.apache.tika.metadata.MAPI","field":"ATTACH_MIME","key":"mapi:attach:mime"}, + {"class":"org.apache.tika.metadata.MAPI","field":"BODY_TYPES_PROCESSED","key":"mapi:body-types-processed"}, + {"class":"org.apache.tika.metadata.MAPI","field":"CONVERSATION_INDEX","key":"mapi:conversation-index"}, + {"class":"org.apache.tika.metadata.MAPI","field":"CONVERSATION_TOPIC","key":"mapi:conversation-topic"}, + {"class":"org.apache.tika.metadata.MAPI","field":"FROM_REPRESENTING_EMAIL","key":"mapi:from-representing-email"}, + {"class":"org.apache.tika.metadata.MAPI","field":"FROM_REPRESENTING_NAME","key":"mapi:from-representing-name"}, + {"class":"org.apache.tika.metadata.MAPI","field":"IMPORTANCE","key":"mapi:importance"}, + {"class":"org.apache.tika.metadata.MAPI","field":"INTERNET_MESSAGE_ID","key":"mapi:internet-message-id"}, + {"class":"org.apache.tika.metadata.MAPI","field":"INTERNET_REFERENCES","key":"mapi:internet-references"}, + {"class":"org.apache.tika.metadata.MAPI","field":"IN_REPLY_TO_ID","key":"mapi:in-reply-to-id"}, + {"class":"org.apache.tika.metadata.MAPI","field":"IS_FLAGGED","key":"mapi:is-flagged"}, + {"class":"org.apache.tika.metadata.MAPI","field":"MESSAGE_CLASS","key":"mapi:message-class"}, + {"class":"org.apache.tika.metadata.MAPI","field":"MESSAGE_CLASS_RAW","key":"mapi:message-class-raw"}, + {"class":"org.apache.tika.metadata.MAPI","field":"PRIORTY","key":"mapi:priority"}, + {"class":"org.apache.tika.metadata.MAPI","field":"RECIPIENTS_STRING","key":"mapi:recipients-string"}, + {"class":"org.apache.tika.metadata.MAPI","field":"SENT_BY_SERVER_TYPE","key":"mapi:sent-by-server-type"}, + {"class":"org.apache.tika.metadata.MAPI","field":"SUBMISSION_ACCEPTED_AT_TIME","key":"mapi:msg-submission-accepted-at-time"}, + {"class":"org.apache.tika.metadata.MAPI","field":"SUBMISSION_ID","key":"mapi:msg-submission-id"}, + {"class":"org.apache.tika.metadata.MachineMetadata","field":"ARCHITECTURE_BITS","key":"machine:architectureBits"}, + {"class":"org.apache.tika.metadata.MachineMetadata","field":"ENDIAN","key":"machine:endian"}, + {"class":"org.apache.tika.metadata.MachineMetadata","field":"MACHINE_TYPE","key":"machine:machineType"}, + {"class":"org.apache.tika.metadata.MachineMetadata","field":"PLATFORM","key":"machine:platform"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_BCC_DISPLAY_NAME","key":"Message:BCC-Display-Name"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_BCC_EMAIL","key":"Message:BCC-Email"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_BCC_NAME","key":"Message:BCC-Name"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_CC_DISPLAY_NAME","key":"Message:CC-Display-Name"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_CC_EMAIL","key":"Message:CC-Email"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_CC_NAME","key":"Message:CC-Name"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_FROM_EMAIL","key":"Message:From-Email"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_FROM_NAME","key":"Message:From-Name"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_TO_DISPLAY_NAME","key":"Message:To-Display-Name"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_TO_EMAIL","key":"Message:To-Email"}, + {"class":"org.apache.tika.metadata.Message","field":"MESSAGE_TO_NAME","key":"Message:To-Name"}, + {"class":"org.apache.tika.metadata.Office","field":"AUTHOR","key":"meta:author"}, + {"class":"org.apache.tika.metadata.Office","field":"CHARACTER_COUNT","key":"meta:character-count"}, + {"class":"org.apache.tika.metadata.Office","field":"CHARACTER_COUNT_WITH_SPACES","key":"meta:character-count-with-spaces"}, + {"class":"org.apache.tika.metadata.Office","field":"COMMENT_PERSONS","key":"msoffice:comment-person-display-name"}, + {"class":"org.apache.tika.metadata.Office","field":"CREATION_DATE","key":"meta:creation-date"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_ANIMATIONS","key":"msoffice:ppt:has-animations"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_ATTACHED_TEMPLATE","key":"msoffice:doc:has-attached-template"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_COMMENTS","key":"msoffice:has-comments"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_DATA_CONNECTIONS","key":"msoffice:excel:has-data-connections"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_DDE_LINKS","key":"msoffice:excel:has-dde-links"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_EXTERNAL_CHART_DATA","key":"msoffice:has-external-chart-data"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_EXTERNAL_LINKS","key":"msoffice:excel:has-external-links"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_EXTERNAL_OLE_OBJECTS","key":"msoffice:has-external-ole-objects"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_EXTERNAL_PIVOT_DATA","key":"msoffice:excel:has-external-pivot-data"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_FIELD_HYPERLINKS","key":"msoffice:has-field-hyperlinks"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_FRAMESETS","key":"msoffice:doc:has-framesets"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_HIDDEN_COLUMNS","key":"msoffice:excel:has-hidden-cols"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_HIDDEN_ROWS","key":"msoffice:excel:has-hidden-rows"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_HIDDEN_SHEETS","key":"msoffice:excel:has-hidden-sheets"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_HIDDEN_SLIDES","key":"msoffice:ppt:has-hidden-slides"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_HIDDEN_TEXT","key":"msoffice:doc:has-hidden-text"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_HOVER_HYPERLINKS","key":"msoffice:has-hover-hyperlinks"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_LINKED_OLE_OBJECTS","key":"msoffice:has-linked-ole-objects"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_MAIL_MERGE","key":"msoffice:doc:has-mail-merge"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_POWER_QUERY","key":"msoffice:excel:has-power-query"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_SUBDOCUMENTS","key":"msoffice:doc:has-subdocuments"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_TRACK_CHANGES","key":"msoffice:has-track-changes"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_VERY_HIDDEN_SHEETS","key":"msoffice:excel:has-very-hidden-sheets"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_VML_HYPERLINKS","key":"msoffice:has-vml-hyperlinks"}, + {"class":"org.apache.tika.metadata.Office","field":"HAS_WEB_QUERIES","key":"msoffice:excel:has-web-queries"}, + {"class":"org.apache.tika.metadata.Office","field":"HIDDEN_SHEET_NAMES","key":"msoffice:excel:hidden-sheet-names"}, + {"class":"org.apache.tika.metadata.Office","field":"IMAGE_COUNT","key":"meta:image-count"}, + {"class":"org.apache.tika.metadata.Office","field":"INITIAL_AUTHOR","key":"meta:initial-author"}, + {"class":"org.apache.tika.metadata.Office","field":"KEYWORDS","key":"meta:keyword"}, + {"class":"org.apache.tika.metadata.Office","field":"LAST_AUTHOR","key":"meta:last-author"}, + {"class":"org.apache.tika.metadata.Office","field":"LINE_COUNT","key":"meta:line-count"}, + {"class":"org.apache.tika.metadata.Office","field":"MAPI_FROM_REPRESENTING_EMAIL","key":"meta:mapi-from-representing-email"}, + {"class":"org.apache.tika.metadata.Office","field":"MAPI_FROM_REPRESENTING_NAME","key":"meta:mapi-from-representing-name"}, + {"class":"org.apache.tika.metadata.Office","field":"MAPI_IMPORTANCE","key":"meta:mapi-importance"}, + {"class":"org.apache.tika.metadata.Office","field":"MAPI_IS_FLAGGED","key":"meta:mapi-is-flagged"}, + {"class":"org.apache.tika.metadata.Office","field":"MAPI_MESSAGE_CLASS","key":"meta:mapi-message-class"}, + {"class":"org.apache.tika.metadata.Office","field":"MAPI_MESSAGE_CLIENT_SUBMIT_TIME","key":"meta:mapi-msg-client-submit-time"}, + {"class":"org.apache.tika.metadata.Office","field":"MAPI_PRIORTY","key":"meta:mapi-importance"}, + {"class":"org.apache.tika.metadata.Office","field":"MAPI_RECIPIENTS_STRING","key":"meta:mapi-recipients-string"}, + {"class":"org.apache.tika.metadata.Office","field":"MAPI_SENT_BY_SERVER_TYPE","key":"meta:mapi-sent-by-server-type"}, + {"class":"org.apache.tika.metadata.Office","field":"NUM_HIDDEN_SLIDES","key":"msoffice:ppt:num-hidden-slides"}, + {"class":"org.apache.tika.metadata.Office","field":"OBJECT_COUNT","key":"meta:object-count"}, + {"class":"org.apache.tika.metadata.Office","field":"OCX_NAME","key":"msoffice:ocxName"}, + {"class":"org.apache.tika.metadata.Office","field":"PAGE_COUNT","key":"meta:page-count"}, + {"class":"org.apache.tika.metadata.Office","field":"PARAGRAPH_COUNT","key":"meta:paragraph-count"}, + {"class":"org.apache.tika.metadata.Office","field":"PRINT_DATE","key":"meta:print-date"}, + {"class":"org.apache.tika.metadata.Office","field":"PROG_ID","key":"msoffice:progID"}, + {"class":"org.apache.tika.metadata.Office","field":"PROTECTED_WORKSHEET","key":"msoffice:excel:protected-worksheet"}, + {"class":"org.apache.tika.metadata.Office","field":"SAVE_DATE","key":"meta:save-date"}, + {"class":"org.apache.tika.metadata.Office","field":"SLIDE_COUNT","key":"meta:slide-count"}, + {"class":"org.apache.tika.metadata.Office","field":"TABLE_COUNT","key":"meta:table-count"}, + {"class":"org.apache.tika.metadata.Office","field":"VERY_HIDDEN_SHEET_NAMES","key":"msoffice:excel:very-hidden-sheet-names"}, + {"class":"org.apache.tika.metadata.Office","field":"WORD_COUNT","key":"meta:word-count"}, + {"class":"org.apache.tika.metadata.Office","field":"WORKBOOK_CODENAME","key":"msoffice:excel:workbook-codename"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLCore","field":"CATEGORY","key":"cp:category"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLCore","field":"CONTENT_STATUS","key":"cp:contentStatus"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLCore","field":"LAST_MODIFIED_BY","key":"cp:lastModifiedBy"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLCore","field":"LAST_PRINTED","key":"cp:lastPrinted"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLCore","field":"REVISION","key":"cp:revision"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLCore","field":"SUBJECT","key":"cp:subject"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLCore","field":"VERSION","key":"cp:version"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"APPLICATION","key":"extended-properties:Application"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"APP_VERSION","key":"extended-properties:AppVersion"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"COMMENTS","key":"w:Comments"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"COMPANY","key":"extended-properties:Company"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"DOC_SECURITY","key":"extended-properties:DocSecurity"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"DOC_SECURITY_STRING","key":"extended-properties:DocSecurityString"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"HIDDEN_SLIDES","key":"extended-properties:HiddedSlides"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"MANAGER","key":"extended-properties:Manager"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"NOTES","key":"extended-properties:Notes"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"PRESENTATION_FORMAT","key":"extended-properties:PresentationFormat"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"TEMPLATE","key":"extended-properties:Template"}, + {"class":"org.apache.tika.metadata.OfficeOpenXMLExtended","field":"TOTAL_TIME","key":"extended-properties:TotalTime"}, + {"class":"org.apache.tika.metadata.PDF","field":"ACTION_TRIGGER","key":"pdf:actionTrigger"}, + {"class":"org.apache.tika.metadata.PDF","field":"ACTION_TRIGGERS","key":"pdf:actionTriggers"}, + {"class":"org.apache.tika.metadata.PDF","field":"ACTION_TYPES","key":"pdf:actionTypes"}, + {"class":"org.apache.tika.metadata.PDF","field":"ANNOTATION_SUBTYPES","key":"pdf:annotationSubtypes"}, + {"class":"org.apache.tika.metadata.PDF","field":"ANNOTATION_TYPES","key":"pdf:annotationTypes"}, + {"class":"org.apache.tika.metadata.PDF","field":"ASSOCIATED_FILE_RELATIONSHIP","key":"pdf:associatedFileRelationship"}, + {"class":"org.apache.tika.metadata.PDF","field":"CHARACTERS_PER_PAGE","key":"pdf:charsPerPage"}, + {"class":"org.apache.tika.metadata.PDF","field":"CONTAINS_DAMAGED_FONT","key":"pdf:containsDamagedFont"}, + {"class":"org.apache.tika.metadata.PDF","field":"CONTAINS_NON_EMBEDDED_FONT","key":"pdf:containsNonEmbeddedFont"}, + {"class":"org.apache.tika.metadata.PDF","field":"DOC_INFO_CREATED","key":"pdf:docinfo:created"}, + {"class":"org.apache.tika.metadata.PDF","field":"DOC_INFO_CREATOR","key":"pdf:docinfo:creator"}, + {"class":"org.apache.tika.metadata.PDF","field":"DOC_INFO_CREATOR_TOOL","key":"pdf:docinfo:creator_tool"}, + {"class":"org.apache.tika.metadata.PDF","field":"DOC_INFO_KEY_WORDS","key":"pdf:docinfo:keywords"}, + {"class":"org.apache.tika.metadata.PDF","field":"DOC_INFO_MODIFICATION_DATE","key":"pdf:docinfo:modified"}, + {"class":"org.apache.tika.metadata.PDF","field":"DOC_INFO_PRODUCER","key":"pdf:docinfo:producer"}, + {"class":"org.apache.tika.metadata.PDF","field":"DOC_INFO_SUBJECT","key":"pdf:docinfo:subject"}, + {"class":"org.apache.tika.metadata.PDF","field":"DOC_INFO_TITLE","key":"pdf:docinfo:title"}, + {"class":"org.apache.tika.metadata.PDF","field":"DOC_INFO_TRAPPED","key":"pdf:docinfo:trapped"}, + {"class":"org.apache.tika.metadata.PDF","field":"EMBEDDED_FILE_ANNOTATION_TYPE","key":"pdf:embeddedFileAnnotationType"}, + {"class":"org.apache.tika.metadata.PDF","field":"EMBEDDED_FILE_DESCRIPTION","key":"pdf:embeddedFileDescription"}, + {"class":"org.apache.tika.metadata.PDF","field":"EMBEDDED_FILE_SUBTYPE","key":"pdf:embeddedFileSubtype"}, + {"class":"org.apache.tika.metadata.PDF","field":"EOF_OFFSETS","key":"pdf:eofOffsets"}, + {"class":"org.apache.tika.metadata.PDF","field":"HAS_3D","key":"pdf:has3D"}, + {"class":"org.apache.tika.metadata.PDF","field":"HAS_ACROFORM_FIELDS","key":"pdf:hasAcroFormFields"}, + {"class":"org.apache.tika.metadata.PDF","field":"HAS_COLLECTION","key":"pdf:hasCollection"}, + {"class":"org.apache.tika.metadata.PDF","field":"HAS_MARKED_CONTENT","key":"pdf:hasMarkedContent"}, + {"class":"org.apache.tika.metadata.PDF","field":"HAS_SIGNATURE_FIELDS","key":"pdf:hasSignatureFields"}, + {"class":"org.apache.tika.metadata.PDF","field":"HAS_XFA","key":"pdf:hasXFA"}, + {"class":"org.apache.tika.metadata.PDF","field":"HAS_XMP","key":"pdf:hasXMP"}, + {"class":"org.apache.tika.metadata.PDF","field":"ILLUSTRATOR_TYPE","key":"pdf:illustrator:type"}, + {"class":"org.apache.tika.metadata.PDF","field":"INCREMENTAL_UPDATE_NUMBER","key":"pdf:incrementalUpdateNumber"}, + {"class":"org.apache.tika.metadata.PDF","field":"IS_ENCRYPTED","key":"pdf:encrypted"}, + {"class":"org.apache.tika.metadata.PDF","field":"JS_NAME","key":"pdf:jsName"}, + {"class":"org.apache.tika.metadata.PDF","field":"NUM_3D_ANNOTATIONS","key":"pdf:num3DAnnotations"}, + {"class":"org.apache.tika.metadata.PDF","field":"OCR_PAGE_COUNT","key":"pdf:ocrPageCount"}, + {"class":"org.apache.tika.metadata.PDF","field":"OVERALL_PERCENTAGE_UNMAPPED_UNICODE_CHARS","key":"pdf:overallPercentageUnmappedUnicodeChars"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDFAID_CONFORMANCE","key":"pdfaid:conformance"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDFAID_PART","key":"pdfaid:part"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDFA_VERSION","key":"pdfa:PDFVersion"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDFUAID_PART","key":"pdfuaid:part"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDFVT_MODIFIED","key":"pdfvt:modified"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDFVT_VERSION","key":"pdfvt:version"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDFXID_VERSION","key":"pdfxid:version"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDFX_CONFORMANCE","key":"pdfx:conformance"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDFX_VERSION","key":"pdfx:version"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDF_EXTENSION_VERSION","key":"pdf:PDFExtensionVersion"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDF_INCREMENTAL_UPDATE_COUNT","key":"pdf:incrementalUpdateCount"}, + {"class":"org.apache.tika.metadata.PDF","field":"PDF_VERSION","key":"pdf:PDFVersion"}, + {"class":"org.apache.tika.metadata.PDF","field":"PRODUCER","key":"pdf:producer"}, + {"class":"org.apache.tika.metadata.PDF","field":"TOTAL_UNMAPPED_UNICODE_CHARS","key":"pdf:totalUnmappedUnicodeChars"}, + {"class":"org.apache.tika.metadata.PDF","field":"UNMAPPED_UNICODE_CHARS_PER_PAGE","key":"pdf:unmappedUnicodeCharsPerPage"}, + {"class":"org.apache.tika.metadata.PDF","field":"XMP_LOCATION","key":"pdf:xmpLocation"}, + {"class":"org.apache.tika.metadata.PST","field":"DESCRIPTOR_NODE_ID","key":"pst:discriptorNodeId"}, + {"class":"org.apache.tika.metadata.PST","field":"IS_VALID","key":"pst:isValid"}, + {"class":"org.apache.tika.metadata.PST","field":"PST_FOLDER_PATH","key":"pst:folderPath"}, + {"class":"org.apache.tika.metadata.PagedText","field":"N_PAGES","key":"xmpTPg:NPages"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"AUTHORS_POSITION","key":"photoshop:AuthorsPosition"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"CAPTION_WRITER","key":"photoshop:CaptionWriter"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"CATEGORY","key":"photoshop:Category"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"CITY","key":"photoshop:City"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"COLOR_MODE","key":"photoshop:ColorMode"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"COUNTRY","key":"photoshop:Country"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"CREDIT","key":"photoshop:Credit"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"DATE_CREATED","key":"photoshop:DateCreated"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"HEADLINE","key":"photoshop:Headline"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"INSTRUCTIONS","key":"photoshop:Instructions"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"SOURCE","key":"photoshop:Source"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"STATE","key":"photoshop:State"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"SUPPLEMENTAL_CATEGORIES","key":"photoshop:SupplementalCategories"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"TRANSMISSION_REFERENCE","key":"photoshop:TransmissionReference"}, + {"class":"org.apache.tika.metadata.Photoshop","field":"URGENCY","key":"photoshop:Urgency"}, + {"class":"org.apache.tika.metadata.QuattroPro","field":"BUILD","key":"wordperfect:Build"}, + {"class":"org.apache.tika.metadata.QuattroPro","field":"ID","key":"wordperfect:Id"}, + {"class":"org.apache.tika.metadata.QuattroPro","field":"LOWEST_VERSION","key":"wordperfect:LowestVersion"}, + {"class":"org.apache.tika.metadata.QuattroPro","field":"VERSION","key":"wordperfect:Version"}, + {"class":"org.apache.tika.metadata.RTFMetadata","field":"CONTAINS_ENCAPSULATED_HTML","key":"rtf_meta:contains_encapsulated_html"}, + {"class":"org.apache.tika.metadata.RTFMetadata","field":"EMB_APP_VERSION","key":"rtf_meta:emb_app_version"}, + {"class":"org.apache.tika.metadata.RTFMetadata","field":"EMB_CLASS","key":"rtf_meta:emb_class"}, + {"class":"org.apache.tika.metadata.RTFMetadata","field":"EMB_ITEM","key":"rtf_meta:emb_item"}, + {"class":"org.apache.tika.metadata.RTFMetadata","field":"EMB_TOPIC","key":"rtf_meta:emb_topic"}, + {"class":"org.apache.tika.metadata.RTFMetadata","field":"THUMBNAIL","key":"rtf_meta:thumbnail"}, + {"class":"org.apache.tika.metadata.Rendering","field":"RENDERED_BY","key":"rendering:Rendered-By"}, + {"class":"org.apache.tika.metadata.Rendering","field":"RENDERED_MS","key":"rendering:rendering-time-ms"}, + {"class":"org.apache.tika.metadata.TIFF","field":"BITS_PER_SAMPLE","key":"tiff:BitsPerSample"}, + {"class":"org.apache.tika.metadata.TIFF","field":"EQUIPMENT_MAKE","key":"tiff:Make"}, + {"class":"org.apache.tika.metadata.TIFF","field":"EQUIPMENT_MODEL","key":"tiff:Model"}, + {"class":"org.apache.tika.metadata.TIFF","field":"EXIF_PAGE_COUNT","key":"exif:PageCount"}, + {"class":"org.apache.tika.metadata.TIFF","field":"EXPOSURE_TIME","key":"exif:ExposureTime"}, + {"class":"org.apache.tika.metadata.TIFF","field":"FLASH_FIRED","key":"exif:Flash"}, + {"class":"org.apache.tika.metadata.TIFF","field":"FOCAL_LENGTH","key":"exif:FocalLength"}, + {"class":"org.apache.tika.metadata.TIFF","field":"F_NUMBER","key":"exif:FNumber"}, + {"class":"org.apache.tika.metadata.TIFF","field":"IMAGE_LENGTH","key":"tiff:ImageLength"}, + {"class":"org.apache.tika.metadata.TIFF","field":"IMAGE_WIDTH","key":"tiff:ImageWidth"}, + {"class":"org.apache.tika.metadata.TIFF","field":"ISO_SPEED_RATINGS","key":"exif:IsoSpeedRatings"}, + {"class":"org.apache.tika.metadata.TIFF","field":"ORIENTATION","key":"tiff:Orientation"}, + {"class":"org.apache.tika.metadata.TIFF","field":"ORIGINAL_DATE","key":"exif:DateTimeOriginal"}, + {"class":"org.apache.tika.metadata.TIFF","field":"RESOLUTION_HORIZONTAL","key":"tiff:XResolution"}, + {"class":"org.apache.tika.metadata.TIFF","field":"RESOLUTION_UNIT","key":"tiff:ResolutionUnit"}, + {"class":"org.apache.tika.metadata.TIFF","field":"RESOLUTION_VERTICAL","key":"tiff:YResolution"}, + {"class":"org.apache.tika.metadata.TIFF","field":"SAMPLES_PER_PIXEL","key":"tiff:SamplesPerPixel"}, + {"class":"org.apache.tika.metadata.TIFF","field":"SOFTWARE","key":"tiff:Software"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"ALTITUDE","key":"geo:alt"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"COMMENTS","key":"w:Comments"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"CONTAINER_EXCEPTION","key":"X-TIKA:EXCEPTION:container_exception"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"CONTENT_TYPE_HINT","key":"Content-Type-Hint"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"CONTENT_TYPE_PARSER_OVERRIDE","key":"Content-Type-Parser-Override"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"CONTENT_TYPE_USER_OVERRIDE","key":"Content-Type-Override"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"CONTRIBUTOR","key":"dc:contributor"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"COVERAGE","key":"dc:coverage"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"CREATED","key":"dcterms:created"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"CREATOR","key":"dc:creator"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"CREATOR_TOOL","key":"xmp:CreatorTool"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"DESCRIPTION","key":"dc:description"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"DETECTED_ENCODING","key":"X-TIKA:detectedEncoding"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"EMBEDDED_BYTES_EXCEPTION","key":"X-TIKA:EXCEPTION:embedded_bytes_exception"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"EMBEDDED_DEPTH","key":"X-TIKA:embedded_depth"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"EMBEDDED_EXCEPTION","key":"X-TIKA:EXCEPTION:embedded_exception"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"EMBEDDED_ID","key":"X-TIKA:embedded_id"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"EMBEDDED_ID_PATH","key":"X-TIKA:embedded_id_path"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"EMBEDDED_RESOURCE_PATH","key":"X-TIKA:embedded_resource_path"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"EMBEDDED_RESOURCE_TYPE","key":"embeddedResourceType"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"EMBEDDED_WARNING","key":"X-TIKA:EXCEPTION:embedded_warning"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"ENCODING_DETECTOR","key":"X-TIKA:encodingDetector"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"FINAL_EMBEDDED_RESOURCE_PATH","key":"X-TIKA:final_embedded_resource_path"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"FORMAT","key":"dc:format"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"HAS_SIGNATURE","key":"hasSignature"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"IDENTIFIER","key":"dc:identifier"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"INTERNAL_PATH","key":"X-TIKA:internalPath"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"IS_ENCRYPTED","key":"X-TIKA:encrypted"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"LANGUAGE","key":"dc:language"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"LATITUDE","key":"geo:lat"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"LONGITUDE","key":"geo:long"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"METADATA_DATE","key":"xmp:MetadataDate"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"MODIFIED","key":"dcterms:modified"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"MODIFIER","key":"meta:last-author"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"NUM_IMAGES","key":"imagereader:NumImages"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"ORIGINAL_RESOURCE_NAME","key":"X-TIKA:origResourceName"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"PARSE_TIME_MILLIS","key":"X-TIKA:parse_time_millis"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"PIPES_RESULT","key":"X-TIKA:pipes_result"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"PRINT_DATE","key":"meta:print-date"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"PUBLISHER","key":"dc:publisher"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"RATING","key":"xmp:Rating"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"RELATION","key":"dc:relation"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"RIGHTS","key":"dc:rights"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"SIGNATURE_CONTACT_INFO","key":"signature:contact-info"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"SIGNATURE_DATE","key":"signature:date"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"SIGNATURE_FILTER","key":"signature:filter"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"SIGNATURE_LOCATION","key":"signature:location"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"SIGNATURE_NAME","key":"signature:name"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"SIGNATURE_REASON","key":"signature:reason"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"SOURCE","key":"dc:source"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"SOURCE_PATH","key":"X-TIKA:sourcePath"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"SUBJECT","key":"dc:subject"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TIKA_CONTENT","key":"X-TIKA:content"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TIKA_CONTENT_HANDLER","key":"X-TIKA:content_handler"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TIKA_DETECTED_LANGUAGE","key":"X-TIKA:detected_language"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TIKA_DETECTED_LANGUAGE_CONFIDENCE","key":"X-TIKA:detected_language_confidence"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TIKA_DETECTED_LANGUAGE_CONFIDENCE_RAW","key":"X-TIKA:detected_language_confidence_raw"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TIKA_META_EXCEPTION_EMBEDDED_STREAM","key":"X-TIKA:EXCEPTION:embedded_stream_exception"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TIKA_META_EXCEPTION_WARNING","key":"X-TIKA:EXCEPTION:warn"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TIKA_PARSED_BY","key":"X-TIKA:Parsed-By"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TIKA_PARSED_BY_FULL_SET","key":"X-TIKA:Parsed-By-Full-Set"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TITLE","key":"dc:title"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TRUNCATED_METADATA","key":"X-TIKA:WARN:truncated_metadata"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"TYPE","key":"dc:type"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"VERSION_COUNT","key":"X-TIKA:versionCount"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"VERSION_NUMBER","key":"X-TIKA:versionNumber"}, + {"class":"org.apache.tika.metadata.TikaCoreProperties","field":"WRITE_LIMIT_REACHED","key":"X-TIKA:EXCEPTION:write_limit_reached"}, + {"class":"org.apache.tika.metadata.TikaPagedText","field":"PAGE_NUMBER","key":"tika_pg:page_number"}, + {"class":"org.apache.tika.metadata.TikaPagedText","field":"PAGE_ROTATION","key":"tika_pg:page_rotation"}, + {"class":"org.apache.tika.metadata.WARC","field":"WARC_PAYLOAD_CONTENT_TYPE","key":"warc:payload-content-type"}, + {"class":"org.apache.tika.metadata.WARC","field":"WARC_RECORD_CONTENT_TYPE","key":"warc:record-content-type"}, + {"class":"org.apache.tika.metadata.WARC","field":"WARC_RECORD_ID","key":"warc:WARC-Record-ID"}, + {"class":"org.apache.tika.metadata.WARC","field":"WARC_WARNING","key":"warc:warning"}, + {"class":"org.apache.tika.metadata.WordPerfect","field":"ENCRYPTED","key":"wordperfect:Encrypted"}, + {"class":"org.apache.tika.metadata.WordPerfect","field":"FILE_ID","key":"wordperfect:FileId"}, + {"class":"org.apache.tika.metadata.WordPerfect","field":"FILE_SIZE","key":"wordperfect:FileSize"}, + {"class":"org.apache.tika.metadata.WordPerfect","field":"FILE_TYPE","key":"wordperfect:FileType"}, + {"class":"org.apache.tika.metadata.WordPerfect","field":"MAJOR_VERSION","key":"wordperfect:MajorVersion"}, + {"class":"org.apache.tika.metadata.WordPerfect","field":"MINOR_VERSION","key":"wordperfect:MinorVersion"}, + {"class":"org.apache.tika.metadata.WordPerfect","field":"PRODUCT_TYPE","key":"wordperfect:ProductType"}, + {"class":"org.apache.tika.metadata.XMP","field":"ABOUT","key":"xmp:About"}, + {"class":"org.apache.tika.metadata.XMP","field":"ADVISORY","key":"xmp:Advisory"}, + {"class":"org.apache.tika.metadata.XMP","field":"CREATE_DATE","key":"xmp:CreateDate"}, + {"class":"org.apache.tika.metadata.XMP","field":"CREATOR_TOOL","key":"xmp:CreatorTool"}, + {"class":"org.apache.tika.metadata.XMP","field":"IDENTIFIER","key":"xmp:Identifier"}, + {"class":"org.apache.tika.metadata.XMP","field":"LABEL","key":"xmp:Label"}, + {"class":"org.apache.tika.metadata.XMP","field":"METADATA_DATE","key":"xmp:MetadataDate"}, + {"class":"org.apache.tika.metadata.XMP","field":"MODIFY_DATE","key":"xmp:ModifyDate"}, + {"class":"org.apache.tika.metadata.XMP","field":"NICKNAME","key":"xmp:NickName"}, + {"class":"org.apache.tika.metadata.XMP","field":"RATING","key":"xmp:Rating"}, + {"class":"org.apache.tika.metadata.XMP","field":"TITLE","key":"xmp:Title"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"CONTRIBUTOR","key":"xmp:dc:contributor"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"COVERAGE","key":"xmp:dc:coverage"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"CREATED","key":"xmp:dcterms:created"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"CREATOR","key":"xmp:dc:creator"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"DATE","key":"xmp:dc:date"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"DESCRIPTION","key":"xmp:dc:description"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"FORMAT","key":"xmp:dc:format"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"IDENTIFIER","key":"xmp:dc:identifier"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"LANGUAGE","key":"xmp:dc:language"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"MODIFIED","key":"xmp:dcterms:modified"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"PUBLISHER","key":"xmp:dc:publisher"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"RELATION","key":"xmp:dc:relation"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"RIGHTS","key":"xmp:dc:rights"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"SOURCE","key":"xmp:dc:source"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"SUBJECT","key":"xmp:dc:subject"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"TITLE","key":"xmp:dc:title"}, + {"class":"org.apache.tika.metadata.XMPDC","field":"TYPE","key":"xmp:dc:type"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"ABS_PEAK_AUDIO_FILE_PATH","key":"xmpDM:absPeakAudioFilePath"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"ALBUM","key":"xmpDM:album"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"ALBUM_ARTIST","key":"xmpDM:albumArtist"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"ALT_TAPE_NAME","key":"xmpDM:altTapeName"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"ARTIST","key":"xmpDM:artist"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"AUDIO_CHANNEL_TYPE","key":"xmpDM:audioChannelType"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"AUDIO_COMPRESSOR","key":"xmpDM:audioCompressor"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"AUDIO_MOD_DATE","key":"xmpDM:audioModDate"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"AUDIO_SAMPLE_RATE","key":"xmpDM:audioSampleRate"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"AUDIO_SAMPLE_TYPE","key":"xmpDM:audioSampleType"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"COMPILATION","key":"xmpDM:compilation"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"COMPOSER","key":"xmpDM:composer"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"COPYRIGHT","key":"xmpDM:copyright"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"DISC_NUMBER","key":"xmpDM:discNumber"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"DURATION","key":"xmpDM:duration"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"ENGINEER","key":"xmpDM:engineer"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"FILE_DATA_RATE","key":"xmpDM:fileDataRate"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"GENRE","key":"xmpDM:genre"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"INSTRUMENT","key":"xmpDM:instrument"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"KEY","key":"xmpDM:key"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"LOG_COMMENT","key":"xmpDM:logComment"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"LOOP","key":"xmpDM:loop"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"METADATA_MOD_DATE","key":"xmpDM:metadataModDate"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"NUMBER_OF_BEATS","key":"xmpDM:numberOfBeats"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"PULL_DOWN","key":"xmpDM:pullDown"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"RELATIVE_PEAK_AUDIO_FILE_PATH","key":"xmpDM:relativePeakAudioFilePath"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"RELEASE_DATE","key":"xmpDM:releaseDate"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"SCALE_TYPE","key":"xmpDM:scaleType"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"SCENE","key":"xmpDM:scene"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"SHOT_DATE","key":"xmpDM:shotDate"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"SHOT_LOCATION","key":"xmpDM:shotLocation"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"SHOT_NAME","key":"xmpDM:shotName"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"SPEAKER_PLACEMENT","key":"xmpDM:speakerPlacement"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"STRETCH_MODE","key":"xmpDM:stretchMode"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"TAPE_NAME","key":"xmpDM:tapeName"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"TEMPO","key":"xmpDM:tempo"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"TIME_SIGNATURE","key":"xmpDM:timeSignature"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"TRACK_NUMBER","key":"xmpDM:trackNumber"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"VIDEO_ALPHA_MODE","key":"xmpDM:videoAlphaMode"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"VIDEO_ALPHA_UNITY_IS_TRANSPARENT","key":"xmpDM:videoAlphaUnityIsTransparent"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"VIDEO_COLOR_SPACE","key":"xmpDM:videoColorSpace"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"VIDEO_COMPRESSOR","key":"xmpDM:videoCompressor"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"VIDEO_FIELD_ORDER","key":"xmpDM:videoFieldOrder"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"VIDEO_FRAME_RATE","key":"xmpDM:videoFrameRate"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"VIDEO_MOD_DATE","key":"xmpDM:videoModDate"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"VIDEO_PIXEL_ASPECT_RATIO","key":"xmpDM:videoPixelAspectRatio"}, + {"class":"org.apache.tika.metadata.XMPDM","field":"VIDEO_PIXEL_DEPTH","key":"xmpDM:videoPixelDepth"}, + {"class":"org.apache.tika.metadata.XMPDM$ChannelTypePropertyConverter","field":"property","key":"xmpDM:audioChannelType"}, + {"class":"org.apache.tika.metadata.XMPIdq","field":"SCHEME","key":"xmpidq:Scheme"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"DERIVED_FROM_DOCUMENTID","key":"xmpMM:DerivedFrom:DocumentID"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"DERIVED_FROM_INSTANCEID","key":"xmpMM:DerivedFrom:InstanceID"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"DOCUMENTID","key":"xmpMM:DocumentID"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"HISTORY_ACTION","key":"xmpMM:History:Action"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"HISTORY_EVENT_INSTANCEID","key":"xmpMM:History:InstanceID"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"HISTORY_SOFTWARE_AGENT","key":"xmpMM:History:SoftwareAgent"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"HISTORY_WHEN","key":"xmpMM:History:When"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"INSTANCEID","key":"xmpMM:InstanceID"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"ORIGINAL_DOCUMENTID","key":"xmpMM:OriginalDocumentID"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"RENDITION_CLASS","key":"xmpMM:RenditionClass"}, + {"class":"org.apache.tika.metadata.XMPMM","field":"RENDITION_PARAMS","key":"xmpMM:RenditionParams"}, + {"class":"org.apache.tika.metadata.XMPPDF","field":"ABOUT","key":"xmp:pdf:About"}, + {"class":"org.apache.tika.metadata.XMPPDF","field":"KEY_WORDS","key":"xmp:pdf:Keywords"}, + {"class":"org.apache.tika.metadata.XMPPDF","field":"PDF_VERSION","key":"xmp:pdf:PDFVersion"}, + {"class":"org.apache.tika.metadata.XMPPDF","field":"PRODUCER","key":"xmp:pdf:Producer"}, + {"class":"org.apache.tika.metadata.XMPRights","field":"CERTIFICATE","key":"xmpRights:Certificate"}, + {"class":"org.apache.tika.metadata.XMPRights","field":"MARKED","key":"xmpRights:Marked"}, + {"class":"org.apache.tika.metadata.XMPRights","field":"OWNER","key":"xmpRights:Owner"}, + {"class":"org.apache.tika.metadata.XMPRights","field":"USAGE_TERMS","key":"xmpRights:UsageTerms"}, + {"class":"org.apache.tika.metadata.XMPRights","field":"WEB_STATEMENT","key":"xmpRights:WebStatement"}, + {"class":"org.apache.tika.sax.AbstractRecursiveParserWrapperHandler","field":"EMBEDDED_RESOURCE_LIMIT_REACHED","key":"X-TIKA:EXCEPTION:embedded_resource_limit_reached"}, + {"class":"org.apache.tika.utils.ParserUtils","field":"EMBEDDED_PARSER","key":"X-TIKA:EXCEPTION:embedded_parser"} +] diff --git a/tika-metadata-schema/src/test/resources/org/apache/tika/metadata/migration-overlay.tsv b/tika-metadata-schema/src/test/resources/org/apache/tika/metadata/migration-overlay.tsv new file mode 100644 index 0000000000..552d8e8868 --- /dev/null +++ b/tika-metadata-schema/src/test/resources/org/apache/tika/metadata/migration-overlay.tsv @@ -0,0 +1,43 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# TIKA-4797 manual migration overlay (core scope, adjudicated + confirmed 2026-07-28) +# The moves/removals the field-identity join could NOT auto-bridge. Everything else auto-renames. +# +# v3<TAB>v4 (v4 = DROPPED means 4.x no longer emits it; not bridgeable) +meta:mapi-from-representing-email mapi:from-representing-email +meta:mapi-from-representing-name mapi:from-representing-name +meta:mapi-importance mapi:importance +meta:mapi-is-flagged mapi:is-flagged +meta:mapi-message-class mapi:message-class +meta:mapi-recipients-string mapi:recipients-string +meta:mapi-sent-by-server-type mapi:sent-by-server-type +# CONSOLIDATION not clean rename: 4.x removed the client-submit key and repoints PST's +# getClientSubmitTime() into SUBMISSION_ACCEPTED_AT_TIME (distinct MAPI props -> mislabel). +# --> IF patches/MAPI-client-submit-time.patch is applied, retarget this to mapi:msg-client-submit-time +# (a CLEAN rename). Until then, the value follows to submission-accepted, so this maps there. +meta:mapi-msg-client-submit-time mapi:msg-submission-accepted-at-time +# DROPPED (confirmed intentional): 4.x OutlookPSTParser sets TikaCoreProperties.INTERNAL_PATH +# (tk:internal-path) = folderPath + "/" + item-name on each mail item -> the folder path became the +# full item path, a SUPERSET. Not a 1:1 value, so the key-rename bridge can't reproduce the folder-only +# value; document "folder path now part of tk:internal-path". Not bridgeable as a rename. +pst:folderPath DROPPED +# RTF embedded-object fields: 4.x renamed the Java fields EMB_* -> EMBEDDED_* AND the keys +# rtf_meta:emb_* -> rtf:embedded-*, so field-identity can't bridge them. Clean renames (targets +# verified present in the 4.x closed set); fuzzy suggested each correctly. +rtf_meta:emb_app_version rtf:embedded-app-version +rtf_meta:emb_class rtf:embedded-class +rtf_meta:emb_item rtf:embedded-item +rtf_meta:emb_topic rtf:embedded-topic
