About Custom Elements

Most of the data processed by a template come from some external data source via its virtual XML-like representation called Data Source Model (DSM), which maps everything onto some elements and their attributes.

Therefore, most of the functionality available in templates (such as iterators, hash-maps and so on) is intended for processing of elements and attributes.

But what if you want to use that functionality to process some different data, for instance, those coming from template parameters or elsewhere?

Custom elements allow you to do that! Using custom elements, you can wrap any your data in the form of elements and attributes. Further, you can process such elements using standard means either separately or together with some elements from the main data source.


Basically, you may need custom elements in two situations:
1).  Extending or completing a set of ordinary elements of the main data source.
Suppose you have some set of references (coming, for instance, from the values of attributes of other elements). Those references contain the qualified names of some elements that you need to print.
At minimum, you should print just the element names. But it will be much better if you add some extended information about each element.
Most of the referenced elements can be found in the data source. The problem is that a few of them may not exist there. That's because those few elements represent some well-known entities, which do not need to be copied everywhere (e.g. this may be some built-in predefined data types and so on). Everyone who knows the subject of that external data source must also know about those basic things.
Well. Everyone, but not your templates! If all the references could be resolved into elements, you would just feed those elements to an Element Iterator, sort them as needed and print everything about each element. But a few elements may be not found, and yet you should print something about them too. At least their names... You have them from the references. But how can you feed such names, which are strings, to the Element Iterator?
Very simply. You should wrap each string with the name in a custom element and pass that element to the Iterator along with the elements from the data source. You can even construct such custom elements so that they will look like real ones (e.g. contain some attributes expected from the real elements). For instance, you may assign the name taken from the reference to the "name" attribute. This may allow you to specify sorting of all elements uniformly (e.g. by the values of "name" attributes contained in both real and custom elements).
2).  Using element/attribute functionality for non-DSM data.
Another situation is when you have some data completely different from the main data source. However, you want to process them with some functionality available only for elements and attributes.
Here is an example.
Suppose you need to design a template to process (document) certain "custom tags" coming from the external data source. Those tags describe some data source specific things. To a template, all such tags will appear as ordinary DSM elements of the same type and all the properties of the tags will be represented by the values of the element attributes.
The "custom" means that some critical properties of those tags (such as possible tag names and their meanings) are unknown in advance. Instead, they are created by the user who produces the data source. In fact, the same person may be using your template to document his/her data source (which may be actually a representation of some project written in Java or other language). What is more, the user may want to be able to customize easily the appearance of specific custom tags in the output documentation, for instance, to provide the tag title and so on. At that, the user does not want to customize your template each time a new tag is introduced. How can you implement such requirements?
You can do this by introducing a special template parameter 'customTag' using which the user can specify how to document each particular custom tag. The parameter would accept a multiple (list) value. Each value item would specify a tag name and how to document that tag (e.g. the tag title and other things).
Further, in your template, the first thing you may program to do will be parsing all the tag specifications passed via 'customTag' parameter. By each tag specification, you can create a custom element and store all the settings from the specification as element attributes. You can put each element in some 'custom-tags' element map (which is a special kind of hash-maps adopted for DSM elements) using the tag name as the hash key.
What is the advantage of all of this? Using the 'custom-tags' element map, you can find very quickly for each custom tag all the user-provided information about how to document that tag! Without the element map, you would need to re-parse the entire 'customTag' parameter value each time you needed to process a particular tag. That would slow down the processing very much (if not making it impossible)!

Using Custom Elements

Custom elements are created with CustomElement() function.

You can load a custom element with some useful data by specifying its value when you create it:


myData = ...; // some your data
...
el = CustomElement (myData);
Later, you can access the data via the GOMElement.value property:

echo ("My data: " + el.value);
Additionally, you can attach to your custom element any number of other pieces of information using attributes. You can do it immediately, when you create the element:

value0 = ...;  // some data
value1 = ...;  // you want to associate
value2 = ...;  // with a custom element
...
el = CustomElement (value0,
  Array (
    Attr ("item1", value1),
    Attr ("item2", value2)
  )
);
or you can add the attributes sometime later:

el.setAttr ("item1", value1);
el.setAttr ("item2", value2);
Further, you can access the values of such attributes using any of the functions available for it:

echo ("value1: " + el.getAttrValue ("item1"));
A custom element may have unlimited number of attributes. Using setAttr() function, at any time, you can add new attributes or change the values of existing ones. You can equally remove any of the attributes:

el.removeAttr ("item1");
Effectively, each custom element serves as a hash-table of its attributes.

Custom Element Features

(1)  Custom elements are created with CustomElement() function, which returns an instance of GOMElement type.

(2)  Each instance returned by CustomElement() function represents a separate DSM element assigned with a unique ID irrelevant of what the element content might be. For example, the following expression is always true:

CustomElement("one").id != CustomElement("one").id
You can retrieve a particular custom element by its ID using findElementByID() function.

(3)  All custom elements have '#CUSTOM' element type, by which you can find or filter them for specific processing.

(4)  Although custom elements are considered to be part of the DSM and maintained by the DSM driver, they are not connected in any way to the external data source (represented by that DSM).

Any data possible to obtain from a custom element are only those that have been assigned to it initially in the form of the element value and its attributes.

(5)  The values of custom elements and their attributes have 'Object' data type and may be single-component only (no list values are possible). For instance, that means that for a custom element the following expression is always true:

el.value == el.fullValue
However, you can assign the objects of any types (including null) to values of custom elements and their attributes.

(6)  Custom elements have no children and cannot be children of any other elements.

Once all references to a custom element or its ID have been lost, that element is lost too. After that, there is no way to retrieve it back!

The unused instances of custom elements may be automatically recycled and, then, reappear back with the same IDs during the next CustomElement() function calls. However, any old data previously associated with the recycled custom elements will be lost.

(7)  In any other respect, custom elements may be used the same way as ordinary once. For instance, you can feed them to Element Iterators, put in element maps and so on.

See Also:

GOMElement, CustomElement(), CustomElements(), toCustomElements(), Attr(), Array(), setAttr(), removeAttr(), getAttrValue(), findElementById()