Metadata Supplier | Version 4

Sophora Metadata Supplier for ARD-Mediathek Developing Guide

This article describes how to develop plugins for the Sophora Metadata Supplier for ARD-Mediathek.

Custom mappings

The Metadata Supplier as a link between the source system and the ARD-Mediathek does not specify the contents of the resources that will be transferred. For this purpose, custom mappers are used as plugins in the Metadata Supplier application. They define the mapping from source objects to ARD Core API resources by creating Metadata Supplier model objects and filling in all the required (and optional) fields. The finished model objects are then returned to the Metadata Supplier application which will in turn continue with the preparation and uploading process to the ARD-Mediathek.

Sophora Metadata Supplier for ARD-Mediathek Components
The components of the Metadata Supplier.

Create a custom mapper plugin

To create a custom mapper plugin, a Java project with the following Maven dependency to the artifact metadata-supplier-mapper has to be created. Note that we provide a metadata-supplier-plugin-example project, which can be used as a starting point for your own custom mapper (GroupId: com.subshell.sophora.metadatasupplier, ArtifactId: metadata-supplier-plugin-example).

We provide helpers for handling Sophora documents in the project metadata-supplier-sophora-commons. The example project demonstrates how to check for Sophora external IDs.

<!-- Sophora Metadata Supplier -->
<dependency>
    <groupId>com.subshell.sophora.metadatasupplier</groupId>
    <artifactId>metadata-supplier-mapper</artifactId>
    <version>${sophora.metadatasupplier.version}</version>
    <scope>provided</scope>
</dependency>
<!-- Helper for Sophora as source system -->
<dependency>
	<groupId>com.subshell.sophora.metadatasupplier</groupId>
	<artifactId>metadata-supplier-sophora-commons</artifactId>
	<version>${sophora.metadatasupplier.version}</version>
    <scope>provided</scope>
</dependency>

Create a launcher project

To start the Metadata Supplier with your custom mapper plugin for development reasons from your IDE you have to use a launcher project. Note that we provide a metadata-supplier-plugin-example-launcher project, which can be used as a starting point (GroupId: com.subshell.sophora.metadatasupplier, ArtifactId: metadata-supplier-plugin-example-launcher).

1. Create a new Maven project that is used as launcher project (e.g. metadata-supplier-with-custom-plugin-launcher) with a dependency to metadata-supplier-application and your custom plugin project created above:

...
<artifactId>metadata-supplier-with-custom-plugin-launcher</artifactId>
...
<dependencies>
	<!-- Metadata Supplier Application -->
	<dependency>
 		<groupId>com.subshell.sophora.metadatasupplier</groupId>
 		<artifactId>metadata-supplier-application</artifactId>
		<!-- The released version of the Metadata Supplier -->
		<version>4.1.0</version>
	</dependency>
	<!-- Your custom Metadata Supplier plugin -->
	<dependency>
 		<groupId>com.mycompany.metadatasupplier</groupId>
		<artifactId>my-custom-metadata-supplier-plugin</artifactId>
		<!-- The development version of your plugin -->
		<version>4.x.y-SNAPSHOT</version>
	</dependency>
</dependencies>
...

2. Create (or copy) an application.yml to the root of your launcher project (next to the pom.xml) and configure it with your settings. See the administration documentation for examples.

3. In Eclipse IDE (IntelliJ IDEA should be similar) create a launch configuration for the launcher project with the following settings:

  • Name: Sophora Metadata Supplier with custom plugin (or similar)
  • Project: metadata-supplier-with-custom-plugin-launcher (your launcher project)
  • Main class: com.subshell.sophora.metadatasupplier.application.Application
  • Working Directory: ${workspace_loc:metadata-supplier-with-custom-plugin-launcher} (the launcher project root)

4. Finally run the launch configuration. The Metadata Supplier should start with your settings and your plugin.

Create custom mappers

The Metadata Supplier recognizes a mapper class by looking for two criteria. It needs to be a Spring component (with the @Component annotation) and it has to extend the IResourceMapper interface. This generic interface can be used to create any kind of resource. There are also ways to map specific kinds of resources with the interfaces that already extend from the base interface. An example would be the IShowMapper to map source objects to resources of type IShow. The following sections go into further detail as to how mappers are implemented. We also provide an ExampleShowMapper in the sources JAR file of the metadata-supplier-plugin-example project. It also determines if an unpublish or republish must be done at the ARD Core API based on the isPublished() on mapped objects that support it.

@Component
@Slf4j
public class ExampleShowMapper implements IShowMapper {

  @Override public boolean accept(SourceDescriptor sourceDescriptor) {
    // To be implemented
  }
  @Override public List<IShow> mapToResources(SourceDescriptor sourceDescriptor, IMappingContext mappingContext) {
    // To be implemented
  }
}

Implement IResourceMapper

The interface methods of the IResourceMapper will be triggered by the IMetadataSupplier (which is called by events from the source system for example). Before any mapping takes place, the accept(SourceDescriptor) method will be called to select the correct mapper for the source object. Only if your custom mapper identifies with the given source descriptor, the mapToResources(SourceDescriptor, IMappingContext) method will be called. In the Sophora environment for example, the SourceDescriptor consists of the UUID and the node type of a Sophora document. So with the accept method you could define if the mapper is suitable to map documents of certain node types.

