Search code examples
templateslanguage-lawyeruml

UML TemplateParameter and placeholder tokens


I am trying to understand how the UML specifies templates. In general, templates whose parameters are not bound to concrete types are represented in most programming languages with a notation including placeholder strings, i.e. the T, K or V in List<T> or Map<K,V>.

Formal TemplateParameters expose one or more ParameterableElements and are owned by their TemplateSignature. But I cannot see any attributes for ParameterableElement which would enable a modeler to store the placeholder names she might define when modeling a new template. Instead of List<T>, it could be named List<NodeType> or maybe List<MyStrangeAndWonderfulThing>...

In order to do this, it seems that there should be a name attribute (or operation) in the abstract interface either of TemplateParameter or ParameterableElement which could be accessed by TemplateSignature. But Both TemplateParameter and ParameterableElement inherit directly from Element which has no such interface.

Under section 7.3.4 Notation on p. 68 of the UML 2.5.1 specification, it says this about the template signature:

The formal TemplateParameter list may be shown as a comma-separated list, or it may be one
formal TemplateParameter per line. The general notation for a TemplateParameter is a string
displayed within the TemplateParameter list for the template:
    <template-parameter> ::= <template-param-name> [‘:’ <parameter-kind> ] [‘=’ <default>]
where <parameter-kind> is the name of the metaclass for the exposed element.

The syntax of <template-param-name> and <default> depend on the kind of ParameteredElement
for this TemplateParameter.

The last sentence in that paragraph is worth re-reading.

IOW, must a conforming C++ implementations of UML first perform an ugly dynamic_cast on the pointer or reference to ParameteredElement in order to fetch the placeholder name? The point is, we don't know what type to cast to yet if the template is not bound to a concrete type. And when we do create a binding, we need to know which name (especially since the same placeholder can be used more than once).

Perhaps this is related to this UML issue raised by Ed Willink back in 2017? https://issues.omg.org/issues/UMLR-741


Solution

  • I am answering my own question because I have found the answer in the meantime: Yes, downcasting from ParameterableElement to NamedElement is apparently necessary (see my last comment above). The placeholder string is queried from the NamedElement::name() function. Fortunately, all concrete classes of ParameterableElement also derive from NamedElement, so this will work.

    Whether or not this is a good OOP design is another story. There might be good reasons for ParameterableElement not to inherit from NamedElement, but this is the current state of the UML.

    (EDIT: Copying and pasting the comment into this answer as suggested above:)

    Well, looks like this is more or less what the OCL constraint on page 100 does (OCL equivalent of a dynamic_cast to NamedElement): 7.8.19.6 Constraints (...) unique_parameters The names of the parameters of a TemplateSignature are unique. inv: parameter->forAll( p1, p2 | (p1 <> p2 and p1.parameteredElement.oclIsKindOf(NamedElement) and p2.parameteredElement.oclIsKindOf(NamedElement) ) implies p1.parameteredElement.oclAsType(NamedElement).name <> p2.parameteredElement.oclAsType(NamedElement).name)