XeroPluginArchitecture

Metadata Architecture

Metadata is information about some software component, perhaps even the existence of such a component. This implementation of meta-data has some different goals from other implementations such as Spring or the JBoss Seam annotations. Some of these goals are:

  1. Allow integration of different sources of meta-data.
  2. Integrate meta-data concepts with the concepts of themes to allow several variants of a system to run simultaneously - eg for some users to have one theme with certain meta-data and another user to have a different theme. This must not be carried too far, else it becomes to complex and intertwined, but it can be quite important to allow a site to have a few different appearances and display variants.
  3. Support site-specific configuration or overriding of meta-data to change some defaults, without requiring changes to the underlying installation.
  4. Efficiently provide access to the meta-data, and be able to pre-compute configuration values such as lists of icons etc.
  5. Keep the defaults for meta-data values close to, or better part of the objects they define. For Java objects, that typically means the use of annotations to define the meta-data values. However, there isn't a good meta-data system for XML files. There are XML configuration files, but those are best used as over-rides to the general configuration of a system rather than being the underlying defaults, and such configuration files aren't part of the item they are configuring.
  6. Allow new EJBs/Facelet/XML/XSL/Javascript to be defined as "existing" as part of the meta-data, and to be included in the overall meta-data. That means that a site can add functionality to the existing system, and then just mix the new meta-data into the existing meta data to add their new functionality to the site.
  7. Minimize copying and duplication of meta-data.
  8. Integrate with Seam meta-data
  9. Allow operation without Seam - although of course, that means you cannot include any Seam based components.
  10. Allow access to underlying Java and other objects as part of the meta-data.

Metadata Files

A meta-data file is just a Java property file. This file is used for providing meta-data that isn't defined elsewhere, as well as declaring where meta-data can be found (that is, where is the elsewhere), and finally, for over-riding meta-data that is defined elsewhere.

A simple example is:

servletFilter=$\{org.dcm4chee.xero.metadata.filter.FilterList}
servletFilter.jaxbFilter=$\{org.dcm4chee.xero.metadata.servlet.JaxbFilter}
servletFilter.jaxbFilter.priority=999999
servletFilter.searchCondition.priority=-1000
servletFilter.source.priority=0
imageFilter.inherit=servletFilter
imageFilter.source=$\{org.dcm4chee.xero.search.study.ImageSearch}
imageFilter.searchCondition=$\{org.dcm4chee.xero.search.study.ImageSearchConditionParser}
imageFilter.emptyFilter.inherit=studyFilter.emptyFilter

This defines imageFilter as being an object that is an instance of the ImageSearch class. It also defines a search condition, some priorities and other information. This meta-data should likely mostly come from the actual objects that define them, rather than needing hard-coded references like these ones.

Metadata Parts

In order to allow meta-data to be combined from multiple sources and to be defined to be about some object, which may not be a Java object, but could be an XML file, or perhaps even a virtual object, where the only direct item of interest is the meta-data itself, the meta-data is defined as a tree of nodes containing values and attributes. The attributes are the meta-data information, while the values are the object about which the information is defined. Thus, in the example above, servletFilter is a node that has a value that is an instance of the FilterList object. Values can be simple strings, class instances, null, EJB values etc. The servletFilter has meta-data about it as defined by a set of sub-nodes, in specific, jaxbFilter, searchCondition and so on.

Value Providers

The value for a meta-data node is provided by a value provider. This allows the values for the nodes to be defined by a separate component. There are a number of pre-defined, default value providers, as well as some that can be included by defining meta-data about the value providers themselves.

Value providers have the following features:

  1. The define what value is provided for a given meta-data node.
  2. They can pre-compute a value based on the meta-data at the time the meta-data is first looked up. For instance, the class constructor could be looked up as a meta-data, or the type of a string could be computed.
  3. They can provide additional meta-data about the value provided, that provides any defaults not defined elsewhere.
  4. They can create an object that is used as information by the created value, to allow values that are created elsewhere to be re-used at multiple locations within the meta-data tree. For instance, a value might be a JBoss service object to perform a search. This is a singleton, but it might have a local search variant and a remote search variant. These could be defined by two different locations in the meta-data tree. (That may not be the best way to implement this if there are in fact multiple remote locations, but it would work for just a single one.)

The default value providers are described below:

NullValueProvider

This value provider allows the meta-data value to be defined to be null. This may not seem like very much, but it allows values to be removed and otherwise made explicit.

InstanceValueProvider

This value provider looks up class instances, and returns a fixed instance for a given location in the meta-data tree. The format it uses is ${CLASS_NAME}, and is shown above for the servlet filter.

String Value Provider

Internally, the meta-data classes just convert the value to a string if no other value provider finds a match.

MetaDataProvider

A property provider is somewhat different from a value provider. This provides adds nodes to the meta-data tree. It can be used to extend the metadata from locations such as Seam components, Facelet xhtml files etc. Any property provider can provide meta-data nodes anywhere in the tree - such a provider would be used for instance to combine multiple providers into one. Alternatively, they can be designed to only provide specific properties based on their configuration.

InheritProvider

The inherit provider allows properties to be re-used from one area to another. For example, the imageFilter inherits from the servletFilter. Thus, the imageFilter value is actually an instance of FilterList, and has child properties such as jaxbProperties.

PropertiesProvider

The properties provider defines how properties get included from a properties file. There is how the properties are read from the initial metadata file - a constructor on MetaDataBean is used that passes a PropertyProvider instance on the metadata file.

XmlMetaDataProvider

This provider scans XML files for attributes within the namespace defined for this XmlMetaDataProvider. That allows you to use namespace based meta-data configuration directly within an XML file or Facelet definition.

To configure, use:

metaDataProvider.xml=$\{org.dcm4chee.xero.metadata.XmlMetaDataProvider}
# URL of this file
metaDataProvider.xml.propertyFile=metadata-test.metadata
# Only look for meta-data entered into root meta-data metadata.
metaDataProvider.xml.rootXml=http://www.dcm4che.org/xero/metadata
metaDataProvider.xml.suffix=.xhtml

Then, to define meta-data, you need to create an XML attribute in a file with suffix .xhtml in the same deployment as metadata-test.metadata. For example, the following defines some meta-data in the meta-data node that contains the above configuration. It would also be possible to have another configuration that produced meta-data in another node, for example, the alt node.

<test 
  xmlns:m="http://www.dcm4che.org/xero/metadata" 
  xmlns:fromXml="http://www.dcm4che.org/xero/metadata/fromXml"
  m:fromXml="valueFromXml"
  xmlns:alt="http://www.dcm4che.org/xero/ajax"
  alt:fromXml="alt from xml"
  >
   <v m:fromXml.a="a">Produces metadata.fromXml.a=a</v>
   <v fromXml:A="EH">Produces metadta.fromXml.A=EH</v>
   <v alt:a="A">Produces ajax.a=a</v>
</test>
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.