Sunday, December 14, 2008

LWJGL Plugin at lwjgl.org

As you may now, GEF3D is moving to Eclipse. GEF3D uses OpenGL for rendering GEF diagrams in 3D, and since OpenGL is a C library, a Java wrapper library has to be used. LWJGL is such a library and GEF3D uses LWJGL. It works with SWT out of the box, that is there is no need for using the SWT-AWT-bridge, which isn't working on Mac OS X (maybe this will change with the new Cocoa version of SWT?). The latest version supports OpenGL 3.0 and runs on Mac, Windows, Linux and Solaris. Unfortunately, the LWJGL library didn't got IP approved. So it cannot be added to the Eclipse orbit project. The good news is, that lwjgl.org now provides an LWJGL Eclipse plugin! Brian Matzon has installed the update site today. Thank you so much, Brian! It is the plugin I wrote for GEF3D, and it is now available at http://lwjgl.org/update/. This plugin is interesting for people developing Eclipse plugins (or using GEF3D), since it simply wraps the LWJGL library (including the native code) into an Eclipse plugin. Not only the libraries are made available, but source code and documentation as well. Another plugin will be made available shortly at the same update site, providing LWJGL support for standalone Java applications developed with Eclipse. This plugin will define a new library "LWJGL Library", that is it resolves the jars, native libs, sources and JavaDoc using the LWJGL plugins above. Since the native libs will be defined as well, a standalone Java application can easily be started using Eclipse's "Run As - Java Application" without the need to set a library path. So, this plugin saves some mouse clicks and configuration problems. With these plugins, it is very easy for Eclipse developers to use OpenGL, either by an Eclipse plugin or by a standalone Java application developed with Eclipse.

Monday, November 24, 2008

Eclipse Summit Europe 2008, Retrospect

