Interface | Description |
---|---|
ElementValidator |
An object which provides validation services for a registered
HdxResourceType . |
HdxContainer |
An
HdxContainer is the Java representation of an HDX object. |
HdxDocumentFactory |
The
HdxDocumentFactory represents a factory which may
be able to convert a given URL into a DOM or an Java/XML Source . |
HdxFacade |
An
HdxFacade maintains an object's representation as a
DOM. |
HdxResourceFactory |
Unifies the various factories for constructing HDX
and related objects from DOM elements and the URIs contained within
them.
|
Class | Description |
---|---|
AbstractHdxFacade |
Skeletal implementation of the
HdxFacade interface. |
HdxDocument |
Hdx implementation of the
org.w3c.dom.Document
interface. |
HdxDocument.NodeUtil |
Collection of rather ragged Node utilities.
|
HdxDOMImplementation |
Provides methods for performing operations that are independent of
any particular instance of the document object model.
|
HdxFactory |
Marshalls all the object creation factories involved
in the Hdx layer.
|
HdxProperties |
Manages a collection of properties for the Hdx system.
|
HdxResourceType |
Encapsulates the types of data contained within the HDX namespace.
|
Exception | Description |
---|---|
HdxException |
General-purpose exception
|
PluginException |
Unchecked exception to indicate that a plugin has violated its contract.
|
This is the package which defines the structure of the HDX system, registers new types, and is responsible for managing the implementations of the various factories required.
HDX is defined as a DOM. This does not mean that an HDX object necessarily is a DOM -- it could be represented as a Source, as a SAX stream, or ultimately not in an XML form at all -- however, it is defined using DOM terminology, and all operations on it are representable in those terms.
An HDX is a DOM Document
node,
which has a document element of type <hdx>
, which
in turn contains other elements of registered
types. HDX does not define or constrain these other types
(instead providing facilities for defining
them), other than to require that they be defined in DOM terms.
The types are not generally processable using the DOM, however, and so they must be transformed into a Java object before work can be done on them. This transformation may involve significant (one-time) work, if the object has to be assembled from information in the DOM, or it may be trivial, if the DOM in fact mirrors some underlying object. During processing, the object will generally be manipulated using some interface defined as part of the resulting Java object's specification.
All important elements in the HDX DOM correspond to types
registered with the HDX system. Only those elements which correspond
to registered types can be constructed as Java objects. However, not
all elements must be registered -- elements which are embedded within
important types, and which do not have to be children of the
<hdx>
element, do not have to be registered or have
handlers.
Types are registered by creating an instance of class
HdxResourceType
, using the static method
newHdxResourceType
.
See below for an example.
The two core classes in the Hdx package are:
HdxResourceType
HdxFactory
The most important interfaces are:
HdxContainer
HdxContainer
. HdxFactory
is
what achieves this, possibly with the background help of an
HdxDocumentFactory
.HdxFacade
The most important interfaces for implementors are:
HdxDocumentFactory
HdxDocumentFactory
are what
constructs HdxContainer
s from URIs and URLs. A class
which is able to construct
a DOM from a particular class of URL -- such as a URL pointing to a
FITS file, for example -- registers a HdxDocumentFactory
instance with HdxFactory
's registerHdxDocumentFactory
: when HdxFactory
is asked to
construct a DOM by a call to its newHdxContainer
methods,
it works through the list of registered factories until one of them
successfully constructs the DOM. The methods of this interface are
not called directly by client code, but are implemented by those
adding new file formats (such as FITS or HDS, say) to the Hdx system.HdxResourceFactory
HdxResourceFactory
type are responsible for exposing a DOM
element as a Java object. The methods of this interface are not
called directly by client code, but are implemented by those adding
new types (such as Weather, say) to the Hdx system.HdxFacade
Ndx
or NDArray
have a
getHdxFacade
method. This can be incorporated into a DOM
based on HdxDocument
by using that class's extension method
HdxDocument.createElement(HdxFacade)
: the
resulting element behaves exactly like a org.w3c.dom
element, except that all its DOM-building (and optionally
DOM-mutating) methods are handled by the HdxFacade
, which
knows exactly the state of the underlying object, and which can return
the underlying object particularly easily.The HdxContainer
interface is used by most code which
wants to use Hdx objects. The two factory interfaces are not
used by client code, but exist in order to be implemented by those
extending the system.
Hdx objects may be synthesized from binary data files such as HDS
or FITS files, or else they may be extracted from the DOMs constructed from
XML files. If the thing (Element or URI) passed to method
newHdxContainer
corresponds to a registered Hdx type and it is in no namespace, then
the input DOM is processed as you might expect.
The factory can also process elements in a more sophisticated way.
If the element passed to newHdxContainer
does not
correspond to a registered type, or it is in the Hdx namespace, then
the method will examine only those elements and attributes in
the Hdx namespace
(see W3C namespaces
spec). This means that the Hdx information is able to be carried
inside another unrelated XML file, invisible to a namespace-aware
processor examinging only the `background' XML.
The Hdx namespace is defined to be
http://www.starlink.ac.uk/HDX
, which string is accessible
as
HdxResourceType.HDX_NAMESPACE
. The Hdx DOM
which is constructed from such an input element contains only the
Hdx-registered elements, in no namespace, so that users of the DOM do
not have to worry about the occasionally subtle details of namespace
processing. Thus the XML file
<rubbish xmlns:x="http://www.starlink.ac.uk/HDX"> <x:hdx> <x:ndx> <x:data uri="file:/tmp/mydata.sdf"/> </x:ndx> </x:hdx> </rubbish>
is transformed into the simpler DOM
<hdx> <ndx> <data uri="file:/tmp/mydata.sdf"/> </ndx> </hdx>
Changes made to the attributes in this transformed DOM are reflected in the original DOM.
Further transformations happen when a DOM is imported into
Hdx. Firstly, the attribute `name
' in the Hdx namespace
is transformed into an element with that name. Secondly, if an
Hdx type has a `hoist' attribute defined (see
setHoistAttribute
),
then any text content of the element will be hoisted up to form the
content of that hoist attribute. Finally, if the Hdx DOM which
results from this does not have <hdx>
as its top
element, but instead an element which is a valid child of
<hdx>
, then it is inserted into a
<hdx>
element. Thus
<mystructure> <mypointer x:name="ndx" xmlns:x="http://www.starlink.ac.uk/HDX"> mydata.sdf </mypointer> </mystructure>
is transformed into
<hdx> <ndx uri="mydata.sdf"/> </hdx>
and processed accordingly.
If you are particularly familiar with the W3C Namespaces
spec, then you will have objected that the `uri
'
attribute in the first example was formally in no namespace,
and should not therefore have been processed. This is true, but it is
so unhelpfully counter-intuitive that as a special case, the
normalisation process described here processes such no-namespace
attributes in the Hdx namespace if the element is itself in
the Hdx namespace, as is the case in the example above.
Use
to extract HDX objects from URIs, and
method
HdxFactory
.getInstance()
.newHdxContainer(URI)
newHdxContainer(Element)
to extract Hdx objects from DOMs, using the namespace mechanism
described above.
To define a new type, you must create a new
HdxResourceType
, using method
HdxResourceType.newHdxResourceType(java.lang.String)
, and then act
on the resulting object to register validators and constructors. For
example, the (very simple) definition of the
HdxResourceType.TITLE
object consists of:
TITLE = HdxResourceType.newHdxResourceType("title"); TITLE.setHoistAttribute("value"); TITLE.setElementValidator(new ElementValidator() { public boolean validateElement(Element el) { // A TITLE element is valid if it has an attribute "value" return HdxResourceType.match(el) == TITLE && el.hasAttribute(TITLE.getHoistAttribute()); } });
The hoist attribute means that, as described in the namespaces section above, the element
<title>My title</title>
is equivalent to the
normalised form <title value="My title"/>
.
The HdxResourceType.HDX
type has a somewhat more
complicated validator, plus the assertion
HDX.setConstructedClass("uk.ac.starlink.hdx.HdxContainer");
that constructed (Java) objects must be instances of the
HdxContainer
interface.
This creation and registration code is located in the static
initialiser of a suitable class. This registration is therefore
performed whenever this class is loaded and initialised. That happens
whenever an object of that class is created, or a static method
invoked. The class may also be loaded explicitly by declaring some
properties, as described in HdxResourceType
.
New types may be declared in their own package, or in the package
uk.ac.starlink.hdx.extension
; non-Starlink types should
not be declared in the uk.ac.starlink.hdx
package, nor in any other package with prefix uk.ac.starlink
.
For an example of a simple class, see the sample class
SimpleWeather.java
, included in the distribution.
To add a new file format which can be given a DOM interface, you
must create a class which implements HdxDocumentFactory
, which turns a URL into a DOM
Document.
Such extending classes are registered with the Hdx system using
HdxFactory.registerHdxDocumentFactory(uk.ac.starlink.hdx.HdxDocumentFactory)
, by a mechanism which is
described in the HdxFactory
class documentation.
These factories can be arbitrarily clever. They can either create
a simple DOM and wait for the work of reading the file to be done by
the constructors registered with the type using
HdxResourceType.registerHdxResourceFactory(uk.ac.starlink.hdx.HdxResourceFactory)
, or else the factory can construct the
object, using a class which implements the HdxFacade
interface, and then create an Element which uses that facade using
HdxDocument.createElement(HdxFacade)
. For
further details about this route, including an example, see the HdxDocumentFactory
documentation.
That covers construction of a complete Hdx DOM from a URI. However, you should also handle, if appropriate, a reference to your new file format from within a DOM. In the case of the Ndx type, that can be done with a construction such as
ndxType.registerHdxResourceFactory(new HdxResourceFactory() { public Object getObject(Element el) throws HdxException { return new BridgeNdx(new DomNdxImpl(el)); } });
where ndxType
is the HdxResourceType
object which this initialiser has obtained either from
HdxResourceType.match("ndx")
or, preferably, from its
initialisation of the Ndx type using newHdxResourceType
.
The class DomNdxImpl
is a class which is private to the
Ndx package.
See the Starlink web pages.
Copyright © 2025 Central Laboratory of the Research Councils. All Rights Reserved.