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);
 }
}