Wednesday, April 28, 2010

Acceleo API and properties files

This post is aimed at anyone that depends on or make use of the Acceleo versions built and provided within the Helios release train, namely 0.9M1-0.9M5 and 3.0M6. If you are not concerned, feel free to ignore it altogether ^^.

We added support for ".properties" files in Acceleo in the latest development version (this support appeared for 3.0M1, at the time named 0.9M1). However we realized that this first version of the properties handling left no place for customization/overriding of properties ; no place for internationalization ; and deployment of generation modules as plugins would most likely cause issues with properties lookup. Bug 311045 and bug 311068 have been opened to track these issues.

If you are one of the early adopters that made use of the property support, you'll need to cope with a little change for the M7 build : in the generated class was an "addProperties" method which allowed you to registered the full path to the properties file that was to be loaded. For example if you had a file named "messages.properties" in package "sample" of plugin "org.eclipse.acceleo.sample", you had to register the path "platform://plugin/org.eclipse.acceleo.sample/sample/messages.properties".

You will now have to return a list through the method "getProperties" (well, "addProperties" is still there yet deprecated), and this list will have to contain "sample.messages" (that is, .) ; and properties file need to be located in source folders.

Likewise, if you had set anything as "generated NOT" in the generated launcher, you will have to manually go through some minor API changes as we ended up creating a common superclass for all launchers. Specifically, launchers now "extends AbstractAcceleoLauncher", and what was once private or protected is now mostly public. This means previously generated launchers that had set any method as "generated NOT" might have to enhance the visibility from private to public. Take note that previously generated launchers that have been built and deployed will not fail and can still be used as is, though enabling re-use of your generator can only be done by letting Acceleo regenerate it (or simply code yourself to take these changes into account).

Sorry about these changes (especially past M6), but we really thought best to remove the bug-prone behavior instead of trying to maintain it since it had never been released in a stable build. The new API should allow for a real use of property files and enhance the re-usability of any generation module.

If you wish to have a look at these changes and cope with them before M7 goes live, they are all accessible in the integration build I201004291415 that went live today (see the download page for the zip or all-in-one update site downloads).

If you have any doubt or questions about these issues, feel free to answer the m2t newsgroup thread I started with a copy of this post.

Tuesday, April 13, 2010

OCL tips and tricks

Acceleo is entirely based on OCL (Object Constraint Language) for all of its model navigation syntax. Though we did simplify it as much as possible for Acceleo (getting rid of redundant casts, increasing the standard library, overriding operators, ...), there are still some things that might cause problems to any beginning user.

Here are a few of the most unsettling language particularities :
  • Operations or features conflicting with reserved OCL keywords (UML anyone?). For example, if your model has a class "Operation" with a feature named "body", then writing "myClass.body" in OCL will result in a somewhat cryptic error : "invalid token 'body'".

    The trick to access such features in OCL is to prefix the feature name with an underscore. For this example, you should have written "myClass._body".

    For the record, the full list of OCL reserved keywords as per the last available OCL version, 3.0, is as follows :

    • and
    • body
    • context
    • def
    • derive
    • else
    • endif
    • endpackage
    • if
    • implies
    • in
    • init
    • inv
    • let
    • not
    • or
    • package
    • post
    • pre
    • static
    • then
    • xor

  • Accessing enumeration values. This might sound obvious to OCL experts, but how would one compare feature values to set enumerated values? The trick here is to qualify the access. For example if you wish to check that an UML operation's visibility is "public", here is what you would do in Java : "if (operation.getVisibility() == VisibilityKind.PUBLIC".

    The OCL equivalent is "if (operation.visibility = VisibilityKind::public)".

  • There is no "elseif" in OCL ; remember to close each individual if properly with endifs : "if (...) then ... else if (...) then ... else ... endif endif"
I believe these are the most annoying (as in "the most subject to cause weird compilation errors") OCL features ; don't hesitate to add yours :p.