MENU

  /   Quick Start

This guide will help you setup MetaFactory and get you started with a demonstration project in 15 minutes.

  1. Get and install MetaFactory
  • Request an evaluation copy of MetaFactory by sending an email to info@metafactory.nl
  • No installation is required, just unzip the received package to a location of your choice and run the run64.bat file inside the main folder if you use it on 64-bit windows.   If you are an OS X user, doubleclick the .dmg file and drag MetaFactory to your applications folder. Read more about the installation for Windows or OSX/macOS. If you are using IntelliJ you can also control MetaFactory from inside the IDE using the IntelliJ plugin. Learn more on how to configure this.
  • Create a new project (File –> New)
    • You will be asked where to save the xml file, choose a location inside your preferred projects location.
    • A default folder structure, including basic versions of model.xml and pattern.xml are also created. MetaFactory requires these files with at least this basic content to run, hence it creates them.

Learn more about the project structure here and read about the functionality of metafactory.xml, model.xml and pattern.xml here:

You have now installed MetaFactory and created a basic project that does not yet do anything. If you are using an IDE to edit the files we recommend configuring it for use with MetaFactory in order to validate the XML and enable auto-completion.  You can check out the required steps hereNow let’s create our first example.

Creating an application with a large amount of entities quickly becomes tedious work. Entity classes contain fields, zero or more overloaded constructors and a set of getters and setters. All these entities need separate controllers, repositories and so on. Now to automate this process we will start by creating entity interfaces as well as the implementation classes.

The following example shows how to produce java pojo classes and interfaces by a pattern and a model. For a very first simple impression of how Metafactory works, you may however want to read the ‘Hello Metafactory world’ example first.

First we define a model:

<?xml version="1.0" encoding="UTF-8"?>
<model xmlns="http://www.firstbase.nl/xsd/personaliom/model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.firstbase.nl/xsd/personaliom/model http://www.firstbase.nl/xsd/personaliom/model.xsd">
  <package name="domain_model">
    <object name="Person">
      <attribute name="firstName" type="String" length="50" notnull="true"></attribute>
      <attribute name="lastName" type="String" length="50" notnull="true"></attribute>
      <reference name="homeAddress" type="Address" notnull="true" multiplicity="1..1"></reference>
      <reference name="workAddress" type="Address" notnull="false" multiplicity="0..1"></reference>
      <reference name="phone" type="Phone" notnull="false" multiplicity="0..n"></reference>    </object>
    <object name="Address">      <attribute name="streetName" type="String" length="100" notnull="true"></attribute>
      <attribute name="zipCode" type="String" length="10" notnull="false"></attribute>
      <attribute name="city" type="String" length="50" notnull="true"></attribute>
      <attribute name="country" type="String" length="50" notnull="false"></attribute>    </object>
    <object name="Phone">      <attribute name="number" type="String" length="30" notnull="true"></attribute>
      <attribute name="description" type="String" length="100" notnull="true"></attribute>
      <reference name="person" type="Person" notnull="true" multiplicity="1..1"></reference>
    </object>
  </package>
</model>

Various attribute values such as ‘type’, ‘length’ and ‘notnull’ are included in the above snippet. However you should know that these values by itself do nothing unless they are explicitly dealt with by the pattern. MetaFactory is designed not to use any default or hidden implementations, thereby providing transparency and control to the programmer.

Note that the <reference> element contains a attribute called ‘multiplicity’. This attribute tells the pattern how many references of the given type the object can contain. For example ‘0..n’ means that the object may contain either zero or any other number of this reference type. The pattern can for example use this attribute as a condition for creating the output code.

Now let’s look at the pattern that creates interfaces and implementations for this model data.

