The CTP Module
UNDER CONSTRUCTION
The CTP module (CTP.jar) contains the code of the CTP application, including all the standard stages and plugins. This article describes the theory of operation of the packages contained in the CTP module. The CTP module is used in CTP, TFS, CTPClient, ISN, and other MIRC software. The intended audience for this article is software engineers extending or maintaining any of that software.
See Setting Up a MIRC Development Environment for information on obtaining and building the VTP module.
The CTP module contains five packages:
- org.rsna.ctp contains the CTP main class and the Configuration singleton class.
- org.rsna.ctp.objects contains classes that implement the four types of objects that CTP can process.
- org.rsna.ctp.pipeline contains the Pipeline class, interfaces that define the types of pipeline stages, and a set of abstract classes that provide starting points for developing each pipeline stage type.
- org.rsna.ctp.plugin contains the interface that defines a plugin and an abstract class that provides a starting point for developing a plugin.
- org.rsna.ctp.servlets contains the standard servlets used in CTP.
- org.rsna.ctp.stdstages contains the standard pipeline stages included in CTP.
Each of these packages will be described in the sections below, with example code where necessary to illustrate the theory of operation. It will be helpful to get the source code and build it so you can reference the Javadocs as you go along.
In addition to the packages listed above, the source code tree also contains packages that are part of helper applications used in CTP:
- org.rsna.installer contains the the installer program for CTP, TFS, and ISN.
- org.rsna.launcher contains the program used to manually launch CTP TFS, and ISN.
- org.rsna.runner contains the program that can be used in a batch job to start or stop CTP, TFS, and ISN. This program is typically used to implement a CTP Linux service.
1 Overview
CTP is a framework for pipelines and plugins.
- A pipeline is an ordered sequence of processing stages. Data objects enter a pipeline at the head end and encounter the stages in sequence.
- A pipeline stage performs some task on a data object when it arrives at the stage as it flows down the pipe.
- A plugin is a module that adds capability to the program outside the scope of a pipeline.
CTP includes a servlet container to provide a user interface for configuring certain features and for accessing data.
CTP is installed using the CTP-installer.jar program that is created when CTP is built. See Setting Up a MIRC Development Environment for information on building CTP. The installer creates a folder called CTP and puts all the necesssary files and subdirectories in it.
CTP is configured by a single XML file. CTP imposes no limits on the number of pipelines or plugins that may be configured or on the number of stages that may be configured in a single pipe. The structure of the configuration file is described in detail in CTP-The RSNA Clinical Trial Processor.
CTP can be run manually through the Launcher.jar program, or it can be run as a Windows or Linux service. See Running CTP as a Windows Service or Running CTP as a Linux Service for details.
The Launcher.jar program is located in the CTP directory. All the modules required for running CTP are located in the CTP/libraries directory or one of its subdirectories. The manifest in the CTP.jar module includes a classpath listing only the util.jar module. When CTP starts, it calls ClasspathUtil.addJars to add all the jar files in the CTP/libraries directory tree to the classpath. By constructing the classpath in this way, developers can add pipeline stages and plugins into CTP without having to modify the CTP build itself.
After setting up the classpath, CTP then loads the configuration. The configuration is encapsulated in the singleton org.rsna.ctp.Configuration class. The Configuration class parses the configuration file and loads the plugins and pipelines. Pipelines load their stages.
Pipelines, stages, and plugins have constructors that take their configuration file XML Element as an argument, and they obtain all their configuration information from it. When these objects are instantiated, the Configuration object is not yet constructed; therefore, the constructors are just for construction of the objects themselves, and they may not reference the Configuration object or any other stages or plugins.
Pipelines, stages, and plugins have start methods that are called after the Configuration object has been constructed and all the pipelines, stages, and plugins have been instantiated. The start methods can reference anything in the Configuration, including other stages and plugins. This two-phase startup is necessary because certain stages are designed to interact with other stages and plugins, so everything has to be constructed before any such interaction can be allowed to occur.
CTP calls the start methods of all the plugins first, followed by the start methods of all the pipelines. The start methods of pipelines call the start methods of their stages. This sequence is important because a stage may depend on a plugin, and therefore a plugin must be completely running before it is referenced.
Pipelines are implemented as asynchronous threads. A pipeline object maintains an ordered list of all its stages. There are four types of stages:
- ImportService
- Processor
- StorageService
- ExportService
These stage types are described in CTP-The RSNA Clinical Trial Processor and Extending CTP. Each stage implements its specific interface. Data objects enter a pipe through an ImportService stage. A pipeline object maintains a separate list of its ImportService stages. When a pipeline is ready to process a new data object, it polls its ImportServices in turn until it finds one that has a data object available. As data objects flow down the pipe, they skip any ImportServices; thus, although ImportServices are configured into the pipeline, they can be thought of as being separate from it, and the order in which they appear - and even where they appear - in the pipeline is not important. (Nevertheless, for human readability, it is best to put the ImportServices first in the pipe.)
SERVER
SHUTDOWN
2 org.rsna.ctp
This package contains the CTP main class and the Configuration class.
3 org.rsna.ctp.objects
This package defines the four object types that CTP can process.
- Note: To be useful in a clinical trial, a data object must contain a set of identifiers that allow the object to be related to other data objects in the trial.
- FileObject represents a file of unknown format. It is the parent class of the other object types. It supplies generic file handling methods. Since the FileObject cannot know anything about the contents of the file, it cannot provide the IDs necessary for a clinical trial; therefore, a FileObject by by itself is not useful. Its utility is only as the parent class of the other object types.
- DicomObject represents a DICOM dataset. It contains a great many methods that provide access to the individual elements in the dataset, including the IDs and UIDs defined in the DICOM standard that are important in a clinical trial. It also provides methods for creating browser-viewable images from the pixels stored in the dataset.
- XmlObject represents an XML file. It provides generic methods for accessing the important identifiers in a clinical trial. Since the schemas of XML data objects used in clinical trials vary, these methods are designed to look in a sequence of common places to find the IDs. The sequences are described in the Javadocs.
- ZipObject represents a zip file. In addition to whatever other files it may contain, a ZipObject must contain a manifest.xml file that carries the necessary clinical trial IDs. CTP treats ZipObjects as atomic data objects, although the ZipObject class provides methods for obtaining the individual files it contains.
The DicomObject, XmlObject, and ZipObject classes all contain matches methods that compute a boolean result from a script that interrogates the object. These methods are used in many pipeline stages to determine whether an object is to be processed. See The CTP DICOM Filter and The CTP XML and Zip Filter articles for information on the script languages.
Because DicomObjects are so critical to imaging trials, and because various manufacturers implement DICOM in various ways, the DicomFilter pipeline stage provides a way to list the operand values it sees when computing its boolean result. To pass those values to the DicomFilter, the matches method of the DicomObject returns a MatchResult object that encapsulates the operand values and the boolean result. (The matches methods of the other two object types just return the boolean result.)
The MatchResult class is also contained in this package, along with a SopClass class that is used by DicomObject to detect certain types of SOP Classes.
4 org.rsna.ctp.pipeline
This package contains:
- the Pipeline class
- the interface definitions for the four stage types
- abstract classes to implement stages
- the QueueManager class used by all the stages that maintain queues of data objects for import or export
- the typesafe enum Status class for returning results from export operations
- the Quarantine class for managing files that are removed from a pipe by a stage
The Status servlet displays a web page summarizing the status of all the plugins, pipelines, and stages. It obtains status information by calling the getStatusHTML methods of all the objects in the configuration. Similarly, the Configuration servlet displays the configuration parameters, and obtains that infomation by calling the getConfigHTML methods. The AbstractPipelineStage provides implementations of these methods to simplify the implementation of stages.
5 org.rsna.ctp.plugin
This package contains:
- the interface definition for a plugin
- an abstract class to implement plugins
As in the case of the AbstractPipelineStage, the AbstractPlugin class provides implementations of the getStatusHTML and getConfigHTML methods to simplify the implementation of plugins.