Metadata Mapper

No UI

Writes file metadata (such as IPTC, EXIF or XMP) from the original file to CELUM information fields. In contrast to the core functionality, this plugin supports multiple candidate sources for one field and is able to transform the value in a multitude of ways before writing it to an information field, for example use the date that a photo was taken and convert it to a keyword of the appropriate season (e.g. DateTaken is 2017-07-07 -> add keyword Summer to the information field Season)

Note that the mapping can only take place when the asset has an asset type and has been released from the upload basket.

Properties

To be configured in {home}/appserver/conf/custom.properties

metadataMapper.license

type: String, required: yes, default: -, since v2.5

The license key for the plugin (product: metadataMapper), provided by brix.

metadataMapper.autoSetAssetType

type: long, required: no, default: 0

Automatically set this asset type when mapping the metadata.

metadataMapper.reinitNodeIds

type: list of long (comma separated), required: no, default: -

If you install the Metadata Mapper after you've already uploaded some asset, you can configure the IDs of all root nodes that should be re-initialized (i.e. apply the mappings all assets within those nodes) through Administration > System Tasks > Other > Metadata Mapper Re-Initializer

Bean Configuration

Because the Metadata Mapper can be quite complex, the main configuration is not done through properties but rather with Spring Beans. The Metadata Mapper expects an XML to be located in {home}/appserver/spring/metadataMapper.xml

Let's consider the following example where we try to map the creator and the creation date:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
    <context:annotation-config/>

    <bean id="metadataMapper" class="ch.brix.metadataMapper.MetadataMapper">
        <property name="mappings" ref="metadataMapperMappings"/>
    </bean>

    <util:list id="metadataMapperMappings" value-type="ch.brix.metadataMapper.AbstractMapping">
        <bean class="ch.brix.metadataMapper.MetadataMapping">
            <property name="fields" value="XMP:Creator,EXIF:Artist,XMP:Source,IPTC:By-line,XMP:CaptionWriter,IPTC:Writer-Editor,EXIF:Copyright,IPTC:CopyrightNotice"/>
            <property name="mapping">
                <bean class="ch.brix.metadataMapper.lib.mappingTypes.infofield.TextInfofieldMapping">
                    <property name="infofieldId" value="136"/>
                </bean>
            </property>
        </bean>
        <bean class="ch.brix.metadataMapper.MetadataMapping">
            <property name="fields" value="IPTC:DateCreated,IPTC:DateTimeCreated,XMP:CreateDate,EXIF:DateTimeOriginal"/>
            <property name="mapping">
                <bean class="ch.brix.metadataMapper.lib.mappingTypes.infofield.DateInfofieldMapping">
                    <property name="infofieldId" value="137"/>
                </bean>
            </property>
            <property name="updateOnNewVersion" value="true"/>
        </bean>
    </util:list>
</beans>

The main player here is the MetadataMapping-class, which needs at least fields and mapping to be configured

  • fields: comma separated list of possible candidates in the format GROUP:TAG (e.g. XMP:Title - to find your tags, exiftool -g -j yourfile.jpg can be helpful). Uses the first non-empty metadata field it finds (unless the property stopAfterFirstValue is set to false). Alternatively you can also pass a fileProperty key to tap into the file properties that CELUM extracts. Note that for videos, mediainfo may be used instead of exiftool - the keys retain their structure (e.g. General:Movie_name).

  • mapping: The mapping bean that takes the extracted value and applies it to an information field. Most mappers also take a value transformer to transform the received value before applying it. There are a lot of different mappers, so they are not explained here in detail. We recommend that you use an IDE and import the jar as a library - this enables auto-complete of all ch.brix.metadataMapper.lib.mappingTypes and their associated nodeFinder and valueTransformer.

    Mappings in the infofield sub-package share some common booleans:

    • overwrite: whether to overwrite existing values with the incomming one (default is true)
    • clearOnEmptyValue: whether to clear the information field when receiving an empty string (default is false)
    • doUpdateCheck: whether to check if the information field already contains the target value (default is false). Note that this may result in an asset reload for cases where the information field is not present yet (performance implications).
  • updateOnNewVersion whether to update the mapped value when a new version is added (default is false)

  • splitString split the received value by this string and map multiple times (useful for keywords)

  • assetTypes only apply this mapping for a list of asset type IDs, e.g. "10050,10051"

Examples

In this case we want to automatically populate the Year noderef with the year that the photo was taken in. Note the use of both the value transformer which converts the date to a year and the node finder which finds the ID of the appropriate year-keyword or creates it if necessary.