This was my first Eclipse event so I was very excited. Unfortunately, my proposal about GEF3D was rejected. But anyway, it was a lot of fun! Here are some thoughts about some talks. Quentin Glineur (Obeo) talked about model-to-model transformations with ATL and QVT. Quentin listed several use cases for m2m-transformations: validation, refactoring, reexpression and consistency checking. He is currently implementing an engine for Declarative QVT based on the ATL virtual machine. Later I had a long discussion with him about model transformations. I'm really exited about his QVT implementation, which will be available at Eclipse.org. Jan Köhnlein, Peter Friese, and Sven Efftige (itemis) presented xText. Since I'm fighting (but don't get me wrong: xText is a super cool tool) with xText for a couple of weeks to get my own transformation language working, I was happy to hear thet the upcoming version of xText will solve a lot of problems, such as easier implementation of expressions or mixing of languages and grammars (I could use that for including OCL). I had lunch with Sven and it seems as if every little problem (or bug) will be solved in the next version of xText, it's a pitty that I have to finish my project before it will be released (feature freeze will be in March 2009, it will be part of Galileo). Since I have heard so much about Jazz I was especially interested in the talk by André Weinand (IBM). For me Jazz looks pretty much like a tool set for Scrum, but this could be a misinterpretation by a Scrum master (like the guy with the hammer for whom anything looks like a nail). I'm still a little bit confused whether Jazz is freely available or not. But it looks definitely impressing and I'd like to work with it. For example, it introduces certain "isolation levels", for example a (personal) repository workspace. That is each developer has his own individual repository for backup and so on, and there will be a separated project repository. Thinking about that I'm wondering how I will work with my code when it has been moved to the Eclipse repository... A while ago I posted a master thesis proposal about visualizing model differences using EMF Compare and GEF3D. Unfortunately, no student has shown interest in this thing. Nevertheless it was very interesting listening to Cédric Brun (Obeo) about EMF Compare. While seeing his slides I was thinking about new cool visualizations, for example an Apple Time Machine like view of different model versions in a repository. One of the highlights was Ed Merks' talk about "The Unbearable Stupidity of Modeling". While I agree with most of his statements, for example the exaggerated use of the prefix "meta", I noticed (again) this little difference between the american and european conception of "model" and related terms such as "abstraction". I have to work out that thing in my thesis ;-). Maybe it's because the great book on model theory by Herber Stachowiak was never translated into English... For people using the word "meta" too much, and thus maybe suffer under some kind of modeling fever (my adviser once diagnosed me with "Modellithis"), I can recommend the very funny article "UML Fever" by Alex E. Bell, or (in severe cases) you may consider joining the Meta-Modellers Anonymous. Or simply read Ed's blog regularly. Scott Lewis and Marcelo Mayworm's talk about ECF (the Eclipse Communication Framework) was quite nice, they showed a small video about two pair programmers editing a single piece of source code using ECF. It's very similar to my beloved editor SubEthaEdit. I'm wondering whether it would be possible to integrate ECD ad GEF3D somehow? David Sciamma (Anyware Technologies) presented the new and upcoming features of the Ecore tools, that is the Ecore diagram editor. Version 0.9 will be part of Galileo. Kristian Duske is currently working on a 3D port of these tools, so it would be nice to keep contact with the 2D developers. To be honest I didn't knew David is also developing these Ecore tools, I "only" knew him as the author of the TopCased UML editor. So it would be the second work of David which will be ported to 3D, since his TopCased UML editor is the one I'm using in all my transformation chain examples (thinking about that I'm reminded to update my 3D version to the latest TopCased UML 2 version, I hope that will be as quickly done as the previous version, that is within two days ;-) ). Having all that trouble with licenses and third party libraries in the context of the review of LWJGL and JOGL (and even my initial GEF3D contribution), I was very curious aboutJanet Campbell's talk about "IP for Eclipse Committers". IP is short for "intellectual property" and this talk was especially about the "due diligence". That is (for people not that familiar with the Eclipse Process) there are a bunch of rules to be followed before code can be committed to Eclipse (i.e. some Eclipse CVS or SVN). IMHO this is an outstanding quality of Eclipse to be very concerned about these issues, even if I have a lot of trouble because of that (LWJGL was not approved, and JOGL is only to be approved because SGI has changed its free license agreements two months ago). So, a big thank you to all that people doing these legal reviews and stuff! It was a really great experience to meet all that people I knew only from their email addresses, and especially people I was mailing with so much for the last couple of weeks because of GEF3D: Chris Aniszczyk, Ed Merks and Anne Jacko. It's a really great community, and I'm happy to be a part of it :-)

Wednesday, November 5, 2008

The Eclipse gef3d project is complete!

Three and a half months ago Chris Aniszczyk asked me if I would like to make GEF3D an Eclipse project. At that time I had released a first version of GEF3D under the EPL. I started GEF3D as part of my Ph.D. project (which still is an ongoing project), but I thought that others may be interested in that framework, so I released it. I didn't knew what I did when I agreed on moving GEF3D to Eclipse. Oh guys, this paperwork and this whole Eclipse process is overwhelming. Fortunately I have two great mentors, Chris Aniszczyk and Ed Merks, helping me through all this just like Virgil guided Dante through all the nine circles of Hell. Thank you, guys! After writing the proposal, creating the creation review slides, filling out several requests and other paperwork, I received a mail today with this subject: "The Eclipse gef3d project is complete!". That's cool! So, in the near future you will find GEF3D at http://www.eclipse.org/gef3d. It will need some time to find code there, because the code has to get clearance first. So long, you will find GEF3D at it's old location at http://gef3d.org. Stay tuned!
PS: I thought I've read about Dante in Ed's Blog some time ago, I vaguely remember a slide on which he compared meta models (and meta meta models) with the circles of Hell, but I cannot find it anymore (I also remember his advice not to go there...). This was when Dante's trip to Hell came back into my mind. Actually I've never read the Divine Comedy. My girl friend once wrote a paper about Botticelli's Dante illustrations, and she made me love this special "comic strip" from the 15th century (and she explained me how to "read" it). I even had the luck to see the original drawings in Berlin once).

Monday, October 13, 2008

