Sunday, December 19, 2010

Making Software Literate: Teaching Code to Read Itself

My previous post introduces the concept of Grammar, Template, and the Metamodel.

Creating metamodel is easy for humans, there is Ecore editor and Ecore Tools for that.

Generating artifacts from a model is also relatively easier... When compared to "reading" artifacts and generating a model.

In the machine world, almost everything is harder to read than to write.

For example, it is easy for a generator to output this:

lastName = "Irawan"
name = "Hendy " + lastName

However, it's not easy to "read" the above artifact. By that I mean that the parser software should "understand" that 'name' contains "Hendy Irawan".

And it brings us to... Interpreter.

Interpreter is an enhanced parser that knows what to do with a model. Advanced interpreters may have behaviors, but the most commonly used functionality is Evaluating Expressions.

An Evaluator transforms expressions in the metamodel to actual values (which are still expressions, called value expression, but do not need further processing). After the example artifact above are parsed AND interpreted/evaluated, the 'name' object will rightly contain 'Hendy Irawan'.

Grammar and Template's Role in Modeling

Grammar and Template are two essential components for model-driven reflection and generation.

Note that this article relates to high-level, abstract view of Model Driven Engineering. And it's going to be boring and theoretical, but I have to write it down so I won't forget. ;-)

With a Grammar, you can 'read' or understand or introspect or reflect or parse or deconstruct or reverse-engineer or (in a way) deserialize... from a concrete artifact, and generating a model as an output.

With a Template, you can 'write' or generate or create or build or construct or (in a way) serialize... an artifact as an output, from a model.

The third element which is required by both processes, is the metamodel. It's actually a prerequirement.

These three are the core ingredients for model driven engineering.

Now to actually bake these ingredients, you need equipment, the tools. Fortunately these are all provided by Eclipse Modeling Framework projects.

The first ingredient you need to create is the metamodel, which usually means an Ecore model. In later phases, the metamodel is not always the first artifact, it can be a generated artifact.

To read an artifact, you need a tool, the parser, that can read your metamodel. And create a grammar in a language that the tool understands. An example is Xtext with its Xtext grammar language. And Xtext, of course, understands Ecore models as the metamodel.

Given: metamodel + grammar --> Xtext, you will get a Parser.

A parser is an artifact reader that is customized to your grammar and metamodel. Given concrete artifact(s) as input, it generates a model as output.

To write to an artifact, you need a tool, that is a generator, that can read your metamodel. Then you create a template in a language that the generator understands.

Such a generator is Eclipse M2T Xpand, and its Xpand language.

Given metamodel + model + template --> Xpand, you get: (textual) artifact!

Actually, the concrete examples above assume one thing: the other metamodel (the "artifact") is a filesystem with text files.

In an abstract way, all transformations are model-to-model (M2M) transformations, hence conceptually requiring two metamodels, not just one. M2T (generation) and T2M (parsing) are conceptually M2M where one side is textual files, or "textual metamodel".

In order for code to understand itself, it must be able to generate a model from its own code.

In order for code to understand itself, it must be able to generate a model (reverse engineer / discover / import) from its own code.

Its model can then be used to generate code and build it, thus understanding and building itself.

Saturday, December 18, 2010

What You Need to Start Model-to-Text Transformation with Xpand

Setup your Model-driven Development Environment:
  1. Get Eclipse IDE, Modeling distribution.
  2. Install Xpand to Eclipse IDE
  3. Install MWE to Eclipse IDE
  4. Ecore Tools is optional, but it helps you to create your metamodel (Ecore model) using a nicer visual diagram editor.

Now you can create your project:
  1. Create your metamodel (.ecore file). Better just use Ecore Tools, and create .ecorediag diagram alongside .ecore file.
  2. Create a .genmodel from your metamodel.
  3. Generate your Model package and classes from the .genmodel.
  4. Create a sample model (instance).
  5. Open the .ecore model file, right click on a EClass and choose Create Dynamic Instance.
  6. Create a Xpand template.
  7. Create a MWE workflow file (.mwe).
  8. Add necessary plugin dependencies to the MANIFEST.MF.
Now you can run the workflow.

The steps above the high-level steps. It sounds complicated and indeed it can be confusing at first. (the reason why I'm blogging this here is so that I won't get confused in the future) ;-)

