Trimm Java extensions

Trimm Java (and its submodules Trimm Groovy/Grails and Trimm JPA) is built around a tiny core code generator that is extended using Extensions that are called EventListeners.

Trimm Java is event centric and every step of the code generation is communicated as Events. This allows TRIMM developers and 3rd party developer to create re-useable Extensions that can be shared. See xxxx for more about how to create your own extensions.

Below is a list of Java specific EventListeners/Extensions (which can also be used from Trimm Groovy/Grails and Trimm JPA)

NOTE: All listeners/extensions are placed in package dk.tigerteam.trimm.mdsd.java.generator.extension unless otherwise noted.

EventListener Class Name (FQCN)DescriptionExample
HashCodeAndEqualsListener

Generates a hashCode and equals¬†method pair (using Commons.Lang’s EqualsBuilder and HashCodeBuilder) for either all properties in the class (if the hashCodeAndEquals stereotype is applied at class level) or for the individual properties (if the hashCodeAndEquals stereotype applied at the property level)

HashCodeAndEquals Stereotype example - both per class and with individual Attribute(s)

HashCodeAndEquals Stereotype example – both per class and with individual Attribute(s)

ImportListener Creates a java import statement for every TRIMM Java Code-Element Type in a Clazz or Interface. If you use any of the AbstractConfigurationBasedCodeGenerator subclasses (e.g. if you use TRIMM from Ant or Maven) then the import listener is automatically configured as the last listener.
SerialVersionUIDGeneratorListenerGenerates a private static final long serialVersionUID field for all Clazz‘ based on their fields/properties.

private static final long serialVersionUID = 590742170313829643L;

ConstructorForImmutablePropertiesListenerCreates a constructor, which allows setting all immutable/readonly properties (i.e. properties which doesn’t have a setter method)
SerializablePojoListenerMakes sure that any given Clazz or Interface always implement Serializable.
The processing will occur deferred and will make sure that implements Serializable only will be applied if it isn’t already a part of the inheritance hierarchy
PropertySugarMethodsEventListenerGenerates setter property sugar accessors called “with” or “addTo” which support fluent interface style programming (where several methods can be chained together without having to insert semicolons).
These with/addTo method takes the value to set as an argument and returns the current object (the object instance that the property is defined within).

import org.joda.time.DateTime;
import java.util.*;

public class Consultation {
  private DateTime consultationDate;

  public DateTime getConsultationDate() {
      return consultationDate;
  }

  public void setConsultationDate(DateTime parameter) {
      this.consultationDate = parameter;
  }

  public Consultation withConsultationDate(DateTime consultationDate) {
      setConsultationDate(consultationDate);
      return (Consultation) this;
  }
  -------------------------------------------------------------------------------
  private Set prescriptionCollection = new HashSet();

  public Set getPrescriptionCollection() {
      return prescriptionCollection;
  }

  public void setPrescriptionCollection(Set parameter) {
      this.prescriptionCollection = parameter;
  }

  public Consultation addToPrescriptionCollection(Prescription... values) {
    getPrescriptionCollection().addAll(Arrays.asList(values));
    return (Consultation) this;
  }
}

ToStringListenerImplements a toString method with the properties from clazz.
You can specify if it should include superClassProperties, collections and sort the output according to the property name (ascending)
BidirectionalGeneratorEventListenerThis listener is responsible for wrapping all bidirectional relationships between properties, by using specialized wrapper classes (such as, but not limited to, OneToOneWrapper, ManyToOneWrapper, OneToOneWrapper, OneToManyCollectionWrapper, ManyToManyCollectionWrapper).
This ensures that if you have defined a bi-directional association between two classes in your Metamodel then the generated java code will ensure that the code behaves accordingly (ie. it acts bi-directionally in-memory), so you don’t have to maintain bi-directionality yourself.
With the following UML definition

---------                ---------
|       | RoleA    RoleB |       |
|   A   |________________|   B   |
|       |                |       |
---------                ---------

Then the following code assertion will hold true

    A a = new A();
    B b = new B();
    a.setRoleB(b);
    assert b.getRoleA() == a

ConstructorListenerSupports the creation of a single Constructor for a Clazz which has the stereotype Constructor.
The arguments/parameters to the constructor can be specified by given the class Attributes/Association that should
be part of the constructor’s arguments with the ConstructorArgument stereotype.
You can also specify an optional Constructor code body by adding a constructorBody Tagged value to the Clazz.

This listeners can also handle super class constructor arguments in case a Clazz inherits from another Clazz which also is annotated
with the Constructor stereotype.

Example of the ConstructorListener

Example of the ConstructorListener

public class Entity {
        private long id;

        public Entity(long id) {
            this.id = id;
        }

        public long getId() {
            return id;
        }

        public void setId(long parameter) {
            this.id = parameter;
        }
    }

    public class Customer extends Entity {
        private String firstName;
        private String lastName;
        private String email;

        public Customer(long id, String firstName, String lastName) {
            super(id);
            this.firstName = firstName;
            this.lastName = lastName;
            throw new RuntimeException("constructorBody");
        }

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String parameter) {
            this.firstName = parameter;
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String parameter) {
            this.lastName = parameter;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String parameter) {
            this.email = parameter;
        }
    }

BuiltInTypesListenerListener which corrects the FQCN for a series of built in types: "date" -> java.util.Date, "bigdecimal" -> java.math.BigDecimal,
"biginteger" -> java.math.BigInteger}, "calendar" -> java.util.Calendar,
and "timestamp" -> java.sql.Timestamp.

Note: This listener should be registered as the very first listener to work properly!

If you use TRIMM Java/JPA/Groovy/Grails from Ant or Maven then BuiltInTypesListener is automatically configured for you.

ClassHierarchyJavaDocListenerDocuments the inheritance hierarchy as JavaDoc for a given Clazz/Interface This will for instance generate documentation such as this for a Clazz Veterinarian together with another class called Customer both inherits from class User

/**
 * Hierarchy:
 * <ul>
 *   <li>User</li>
 *   <ul>
 *     <li><b>Veterinarian</b></li>
 *     <li>Customer</li>
 *   </ul>
 * </ul>
 */

GetOrNewListenerCreates a nice sugar method for 1-1 and Many-1 associations, which allows fetching the association, and in case it doesn’t exist creates a new association and assigns it.
For a class Person with a (1-1) association to an Address class through the property "homeAddress" it will create a person.getOrNewHomeAddress() property sugar method.
MetaTypeJavaDocListenerWrites out MetaType information to all Clazz, Property and Field as Javadoc, so the extension developer can see the relationship between the MetaModel and the CodeModel (ie. the java code generated). It’s very useful for extension debugging purposes.
Example:

public class Consultation {
  /**
   * Extra Meta info:
   * Meta id = 'EAID_dstA24611_D82C_447f_A49F_364EAE326C1E'
   * Visibility = 'Public'
   * TaggedValues = '{}'
   * Fabricated = 'false'
   * StereoTypes = ''
   * Name = 'null'
   * Cardinality = '1; 1'
   * Ordered = 'false'
   * Static = 'false'
   * Bounds = 'n/a; n/a'
   * Aggregation = 'None'
   * IsPartInAssocation = 'true'
   * Meta association id = 'EAID_A9A24611_D82C_447f_A49F_364EAE326C1E'
   * IsOwnerOfAssocation = 'true'
   * IsAssocationBidirectional = 'true'
   * AssociationType = 'ManyToOne'
   * OppositePropertyInAssociation = 'EAID_srcA24611_D82C_447f_A49F_364EAE326C1E'
   */
  private Veterinarian veterinarian;