public interface HdxFacade extends Cloneable
HdxFacade
maintains an object's representation as a
DOM. As well as generating the DOM representation, this type
provides optional support for altering the underlying object
through a DOM interface. Although it is implementations of this
interface which are ultimately responsible for generating XML in
the HDX system, the methods here are not intended to be
invoked directly by application code: instead, use the method HdxFactory.newHdxContainer(HdxFacade)
, and use the DOM and Source
methods on the resulting HdxContainer
. Though this
may seem roundabout, it means that the resulting XML has been
through whatever normalization or relativization steps are
required.
XXX getDOM
method is almost certainly disappearing!
Thus these class comments need a rewrite.
Only the synchronizeElement
,
getObject
and getHdxResourceType
methods
need have non-trivial implementations. This interface can most
efficiently be implemented by extending AbstractHdxFacade
.
The getDOM
and getSource
methods, can
be straightforwardly implemented in terms of
synchronizeElement
, and this is what is done in
AbstractHdxFacade
. These two methods,
getDOM
and getSource
, are complementary:
one is a convenience interface for the other. Which is which,
however, will vary between implementations, and client code should
call whichever one of the two is actually required.
The remaining methods, addChildBefore
,
replaceChild
and setAttribute
, which mutate
the DOM, may have trivial implementations which always return null,
indicating that the DOM is effectively read-only. If it is
appropriate for the facade to support modification, then these three
DOM-mutation methods are sufficient to support all the relevant
methods of the Element
interface.
Modifier and Type | Method and Description |
---|---|
boolean |
addChildBefore(Element parent,
Element newChild,
Element refChild)
Adds a new child to an element.
|
Object |
clone()
Creates and returns a copy of this object.
|
HdxResourceType |
getHdxResourceType()
Obtains the
HdxResourceType which this is a facade for. |
Object |
getObject(Element el)
Obtains the object which the given Element is a facade for.
|
Source |
getSource(URI base)
Produces a
Source representing the object. |
boolean |
replaceChild(Element parent,
Element newChild,
Element oldChild)
Replaces or removes a child.
|
boolean |
setAttribute(Element el,
String name,
String value)
Sets an attribute on an element.
|
Object |
synchronizeElement(Element el,
Object memento)
Adds attributes and children to the given element, to represent
the current state of the object as a DOM.
|
Object synchronizeElement(Element el, Object memento) throws HdxException
Document
obtained by invoking
Node.getOwnerDocument()
on the element. This
Document
will in fact be an instance of
HdxDocument
, which implements the standard
Document
interface with the addition of HdxDocument.createElement(HdxFacade)
, which the implementing
code is therefore free to use (this is an understatement -- the
entire point of this interface is to give an implementing class the
opportunity of using this method).
The element will have the type
this.getHdxResourceType().xmlname()
.
This method is called frequently, and the implementing
object should therefore take care to do no more work than is
necessary. To assist in this, the caller will preserve a
memento on behalf of the implementor. This memento is
the object returned by this method, which is re-presented when
the synchronizeElement
method is next called (this
is an example of `memento' pattern, although that is more
commonly associated with undo actions than the cache-like
operation described here). If the implementing object needs to
preserve some state, to remind it of its own state when it last
synchronised the element, then it should wrap that state in
some object or other and return it from this method. This
might be as simple as a hash-code.
The first time this method is called, the memento will be null.
The returned memento may be null if, for example, the implementor can extract all its relevant state information from the DOM it receives in the Element; or if the object is immutable, so that the Element attributes and children are correct if they are there at all. This null memento will be duly returned to the implementor on any future invocation. In such a case, the implementor might need to be careful to distinguish this returned null memento from the null memento provided when the method is called the first time.
It is perfectly feasible for the implementor to return itself as the memento.
el
- an element which is to be made consistent with the
current state of the objectmemento
- either null, if this is the first time this
method has been called, or the object which was returned by
this method last time it was called (which may be null if that
is what the method chose to return)HdxException
- if it is for some reason impossible to
update the DOM. The method should regard this as something
akin to a `can't happen' error: this thrown exception will
be converted to a DOMException
if that is
reasonable for the caller, but if not, may be converted to a
PluginException
.Source getSource(URI base) throws HdxException
Source
representing the object.
This method, and getDOM
are partners, in the sense that
one is a convenience interface for the other, but which one is
which depends on the implementation. Since the conversion between
a DOM and a Source might possibly require some processing, client
code should use the method which returns the type of object it
actually wants.
The XML in general may contain URLs, for instance referencing the
array components of the NDX. How these are written is determined
by the base
parameter; URLs will be written as relative
URLs relative to base
if this is possible (e.g. if they
share a part of their path). If there is no common part of the
path, including the case in which base
is null
,
then an absolute reference will be written.
base
- the base URI against which URIs written within the XML
are considered relative. If null, all are
written absolute.HdxException
- if the Source
cannot be
generated fo some reasonSourceReader
boolean setAttribute(Element el, String name, String value)
This is an optional operation. An implementation may simply return null to indicate that this operation is not supported.
el
- the element which is to have the attribute setname
- the attribute which is to be setvalue
- the new value of the attribute. If the value is
null, the attribute is removed. Setting the value to the empty
string is allowed, and is not the same as setting it to null.boolean addChildBefore(Element parent, Element newChild, Element refChild)
This is an optional operation. An implementation may simply return null to indicate that this operation is not supported.
parent
- the element which is to receive the new childnewChild
- The child to be addedrefChild
- if non-null
, the new child is to
be inserted before refChild
. If refChild
is
null
, the new child is to be appended to the end
of the list of children.boolean replaceChild(Element parent, Element newChild, Element oldChild)
This is an optional operation. An implementation may simply return null to indicate that this operation is not supported.
parent
- the element which is to have its children changednewChild
- the replacement element. If this is
null
, then oldChild
is deleted.oldChild
- the element which is to be replaced.Object getObject(Element el) throws HdxException
The returned element must match the class appropriate for
the Hdx type this element corresponds to. That is the return
value obj
must be such that the following are true
HdxResourceType.match(el).getConstructedClass().isInstance(obj)
HdxResourceType.match(el) == facade.getHdxResourceType()
facade
of this interface, and if
el
is the Element
which this facade is linked to.el
- an Element which is to be transformed into an objectHdxException
- if the facade does not know how to recover
the object type it has been asked for. This will also happen
if the element el
does not correspond to a known
HdxResourceType
.HdxResourceType getHdxResourceType()
HdxResourceType
which this is a facade for.
This is not (just) a convenience method. Although the same
information is retrievable by calling getSource(java.net.URI)
, and
calling HdxResourceType.match(Element)
on the top
element obtained from it,
getSource
may involve significant
processing, and
Source
, since the root of the resulting document
(matched by the XPath /
) is not guaranteed to be
the `top' node of the DOM (see DOMSource.DOMSource(Node)
)
HdxResourceType
this facade representsObject clone()
The AbstractHdxFacade
skeleton implementation
implements this as simply
public Object clone() { return super.clone(); }which is generally suitable. If, however, the underlying object, or its DOM, is mutable, and particularly if the
addChildBefore()
, replaceChild()
and
setAttribute()
methods are implemented, the
implementation should very probably add a cleverer
clone()
method. Recall that
if clone()
is overridden, equals()
and hashCode()
should be overridden also.Copyright © 2025 Central Laboratory of the Research Councils. All Rights Reserved.