<bean class="ch.brix.metadataMapper.MetadataMapping">
    <property name="fields" value="IPTC:DateCreated,IPTC:DateTimeCreated,XMP:CreateDate,EXIF:DateTimeOriginal"/>
    <property name="mapping">
        <bean class="ch.brix.metadataMapper.lib.mappingTypes.infofield.NodeReferencingInfofieldByNameMapping">
            <property name="infofieldId" value="114"/>
            <property name="exclusive" value="false"/>
            <property name="valueTransformer">
                <bean class="ch.brix.metadataMapper.lib.valueTransformer.DateToYearTransformer"/>
            </property>
            <property name="nodeFinder">
                <bean class="ch.brix.metadataMapper.lib.nodeFinder.DefaultNodeFinder">
                    <property name="rootNodeId" value="1545"/>
                    <property name="createIfNotFound" value="true"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>

Here's another example (the one with the seasons from the intro) where we don't use a node finder, as there are only 4 valid values.

<bean class="ch.brix.metadataMapper.MetadataMapping">
    <property name="fields" value="IPTC:DateCreated,IPTC:DateTimeCreated,XMP:CreateDate,EXIF:DateTimeOriginal"/>
    <property name="mapping">
        <bean class="ch.brix.metadataMapper.lib.mappingTypes.infofield.NodeReferencingInfofieldMapping">
            <property name="infofieldId" value="114"/>
            <property name="valueTransformer">
                <bean class="ch.brix.metadataMapper.lib.valueTransformer.DateToSeasonTransformer">
                    <property name="springNodeID" value="1541"/>
                    <property name="summerNodeID" value="1542"/>
                    <property name="autumnNodeID" value="1543"/>
                    <property name="winterNodeID" value="1544"/>
                </bean>
            </property>
        </bean>
    </property>
    <property name="updateOnNewVersion" value="true"/>
</bean>

Here's a more involved example there we take a bunch of keywords, split them with a delimiter, and then go look for matching nodes (and create them if necessary)

<bean class="ch.brix.metadataMapper.MetadataMapping">
   <property name="fields" value="IPTC:Keywords,IPTC:XPKeywords,XMP:Keywords,XMP:XPKeywords,EXIF:Keywords,EXIF:XPKeywords" />
   <property name="mapping">
       <bean class="ch.brix.metadataMapper.lib.mappingTypes.infofield.NodeReferencingInfofieldByMultiNameMapping">
           <property name="infofieldId" value="123" />
           <property name="delimiter" value="[,;]\s*" />
           <property name="delimiterAsRegex" value="true" />
           <property name="exclusive" value="false" />
           <property name="nodeFinder">
               <bean class="ch.brix.metadataMapper.lib.nodeFinder.DefaultNodeFinder">
                   <property name="rootNodeId" value="456" />
                   <property name="createIfNotFound" value="true" />
                   <property name="createInNodeId" value="789" />
                   <property name="matchType" value="EXACT_CASE_INSENSITIVE" />
               </bean>
           </property>
       </bean>
   </property>
</bean>

A note on shading

All mappers, value transformers and node finders are located in the generic package ch.brix.lib. These however get shaded when included in any project to _ch.brix.ARTIFACTID.lib (so ch.brix.metadataMapper.lib in this case) in order to avoid conflicts with other plugins that may use the same libs at different version levels. When developing the mappings in your IDE, we recommend that you import the compiled jar as a library (Intellij: Project Settings > Libraries > + > Java, select the jar).

Compatibility Matrix

metadataMapper CELUM (min. version)
1.0 5.11.0
1.1 5.12.0
1.2 5.12.2
1.3 5.12.4
2.0-2.4 5.13.3
2.5+ 5.13.4 (tested up to 6.16)

Release Notes

1.0

Released 2016-03-18

  • Initial Version

1.1

Released 2016-04-12

  • Fixed shading configuration

1.2

Released 2016-03-18

  • Added support for versions
  • Added initialization task

1.3

Released 2018-02-09

  • Updated mapping library to support new mapping types
  • Fixed mapping not triggering when upload happens via SDK
  • Various improvements regarding multi-threading

2.0

Released 2018-03-22

  • Refactoring of mappers to differentiate between those that need to wait for file metadata to arrive and those who don't

2.1

Released 2018-07-24

  • Added support for the async SDK events

2.2

Released 2018-09-07

  • Added support custom mappings (interface)

2.3

Released 2018-09-12

  • Updated mapping library to support new mapping types

2.4

Released 2018-11-29

  • Added support for original file mappings

2.5

Released 2019-01-19

  • Added license
  • CELUM 6.4 (19.10) compatible

2.6

Released 2021-09-27

  • Fixed fields property not having a guaranteed order, rendering the "first of..." promise meaningless