The generic type support touches three levels:
The template support deals with two issues: Template definition and Template binding.
The first requirement of this integration is to capture the generic type data, convert it into UML and then display it in a UML diagram. Here is an example of java.util.Collection.
In the diagram above, we find the class template, operation template and operation parameter template. In the class template, “ E ” is a template variable type, which is used in the method add(E) .
We can also find an operation template using a local template variable:
<T> T[] toArray(T[] a);
where the variable “ T ” is an operation template variable. It is used in the scope of this method.
Besides the template definition, it is necessary to show the template utilization relationship, called template binding. In the above diagram, this relationship is shown as an arrow “ E -> ? ”. The first example is the following method:
boolean retainAll(Collection<?> c);
The class template variable “ E ” of the collection binds to an unspecified type in the argument for this method.
eUML2 uses a template engine to generate the Java code. In the Free edition, the template engine is JDT’s one, which provides only getter/setter. In Studio edition, it is possible to use the powerful Velocity template engine. Of course, it can be disabled in the Preferences.
JDT template provides a getter/setter code generation pattern. This pattern is used by the eUML2 Free edition or when the Velocity template engine is disabled in the Studio edition.
Here is the standard JDT template pattern.
$(modifiers) ${field_type} ${field}; /** * @return Returns the ${bare_field_name}. */
$(modifiers) ${field_type} get${bare_field_name} () { return ${field};
} /** * @param ${param} The ${bare_field_name} to set. */ $(modifiers) void set${bare_field_name} (${field_type} ${param}) { ${field} = ${param}; }
In the case of the type boolean , the prefix of the getter is “ is ” instead of “ get ”.
The key-words in blue color and bold/italic enclosed in brackets followed by a $ character, are template variables. Here is the detailed description of each variable
Variable name |
Description |
---|---|
$(modifiers) |
Java member such as public, protected, private, final static etc… |
${field_type} |
Field member type |
${field} | Field member name |
${bare_field_name} | Normalized file name by removing the prefix/suffix defined in Preferences->Java->Code Style. In general, the first letter is capital. |
${param} | The parameter name based on the prefix/suffix defined in Preferences->Java->Code Style. |
eUML2 inserts two new variables for UML model storage purposes:
Variable name |
Description |
---|---|
$(uml_property_specification) |
This variable contains all UML information about the property such as property name, cardinality, stereotype, dependencies etc… |
${uml_property_member} |
This variable is used to mark the property membership of an accessor. The syntax is @uml.property name=”${property_name}” |
The template patterns are changed as following:
/** * ${uml_property_specification} */ $(modifiers) ${field_type} ${field}; /** * @return Returns the ${bare_field_name}. * ${uml_property_member} */
$(modifiers) ${field_type} get${bare_field_name} () { return ${field};
} /** * @param ${param} The ${bare_field_name} to set. * ${uml_property_member} */ $(modifiers) void set${bare_field_name} (${field_type} ${param}) { ${field} = ${param}; }
In the following model, the Company and Project have a qualified association. The field type of this association is designed as java.util.Map.
The generated codes based on the JDT templates are as follows:
/** * @uml.property name="project" * @uml.associationEnd multiplicity="(0 -1)" * inverse="person:model.Company" * qualifier="key:java.lang.Object model.Project" */ private Map<Object, Collection<Project>> projectMap; /** * Getter of the property <tt>project</tt> * @return Returns the project. * @uml.property name="project" */ public Map<Object, Collection<Project>> getProject() { return projectMap; } /** * Setter of the property <tt>project</tt> * @param company The project to set. * @uml.property name="project" */ public void setCompany(Map<Object, Collection<Project>> project) { this.projectMap = project; }
On top of the velocity template engine, eUML2 Studio provides more powerful template capabilities. Not only can users easily change the template definition, but also override the template definition or/and change the application scope at project, package, class and even property granularity.
Three template files are provided to handle three kinds of collection:
Variable name |
Template file name | Description |
---|---|---|
java.util.Collection |
uml2.Property-java.util.Collection.vm | General collection template |
java.util.List |
uml2.Property-java.util.List.vm | General ordered collection template. |
Java.util.Map | uml2.Property-java.util.Map.vm | Qualified association template. |
Here is the outline of the methods defined in these files. Please reference the Studio documentation for detailed information.
{ElementType} get{PropertyName}; boolean is{PropertyName}Empty; boolean contains{PropertyName}({ElementType} o); Iterator<{ElementType}> {PropertyName}Iterator(); {ElementType} [] toArray(); <T extends {ElementType}> T[] toArray(T[] a) ; boolean add({ElementType} o); Object remove({ElementType} o); boolean containsAll{PropertyName}(Collection<? extends {ElementType}> c); boolean addAll{PropertyName}(Collection<? extends {ElementType}> c); void clear{PropertyName}();
int {PropertyName}Size(); boolean is{PropertyName}Empty(); boolean contains{PropertyName}({ElementType} o); Iterator<{ElementType}> iterator(); {ElementType} [] toArray(); <T extends {ElementType}> T[] toArray(T[] a); boolean add{PropertyName}({ElementType} o); Object remove{PropertyName}(Object o); {ElementType} get{PropertyName}(int index); void add{PropertyName}(int index, {ElementType} element);
int{PropertyName}Size(); boolean is{PropertyName}Empty(); boolean containsKey{PropertyName}({Qualifier.Key} o); boolean containsValue{PropertyName}({Qualifier.Value} value); {Qualifier.Value} get{PropertyName}({Qualifier.Key} key); {Qualifier.Value} put{PropertyName}({Qualifier.Key} key, {Qualifier.Value} value); {Qualifier.Value} remove{PropertyName}({Qualifier.Key} key); Set<{Qualifier.Key}> keySet{PropertyName}(); Collection<{Qualifier.Value}> values{PropertyName}();
Back to the same example as for JDT template, the new version of the implementation is as follows:
/** * @uml.property name="project" * @uml.associationEnd multiplicity="(0 -1)" * inverse="company:model.Project" qualifier="key:java.lang.Object model.Project" */ private Map<Object, Collection<Project>> projectMap; /** * Getter of the property <tt>project</tt> * @return Returns the projectMap. * @uml.property name="project" */ public Map<Object, Collection<Project>> getProject() { return projectMap; } /** * Returns a set view of the keys contained in this map. * @return a set view of the keys contained in this map. * @see java.util.Map#keySet() * @uml.property name="project" */ public Set<Object> projectKeySet() { return projectMap.keySet(); } /** * Returns a collection view of the values contained in this map. * @return a collection view of the values contained in this map. * @see java.util.Map#values() * @uml.property name="project" */ public Collection<Collection<Project>> projectValues() { return projectMap.values(); } /** * Returns <tt>true</tt> if this map contains a mapping for the specified key. * @param key key whose presence in this map is to be tested. * @return <tt>true</tt> if this map contains a mapping for the specified key. * @see java.util.Map#containsKey(Object) * @uml.property name="project" */ public boolean projectContainsKey(Object object) { return projectMap.containsKey(object); } /** * Returns <tt>true</tt> if this map maps one or more keys to the specified value. * @param value value whose presence in this map is to be tested. * @return <tt>true</tt> if this map maps one or more keys to the specified value. * @see java.util.Map#containsValue(Object) * @uml.property name="project" */ public boolean projectContainsValue(Collection<Project> project) { return projectMap.containsValue(project); } /** * Returns the value to which this map maps the specified key. * @param key key whose associated value is to be returned. * @return the value to which this map maps the specified key, or * <tt>null</tt> if the map contains no mapping for this key. * @see java.util.Map#get(Object) * @uml.property name="project" */ public Collection<Project> getProject(Object object) { return (Collection<Project>) projectMap.get(object); } /** * Returns <tt>true</tt> if this map contains no key-value mappings. * @return <tt>true</tt> if this map contains no key-value mappings. * @see java.util.Map#isEmpty() * @uml.property name="project" */ public boolean isProjectEmpty() { return projectMap.isEmpty(); } /** * Returns the number of key-value mappings in this map. * @return the number of key-value mappings in this map. * @see java.util.Map#size() * @uml.property name="project" */ public int projectSize() { return projectMap.size(); } /** * Setter of the property <tt>project</tt> * @param value the projectMap to set. * @uml.property name="project" */ public void setProject(Map<Object, Collection<Project>> project) { projectMap = project; } /** * Associates the specified value with the specified key in this map * (optional operation). * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. * @return previous value associated with specified key, or <tt>null</tt> * @see java.util.Map#put(Object,Object) * @uml.property name="project" */ public Collection<Project> putProject(Object object, Collection<Project> project) { return (Collection<Project>) projectMap.put(object, project); } /** * Removes the mapping for this key from this map if it is present * (optional operation). * @param key key whose mapping is to be removed from the map. * @return previous value associated with specified key, or <tt>null</tt> * if there was no mapping for key. * @see java.util.Map#remove(Object) * @uml.property name="project" */ public Collection<Project> removeProject(Object object) { return (Collection<Project>) projectMap.remove(object); } /** * Removes all mappings from this map (optional operation). * @see java.util.Map#clear() * @uml.property name="project" */ public void clearProject() { projectMap.clear(); }