Unified Expression Language specification plus some enhancements for and in Dart.

>

RikuloRikulo

Blog

Back to index


Rikulo EL, an Expression Language for and in Dart

Isn't EL for Java and JSP/JSF?

Yes, it is. And with Rikulo EL, you are now enabled to use EL for and in Dart, too.

And No, it is not.

EL indeed is more of a specification than an implementation. You can see it as a light weight scripting mechanism allowing you to easily access application logic and data with simple expression. You can see it as a templating engine that helps you generate proper text format of your choice. You can hook it with your presentation layer and do things similar to JSP pages. Or you can even use it to establish the whole data binding system that support MVVM design patterns.

Use Rikulo EL

Rikulo EL implements the EL specification thus you can use it as what you have used it before if you are familiar with it. Or maybe you want to check the EL specificationn for details.

Nevertheless, I will show you the enhancements that Rikulo EL added that are specific for Dart language.

Access variables

Following is a typical "Hello World" example. The variable to be evaluated is provided by use of VariableMapper.

import 'dart:mirrors' show reflect;
import 'package:rikulo_el/el.dart';

class Person {
  String name;
  Person(this.name);
}

void main() {
  //Prepare an expression factory.
  ExpressionFactory ef = new ExpressionFactory();

  //Prepare the expression script
  //expression inside #{...} is to be evaluated
  String script = 'Hello, #{person.name}!';

  //Prepare an expression context.
  ELContext ctx = new ELContext(
    resolveVariable:
      (String name) => name == 'person' ? new Person('Rikulo'): null);

  //Parse the script and create a value expression which expect a String type
  ValueExpression ve = ef.createValueExpression(ctx, script, reflect('').type);

  //Evaluate the expression and return the evaluated result
  print(ve.getValue(ctx)); //'Hello, Rikulo!'
}

Instead of reflecting the string's type (with reflect()), you can use STRING_MIRROR instead.

Access functions

Following is still a typical "Hello World" example. Here we use FunctionMapper.

import 'dart:mirrors' show reflect;
import 'package:rikulo_el/el.dart';

class Person {
  String name;
  Person(this.name);
}

void main() {
  //Prepare an expression factory.
  ExpressionFactory ef = new ExpressionFactory();

  //Prepare the expression script
  //expression inside #{...} is to be evaluated
  String script = 'Hello, #{currentPerson().name}!';

  //Prepare an expression context.
  Person currentPerson() => new Person('Rikulo');
  ELContext ctx = new ELContext(
    resolveFunction:
      (String name) => name == "currentPerson" ? currentPerson: null);

  //Parse the script and create a value expression which expect a String type
  ValueExpression ve = ef.createValueExpression(ctx, script, reflect('').type);

  //Evaluate the expression and return the evaluated result
  print(ve.getValue(ctx)); //'Hello, Rikulo!'
}

Allow using Dart array syntax in EL expression

There is no counter part in EL specification and Rikulo EL enhances the parser and evaluator to handle the Dart arrays. Following is a simple example.

import 'dart:mirrors' show reflect;
import 'package:rikulo_el/el.dart';

class Person {
  String name;
  Person(this.name);
}

void main() {
  //Prepare an expression factory.
  ExpressionFactory ef = new ExpressionFactory();

  //Prepare the expression script
  //expression inside #{...} is to be evaluated
  String script = 'Hello, #{[henri, john, mary][0].name}!';

  //Prepare an expression context.
  Person getPerson(String name) {
    switch (name) {
      case 'henri':
        return new Person('Henri');
      case 'john':
        return new Person('John');
      case 'mary':
        return new Person('Mary');
    }
  }
  ELContext ctx = new ELContext(resolveVariable: getPerson);

  //Parse the script and create a value expression which expect a String type
  ValueExpression ve = ef.createValueExpression(ctx, script, reflect('').type);

  //Evaluate the expression and return the evaluated result
  print(ve.getValue(ctx)); //'Hello, Henri!'
}

Note that such Dart array instance is created everytime the value expression is evaluated and its life scope is only within that "Evaluation". That is, after the evaluation is done, it will be left as is and finally garbage collected.

Allow using Dart map syntax in EL expression

import 'dart:mirrors' show reflect;
import 'package:rikulo_el/el.dart';

class Person {
  String name;
  Person(this.name);
}

void main() {
  //Prepare an expression factory.
  ExpressionFactory ef = new ExpressionFactory();

  //Prepare the expression script
  //expression inside #{...} is to be evaluated
  String script = 
    "Hello, #{{'henri' : henri, 'john' : john, 'mary' : mary}['henri'].name}!";

  //Prepare an expression context.
  Person getPerson(String name) {
    switch (name) {
      case 'henri':
        return new Person('Henri');
      case 'john':
        return new Person('John');
      case 'mary':
        return new Person('Mary');
    }
  }
  ELContext ctx = new ELContext(resolveVariable: getPerson);

  //Parse the script and create a value expression which expect a String type
  ValueExpression ve = ef.createValueExpression(ctx, script, reflect('').type);

  //Evaluate the expression and return the evaluated result
  print(ve.getValue(ctx)); //'Hello, Henri!'
}

Note that such Dart map instance is created everytime the value expression is evaluated and its life scope is only within that "Evaluation". That is, after the evaluation is done, it will be left as is and finally garbage collected.

Conclusion

Rikulo EL implements the Unified Expression Language specification and adds some enhancement features specific for Dart language. Authoring the presentation layer(web pages) in Dart and Rikulo will be easier and more versatile. It will serve as the important base templating engine for Rikulo UXL UI eXtensible Language and the Rikulo ORM libraries. Stay tuned.

comments powered by Disqus

CATEGORIES