Building Components
Components of the model are constructed by using the builder pattern, which is a software design pattern. Different types of components require the use of different builders. The interfaces for these builders were listed in the previous section. However, a concrete implementation of a builder is required to do any real work.
Builder objects can be created by using the ComponentBuilderFactory class
that is defined in the curam.util.client.model package. The factory class provides
a number of factory methods to create builders. Only the use of the following factory methods
are supported in the Cúram application:
createComponentBuilder- Creates and returns an object implementing the
ComponentBuilderinterface. Use this to build generic components that do not require a binding and that do not contain other components. createFieldBuilder- Creates and returns an object implementing the
FieldBuilderinterface. Use this to build fields that are bound to data sources. createContainerBuilder- Creates and returns an object implementing the
ContainerBuilderinterface. Use this to build components that may contain other components of any kind.
The component builders present a simple, flat API for creating components. They eliminate the need to understand the internal structure of components. In particular, the properties of the objects that hold additional information about a component, such as bindings, parameters, and links can be defined directly through the builder interface; there is no need to create instances of these objects or understand how they are stored.
To use a builder, instantiate it using the appropriate factory method and then call the
appropriate setter methods to set the properties of the component that is being built. When
complete, call getComponent to get the instance of the newly built component
object. When getComponent is called and returns the new component, the builder
object resets all of the properties and can be reused to build another component. Until
getComponent is called, many of the simple properties can be set again to overwrite
their existing values. However, this can not work for properties that represent items in
collections, such as the parameters of the component.
Once built, components are immutable, much like java.lang.String objects, or the
Path objects described in Accessing Data with Paths. The only way to change a property of a component is to build a new component with the modified
value for that property. Component builders can be used to create entirely new components, but are
commonly used to create new components that are modified copies of other components to overcome this
immutability. The starting point in this process is the component that will act as the
prototype for the new component. Create the builder object and then pass the prototype
component to the builder's copy method. This sets all of the properties of the
component to be built from the properties of the prototype component. Use the setter method of the
builder to overwrite (including with a null value) the properties of the new component that differ
from the prototype component. Finally, call the getComponent method on the builder
to get the new component that is the modified copy of the original, prototype component. A typical
use of this copy-and-modify process is when making multiple copies of a Field
object, changing the domain and extending the paths, before delegating the copy of the field for
rendering by another renderer plug-in class.
When copying a prototype Container object by using the builder's
copy method, all of the child components of the container are copied by reference.
A reference is sufficient, as the child components are immutable. Because references are used, any
child that is itself a container becomes a child of the new container complete with its own child
components. When it is necessary to change the children of a Container that must be
copied by using a builder, the copyShallow method is called on the
ContainerBuilder instead of the copy method. The
copyShallow method does not copy any references to the child components. Copy these
references one-by-one by iterating over the child components of the prototype container and then
calling the add method on the ContainerBuilder. The child
components can be copied and modified, or even selectively omitted, during this process if
required.