<?xml version="1.0" encoding="UTF-8"?>
<pattern xmlns="http://www.firstbase.nl/xsd/personaliom/pattern" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.firstbase.nl/xsd/personaliom/pattern http://www.firstbase.nl/xsd/personaliom/pattern.xsd">
  <properties>
    <java.output.directory>java</java.output.directory>
  </properties>
  <package name="com.firstbase.ba.example6a.pojo" package="domain_model">
    <interface name="I${object.name}" foreach="object">
      <attribute name="id" access="rw">
        <datatype>long</datatype>
        <apicomment>primary key</apicomment>
      </attribute>
      <attribute name="${attribute.name}" access="rw" foreach="attribute">
        <datatype>${attribute.type}</datatype>
        <apicomment>${attribute.name} property</apicomment>
      </attribute>
      <attribute name="${reference.name}" foreach="reference" access="rw" condition="${reference.multiplicity}=0..1 OR ${reference.multiplicity}=1..1">
        <datatype>I${reference.type}</datatype>
        <apicomment>Reference to I${reference.type} object</apicomment>
      </attribute>
      <attribute name="${reference.name}Set" foreach="reference" access="rw" condition="${reference.multiplicity}=0..n OR ${reference.multiplicity}=1..n">
        <library>java.util.Set</library>
        <datatype><![CDATA[Set<I${reference.type}>]]>
        </datatype>
        <apicomment>Set of I${reference.type} objects</apicomment>
      </attribute>
      <operation name="add${firstUpper(${reference.name})}" foreach="reference" condition="${reference.multiplicity}=0..n OR ${reference.multiplicity}=1..n">
        <apicomment>Utility method to add a object of type I${reference.type} to ${reference.name}Set</apicomment>
        <parameter name="${firstLower(${reference.name})}">
          <datatype> I${reference.type}</datatype>
          <apicomment> object to add to ${reference.name}Set</apicomment>
        </parameter>
      </operation>
      <operation name="delete${firstUpper(${reference.name})}" foreach="reference" condition="${reference.multiplicity}=0..n OR ${reference.multiplicity}=1..n">
        <parameter name="${firstLower(${reference.name})}">
          <datatype> I${reference.type}</datatype>
        </parameter>
      </operation>
    </interface>
    <class name="${object.name}Impl" foreach="object">
      <implements>I${object.name}</implements>
      <attribute name="id" access="rw">
        <datatype>long</datatype>
        <apicomment>primary key</apicomment>
      </attribute>
      <attribute name="${attribute.name}" foreach="attribute" access="rw">
        <datatype>${attribute.type}</datatype>
      </attribute>
      <attribute name="${reference.name}" foreach="reference" access="rw" condition="${reference.multiplicity}=0..1 OR ${reference.multiplicity}=1..1">
        <datatype> I${reference.type}</datatype>
      </attribute>
      <attribute name="${reference.name}Set" foreach="reference" access="rw" condition="${reference.multiplicity}=0..n OR ${reference.multiplicity}=1..n">
        <library>java.util.Set</library>
        <library>java.util.HashSet</library>
        <datatype><![CDATA[Set<I${reference.type}>]]></datatype>
        <body><![CDATA[
          new HashSet<I${reference.type}>()
        ]]></body>
      </attribute>
      <operation name="add${firstUpper(${reference.name})}" foreach="reference" condition="${reference.multiplicity}=0..n OR ${reference.multiplicity}=1..n">
        <parameter name="${firstLower(${reference.name})}">
          <datatype> I${reference.type}</datatype>
        </parameter>
        <body> ${firstLower(${reference.name})}.${getSetterName(${reference.type},${object.name})}(this);
          ${reference.name}Set.add(${firstLower(${reference.name})});</body>
      </operation>
      <operation name="delete${firstUpper(${reference.name})}" foreach="reference" condition="${reference.multiplicity}=0..n OR ${reference.multiplicity}=1..n">
        <parameter name="${firstLower(${reference.name})}">
          <datatype> I${reference.type}</datatype>
        </parameter>
        <body> ${firstLower(${reference.name})}.${getSetterName(${reference.type},${object.name})}(null);
          ${reference.name}Set.remove(${firstLower(${reference.name})});</body>
      </operation>
    </class>
  </package>
</pattern>

 

A few explanations regarding this pattern:

  • The <package> element tells the name of the java package that the produced class will be in. This element also has a ‘package’ attribute which refers to the group of objects that is defined in model.xml.
  • Model objects are dynamically accessed using MetaFactory’s expression language. Expressions such as ${object.name} are known at the time of execution because a pattern is always executed within the context of the part of the domain model that MetaFactory is iterating over, such as a package, object or property. Read more about expressions here.
  • <![CDATA ]> tags are required sometimes to escape the XML reserved symbols, such as ‘<‘
  • The attribute ‘access=”rw” (of the <attribute> element) tells MetaFactory to generate getters and setters for this attribute.
  • The <operation> element is used to pattern Java methods.

Now that you have updated the code of our newly created project it is time to let MetaFactory run and generate all the code (menu Transform -> Run). You can find the generated code here.

Tip: add some new data entities of your own to the model and see how that works out in the output.

Good job, you’ve just created your first code with MetaFactory. While XML patterns help you enforce structure and consistency both in your patterns and in the resulting Java classes, only using this technique does come with limitations in flexibility. Snippets are the power tool in Metafactory that overcome these limitations and provide you with the templating freedom of using Freemarker or Velocity.  You can either evaluate a snippet into true or false as a condition to operate your xml pattern on or write complete method bodies and even classes with it. Do you value the structured approach and out of the box functionality of xml more, or the templating freedom of snippets? Mind that a very basic XML pattern is required as a container for your snippet, but other than that you are free in how you use snippets in your patterns. To learn more about callings snippets from your pattern you can check out another example. More information about the possibilities of snippets can be found here.

Please check out the MetaFactory Tuturial for more code examples!