String.valueOf(Object obj) vs. Object.toString()

I'm programming with Java for more than 10 years now and I have always used Object.toString() to print out any kind of objects, usually for debugging and logging purposes. Looking at code written by others, this seems to be pretty usual. But there is a big problem: the object may be null. In this case, the call to Object.toString() will result in a NullPointerException. Sometimes ;-) I'm well aware of this problem, so I usually wrote ((obj==null)?"null":obj.toString()). By accident I found this nice function a day ago: String.valueOf(Object obj). What does it do? It's a static method and it looks like that: return (obj == null) ? "null" : obj.toString();. Looks pretty familiar. Why didn't I found this method earlier? Carnival barker: "Are you using this method? If not, start today and bugs like this will become history!" So, I would recommend to use String.valueOf(Object obj) rather than Object.toString(). But there are others (e.g. here or there) who recommend to prefer Object.toString(), because you can save one method call. IMHO this is the wrong place to start optimizations. I also found some tutorials which explain that you can use one or the other without discussing the differences. Maybe that's why I needed 10 years to find this nice static method.

Wednesday, September 24, 2008

Simple Query-Language for Dynamic EMF Model

Usually I'm generating the model code from my ecore models. But sometimes I want to simply query a model, and in these cases a dynamic EMF model is good enough. I wrote a small helper class, providing a very simple query language for dynamic EMF very similar to the JSP Expression Language -- of course less powerful. You can query an EObject using a dot notation and square brakets for defining the index of a list item. E.g.
Object street = eval( eobj, "person.address[0].street");
will return the street of the first address entry. The utility class will create nice error messages if something goes wrong. This is the grammar of the language:

query    := feature ( "." feature )*
feature  := <name> ( "[" <index> "]" )?
Maybe there's another way of accessing dynamic EMF that easy, maybe using some (at least for me: hidden) EMF utility class. If you know a better solution, please let me know! Here is the utility class:
/**
* Author: jevopi
* (C) 2008 jevopi
*/
public class DynEcoreUtil {

 /**
  * Returns value of specified feature path. For specifying the feature path,
  * a dot notation is used, if a list is to be parsed, square brakets with
  * index are used.
  *
  * @param obj
  * @param featurePath
  * @return
  */
 public static Object eval(Object obj, String featurePath) {
  StringTokenizer st = new StringTokenizer(featurePath, ".");
  String feature = "";
  Object value = obj;
  try {
   while (st.hasMoreTokens()) {
    obj = value;
    feature = st.nextToken();
    if (feature.endsWith("]")) {
     int splitPos = feature.lastIndexOf("[");
     int index = Integer.parseInt(feature.substring(
       splitPos + 1, feature.length() - 1));
     feature = feature.substring(0, splitPos);
     value = fvl((EObject) obj, feature, index);
    } else {
     value = fv((EObject) obj, feature);
    }
   }
   return value;

  } catch (Exception ex) {
   if (feature == null || !(obj instanceof EObject)) {
    throw new IllegalArgumentException("Can't resolve "
      + featurePath + ", feature " + feature + " not found.",
      ex);
   } else {
    EObject eobj = (EObject) obj;
    EClass eclass = eobj.eClass();
    StringBuffer strb = new StringBuffer("Can't resolve "
      + featurePath + ", feature " + feature + " not found.");
    strb.append("Possible features of type " + eclass.getName());
    strb.append(": ");
    boolean bFirst = true;
    for (EStructuralFeature sf: eclass.getEStructuralFeatures()) {
     if (!bFirst) strb.append(", "); else bFirst = false;
     strb.append(sf.getName());
    }
    throw new IllegalArgumentException(strb.toString(), ex);
   }
  }
 }

 static Object fv(EObject obj, String name) {
  EStructuralFeature feature = obj.eClass().getEStructuralFeature(name);
  return obj.eGet(feature);
 }

 static Object fvl(EObject obj, String name, int index) {
  EList<object> list = (EList<object>) fv(obj, name);
  return list.get(index);
 }
}