If you want the simplest thing, use the New Xpand Project Wizard - Sample Xpand Project and it'll provide up a ready-to-use Ecore+Xpand+MWE  setup for you. :-)

Note: MWE and Xpand package names has changed since moved from openArchitectureWare to Eclipse Modeling Framework umbrella, so be aware of this when following older tutorials.

How to Solve MWE/Xpand Workflow Problems/Errors

What to Check :

1. Check your model file (.xmi). See: http://spring-java-ee.blogspot.com/2010/12/fixing-eclipse-mwe-error-workflow.html

2. Check your plugin.xml file, make sure it contains extension on org.eclipse.emf.ecore.generated_package . Sample:

   <extension point="org.eclipse.emf.ecore.generated_package">
      <package
            uri="http://www.bippo.co.id/shop/3.0/magentoconfig/1.0"
            class="id.co.bippo.magento.config.MagentoConfigPackage"/>
   </extension>

3. Check that you've (re-)generated your model classes. Open your .genmodel and regenerate the Model.

Fixing Eclipse MWE Error: Workflow interrupted. Reason: Couldn't load resource under platform:/resource/*.xmi : org.eclipse.emf.ecore.xmi.PackageNotFoundException: Package with uri 'http://*' not found.

If you ever tried to run an Eclipse MWE Workflow, most likely to do M2T (Model-to-Text) transformation using Xpand from an EMF Ecore model to text files, you'll surely encounter several errors at first (or later).

For my case, the error is as follows:

0    INFO  WorkflowRunner     - --------------------------------------------------------------------------------------
7    INFO  WorkflowRunner     - EMF Modeling Workflow Engine 1.0.0, Build v201008251122
7    INFO  WorkflowRunner     - (c) 2005-2009 openarchitectureware.org and contributors
7    INFO  WorkflowRunner     - --------------------------------------------------------------------------------------
8    INFO  WorkflowRunner     - running workflow: /home/ceefour/project/Bippo/modeling_workspace/id.co.bippo.models/src/workflow/makegradle.mwe
8    INFO  WorkflowRunner     -
542  INFO  StandaloneSetup    - Registering platform uri '/home/ceefour/project/Bippo/modeling_workspace'
686  INFO  CompositeComponent - Reader: Loading model from platform:/resource/id.co.bippo.models/src/demo.bippo.co.id.xmi
780  ERROR WorkflowRunner     - Workflow interrupted. Reason: Couldn't load resource under platform:/resource/id.co.bippo.models/src/demo.bippo.co.id.xmi : org.eclipse.emf.ecore.xmi.PackageNotFoundException: Package with uri 'http://www.bippo.co.id/shop/3.0/magentoconfig/1.0' not found. (platform:/resource/id.co.bippo.models/src/demo.bippo.co.id.xmi, 2, 312)

This seemed like the dreaded platform:/resource URI common pitfall.

However, in my case the problem was inside the .xmi model file itself :

xsi:schemaLocation="http://www.bippo.co.id/shop/3.0/magentoconfig/1.0 ../metamodel/magento-config.ecore"

I was moving the metamodel (Ecore model) to another folder/package, however the XMI file's schemaLocation was hardcoded to a specific path.

Fix the schemaLocation, and it would work fine.

Wednesday, December 15, 2010

Gradle Build Script (build.gradle) for Writing Gradle Plugins

Gradle is a great build system written in Groovy programming language and that uses build scripts written in Groovy as well.

There are several ways to write a Gradle plugin and the most extensible one (also the most complicated) is to build the plugin as a separate project.

I tried to find documentation on how to do this but I can only find actual guide for writing "embedded" Gradle plugins (the plugins are contained inside buildSrc folder). But to move the plugin out of buildSrc folder and make it independent, you can use a build.gradle build script file like this in your plugin:


apply {
    plugin 'java'
    plugin 'groovy'
    plugin 'maven'
    plugin 'eclipse'
}

group = 'gradle-plugin-javafx'
version = '0.2.0-SNAPSHOT'

dependencies {
    compile gradleApi()
    groovy localGroovy()
}

Change group and version properties with your own.

Also, you can leave out applying the 'java', 'eclipse', and 'maven' plugins if you don't use them.

Source: http://code.google.com/p/gradle-plugin-javafx/source/browse/build.gradle