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 functionality of metafactory.xml, model.xml and pattern.xml:

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. It should however be noted that inserting lengthy expressions in a condition or extensive code into an xml element can look messy . Additionally the expressions that xml allows can not have a lot of intelligence. In these situations you want to rely a lot on snippets (Freemarker or Velicity) to construct your expressions and code in. You can easily use the result of your snippet (true, false, a piece of code etc.) inside your xml pattern. To learn more about it you can check out another example.

Please check out the MetaFactory Tuturial for more code examples!