Red Hat Training

A Red Hat training course is available for Red Hat JBoss Data Virtualization

15.2. Custom Sequencers

15.2.1. The Sequencer Framework

A sequencer is actually a plain old Java object (POJO). To create a sequencer, create a Java class that extends a single abstract class, called Sequencer :
package org.modeshape.jcr.api.sequencer;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;

public abstract class Sequencer {

    ...

    /**
     * Execute the sequencing operation on the specified property, which has recently
     * been created or changed.
     *
     * Each sequencer is expected to process the value of the property, extract information
     * from the value, and write a structured representation (in the form of a node or a
     * subgraph of nodes) using the supplied output node. Note that the output node
     * will either be:
     *   1. the selected node, in which case the sequencer was configured to generate the
     *      output information directly under the selected input node; or
     *   2. a newly created node in a different location than node being sequenced (in
     *      this case, the primary type of the new node will be 'nt:unstructured', but
     *      the sequencer can easily change that using Node.setPrimaryType(String) ).
     *
     * The implementation is expected to always clean up all resources that it acquired,
     * even in the case of exceptions.
     *
     * @param inputProperty the property that was changed and that should be used as
     *        the input; never null
     * @param outputNode the node that represents the output for the derived information;
     *        never null, and will either be a new node if the output is being placed
     *        outside of the selected node, or will not be new when the output is to be
     *        placed on the selected input node
     * @param context the context in which this sequencer is executing, and which may
     *        contain additional parameters useful when generating the output structure; never null
     * @return true if the sequencer's output should be saved, or false otherwise
     * @throws Exception if there was a problem with the sequencer that could not be handled.
     *         All exceptions will be logged automatically as errors by ModeShape.
     */
    public abstract boolean execute( Property inputProperty,
                                     Node outputNode,
                                     Context context ) throws Exception;

    /**
     * Initialize the sequencer. This is called automatically by ModeShape, and
     * should not be called by the sequencer.
     * <p>
     * By default this method does nothing, so it should be overridden by
     * implementations to do a one-time initialization of any internal components.
     * For example, sequencers can use the supplied 'registry' and
     * 'nodeTypeManager' objects to register custom namesapces and node types
     * required by the generated content.
     * </p>
     *
     * @param registry the namespace registry that can be used to register
     * custom namespaces; never null
     * @param nodeTypeManager the node type manager that can be used to register
     * custom node types; never null
     */
    public void initialize( NamespaceRegistry registry,
                            NodeTypeManager nodeTypeManager ) {
    }

}
The abstract class also contains fields and getters (not shown above) for the name, description, and path expressions that are automatically set by the hierarchical database during repository initialization. The initialize(...) method is run upon repository initialization and can be overridden by an implementation to register (if required) any custom namespaces and node types required by the sequencer's generated output.

Note

The outputNode might belong to a different javax.jcr.Session object than the inputProperty , if the input and output paths of the sequencer configuration specify different workspaces. Therefore, be careful that all changes are made using the output node and its session.
The inputs to the sequencer depend on how it is configured, but often the inputProperty represents the jcr:data BINARY property on the jcr:content child of an nt:file node. The outputNode , however, will be one of two things:
  1. If there is no output path in the path expression, then the sequenced output is to be placed directly under the selected node, so therefore the outputNode will be the existing node being sequenced. In this case, the sequencer should place all content under the output node. In this case, the sequencers are not allowed to change the primary type.
  2. Otherwise, the sequenced output is to be placed in a different location than the selected node. In this case, the hierarchical database uses the name of the selected node and creates a new node under the output path. This new node will have a primary type of nt:unstructured, but sequencers are allowed to change the primary type.
The final parameter to the execute(...) method is the SequencerContext object, which is an interface containing some extra information often useful when sequencing files:
package org.modeshape.jcr.api.sequencer;

import java.util.Calendar;

/**
 * The sequencer context represents the complete context of a sequencer invocation.
 * Currently, this information includes the current time of execution.
 */
public interface SequencerContext {

    /**
     * Get the timestamp of the sequencing. This is always the timestamp of the
     * change event that is being processed.
     *
     * @return timestamp the "current" timestamp; never null
     */
    Calendar getTimestamp();

}