@Override
public boolean accept(SourceDescriptor sourceDescriptor) {
  boolean accepted;
  // For example you can check the type of the source.
  accepted = sourceDescriptor.hasSourceType(ACCEPTED_TYPE_NAME);
  // Sophora users may use the SophoraSourceDescriptor to use Sophora wordings.
  accepted = SophoraSourceDescriptor.isValidForNodeType(sourceDescriptor, ACCEPTED_TYPE_NAME);
  return accepted;
}

In the mapToResources(SourceDescriptor, IMappingContext) method, the mapping from your source objects to the Metadata Supplier model objects takes place. It provides you with the descriptor of the source object that needs to be mapped and an additional parameter of type IMappingContext which is explained in the following section. Since the mapper is responsible to retrieve the source object from the source system in order to map it, you may use a mechanism like Spring Data Sophora in the Sophora context. After the mapping process, the finished resource(s) have to be returned as a list, which may be empty if the mapping has failed. The Metadata Supplier automatically sorts the returned resource objects into the correct order for delivery to the ARD-Mediathek.

@Override
public List<IShow> mapToResources(SourceDescriptor sourceDescriptor, IMappingContext mappingContext) {
  // The id of the source object is needed to get the source object from the source system.
  String sourceId = sourceDescriptor.getSourceId();
  // Sophora users may use the Sophora wordings of the SophoraSourceDescriptor.
  sourceId = SophoraSourceDescriptor.getExternalId(sourceDescriptor);
  IShowSourceObject myShowSourceObject = mySourceSystem.getShowSourceObject(sourceId);

  ShowBuilder<?, ?> showBuilder = Show.builder()
    .withTitle(myShowSourceObject.getTitle())
    .withExternalId(new ExternalId(sourceId))
    .withPublished(myShowSourceObject.isOnline())
    (...)
  // An image collection containing the added images will be created by the Metadata Supplier.
  for (IImage image : images) {
    showBuilder.withImage(image);
  }

  IShow show = showBuilder.build();
  return Collections.singletonList(show);
}

Give (editorial) feedback

By calling the given addFeedback(...) methods on the IMappingContext visitor object, it can be used to collect information, warnings and errors (enum FeedbackType) that may occur during the mapping process.

// A show cannot be mapped without images.
if (myImageSourceObjects.isEmpty()) {
  mappingContext.addFeedback(FeedbackType.ERROR, "The show has no images.");
  return Collections.emptyList();
}

After the new or updated resource has been sent to the ARD-Mediathek (which may succeed or fail), the feedback messages from the mapper as well as additional feedback from the Metadata Supplier itself are sent to all registered IFeedbackHandlers. In case of the Sophora FeedbackHandler that feedback is displayed to the user in Sophora, but you are also able to create your own IFeedbackHandler. It needs to be a Spring component (with the @Component annotation) so that the Metadata Supplier can find it. The Metadata Supplier calls the handleFeedback(Feedback) method for each collected feedback during the mapping, saving, unpublishing and republishing process of a source. You can handle this feedback here in your own way, e.g. by logging, sending e-mails, writing back to the source system, etc.

@Component
@Slf4j
class ExampleFeedbackHandler implements IFeedbackHandler {

  @Override
  public void handleFeedback(Feedback feedback) {
    // In this example we just log the error messages
    SourceDescriptor sourceDescriptor = feedback.getSourceDescriptor();
    log.info("Feedback for {}", sourceDescriptor);
    // You can get all feedback entries or filtered by type.
    for (FeedbackEntry errorEntry : feedback.getEntries(FeedbackType.ERROR)) {
      log.error("- {}", errorEntry.getMessage());
    }
}

Register used sources

The addUsedSource(...) method on the IMappingContext visitor object should be called for each additional source object that is used during the mapping of a source. The Metadata Supplier will save the connection between those objects in a database so that next time when one of the "used sources" is mapped, it will automatically trigger the mapping of all sources that have been "users" of this source object. This makes sure a source object is always up-to-date if one of its "used sources" has changed.

SourceDescriptor sourceDescriptorOfUsedSourceObject = new SourceDescriptor(mySourceObject.getId(), mySourceObject.getType());
// Sophora users may use the Sophora wordings of the SophoraSourceDescriptor.
sourceDescriptorOfUsedSourceObject = SophoraSourceDescriptor.create(mySourceObject.getId(), mySourceObject.getType());
mappingContext.addUsedSource(sourceDescriptorOfUsedSourceObject);

Install a custom mapper plugin

When the Java project with the custom mapper(s) is built, the result has to be a JAR that includes all its dependencies (jar-with-dependencies). Then place your built plugin JAR in the plugins folder which is located next to the Metadata Supplier Application JAR file.

By default the Metadata Supplier scans for new components in the package com.subshell.sophora.metadatasupplier (and all sub packages). If you created your mapper implementation in another package, you have to configure that in your application.yml.

---
# Application settings
spring:
  application:
    spring-additional-base-packages: 'my.custom.package.name'

Last modified on 11/22/21

The content of this page is licensed under the CC BY 4.0 License. Code samples are licensed under the MIT License.

Icon