Metadata Mapper

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 approptiate 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.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 withing 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.MetadataMapping">
        <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 maping to be configured

  • fields: comma separated list of possible candidates in the format GROUP:TAG (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.
  • 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. Available classes include:
    ├── mappingTypes
    │   ├── AssetAvailabilityMapping
    │   ├── AssetNameMapping
    │   ├── AssetTypeMapping
    │   ├── ConditionalMapping
    │   ├── conditionTypes
    │   │   ├── AndCondition
    │   │   ├── AssetOrNodeTypeCondition
    │   │   ├── NotCondition
    │   │   ├── OrCondition
    │   │   ├── StringValueContainsCondition
    │   │   └── StringValueEqualsCondition
    │   ├── infofield
    │   │   ├── CheckboxInfofieldMapping
    │   │   ├── DateInfofieldMapping
    │   │   ├── DoubleInfofieldMapping
    │   │   ├── DropdownInfofieldMapping
    │   │   ├── InfofieldMultiMapping
    │   │   ├── LocalizedTextInfofieldMapping
    │   │   ├── NodeReferencingInfofieldByMultiNameMapping
    │   │   ├── NodeReferencingInfofieldByNameMapping
    │   │   ├── NodeReferencingInfofieldMapping
    │   │   ├── NodeReferencingInfofieldMultiMapping
    │   │   ├── NumberInfofieldMapping
    │   │   └── TextInfofieldMapping
    │   ├── MultiMapping
    │   ├── NodeAssignmentMapping
    │   ├── NodeByNameAssignmentMapping
    │   ├── NodeReferencingHierarchyMapping
    │   └── ValueSplitMapping
    ├── nodeFinder
    │   ├── DefaultNodeFinder
    │   ├── DivNodeFinder
    │   └── LocalizedNodeFinder
    └── valueTransformer
        ├── AspectRatioTransformer
        ├── AssetTypeNameTransformer
        ├── ColorspaceTransformer
        ├── DateToDaytimeTransformer
        ├── DateToMonthTransformer
        ├── DateToSeasonTransformer
        ├── DateToYearTransformer
        ├── DurationTransformer
        ├── IdMappingTransformer
        ├── RegexTransformer
        └── SubstringTransformer
  • 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 (usefull for keywords)
  • assetTypes only apply this mapping for a list of asset type IDs, e.g. "10050,10051"

Now that we've seen all the possibilities, let's consider a more interesting example. 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 is 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>

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 aviod conflicts with other plugins that may use the same libs at different version levels. When developing the mappings in your IDE, you may need to apply the shading (in both directions) yourself in order to get autocompletion. If you know of a better way, let us know :-)