.. ******************************************************************************* * MetaFactory.io R2 * Technical Documentation * * File name : Example-UsingSnippets.rst * Created by : MetaFactory (Marnix Bochove) * Updated by : Niels de Nies * * MetaFactory BV Amsterdam ******************************************************************************* .. include:: /inline-images.txt .. include:: /external-links.txt SDA example using snippets ========================== This example demonstrates how a template engine can be used to create code. In the :ref:`Hello World` example (Tutorial 01) all code is created by a XML code instruction. Although XML is great to define the structure of a class it isn’t well suited for creating the body of a method when the method needs to access the model object. This is why a snippet (a freemarker or velocity template) can be used in MetaFactory. To use a snippet the following expressions can be used: .. code-block:: ${fmsnippet.path.to.your.freemarker.template} or .. code-block:: ${snippet.path.to.your.velocity.template} Code Instruction ---------------- With the following code instruction, we create pojo classes from a model and use Freemarker to create the toString, equals and hashcode methods: .. code-block:: xml :caption: code instruction to create POJO classes :name: Using snippets-01 :linenos: :emphasize-lines: 93,100,109 src/main/java/ src/main/resources src/test/java/ src/test/resources org.metafactory.example.usingsnippets ${pattern.property.base}.model.implementation ${object.name} ${reference.type} ${pattern.property.model.implementation.package}.${pattern.property.model.implementation.class} ${fmsnippet.java.pojo.enum.enumConstants} ${attribute.type} ${fmsnippet.java.pojo.attribute.apicomment} ${model.property.attribute.entity.default.value} ${fmsnippet.java.pojo.operation.setter} ${pattern.property.model.implementation.reference} ${pattern.property.model.implementation.reference} java.util.HashSet java.util.Set ]]> ()]]> ${attribute.type} ${reference.type} ${fmsnippet.java.pojo.operation.constructor.constructor-use-fields} ${pattern.property.model.implementation.reference} ${fmsnippet.java.pojo.operation.addToSet} ${pattern.property.model.implementation.reference} ${fmsnippet.java.pojo.operation.deleteFromSet} FIXME define businesskeys in model boolean ${pattern.property.model.implementation.class} ${fmsnippet.java.pojo.operation.equals.equals-use-businesskey} FIXME define businesskeys in model integer ${fmsnippet.java.pojo.operation.hashcode.hashCode-use-businesskey} String ${fmsnippet.java.pojo.operation.tostring.toString-use-all-attributes} Model ----- This is the model used: .. code-block:: xml :caption: model.xml :name: Using snippets-02 :linenos: false Persons 2 1 false Addresses 1 2 false Phones 1 Project ------- For completeness, here is the MetaFactory project file used: .. code-block:: xml :caption: Project :name: Using snippets-03 :linenos: model.xml pattern.xml snippets true true true true Phone class created ------------------- This is the Phone class, created by MetaFactory. The toString method is highlighted: .. code-block:: java :caption: Phone class :name: Using snippets-04 :linenos: :emphasize-lines: 23-33 package org.metafactory.example.usingsnippets.model.implementation; /** * Phone - Created by MetaFactory: Automation of Software Development * * @author - marnix */ public class Phone { private String number; private String description; private Person person; // Getters and setters omitted /** * toString - * * @return String */ public String toString() { StringBuilder result = new StringBuilder("Phone: "); result.append("number=" + number); result.append(", "); result.append("description=" + description); return result.toString(); } /** * equals - Fields used as businesskey: 1) number. * * @param phone * @return boolean */ public boolean equals(final Phone phone) { boolean result = true; // If all business keys are null, return false if (this.getNumber() == null) { result = false; } else { if (this.getNumber() != null && !this.getNumber().equals(phone.getNumber())) { result = false; } } return result; } /** * hashCode - Fields used as businesskey: 1) number. * * @return integer */ public int hashCode() { int result; result = 14; if (number != null) { result = 29 * result + this.getNumber().hashCode(); } return result; } } Freemarker snippet ------------------ The following Freemarker snippet is used to create this toString method as declared at line 109 in :numref:`Using snippets-01`. .. code-block:: :caption: Freemarker snippet :name: Using snippets-05 :linenos: <#--stop if $currentModelObject is null--> <#if !(currentModelObject)??> <#stop "currentModelObject not found in context" > <#assign modelObjectName = currentModelObject.getAttributeValue("name")> <#assign modelObjectNameFL = modelObjectName?uncap_first> StringBuilder result = new StringBuilder("${modelObjectName}: "); <#assign attributes = currentModelObject.getChildren("attribute", nsModel)> <#list attributes as attribute> <#assign attributeName = attribute.getAttributeValue( "name")> <#assign attributeType = attribute.getAttributeValue( "type")> <#assign javaType = generator.getJavaType(attributeType)> <#-- Add a , after first iteration of this loop using index variable created by freemarker --> <#if (attribute_index > 0) > result.append(", "); <#if (generator.isPrimitiveJavaType(attributeType)) > result.append("${attributeName}=" + ${attributeName}); // I am primitive <#else> <#-- handle primitive types other than objects --> <#if (javaType == "String") > result.append("${attributeName}=" + ${attributeName}); <#else> result.append("${attributeName}=" + ${attributeName}.toString()); return result.toString(); Evaluation ---------- With the above template the developer coded exactly how the toString method must be created for all classes. With **MetaProgrammimg** the developer creates all methods at a meta level. The MetaFactory project can be downloaded here: :download:`example-using-snippets `