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);
}
}
1 comment:
Maybe you should check out OGNL, I think it does exactly what you want, and more:
http://www.ognl.org/
Post a Comment