Thursday, October 18, 2007

Superfast Model Driven Development with EMF (I)

Or: write a text adventure game in no time

One of the technologies that I use quite a lot is EMF. It has helped me increase my development speed enormously, and I use it pretty much every time I need a little data model.

What is lesser known is that you don't actually need to be writing Eclipse plugins to take advantage of EMF. You can use EMF in any old Java program. Another thing Eclipse gives you is tooling around EMF and tooling for your own model, which makes it super handy.

So with the Eclipse tooling you get a nice UML editor on your EMF class model. Eclipse generates all the EMF runtime code for you, and it also generates a model instance editor, so basically you get a data entry tool for your model as well, which can be quite useful.
In addition to the modeling stuff, the EMF runtime also gives you a loading and saving of your model (to an XML file format called XMI). All of this stuff is available for free as open source.

So I've used it to write a little text adventure game framework (add your own graphics later ;) You can define the actual text adventure in the EMF model. EMF is also used to provide the load and save game functionality.

So I started off with Eclipse 3.3.1 with EMF and GMF installed (see here how that's done). We need GMF to do the graphical UML editing. I've posted a little how-to on this, in case you need help.

In this posting I'm creating the model and will generate a data entry editor for my model. The next posting will focus on the actual game and how you run it as a simple Java app.

1. Create the model
Create a project called EMF_Adventure.model and add an Ecore Model file to it (in Eclipse go to File | New | Ecore Model) and call it Adventure.ecore.

Then right-click on the Adventure.ecore file in the tree, and select 'Initialize ecore_diagram diagram file' from the popup menu. Double-click the Adventure.ecore_diagram that has just been generated and you're in the UML editor (click on the image for a clearer picture):

So now we actually create our model. My little model for the adventure game looks like this:

My model contains the definition of the structure of an Adventure.
  • The Adventure entity contains a number of Locations (containment is visualized using the diamond UML notation). One of these locations is to be the start location of the game.
  • Locations in turn have routes to other locations, they also possibly contain items. Every location has a name and a description and an ID.
  • A Route object describes how to get from one location to another.
  • Items are things you can find on a location. Certain items are visible, you just see them and can pick them up. Other items are a hidden, for instance, if you want to find the treasure you will need to dig, otherwise you don't see it. In this case there might be a precondition on another item that you need to have in your inventory to perform this action. In order to dig you may need a spade.
Besides the adventure definition, the model also contains a representation of the Inventory which contains all the items you have picked up during the game. EMF is quite nice in that it make sure the model is consistent. This means that contained objects can only have one container. So by adding an Item to your Inventory EMF will automatically remove it from the Location.

Finally the definition contains an entity used for saving and loading games. The SaveGame entity has a reference to the location where you saved the game and also holds the inventory that you had when you saved.

Another way to look at the same model is by opening the Adventure.ecore file, which gives you a tree-type view on the model.

You can either edit the model using the diagram editor or using the ecore editor. They generally keep each other in sync.

Find the Adventure.ecore file that I created here.

2. Generate a data entry tool for your model
The first thing you will need to do in order to use your EMF model is to generate code from it.

To generate your code you need to create a .genmodel file. Do this by going File -> New -> Other and then select 'Eclipse Modeling Framework | EMF Model'.

Just call it Adventure.genmodel, select 'Ecore model' as the Model Importer on the next page and then pick your Adventure.ecore file from your workspace. Then finish the wizard.

The Adventure.genmodel file contains a whole lot of settings that influence how the EMF code generation is done. I normally change at least one setting. By default EMF generates code in the project that holds the .genmodel file. I always prefer to have the generated code in another project, so I typically change the following property:
Model Directory: change from /EMF_Adventure.model/src to /EMF_Adventure/src
Then right-click on the top-level Adventure node in the Aventure.genmodel file and select 'Generate All':

The model generation gives us a couple of options:
  • Generate Model Code - this is the code that we will be using at runtime. Its an implementation of the model that we defined.
  • Generate Editor Code - this generates an Eclipse editor to fill your model with data. It can be really handy to populate your model. The Edit Code that is also generated is used internally by the editor.
  • Generate Test Code - this will create a plugin that contains test templates and some sample code that utilizes your model.
After running the generation you will get 4 new projects in your workspace that all compile without errors:

In this screenshot (again click on it for a high-res version) you can see some of the generated code. Currently open is the Item class which contains getters and setters for all the properties we defined in the model. Both interface and implementation are generated for the model, our implementation is generated in the adventure.impl package.

Now we can run it to create our adventure content! Just right-click any of the newly generated projects and select 'Run As -> Eclipse Application'.
This starts up a separate Eclipse Runtime that contains your newly generated editor. Create a new project in it and add a new adventure model file by going 'File -> New -> Example EMF Creation Wizards -> Adventure Model':

Call it My.adventure and select 'Adventure' as the Model Object in the last wizard page.

Once you have your file, you can double-click it and voilĂ  there is your editor where you can define your adventure. It will allow you to create all your locations, items and routes. It also has a properties view where various properties are edited. And this all without writing a single line of code!

The actual file edited is an XML file. I created one based on a little adventure I made with my kids a little while ago, you can find it here.

In the next post, we'll create the adventure runtime.

6 comments:

pookzilla said...

This series looks fantastic! You picked an excellent example to engage us nerds. :)

Avery R said...

So if "Initialize ecore_diagram diagram file" doesn't show up, what have I done wrong?

Avery R said...

You need to set the Compliance Level =6.0 before you generate the code. Otherwise the generic code references won't be created to match the code given in later blog entries.

davidb said...

Avery R, from your second comment I assume you got past your problem re 'Initialize ecore_diagram file' not showing up. This is caused by GMF not being properly installed - it should be all covered by this posting.

Thanks for your comment regarting the compliance level. I don't remember having to set this myself, but I think I used JDK 1.6 as the default JDK for my Eclipse installation.

Ed Merks said...

David,

It seems that some older posts got re-posted yesterday for no apparent reason. The same thing happened with a few of my older posts.

Note that the Ecore Tools project now provides an enhanced version of the graphical Ecore editor that I highly recommend. I've been using it to replace the moldy old Rose diagrams starting with Ecore itself as I described in Was Gany Good to You.

davidb said...

Hi Ed,

>It seems that some older posts got
>re-posted yesterday for no apparent
>reason. The same thing happened
>with a few of my older posts.

Thanks for the heads-up. I hadn't noticed this myself.

I'll have a go at the new ECore editor that's available. It looks really cool!

Cheers,

David