Thursday, October 31, 2013

ORMapping in Dart (Part2)

I started the implementation of Object Relational Mapping tool like JPA in Dart.
The approach follows the outline I posted before.
But there were several differences.

One is basically I decided to go with minimalist approach.
Always it creates more problem in the end if we rely on many outer resources.
In this case, I just went with my own Postgres scheme generation, sql generation etc.
In fact, it is not so complicated.
And for this kind of tool, we don't need much feature of SQL.

The reason I chose Postgres was the Dart lib for Postgres had BSD license.
MySQL driver in Dart was GPL. But Postgres may be better choice than MySQL technically.

Right now, it can generate DB scheme from annotated class definition, and it support CRUD*create/read(query) /update/delete operations.
persistence object has several level of state.

remaining things are:
  1.  how to support reference and relation. These are actually subtle issue inherent for many ORM system.
    Since if we fetch all associated objects, it may need to copy whole db content.
    So it is important to minimize fetching data.
  2.  how to support relationship. Even though we define relationship as List or reference, but, in particular, the List representation are sort of useless.
    Conceptually, relationship don't have to be represented as entity properties.
    In JPA, it also supports separate query, so it is better not to use List attribute.
 For reference, if we uses strict evaluation, it may end up fetching all data, so we must use lazy evaluation for fetching reference.
There is  some interesting issue for this, since most of postgres API is using Future, how can we avoid asynchronous operation for getting referenced object?
We may need to introduce some operator to change Future to synchronous call by  monitoring the asynchronous call was finished or not.

Also in order to support lazy evaluation, some fieldstate object associated to the filed may need to keep entity id in it, and if the filed is accessed,  it need to fetch from db and assign to the actual object field.
These are a bit complicated, but relatively straightforward.

But the relationship, List field is quite bad.
Essentially if there are large number of associated entities, such whole set is useless. If it cannot be used in general situation, it is better not to use it.

Actually, I created this binding scheme, so I can also change the type to represent relationship.
So instead of List<B>, I may use Rel<A, B>, Ref<A>. and Rel<A, B> class will provide query methods. and it will not maintains fetched objects. In fact, query and managing entity objects for transactional scoped are contradicting requirement.
Often fetched object may not have to be managed(read only).
So it will be useful to provide separate fetching mode so that it will reduce managed fetched objects.

For creating one/many to many relationship, it may be better to reflect such change immediately in database, and do not keep such info in memory unless corresponding object is managed in memory(such case, it need to reflect both sides). this simplify fetching data from database consistently.

class A {
  @OneToMany(mappegBy:"a")
  Rel<A, B> bs;

}
class B {
  @ManyToOne
  Ref<A> a;
}

Following is the test program.

@Table(name: "A")
class A extends Persistence {
    @Id()
    @Basic(optional: false)
    @Column(name: "id")
    String _id;

    @Basic(optional: false)
    @Column(name: "i")
    int _i;
    
    @ManyToOne()
    B _b;

    @OneToMany(mappedBy: "a")
    List<C> _cs;
    
    String get id => get(const Symbol("id"));
    void set id(String v)=>set(const Symbol("id"), v);

    int get i => get(const Symbol("i"));
    void set i(int v)=>set(const Symbol("i"), v);

    B get b => get(const Symbol("b"));
    void set b(B v)=>set(const Symbol("b"), v);

    List<C> get cs => get(const Symbol("cs"));
    void set cs(List<C> v)=>set(const Symbol("cs"), v);
    
    String toString() => "A(id: ${id}, i: ${i}, b: ${b}, cs: ${cs})";
}

@Table(name: "B")
class B extends Persistence {
  @Id()
  @Basic(optional: false)
  @Column(name: "id")
  String _id;

  @Basic(optional: false)
  @Column(name: "s")
  String _s;
  
  @ManyToOne()
  A _a;

  @OneToMany(mappedBy: "a")
  List<C> _cs;
  
  String get id => get(const Symbol("id"));
  void set id(String v)=>set(const Symbol("id"), v);

  String get s => get(const Symbol("s"));
  void set s(String v)=>set(const Symbol("s"), v);

  A get a => get(const Symbol("a"));
  void set a(A v)=>set(const Symbol("a"), v);

  List<C> get cs => get(const Symbol("cs"));
  void set cs(List<C> v)=>set(const Symbol("cs"), v);
  
  String toString() => "B(id: ${id}, s: ${s})";
}

@Table(name: "C")
class C extends Persistence {
  @Id()
  @Basic(optional: false)
  @Column(name: "id")
  String _id;

  @Basic(optional: false)
  @Column(name: "i")
  int _i;
  
  @ManyToOne()
  B _b;

  @OneToMany(mappedBy: "a")
  List<C> _cs;
  
  String get id => get(const Symbol("id"));
  void set id(String v)=>set(const Symbol("id"), v);

  int get i => get(const Symbol("i"));
  void set i(int v)=>set(const Symbol("i"), v);

  B get b => get(const Symbol("b"));
  void set b(B v)=>set(const Symbol("b"), v);

  List<C> get cs => get(const Symbol("cs"));
  void set cs(List<C> v)=>set(const Symbol("cs"), v);
  
  String toString() => "C(id: ${id}, s: ${i})";
}

Future<int> test0(_) =>
    persistenceMgr.deleteTables([A, B, C]).then((int n) {
      print("deleteTables done. ${n}");
    });

Future<int> test1(_) => persistenceMgr.createTables([B, C, A]);

Future<bool> test2(_) {
  A a1 = new A()
    ..managed = true
    ..id = "a1"
    ..i = 10;
  
  A a2 = new A()
    ..managed = true
        ..id = "a2"
        ..i = 20;
 
  return persistenceMgr.commit();
}

Future<bool> test3(_) {
  IClassMirror cmirror = ClassMirrorFactory.reflectClass(A);
  Selector<A> selector = new Selector<A>(cmirror);
  return selector.query(where: "id = 'a1'")
    .then((A a){
      print("==>> a: ${a}");
      a.i = 100;
      return persistenceMgr.commit();
    })
    .then((_)=>selector.queryAll())
    .then((List<A> as){
      print("==>> as: ${as}");
      return true;
    });
}

Future test4a(_) {
  IClassMirror cmirror = ClassMirrorFactory.reflectClass(A);
  Selector<A> selector = new Selector<A>(cmirror);
  return selector.query(where: "id = 'a2'")
    .then((A a){
      print("1a==>> a: ${a}");
      if (a == null) {
        return false;
      }
      print("1b==>> a: ${a}");
      return a.delete();
    })
    .then((ok) {
      if (!ok) {
        return false;
      }
      return selector.query(where: "id = 'a1'")
      .then((A a){
        print("2==>> a: ${a}");
      });    
    });
}

Future test4b(_) {
  IClassMirror cmirror = ClassMirrorFactory.reflectClass(A);
  Selector<A> selector = new Selector<A>(cmirror);
  return selector.queryAll()
  .then((List<A> as)=>Future.forEach(as, (A a)=>a.delete()))
  .then((ok) => selector.query(where: "id = 'a1'"))
  .then((A a){
      print("2==>> a: ${a}");
      //a.delete();
   });
}

void main() {
  
  // register reflection factory
  initClassMirrorFactory();
  
  setDBAdaptor(new PostgresDBAdaptor());
  
  test1(null).then(test2).then(test3).then(test4b).then(test0).then((_) { print(">>> completed."); });
}
And this is the output.

==>createTables: CREATE TABLE B (
id varchar(256) primary key,
s varchar(256),
a varchar(256));

CREATE TABLE C (
id varchar(256) primary key,
i int,
b varchar(256));

CREATE TABLE A (
id varchar(256) primary key,
i int,
b varchar(256));

ALTER TABLE B ADD CONSTRAINT b_a_fkey FOREIGN KEY (a) REFERENCES A(id);
ALTER TABLE C ADD CONSTRAINT c_b_fkey FOREIGN KEY (b) REFERENCES B(id);
ALTER TABLE A ADD CONSTRAINT a_b_fkey FOREIGN KEY (b) REFERENCES B(id);

>> createInsert: INSERT INTO A (id, i, b) VALUES
( E'a1' , 10, null);
>> createInsert: INSERT INTO A (id, i, b) VALUES
( E'a2' , 20, null);
>> DBTable.query: SELECT id, i, b FROM A WHERE id = 'a1'
==>> a: A(id: a1, i: 10, b: null, cs: null)
>> createUpdate: UPDATE A SET id =  E'a1' , i = 10, b = null WHERE id =  E'a1' ;
>> createUpdate: UPDATE A SET id =  E'a2' , i = 20, b = null WHERE id =  E'a2' ;
>> createUpdate: UPDATE A SET id =  E'a1' , i = 100, b = null WHERE id =  E'a1' ;
>> DBTable.queryAll: SELECT id, i, b FROM A
==>> as: [A(id: a2, i: 20, b: null, cs: null), A(id: a1, i: 100, b: null, cs: null)]
>> DBTable.queryAll: SELECT id, i, b FROM A
>> createDelete: DELETE FROM A WHERE id =  E'a2' ;
>> createDelete: DELETE FROM A WHERE id =  E'a1' ;
>> DBTable.query: SELECT id, i, b FROM A WHERE id = 'a1'
2==>> a: null
==>deleteTables: ALTER TABLE A DROP CONSTRAINT a_b_fkey;
ALTER TABLE B DROP CONSTRAINT b_a_fkey;
ALTER TABLE C DROP CONSTRAINT c_b_fkey;
DROP TABLE A, B, C;

deleteTables done. null
>>> completed.

Saturday, October 26, 2013

Several Dart bugs I encountered => found how to avoid the problem

The problem I reported in the previous post was really annoying.
It caused bunch of strange problems and there was no clue for the real reason why import fail, why 'a is A' does not have expected value.
The actual fix was to change return type of get listeners from List<ComponnetAction> to List<RowAction>. these types are defined by typedefs. After this change, everything got normal .
  
typedef void ComponentAction(Event event, Component c);
typedef void RowAction(Event event, Row row);

// this caused the problem:
//List<ComponentAction> get listeners => table.row_listeners;

// shoudl use this instead.
List<RowAction> get listeners => table.row_listeners;

Such a subtle difference caused a lot of strange problems without any meaningful error messages. Actually, the main bug may be the failed handling of ComponentAction, but even if it cannot be used there, Dart should report such error so that it can be corrected easily. 

I was a bit feeling not to use Dart if the quality of system is such low.
In facts, there were other bugs which is quite disappointing to know  the level of quality control of bug fixes.

1) wrong type of methods for reflect(new List<A>()).type,

{
    ClassMirror cmirr = reflect(new List()).type;
    print(">>0@@ cmirr.reflectedType: ${cmirr.reflectedType}");
    cmirr.getters.forEach((k, MethodMirror md){
      Type tm = null;
      if (md.returnType is ClassMirror) {
        tm = (md.returnType as ClassMirror).reflectedType;
        print(">>1@@ k: ${k}, tm: ${tm}");
      } else if (md.returnType is TypeVariableMirror) {
        TypeVariableMirror tvmirr = md.returnType;
        print(">>2@@ tvmirr: ${tvmirr.runtimeType}");
      }
    });
  }

The result of executing this is:

>>0@@ cmirr.reflectedType: List<A>
>>1@@ k: Symbol("length"), tm: int
>>1@@ k: Symbol("_capacity@0x36924d72"), tm: int
>>1@@ k: Symbol("first"), tm: A
>>1@@ k: Symbol("last"), tm: A
>>1@@ k: Symbol("single"), tm: A
>>1@@ k: Symbol("isEmpty"), tm: bool
>>1@@ k: Symbol("isNotEmpty"), tm: bool
>>1@@ k: Symbol("reversed"), tm: Iterable<T>
>>1@@ k: Symbol("iterator"), tm: Iterator<T> 

This issue was discussed with Gilad, and he told me Google team is working on this issue. At the time, first 's type was not substituted to A, this issues was definitely fixed.
But the type parameter of the generic type of  reversed an iterator is still T, not substituted to A.
These type related implementation is quite basic, must have highest quality.
Although they fixed, the way to fix without addressing all problem was very sloppy.
I reported this issue, but they looks not setting higher priority.

2) Another case was dart2js bug, which crashed dart2js. For this issue I observed the same problem after they 'fixed' the issue, but  they could not fix all the cases. Although the response time and fixed time was good, related issued should be checked when one issue was reported.(take more time to examine related issues rather than fixing fast)

3) the reflectClass behavior is really bad. and alternative way to get runtimeType though instantiating object is just absurd.
These things indicate the design of mirror is not well guided.
They may be busy for many stuff, but some basic language core thing should be implemented in highest quality.

My impression is Dart team is too much focusing on Polymer.
Often such politically overselling approach is proved to be misguiding/useless in the end, but it will waste a lot of people's energy and time.

Friday, October 25, 2013

ORMapping in Dart

A persistence support using relational DB is very basic requirement for any real world applications.
Right now, there seems no such tools available in Dart.
but there are a few DB driver for SQL server.
in this situation, what we can do in simplest way would be following.
  1.  delegate generating db scheme to JPA. In order  to do this, we use the same annotation as JPA in Dart class. and from this dart class, using reflection, we generate Java source code with the same JPA annotation defined in the dart class. The rest of generating scheme in db can be automated in some script.
  2.  Once we had a db scheme, we can access db. one way is to use Java itself to access db and Dart will access the object as Json through web API, but this approach may make system complicated since Dart needs Java server. So if we avoid intermediate Java and can directly access DB, that would be more simple approach.Since Dart class has already annotations, so it should be possible to provide reflection based plumbing to map row data to entity properties.
 Normally we will need to start from defining abstract(interface) class for db entity(table).
then we need to provide the implementation class for this interface.
But manual implementation of such implementation class are tedious and mechanical. It should be automated. One way is just to generate such an implementation class from the interface classes. But code generation approach often create more problem for maintenance etc. So it is better to avoid this approach. Also code generation bloat the code size, and it will not good approach for running on client side.

but if we define abstract class we need to define another class implementing the methods, so in this approach, we cannot avoid code generation.
So we need to define a concrete class which has no db mapping codes.

The simple solution for this is just using inheritance.

@Entity()
@Table(name: "A")
class A extends Persistence {
    @Id()
    @Basic(optional: false)
    @Column(name: "id")
    String _id;

    @Basic(optional: false)
    @Column(name: "i")
    int _i;
    
    @ManyToOne()
    B _b;

    @OneToMany(mappedBy: "a")
    List<C> _cs;
    
    String get id => get(const Symbol("id"));
    void set id(String v)=>set(const Symbol("id"), v);

    int get i => get(const Symbol("i"));
    void set i(int v)=>set(const Symbol("i"), v);

    B get b => get(const Symbol("b"));
    void set b(B v)=>set(const Symbol("b"), v);

    List<C> get cs => get(const Symbol("cs"));
    void set cs(List<C> v)=>set(const Symbol("cs"), v);
}
we define persistence root class called Persistence. This class will use reflection for intercepting getter/setter to access database. The only annoyance is we needs to define getter/setter calling methods get/set defined in the Persistence class. This would be a reasonable compromise. If dart has a build-in intercepting mechanism for getter/setter, we may further skip this definitions, and it may be a good proposal for Dart language..

The basic idea required to implement the Persistent class is the same as Monitor class, but it uses different annotation(JPA style), and will have SQL Driver access codes.

Another aspect of OR mapping is query. Often they introduce new query language mainly to avoid join operation. So we may create such query language or implement some standard query language in Dart, but we may just use ordinary SQL for this purpose. if it uses many-to-many relationship,  JPA creates intermediate table so writing query require such knowledge, but other relationships , the db table representation is simple. (and it is better to avoid many-to-may to simplify the db scheme).

So I think I will just go with SQL query based approach.
 But still some idea from https://github.com/polux/parsers, may be used to implement simple query language.

Friday, October 18, 2013

Zen Style: Semantics Oriented, Contextual Programming

The title of this blog is suggestive.
Like a monk in Zen temple, a programmer should not work hard for low level thing, but just try hard to identify the essence of the problem, then the rest will follow magically with no effort.

Declarative programming style is something common to this style. we don't care some procedural steps, which are very low level, but just concentrate on the relationship.
But declarative style itself are still not powerful enough. We must be able to extend the declarative constraint enforcing mechanism in the programming. It is sort of reflective approach, the goal of this approach is to create autonomous intelligent program driven by knowledge and semantics, context, rules etc. Essentially the output is not cumming just from the written code, but the as a synthesis of machine intelligence and the directive programming which will be short in size.

Normally such kind of programming were not easy. But these days, reflection library can be used to assist such programming style. Annotation is actually very under evaluated naming, but it has big potential. we can change ordinarily programming behavior outside of written code using such annotation information and specific library using reflection.

The code I developed for GUI is such an example.
Essentially the goal of the approach is to support declarative GUI development.
Some structural/layout related coding are defined with no procedural codes.

And procedural code which are associated with how the GUI will respond to user input etc are cleanly separated from these GUI code.

In normal program, we cannot change the timing of setting some property values etc, but using reflection library, it can implicitly set these values based on annotation, field type, context class type etc.
So we may think of this as semantics driven program, or contextual program. We can improve programming productivity by delegating certain annoying patterns to such library.
This is quite close to changing our language itself. So that is the essence of reflectivity.

These things could have been done in Java, but Java's generics were poor at runtime compared to Dart, Dart has more potential utilizing generic's type information. This is important difference. Java could not know itself at runtime, but Dart can. One interesting example was the CouchDB json parser which will use provided applied generic type information to determine sub json's type information as posted before.
Another reason may come from just the basic verboseness of Java language. There are so many restrictions, like anonymous class, even something can be done better, in the faces of such a bloated code, the gain would have reduced a lot.
That would have been discouraging some effort. AOP activities were something to be mentioned, but I have never seen such AOP application for GUI library in Java.
The cascading syntax is very small syntactic addition, but it has a big potential to eliminate all html  based development. Also many future, higher order functional make code very short.
Only in such an environment, these new approach will shine.

Here is a new revised version of sample code I posted before.
in the first part of code are dedicated to GUI presentation. Also the idea of this approach is to assist component style web development which combine the behavioral logic in the component, so such sub components are also declared as final field property with annotations.
From this annotation information and the declaring class, ie, CRUDView as subclass of Component class, when the object is instantiated, the super class Component will start analysing the annotation
 through reflection library, and setting corresponding property in the subcomponents(like label value in the annotation).

class CRUDView extends Component {
  static const String CRUD = "g_cud_view";
  DivElement _content;
  DivElement _actions;

  @UI_Table()
  final Table<Expense> table = new Table<Expense>();
  
  @UI_Form()
  final Form<Expense> form = new Form<Expense>();
 
  @UI_Button(label: "Load")
  final ButtonComp loadButtom = new ButtonComp();
  
  @UI_Button(label: "New")
  final ButtonComp newButtom = new ButtonComp();
  
  @UI_Button(label: "Save")
  final ButtonComp saveButtom = new ButtonComp();
  
  @UI_Button(label: "Delete")
  final ButtonComp deleteButtom = new ButtonComp();
  
  Element _updateElement(Element elm) => 
      elm
      ..classes.add("section")
      ..nodes.add(new Element.html("<header class='section'>${table.modelType} Table</header>"))
      ..nodes.add(_content = new Element.tag("div")
        ..classes.add("g_crud_view_table")
        ..nodes.add(table.element))
      ..nodes.add(_actions = new Element.tag("div")
        ..id = "actions"
        ..classes.add("section")
        ..nodes.add(loadButtom.element)
        ..nodes.add(newButtom.element)
        ..nodes.add(saveButtom.element)
        ..nodes.add(deleteButtom.element))
      ..nodes.add(form.element)
      ..nodes.add(new Element.html("<footer class='section' id='footer'></footer>"));
 
This part defines more behavioral aspect of program.It defines how application respond to the user input etc. these are nothing to do with GUI. We may still reduce direct association of the action with each GUI components if we introduce Monitored fields as I have done in namebudge application.

  // this should be injected by AOP approach from out side..
  ICouchDbClientDAO<Expense> dao = new CouchDbClientDAO<Expense>(Expense, sampleJsonMapper);
  
  CRUDView() {
    this.classes.add(CRUD);
    Type _Expense = Expense;
    table
      ..modelType = _Expense
      ..formatFunctionMap[ExpenseType] = ExpenseTypeComp.format;
    
    form
      ..modelType = _Expense
      ..inputFactoryCache.specialInputCompMap[ExpenseType] = ExpenseTypeComp.inputCompFactory
      ..inputFactoryCache.adhocCompMap['detail'] = 'textarea'; // should be moved to annottaion!
    
    loadButtom.onClick((_) {
      dao.fetchAll().then((List<Expense> es){
        table.load(es);
        //print('loaded data from db; ${es}');
      });
    });
    
    newButtom.onClick((_) {
      Expense e = form.create();
      _changeButtonState(true, false, true);
      //print('new in db');
    });
    
    saveButtom.onClick((_) {
      if (form.e != null) {
        Expense e = form.save();
        if (e == null) {
          //print('form is empty, click New, or select arow before Save.');
          return;
        }
        // this part is tricky..
        // since e is fill from InputText, when it is empty text, it will assign "" instead of null..
        if (e.id == "") e.id = null;
        if (e.rev == "") e.rev = null;
        ((e.id == null)?dao.insert(e):dao.update(e)).then((Expense e0){
          e.id = e0.id;
          e.rev = e0.rev;
          table.addOrUpdate(e);
          _changeButtonState(false, true, true);
          //print('updated in db e0: ${sampleJsonMapper.toJson(e0)}, e: ${sampleJsonMapper.toJson(e)}');
        });
      }
    });
    
    deleteButtom.onClick((_) {
      Expense e = form.e;
      if (e != null) {
        dao.delete(e).then((ok){
          if (ok) {
            form.delete();
            table.delete(e);
            _changeButtonState(false, true, true);
            //print('deleted in db');
          }
        });
      }
    });
    _changeButtonState(false, true, true);
    
    table.row_listeners.add((ev, row){
      Expense e = row.e;
      form.load(e);
      _changeButtonState(false, false, false);
    });
  }
  
  void _changeButtonState(bool new_disable, bool save_disable, bool delete_disable) {
    newButtom.node.disabled = new_disable;
    saveButtom.node.disabled = save_disable;
    deleteButtom.node.disabled = delete_disable; 
  }
  
  Element createElement() => addSubComponents0(newElem("div"));
  
  Element update() => addSubComponents0(initElem());
      
  Element addSubComponents0(Element elm) => addListeners(_updateElement(elm));
}

This is one application of annotation and reflection, the other application I introduced was Monitor. Monitor is useful to separate GUI interaction and actual semantics.It may be considered as more efficient version of Event driven code.
Monitor is achieving similar goal as Observable does in Ploymer, but it is general purpose class, which may be used for OR mapped entity classes to support lazy loading etc.

Anyway, I will need to describe them in more detail later.

Several Dart bugs I encountered

I refactored the codes so that new implicit delayed UI component initialization can be used.
And I found a few restriction and bugs of Dart.

  1. I needed to define default constructor without taking optional values. this is required to create UI component object without taking any parameters, in particular, parent value can not be passed at the property declaration time.
    So I first tried to use optional parameter '{}', but when I combined with Monitor suing Mixen, I found it does not allow to use mixin with a class in which the default constructor has optional parameters.
  2. So I first try to avoid changing existing constructors(although it was not bad idea to change so, but it needed more changes), I moved Monitor class to be used as super class of the top level Component class. Then what I saw during execution was very strange problem. There was annotation class called Monitored, and reflection will get the instance through metadata, and in order to identify proper annotation class, it uses 'is" operator.
    What happened was that 'obj is Monitored' was not true even obj's runtimeType is Monitored!
    This kind of things happen in Java when different class loaders are used to instantiate an object, but in Dart, we will not manipulate class loading, so quite strange. So I basically abandoned this approach, and took the mixin approach again.(this was OK, since this approach would be more narrowly scoped, and appropriate for the purpose).
  3. after all required changes are finished, and could run properly with DartVM mode, I tested this app with static mirror library which are to be used for javascript mode.
    If I run this with Dart VM, it run properly, but if we use javascript mode, the dart2js compiler crashed.
    Actually the message of the compiler problem was the same as a bug I reported before, and it was quickly fixed(but  I did not verify it for myself.) So I thought this would be fixed if I update the dart sdk(r28355) since the fixed version was older that that revision.
    But I found it was not fixed. Actually there were some workaround to fix previous problem using variable instead of direct type value, but this issue was not fixed by this workaround. So this may indeed be another bug.
  4. Another problem I faced was the getting ClasssMirror of generic type. In order to provide javascript mode, portal mirror need to provide basic reflection features from concrete classes.
    For instance it need to use generic type's type(Type). right now, in order to have right type value, namely the type where parameters are substituted is only to go through instantiating the object.
    but new implicit delayed UI component initialization will call reflection library when  the default constructor is called. So this introduced infinite loop. Actually these kind of problems were I anticipated when I knew the current  way to get Type. Essentially this is very dirty trick. Also some case, this will case unnecessary resource usage as well. I avoided this problem using dirty trick to use static variable not to call the sub component initialization(although the global variable is defined as private, so it is not so bad way..).
  5. This issue also made clear the current constructor has a lot of restriction, lack of flexibility. The simple way to avoid this in Java was to define another constructor to take such flag to disable calling sub component initialization. But in Dart, if we define one constructor, there is no other way to define another.   So I was forced to use global variable.

Wednesday, October 16, 2013

Implicit Delayed Initialization of GUI Components with Reflection

Previous sample code is a bit inferior compared to polymer HTML GUI specification style since the layout related codes were scattered around many places. It should have more declarative specification gathered in the close places.

One of the main reason for this mess was these sub components need to know the parent and it is impossible to get access in field declaration parts. So they must have been moved to constructor.
Also attribute related specification clutter the codes.

We can fix these issues by introducing two ideas.
  1.  use annotation for sub components in which attribute specification(small GUI related information, will be specified.
  2.  Implicit delayed initialization of sub components. This means when a component is instantiated, it will inspect these annotated sub component fields, and set the parent and additional information depending on the annotation and its parameters. The nice thing about this approach is that this procedure is recursive.
    when  the component is created, it starts initializing the sub components whose sub components are already initialized when the sub component is created.
Followings will be the new way to define layout.

class NameBadge extends Component with Monitor {

  @UI_TextInput(label: "Enter New Name:", String)
  final TextInputComp textInput = new TextInputComp();
  
  @UI_Button(label: "Generate pirate name")
  final ButtonComp button = new ButtonComp();
  
  @UI_Radio(label: "Male", name:"maleOrFemale")
  final RadioComp maleRadio = new RadioComp();
  
  @UI_Radio(label: "Female", name:"maleOrFemale")
  final RadioComp femaleRadio = new RadioComp();
  
  Element _createElement(Element elm) => 
      elm
        ..nodes.add(
            new Element.div()
              ..classes.add("entry")
              ..nodes.add(textInput.element)
              ..nodes.add(button.element)
              ..nodes.add(maleRadio.element)
              ..nodes.add(femaleRadio.element))
        ..nodes.add(
            new Element.div()
              ..classes.add("outer")
              ..nodes.add(new Element.div()..classes.add('boilerplate')..text = 'Hi! My name is')
              ..nodes.add(_initDiv0(new Element.div()..classes.add('name')..text = _badgename)));
  ...

  NameBadge(Component parent): super(parent, const[APP]) {
    this.button.onClick((e) { badgename = pirateName(); });
    this.maleRadio.onClick((_, comp){ male = true; });
    this.femaleRadio.onClick((_, comp){ female = true; });
    ...

Tuesday, October 15, 2013

Reflective Interceptor, Monitor in Dart (Part 2)

Here is a sample code using Monitor. This sample was created from dart-tutorials-samples-Master/web/namebadge so that we can compare the differences.

In order to have getter/setter interception, we need to use Mixin with Monitor or extend Monitor.
We need to define monitored private fields, and public getter/setter corresponding to these private annotated fields.
The public getter/setter will call inherited methods get/set defined in Monitor.
This part is sort of mechanical, and may be a bit annoying to repeat, but it is better than using  code generator.
Also we need to define actions to be triggered when setter/getter are called using addSetListener, addGetListner.

When we use setter for private variables, like '_male = true;', then no actions are triggered. but if we use public setter, like 'male = true; ' then, it will trigger the registered actions.

Compared the both code size, Polymer looks better. But this approach is simpler and flexible. we don't have to rely on some convention between Polymer html and dart class bound to the polymer element.
Also there is no need to maintain two files system closely associated with each others. That will become maintenance night mare.

Since this is normal dart code, much more complicated things can be done without struggling with the restriction posed by Polymer.

I don't like ugly JSP style mixing of control in html file.
If we use cascading style to build html Element, the size of code is comparable(may be smaller?) to HTML. And we can do much more flexible thing in dart.

One advantage of using HTML is it uses less dart code. the code size can be smaller than program based one.
but if we develop dynamic web site, such a difference may be ignorable.

And we want to take generic web component approach like Form, Table, Polymer style approach does not work.

This is using my portable_mirror lib,  it works using both dart VM using dart:mirrors lib, and javascript mode with static stubs.

import 'dart:html';
import 'dart:math';

import "../../gui_component/lib/monitor_lib.dart";
import "package:gui_component/gui_component_lib.dart";

class NameBadge extends Component with Monitor {
  static const String APP = "g_namebage";
  TextInputComp textInput;
  ButtonComp button;
  RadioComp maleRadio;
  RadioComp femaleRadio;
  
  Element _div0;
  Element _initDiv0(Element e) => _div0 = e;

  @Monitored()
  String _badgename = 'Bob';
  @Monitored()
  bool _male = false;
  @Monitored()
  bool _female = true;

  String get badgename => get(const Symbol('badgename'));
  void set badgename(String v) => set(const Symbol('badgename'), v);
  
  bool get male => get(const Symbol('male'));
  void set male(bool v) => set(const Symbol('male'), v);
  
  bool get female => get(const Symbol('female'));
  void set female(bool v) => set(const Symbol('female'), v);
  
  NameBadge(Component parent): super(parent, const[APP]) {
    this.textInput = new TextInputComp(this, "Enter New Name:", String);
    this.button = new ButtonComp(this, "Generate pirate name", (e) { badgename = pirateName(); });
    this.maleRadio = new RadioComp(this, "Male", "male", _male, name:"maleOrFemale")..onClick((_, comp){ male = true; });
    this.femaleRadio = new RadioComp(this, "Female", "female", _female, name:"maleOrFemale")..onClick((_, comp){ female = true; });
    
    addSetListener(const Symbol("badgename"), (NameBadge target, String old_value, String new_value){
      textInput.value = new_value;
      _div0.text = new_value;
    });
    addSetListener(const Symbol("male"), (NameBadge target, bool old_value, bool new_value){
      if (old_value == new_value) return;
      if (_male && _female) female = false;
    });
    addSetListener(const Symbol("female"), (NameBadge target, bool old_value, bool new_value){
      if (old_value == new_value) return;
      if (_female && _male) male = false;
    });
  }

  String pirateName() => (_female)?new PirateName.female().name:new PirateName.male().name;
  
  Element createElement() => addSubComponents0(newElem("div"));
  
  Element update() => addSubComponents0(initElem());
  
  Element addSubComponents0(Element elm) => addListeners(
      elm
        ..nodes.add(
            new Element.div()
              ..classes.add("entry")
              ..nodes.add(textInput.element)
              ..nodes.add(button.element)
              ..nodes.add(maleRadio.element)
              ..nodes.add(femaleRadio.element))
        ..nodes.add(
            new Element.div()
              ..classes.add("outer")
              ..nodes.add(new Element.div()..classes.add('boilerplate')..text = 'Hi! My name is')
              ..nodes.add(_initDiv0(new Element.div()..classes.add('name')..text = _badgename))));
}

Following codes are from original dart-tutorials-samples-Master/web/namebadge.
In polymer version, we need to write both dart program and corresponding polymer html files. So this dart part is short compared to my monitor based implementation, but if we compare with dart and html, the code size difference will become less.

import 'dart:html';
import 'dart:math';
import 'package:polymer/polymer.dart';

@CustomTag('name-badge')
class NameBadge extends PolymerElement with ObservableMixin {
  @observable String badgename = 'Bob';
  @observable bool female = true;
  @observable bool male = false;
    
  NameBadge() {
    bindProperty(this, const Symbol('female'), () {
        if (female) {
          male = false;
        }
        notifyProperty(this, const Symbol('name'));
      });
    bindProperty(this, const Symbol('male'), () {
        if (male) {
          female = false;
        }
        notifyProperty(this, const Symbol('name'));
      });
  }

  void pirateName(Event event, var detail, Node target) {
    if (female) {
      badgename = new PirateName.female().name;
    } else {
      badgename = new PirateName.male().name;
    }
  }
}

<polymer-element name="name-badge">
  <template>
    <style>
    .entry {
      padding-bottom: 20pt;
    }
    .outer {
      border: 2px solid brown;
      border-radius: 1em;
      background: red;
      font-size: 20pt;
      width: 12em;
      height: 7em;
      text-align: center;
    }
    .boilerplate {
      color: white;
      font-family: sans-serif;
      padding: 0.5em;
    }
    .name {
      color: black;
      background: white;
      font-family: "Marker Felt", cursive;
      font-size: 45pt;
      padding-top: 0.5em;
      padding-bottom: 0.3em;
    }
    </style>
    <div class="entry">
      <label for="newName">Enter New Name:</label>
      <input type="text" id="newName" value="{{badgename}}">
      <button on-click="pirateName">Generate pirate name</button>
      <input name="maleOrFemale" type="radio" value="male" checked={{male}}>Male
      <input name="maleOrFemale" type="radio" value="female" checked={{female}}>Female
    </div>
    <div class="outer">
      <div class="boilerplate">
        Hi! My name is
      </div>
      <div class="name">
        {{badgename}}
      </div>
    </div>
  </template>
  <script type="application/dart" src="name_badge_element.dart"></script>
</polymer-element>



Monday, October 14, 2013

Reflective Interceptor, Monitor in Dart (Part 1)

In GUI, persistent data programming, the interceptor for the field access is fundamental.
It can enhance the field access with additional behaviors.
It may trigger another action, or keep recording of some internal changes.
But these behaviors should be irrelevant for the caller of these getter/setter.

These things has been implemented as part of general AOP type injection mechanism like CGlib, asm etc, but these approach would not be possible in Dart,  and overkill for this limited range of interception (getter/setter).

Dart introduced @observable Observable mixin, but Observable class seems not general purpose class, but restricted to polymer html file.

So it is interesting to find an alternative way to support similar idea in more general setting,and apply it to my web-framework, gui-components library.

For this purpose, I created the Monitor class. for the name of the field annotation  to be monitored by Monitor class is 'Monitored'. This Monitor class can be used with mixin as well as subclassing, so any class can be changed to a Monitor class easily.

Thursday, October 10, 2013

JsonMapper and JPA

One area I haven't investigated for Jason Mapper is the case where entity  have general network structure rather than tree structure where no sharing of objects occurs

I need to check how dart handle such cases, for parse, stringify.
When I checked the dart:json code, there was a code to check repeated occurrence  (for the recent version of Json lib.)

for stringify, if it does not check, either the same entity will be serialized repeatedly, and worst, if there are circular references, it will go into infinite loop.

for parse, essentially original json string need to have some id information so that other part of json code can refer to it.
when json see new json id, it may not be loaded yet, so substituting the actual object must be delayed until that object is created. so the fromJson will be more complicated.(but it will be still simple if we push closure to assign to the entity field  with given parameter, and when object is created with given id, it should  retrieve those closures and apply them with the newly created entity object.)

There is a Java project called jackson, I guess it will handle such cases, and if there is a some notation to represent such reference in json, Dart's json mapper should follow the convention.

This is important, since json is good format to communicate Java and Dart.
 If both are following the same format, we can pass Dart's object to Java, and vice versa.
This may happen through Dart's VM and JVM message passing protocol similar to Dart's  javascript call mechanisms (although I don't know if such lib exist now), or through HTTP protocol using REST style API such as CouchDB.
Both approaches are relying on converting an entity object to json string.

The useful application of this approach will be the support of JPA(Java Persistence API) in Dart.
It will be achieved by a Restfull service in HTTP server implemented by Servlet where the mapped Java object are to be serialized to Json string(using Jackson).

Since building JPA like service in Dart will be not simple task, this will be a quickest  way. the main problem will be some performance issues for server side Dart's access to JPA.(For client side, if it directly calls this servlet service, there should be no performance issues.) 
But such loosely coupled architecture will allow to use separate CPU cores for JVM to run Java Servlet for JPA and Dart VM to run HTTP client(server) to consume(provide) JPA services from servlet, so it may not be so inefficient.

Also if we provide such restful service, it may be called directly from client side (browser).
We may consider an additional query for Restful API in which query condition can be expressed as a dart expression  like CouchDB (CouchDB uses JavaScript for such filter function).
This may require some dynamic loading of Dart code, so it may not be so straightforward, but it may be interesting to investigate the possibility.

For such a binding, there should be a tool to map between Dart and Java persistent classes.
One direction is to start from annotated Dart classes, and generate corresponding Java JPA entity classes with the same annotation.

The other direction is to start JPA Entity Java classes, and generate Dart annotated classes.

For this end, we should define Dart annotation classes corresponding to JPA annotation classes in Java.

JsonMapper application for CouchDB HTTP data handling

There is a neat application of JsonMapper for CouchDB HTTP data conversion. Couch DB is based on json data. So it is good application area to apply jsonMapper between entity object and serialized object. (Here we see an interesting combination of generic type. Namely by defining generic classes, we can create a flow to pass the entity type to the 'doc' field type at runtime. )

In order to extract entities list from json HTTP output, and do some none standard plumbing of attributes(id must be mapped from _id, rev is from _rev), we can use a single fromJson method.

we define following generic class:

class CouchDBFetchData<T> {
  List<CouchDBFetchRowData<T>> _rows;
  
  List<CouchDBFetchRowData<T>> get rows => _rows;
  void set rows( List<CouchDBFetchRowData<T>> rows) { _rows = rows; }
}

class CouchDBFetchRowData<T> {
  T _doc;
  T get doc => _doc;
  void set doc(T doc) { _doc = doc; }
}

This class does not define all json properties, but they are ignored when json is mapped to the entity object.
then we can apply fromJson to the json output. This is the all things we need to get the list of entities. But unfortunately, right now, since there is a bug (as mentioned in previous post), this will fails. but if it is fixed, this should work.

  Future> getAll() {
    return _getData("/$dbName/_all_docs?include_docs=true")
        .then( (json) {
          if (json != "") {
            CouchDBFetchData<T> data = jsonMapper.fromJson(
              new CouchDBFetchData<T>().runtimeType, json, attr_redirect_map: {'id':'_id', 'rev':'_rev'});
            return data.rows.fold([], (list, CouchDBFetchRowData<T> row)=>list..add(row.doc));
          } else {
            return new List();
          }
        }).catchError((_)=>[]);
  }

here is the original inefficient, inelegant approach.

  Future> getAll() {
    return _getData("/$dbName/_all_docs?include_docs=true")
        .then( (json) {
          if (json != "") {
            Map data = parse(json);
            for (var rowData in data["rows"]) {
              Map map = rowData["doc"];
              map['id'] = map['_id'];
              map.remove('_id');
              map['rev'] = map['_rev'];
              map.remove('_rev');
              String json1 = stringify(map); // ugry
              T t = jsonMapper.fromJson(modelType, json1);
              ts.add(t);
          } else {
            return new List();
          }
        }).catchError((_)=>[]);
  }

Tuesday, October 8, 2013

Dart's reflection details

Since I needed to manipulate reflection library to develop reflective json_mapper, I investigated some fine details of library. And found strange behavior.
So I asked to dart-misc mailing list.
Fortunately these question was answered by Gilad Bracha(main designer of Dart), so it became clear for what I should expect from Dart now.

Following style will return a mirror for generic class 'declaration'.

ClassMirror cmirror = reflectClass(new List<A>().runtimeType) 
(ClassMirror cmirror = reflectClass(List<A>)) // not supported yet

the above cmirror correspond to the generic class 'declaration', which is equivalent to none applied generic type, so the type including type variables in the generic class still contain type variables when it is inspected by reflection library. This is called a generic declaration.

So the strange things are even List<A> are applied generic class(type variable are substituted by A), but the  reflectClass returns List<T> class which does not corresponding to any runtime type of an object. I don't know why this is so designed, but this is confusing, and quite useless return result for most of the applications.

But as long as there are some way to return Type of applied generic class, it will be OK.
in fact, there is such a way, but it would be difficult to know without having told the difference!

This will return a mirror for applied generic class. (but not complete yet.. since there is a bug now)

ClassMirror cmirror = reflect(new List<A>()).type;
(ClassMirror cmirror = reflectType(List<A>)) // not supported yet

This cmirror is corresponding to applied generic class, and if we do print  cmirror.reflectedType, it prints List<A>.
So it seems OK, but in fact, I already knew this was not OK.

For json_mapper, we need to get field's type in order to process sub json string.

but if we run following code, the field types are none applied generic types. namely including type variables, not substituted by applied types.

ClassMirror cmirr = reflect(new List()).type;
    print(">>0@@ cmirr.reflectedType: ${cmirr.reflectedType}");
    cmirr.getters.forEach((k, MethodMirror md){
      Type tm = null;
      if (md.returnType is ClassMirror) {

        tm = (md.returnType as ClassMirror).reflectedType;
        print(">>1@@ k: ${k}, tm: ${tm}");
      } else if (md.returnType is TypeVariableMirror) {
        TypeVariableMirror tvmirr = md.returnType;
        print(">>2@@ tvmirr: ${tvmirr.runtimeType}");
      }
    });
output:

>> type: ChouchDBFetchData
>>0@@ cmirr.reflectedType: List
>>1@@ k: Symbol("length"), tm: int
>>1@@ k: Symbol("_capacity"), tm: int
>>2@@ tvmirr: _LocalTypeVariableMirrorImpl
>>2@@ tvmirr: _LocalTypeVariableMirrorImpl
>>2@@ tvmirr: _LocalTypeVariableMirrorImpl
>>1@@ k: Symbol("isEmpty"), tm: bool
>>1@@ k: Symbol("isNotEmpty"), tm: bool
>>1@@ k: Symbol("reversed"), tm: Iterable
>>1@@ k: Symbol("iterator"), tm: Iterator

So essentially right now, there is no way to handle generic class properly.
Fortunately, Gilad agreed this is bug, and google teams is now working on fixing this problem. Actually this is a big bug.

So maybe we will get better mirror lib soon.
Other related issues seems also addressed later release.

like reflectClass(typedef List<A>)(here typedef keyword is 'required' to avoid parsing issue..)
and 'invariant'  reflectType, which probablly it returns applied generic class.

here is his answers:
I've been meaning to update the mirror tutorial on our site, but because significant changes are coming soon, I'm delaying that just a tad longer. That said, those changes have nothing to do with this issue, so I'll try and answer your question here. Bear with me, as it is slightly non-obvious and requires some background.

(A)  ClassMirrors reflect both the classes of objects and class declarations. What's the difference between the class of an object and a class declaration?  Well, in a world without generics you can leave the distinction to philosophers, but once you have generics, you want to distinguish between the one declaration of the generic (i.e, the declaration in the source code) and its many invocations (such as List<String>, List<bool> etc.), aka parameterized types.  All the invocations share the same declaration.

This matters when you ask a class mirror for its methods, and then look up a method and ask for its return type. If the mirror is on List<int>, then the return type of the method #first will be int; if it is List<Element> it will be Element etc.  If ask the same question on a declaration, the return type is E, which is a type variable (and no actual object has a type variable as its type; the type variable is always bound to some specific type).

There is never an object whose type is a generic declaration. Hence there is no Type object that corresponds to a generic declaration, and so a mirror on generic declaration has no Type object associated with it. Which is why hasReflectedType on such a mirror returns false. If you still try and get the reflectedType, it throws. 

Hence the behavior you are seeing. 

Now you might ask why.  We could have reflectClass give you a mirror on the specific Type you passed in, and then the invariant you expected would hold. However, then we'd have a problem if you wanted to get at the declaration. If you wrote reflectClass(List) you might well expect the result to be a mirror on the declaration, but you'd be disappointed. Let's say we have a class 

class G<T> ...

In Dart, the identifier G, used without type arguments, always denotes G<dynamic>.  So you would not get a mirror on the declaration of G (or of List) but a mirror on a specific parameterized type (G<dynamic> or List<dynamic> as the case might be).

We decided to keep reflectClass for the declaration. If you want a mirror on a specific parameterized type, you can get it by reflecting on an instance and asking the instance mirror for its type

reflect(new List<A>()).type

we are planning on adding a function reflectType() that would always return a mirror on the specific Type object passed to it. The the invariant

reflectType(t).reflectedType == t

Dart's annotation

I refined the look and feel of sample app using Dart's annotation.

This feature is very useful for customizing a lot of thing without touching the code itself.
So there are quite a lot of area to use annotations.

The annotation mechanism of Dart is quit easy to use, it is also part of dart:mirrors. So in order to use this on browser, we still need to use my portable_mirror library(I extended the API for this).

The things I have done is:
  1. Table
    • remove id and rev column from table
    • change expenseType to type
       
  2. Form
    • disable id, rev text input
These are specified by annotation for the getter  in Expense class.
Also I fixed table so that it has max height and can use scroll.
So this GUI is now looks beter. but it will be useful to support more annotations to adjust look and feel such as ordering specification. location to put text etc.

class Expense  {
  ....
  
  @GUI_Table(invisible: true)
  @GUI_Form(disabled: true)
  String get id => _id;
  void set id(String i) { _id = i; }
  
  @GUI_Table(invisible: true)
  @GUI_Form(disabled: true)
  String get rev => _rev;
  void set rev(String value) { _rev = value; }
  
  @GUI_Table(label: "type")
  ExpenseType get expenseType => _type;
  void set expenseType(ExpenseType i) { _type = i; }
  
  ...
}

Sunday, October 6, 2013

Reflective JsonMapper (Part 3)

Originally I planed to use generics, but now it is better not to call it generic, but we call it reflective.
  
I completed the support of List(and Map) property in Entity class, and this works for both dynamic(with dart:mirrors lib for Dart VM) and static mode(for javascript).
But I haven't tested on javascript mode yet, but it should work. Also I haven't tested the map case. I will do it later.
This version was committed to Github.

Following is the sample code to show the support of List field in a class.

class A {
  int _i = 0;
  List<B> _bs = [];
  
  A(this._i, this._bs);
  factory A.create() => new A(111, []);
  
  int get i => _i;
  void set i(int ii) { _i == ii; }
  
  List<B> get bs => _bs;
  void set bs(List<B> bs) {_bs = bs; }
}

class B {
  String _s = 'zz';
  B(this._s);
  factory B.create() => new B('ss');
  String get s => _s;
  void set s(String ss) { _s == ss; }
}

test_simple_model() {
      A a = new A.create()..i = 10
        ..bs.add(new B.create()..s = "vvv")
        ..bs.add(new B.create()..s = "eee");
      
      String json = sampleJsonMapper.toJson(a);
      print(">>A@1 test_toJson json: ${json}");
      
      A a1 = sampleJsonMapper.fromJson(A, json);
      print(">>A@2 test_Json a1: ${a1}");
}

And the output of execution:
>>A@1 test_toJson json: {"i": 111,"bs": [{"s": "ss"},{"s": "ss"}]}
>> obj: Instance of 'A'
>>A@2 test_Json a1: Instance of 'A'
>> json: {"i": 10,"bs": [{"s": "ss"},{"s": "vv"}]}

Actually the support of generic type property was a bit difficult due to some confusing behavior of reflectedType property of ClassMirror. And some irreversible operation of types and  typeArguments behavior.

But by keeping type instead of extracting from ClassMirror, I could avoid the current restriction of Miror library. Probably Dart is still early stage, such mirror behavior should be refined.

Following are the problems I found:

1) why we cannot do followings:

var t1 = List<A>;
var cmirr = reflectClass(List<A>);

while we can do for none generic class:
car t = A;
var cmirr = reflectClass<A);

2) how can I create ClassMirror object which has reflectedType.
if we create CirrorClass through reflectClass(new List<B>().runtimeType),
it does not have reflectedType. but if we get ClassMirror from  bs of  A, it has a reflectedType. So there should be some way to create Mirror class which has reflectedType.

3) the reflectClass<List<A>) has all information to make cmirror to have reflectedType(since argumentType A is provided).
It should return ClassMirror with reflectedType.
I think this is very inconvenient behavior, and should be called a bug.

library dart_generics_test;

import 'dart:mirrors';

class A {
  int _i = 0;
  List<B> _bs = [];
  
  int get i => _i;
  void set i(int ii) { _i == ii; }
  
  List<B> get bs => _bs;
  void set bs(List<B> bs) {_bs = bs; }
}

class B {
  String _s = 'zz';
  
  String get s => _s;
  void set s(String ss) { _s == ss; }
}

test_generics() {
  {
    /*
    ClassMirror immir0 = reflectClass(List<B>); // <== this cannot be compiled!
    Type t0 = immir0.reflectedType;
    print(">> ${t0}");
    */
    
    // following code is to get a Type of List<B>, a work around to avoid above problem.  
    InstanceMirror immir = reflect(new List<B>());
    Type t = immir.type.reflectedType;
    print(">>1.1 ${t}");
    
    /*
    ClassMirror cmirr = reflectClass(t);
    Type t2 = cmirr.reflectedType; // here t2 == t, but it throws exception
    print(">>1.2 ${t2}");
    */
  /*
   * Unhandled exception:
Unsupported operation: Declarations of generics have no reflected type
#0      _LocalClassMirrorImpl.reflectedType (dart:mirrors-patch/mirrors_impl.dart:304:7)
#1      test_generics (file:///opt/dart-workspace/reflective_web_dev_kit/sample_app/bin/sample_json_mapper_test.dart:76:21)
#2      main (file:///opt/dart-workspace/reflective_web_dev_kit/sample_app/bin/sample_json_mapper_test.dart:81:16)
   * 
   */
  }

  {
    Type t1 = new B("nn").runtimeType;
    print(">>2.1 ${t1}");
  
    ClassMirror cmirr1 = reflectClass(t1);
    Type t2 = cmirr1.reflectedType; // this is ok
    print(">>2.1 ${t2}");
  }

  {
    Type t1 = new List<B>().runtimeType; // return List<B>
    print(">>3.1 t1: ${t1}");
  
    ClassMirror cmirr1 = reflectClass(t1);
    Type t2 = cmirr1.runtimeType; // return _LocalClassMirrorImpl
    print(">>3.2 t2: ${t2}"); 
    print(">>3.3 cmirr1.hasReflectedType: ${cmirr1.hasReflectedType}"); 
    
    Type t4 = cmirr1.reflectedType; // here it should be t4 == t0, but it throws exception
    print(">>3.3 t4: ${t4}");
  }

  {
    ClassMirror cmirr = reflectClass(A);
    cmirr.getters.forEach((k, MethodMirror md){
      Type tm = (md.returnType as ClassMirror).reflectedType; // this is OK
      print(">>4.1 k: ${k}, tm: ${tm}");
    });
  }
}

main() {
  test_generics();
}

Blogger tip: how to use pretty print

I did not like embedding dart code using quote.
So I a bit investigated to support pretty print in blogger.

Following is the way I found:

  •  open template HTML edit
    add following code just before </head> 
<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js"></script>
    • Blogger Template Designer->Adbanced->Add CSS

      Add following codes:
      pre {
      overflow: auto;
      width: 580px;
      
       white-space: pre-wrap;       /* css-3 */
       white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
       white-space: -pre-wrap;      /* Opera 4-6 */
       white-space: -o-pre-wrap;    /* Opera 7 */
       word-wrap: break-word;       /* Internet Explorer 5.5+ */
      }
      
      /* https://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css */
      
      .prettyprint {
          background: #EEE;
      }
      
      
    •  when you want to embed code, use HTML view, and put code snippets in:
      <pre class="prettyprint lang-dart">Code!</pre>
    https://code.google.com/p/google-code-prettify/wiki/GettingStarted

    http://google-code-prettify.googlecode.com/svn/trunk/README.html

    http://google-code-prettify.googlecode.com/svn/trunk/styles/index.html

    But there is an issue for <, >. they will be recognized as special characters(by html parser?), and enclosed parts are not shown. So if we have these characters, we need to replace them with &lt;, &gt; respectively(i.e, in Code).
    This should be handled by run_prettify.js though.

    GUI action design pattern

    The sample app(CRUDView) class is not so clean with respect to the implementation of how mouse action would trigger window state changes, like some button are disabled and the others are enabled etc.

    Each component class should not have to know anything except what they suppose to do, i.e, some state change.

    All the GUI action should be understood as state transition.
     if we append listener to each node's listener, that is still bad.

    the controlling logic is tightly associated with specific GUI action.
    But what the mouse action will change is the state and that state change is the reason for the logic of GUI change.

    so the logic should be centered around the state change.

    for instance, following code may describe the state transition of each mouse click for the buttons.

    state('a1')..>state('a2')['load'] = load
        ..>state('s3')['save'] = save;
    
    state('a2')..>state('a2')['clear'] = clear
        ..>state('s3')['edit'] = edit;
    

    That way, we see the real logic behind the GUI action. often such a  state is not explicitly expressed in the application code as in the current CRUDView code. and action methods are called from many places associated with buttons.
    That messy way should be avoided.


    GenericType spec in test code

    It is always useful if we have a good unit tests to understand the language spec in details. It is much easier to understand from concrete examples than hight level abstract and often ambiguous description.

    For dart mirror, the code API is not useful, and there are not much detailed explanation of mirror features, so I checked   /dart/tests/lib/mirrors/ folder.

    following test code is useful to understand mirror for generic classes.


    // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
    // for details. All rights reserved. Use of this source code is governed by a
    // BSD-style license that can be found in the LICENSE file.
    
    library test.type_arguments_test;
    
    import 'dart:mirrors';
    
    import 'package:expect/expect.dart';
    
    class A<T> {}
    class B extends A {}            // Same as class B extends A<dynamic>.
    class C extends A<num, int> {}  // Same as class C extends A<dynamic>.
    class D extends A<int> {}
    class E<S> extends A<S> {}
    class F<R> extends A<int> {}
    class G {}
    class H<A,B,C> {}
    
    typeParameters(mirror, parameterNames) {
      Expect.listEquals(parameterNames.map((n) => new Symbol(n)).toList(),
                        mirror.typeVariables.keys.toList());
    }
    
    typeArguments(mirror, argumentMirrors) {
      Expect.listEquals(argumentMirrors,
                        mirror.typeArguments.values.toList());
      if (!mirror.isOriginalDeclaration) {
        Expect.listEquals(mirror.typeVariables.keys.toList(),
                          mirror.typeArguments.keys.toList());
      }
    }
    
    main() {
      // Declarations.
      typeParameters(reflectClass(A), ['T']);
      typeParameters(reflectClass(B), []);
      typeParameters(reflectClass(C), []);
      typeParameters(reflectClass(D), []);
      typeParameters(reflectClass(E), ['S']);
      typeParameters(reflectClass(F), ['R']);
      typeParameters(reflectClass(G), []);
    
      typeArguments(reflectClass(A), []);
      typeArguments(reflectClass(B), []);
      typeArguments(reflectClass(C), []);
      typeArguments(reflectClass(D), []);
      typeArguments(reflectClass(E), []);
      typeArguments(reflectClass(F), []);
      typeArguments(reflectClass(G), []);
    
      Expect.isTrue(reflectClass(A).isOriginalDeclaration);
      Expect.isTrue(reflectClass(B).isOriginalDeclaration);
      Expect.isTrue(reflectClass(C).isOriginalDeclaration);
      Expect.isTrue(reflectClass(D).isOriginalDeclaration);
      Expect.isTrue(reflectClass(E).isOriginalDeclaration);
      Expect.isTrue(reflectClass(F).isOriginalDeclaration);
      Expect.isTrue(reflectClass(G).isOriginalDeclaration);
    
      Expect.equals(reflectClass(A), reflectClass(A).originalDeclaration);
      Expect.equals(reflectClass(B), reflectClass(B).originalDeclaration);
      Expect.equals(reflectClass(C), reflectClass(C).originalDeclaration);
      Expect.equals(reflectClass(D), reflectClass(D).originalDeclaration);
      Expect.equals(reflectClass(E), reflectClass(E).originalDeclaration);
      Expect.equals(reflectClass(F), reflectClass(F).originalDeclaration);
      Expect.equals(reflectClass(G), reflectClass(G).originalDeclaration);
    
      // Instantiations.
      typeParameters(reflect(new A<num>()).type, ['T']);
      typeParameters(reflect(new B<num>()).type, []);
      typeParameters(reflect(new C()).type, []);
      typeParameters(reflect(new D()).type, []);
      typeParameters(reflect(new E()).type, ['S']);
      typeParameters(reflect(new F<num>()).type, ['R']);
      typeParameters(reflect(new G()).type, []);
      typeParameters(reflect(new H()).type, ['A', 'B', 'C']);
    
      var numMirror = reflectClass(num);
      var dynamicMirror = currentMirrorSystem().dynamicType;
      typeArguments(reflect(new A<num>()).type, [numMirror]);
      typeArguments(reflect(new A<dynamic>()).type, [dynamicMirror]);
      typeArguments(reflect(new A()).type, [dynamicMirror]);
      typeArguments(reflect(new B()).type, []);
      typeArguments(reflect(new C()).type, []);
      typeArguments(reflect(new D()).type, []);
      typeArguments(reflect(new E<num>()).type, [numMirror]);
      typeArguments(reflect(new E<dynamic>()).type, [dynamicMirror]);
      typeArguments(reflect(new E()).type, [dynamicMirror]);
      typeArguments(reflect(new F<num>()).type, [numMirror]);
      typeArguments(reflect(new F<dynamic>()).type, [dynamicMirror]);
      typeArguments(reflect(new F()).type, [dynamicMirror]);
      typeArguments(reflect(new G()).type, []);
      typeArguments(reflect(new H<dynamic, num, dynamic>()).type,
          [dynamicMirror, numMirror, dynamicMirror]);
    
      Expect.isFalse(reflect(new A<num>()).type.isOriginalDeclaration);
      Expect.isTrue(reflect(new B()).type.isOriginalDeclaration);
      Expect.isTrue(reflect(new C()).type.isOriginalDeclaration);
      Expect.isTrue(reflect(new D()).type.isOriginalDeclaration);
      Expect.isFalse(reflect(new E<num>()).type.isOriginalDeclaration);
      Expect.isFalse(reflect(new F<num>()).type.isOriginalDeclaration);
      Expect.isTrue(reflect(new G()).type.isOriginalDeclaration);
      Expect.isFalse(reflect(new H()).type.isOriginalDeclaration);
    
      Expect.equals(reflectClass(A),
                    reflect(new A<num>()).type.originalDeclaration);
      Expect.equals(reflectClass(B),
                    reflect(new B()).type.originalDeclaration);
      Expect.equals(reflectClass(C),
                    reflect(new C()).type.originalDeclaration);
      Expect.equals(reflectClass(D),
                    reflect(new D()).type.originalDeclaration);
      Expect.equals(reflectClass(E),
                    reflect(new E<num>()).type.originalDeclaration);
      Expect.equals(reflectClass(F),
                    reflect(new F<num>()).type.originalDeclaration);
      Expect.equals(reflectClass(G),
                    reflect(new G()).type.originalDeclaration);
      Expect.equals(reflectClass(H),
                    reflect(new H()).type.originalDeclaration);
    
      Expect.notEquals(reflect(new A<num>()).type,
                       reflect(new A<num>()).type.originalDeclaration);
      Expect.equals(reflect(new B()).type,
                    reflect(new B()).type.originalDeclaration);
      Expect.equals(reflect(new C()).type,
                    reflect(new C()).type.originalDeclaration);
      Expect.equals(reflect(new D()).type,
                    reflect(new D()).type.originalDeclaration);
      Expect.notEquals(reflect(new E<num>()).type,
                       reflect(new E<num>()).type.originalDeclaration);
      Expect.notEquals(reflect(new F<num>()).type,
                       reflect(new F<num>()).type.originalDeclaration);
      Expect.equals(reflect(new G()).type,
                    reflect(new G()).type.originalDeclaration);
      Expect.notEquals(reflect(new H()).type,
                       reflect(new H()).type.originalDeclaration);
    
      // Library members are all uninstantaited generics or non-generics.
      currentMirrorSystem().libraries.values.forEach((libraryMirror) {
        libraryMirror.classes.values.forEach((classMirror) {
          // TODO(12282): Deal with generic typedefs.
          if (classMirror is! TypedefMirror) {
            Expect.isTrue(classMirror.isOriginalDeclaration);
            Expect.equals(classMirror, classMirror.originalDeclaration);
          }
        });
      });
    }
    

    Generic Class is not a first class citizen?

    I tried to complete fromJson implementation, a method to instantiate an object of given type from its serialized json string, then I found some interesting limitation of Dart language.
    I guess this is not planed feature, but something which are to be improved later.

    for instance, the support of getClass in Java is not supported in dart now. (this will be obj.type getter). but I read a proposal, this is going to be supported.

    there are two issues.

    if we have a function taking Type value as the argument,  like f(A), this works as expected. but we cannot write f(A<B>)!.
    also Type a = A<B> is not allowed.
    So in a sense, generic class is not a first class citizen in Dart now.

    Also similar, but more strange problem is following:

      InstanceMirror immir = reflect(new List<B>());
      Type t = immir.type.reflectedType;
      print(">> ${t}");
      ClassMirror mirr = reflectClass(t);
      print("2>> ${mirr.reflectedType}");
    

    Since we cannot use List<B>, we need to create this type by reflect(new List<B>()).type.reflectedType. and this will be shown as List<B>.
    but if we use this type to create ClassMirror, the getter call, mirr.reflectedType will cause runtime error.

    >> List<B>
    Unhandled exception:
    Unsupported operation: Declarations of generics have no reflected type
    #0      _LocalClassMirrorImpl.reflectedType (dart:mirrors-patch/mirrors_impl.dart:304:7)
    #1      test_generics (file:///opt/dart-workspace/reflective_web_dev_kit/sample_app/bin/sample_json_mapper_test.dart:77:21)
    #2      main (file:///opt/dart-workspace/reflective_web_dev_kit/sample_app/bin/sample_json_mapper_test.dart:82:16)
    

    This is actually not good for portable_mirror librray.
    Since creating Type through dart:mirrors library is not allows in javascript mode.

    For example, couchdb_client_dao(in browser side) need to convert json string of list to list of entity. So ideally, this should be parsed by jsonMapper's fromJson. and it requires type value in the first argument, e.g, fromJson(List<modelType>, json).

    This issue would not be limited to javascript mode. but it would also affect to the Dart VM mode.
    So in order to avoid this problem in DartVM mode(as well as JavaScript mode), it will be necessary to avoid using Type. Instead, it should always use IClassMirror.

    Although that may fix the jsonMapper, but this issue may influence in entire application
    So one approach is not to worry about the generic type case(including list/map), and wait until this mirror issue is fixed..

    Saturday, October 5, 2013

    Github: Reflective Web dev kit

    Since several components based on reflection approach are now integrated, and working fine,  I uploaded the Dart project to Github:

    https://github.com/calathus/reflective_web_dev_kit

    There are a few more things to do, but this is not bad timing to clean up the project structure and store it to github.

    here is the readme file:

    Reflective Web Dev Kit

    Overview

    The goal of this project is to create a small end2end sample application using component based approach. Dart's mirror library will be applied to several area of web application, GUI, Database Access, client/server communication. Thus the project is called 'reflective' web dev kit.
    See following blog site: http://dartathus.blogspot.com

    1. portable_mirror

    right now, darts:mirrors library cannot be used in javascript mode. So if we directly use this library, most of code cannot be run on browser. This lib provides a portable mirror API to support (small subset of) mirror features. There are two implementations for this API class. one depends on static classes, and the other depends on dart:mirror. No code changes are required to run application on javascripts mode or Dartium mode(using Dart VM).

    2. json_mapper

    json mapping based on mirror library. this automatically map json to corresponding entity instance

    3.couchdb

    dao api for couchdb based on mirror/json_mapper. this provides server side json_proxy, and client side couchdb dao library

    4. gui_component

    a framework to create web application using component based design, also table/form are implemented as generic class using mirror.

    5. sample_app

    This is a sample web application using these libraries. This web application supports CRUD operation using Table and Form.


    Thursday, October 3, 2013

    Generic Json Mapper(Part 2)

    In the previous post, I showed how to generate entity object from json string and type information.
    Although I have already written the reverse direction(generating json from entity object),  it was written from scratch(since it was simple), and I wanted to see how I can use dart:json library in a similar way.

    Then I found there is a class _JsonStringifier in json.dart in Dart sdk lib.
    But as the name shows, it is private class, so I cannot extend the class and override some of the methods. If it is possible, I can do the similar things.
     That was a bit of disappointment. Actually the class  should be changed to public class.

    By the way, I found Dartson was posted just 1 hour after I posted to Dartisans.
    I think Json is quite universal data structure in web application, and this kind of binding are very powerful tool.

    For the Dartson, I clone the project, and saw the code.
    It is well written, although it is not yet supporting for javascript mode usage, it seemed planed to support it.

    Essentially the main difference between our approaches is that  I took 'SAX' parser approach, and Dartson took DOM node approach. But right now, I just extended the library class, during the parsing it still creates maps, and uses the map to create an entity, then the map is immediately discarded.

    If we use this approach, such an intermediate map creation can be avoided. We can just use stack to push all the key, value objects.
    If we use such approach, it will be faster than Dartson.

    Since Dartson is actually using json library to create intermediate json object(consisting List, Map, primitive values), the parsing quality will be as good as dart json library.

    But Dartson seems not supporting irregular cases, like DateTime parsing/serialization, none Bean like classes where we need to call special factory/constructor(like ExpenseType).

    I think it is better to have an ability to adjust such exceptional cases, otherwise, the tool's applicability will be unnecessarily limited.

    //
    // entity(including list, map) stringifier
    //
    class EntityJsonStringifier extends _JsonStringifier {
      final ISpecialTypeMapHandler mapHandler;
      
      EntityJsonStringifier(this.mapHandler): super(null);
      
      String toJson(final obj, {StringSink output}) {
         this..sink = (output != null)?output:new StringBuffer()
        ..seen = [];
        stringifyValue(obj);
        return sink.toString();
      }
    
      // @Override
      void stringifyValue(final object) {
        if (!stringifyJsonValue(object)) {
          checkCycle(object);
          try {
            // if toJson is defined, it will be used.
            var customJson = object.toJson();
            if (!stringifyJsonValue(customJson)) {
              throw new JsonUnsupportedObjectError(object);
            }
          } catch (e) {
            // if toJson is not defined..
            if (!stringifyJsonValue(object)) {
              stringifyEntity(object);
            }
          }
          seen.removeLast();
        }
      }
      
      void stringifyEntity(final object) {
        // this require dirt:mirrors
        Type t = ClassMirrorFactory.getType(object);
        StringifierFun stringfier = mapHandler.stringifier(t);
        if (stringfier != null) {
          sink.write(stringfier(object));
          return;
        }
        
        //
        IClassMirror cmirror = ClassMirrorFactory.reflectClass(t);
        IInstanceMirror iimirr = cmirror.reflect(object);
        
        sink.write('{');
        int idx = 0;
        Map fmap = cmirror.fieldTypes;
        int lastIdx = fmap.length-1;
        fmap.forEach((k, IFieldType ft){
          sink.write('"${ft.name}": ');
          stringifyValue(iimirr.getField(k).value);
          sink.write((idx == lastIdx)?"":",");
          idx++;
        });
        sink.write('}');   
      }
    }
    
    

    Wednesday, October 2, 2013

    Generic Json Mapper(Part 1)

    I finished the json mapper implementation based on restricted (my) mirror library.
     The idea is by providing a target class information for a given Json string, it automatically creates the instance of the given class filled with the json data.

    Following is the sample codes:
     final Map<Type, ConstructorFun> entityCtors = {
        ExpenseType: (Map map)=>new ExpenseType(map['name'], map['code'])};

      final Map<Type, StringifierFun> stringifiers = {
        ExpenseType: (ExpenseType et) => '{"name": "${et.name}", "code": "${et.code}"}'};

    var jsonMapper = new JsonMapper(new SpecialTypeMapHandler(entityCtors, stringifiers: stringifiers));

    Expense e = new Expense.Default()
      ..id = "aaa"
      ..rev = "mmm"
      ..amount = 111
      ..date = new DateTime.now()
      ..detail = "asdjah"
      ..isClaimed = true
      ..expenseType = const ExpenseType("Hotel", "HT");

      String json = jsonMapper.toJson(obj);
      print(">> json: ${json}");
      Object obj = jsonMapper.fromJson(Expense, json);
      print(">> obj: ${obj}");
     
    I have not yet finished two cases, when attribute has List or Map value.
    I will do it later.
    But actually there are a bit of difficulty for these cases.
    In order to get List type's parameter type information, the current simple mirror API must be extended.
    And a list may contains an instance of the different subclass of List's element type.
    Map has a similar problem.
    Also even if the field type is defined as ordinary class, the actual instance may be of subclass of that class.
    So the current implementation is not covering such cases(yet).
    But if we know all the available classes at the run time, we may be able to uniquely identify appropriate class. anyway if there are some ambiguity, that is inherent to the given json itself.

    Also if we provide possible subclass information in the list value property as annotation, we can determine the class  efficiently.

    This code was actually done by extending existing dart:json library. so it covers quite rigorously the spec of json.(but in fact, it uses old version of json code. what is the difference between the latest and older code?

    This code does ot suport List, Map properties yet..
    library json_mapper_v1;
    
    import "dart:json";
    
    import 'package:portable_mirror/mirror_api_lib.dart';
    
    part 'src/dart_JsonStringifier.dart'; // this should be eliminated, dart:json should have pblic class JsonStringifier instead of _JsonStringifier
    
    typedef dynamic ConstructorFun(Map map);
    typedef dynamic StringifierFun(Object obj);
    typedef dynamic ConvertFun(Object obj);
    
    abstract class ISpecialTypeMapHandler {
      ConstructorFun entityCtor(Type type);
      StringifierFun stringifier(Type type);
      ConvertFun convert(Type type);
    }
    
    class SpecialTypeMapHandler implements ISpecialTypeMapHandler {
      final Map entityCtors;
      final Map _converts = {DateTime: (Object value)=>DateTime.parse(value)};
      final Map _stringifiers = {DateTime: (DateTime dt) => '"${dt.toString()}"'};
      
      SpecialTypeMapHandler(this.entityCtors, {Map converts, Map stringifiers}) {
        if (converts != null) _converts.addAll(converts);
        if (stringifiers != null) _stringifiers.addAll(stringifiers);
      }
      
      ConstructorFun entityCtor(Type type)=>(entityCtors == null)?null:entityCtors[type];
      ConvertFun convert(Type type)=>_converts[type];
      StringifierFun stringifier(Type type)=>_stringifiers[type];
    }
    
    //
    //
    //
    abstract class IJsonMapper {
      Object fromJson(Type modelType, String json);
      
      String toJson(final object, {StringSink output});
    }
    
    class JsonMapper implements IJsonMapper {
      EntityJsonParser parser;
      EntityJsonStringifier stringifier;
      ISpecialTypeMapHandler mapHandler;
      
      JsonMapper(this.mapHandler, {_Reviver reviver}) {
        parser = new EntityJsonParser(mapHandler, reviver: reviver);
        stringifier = new EntityJsonStringifier(mapHandler);
      }
    
      Object fromJson(Type modelType, String json) => parser.parse(modelType, json);
      String toJson(final object, {StringSink output}) => stringifier.toJson(object, output: output);
    }
    
    //
    // json parser
    //
    typedef _Reviver(var key, var value);
    
    class EntityJsonParser {
      //EntityBuildJsonListener listener; // TODO.. this would be effcient way..
      ISpecialTypeMapHandler mapHandler;
      _Reviver _reviver;
      
      EntityJsonParser(this.mapHandler, {_Reviver reviver}) {
        _reviver = reviver;
      }
      
      EntityBuildJsonListener getListener(Type modelType) =>(_reviver == null)?new EntityBuildJsonListener(mapHandler, modelType)
          :new EntityReviverJsonListener(mapHandler, modelType, _reviver);
    
      dynamic parse(Type modelType, String json) { 
        EntityBuildJsonListener listener =  getListener(modelType);
        new JsonParser(json, listener).parse();
        return listener.result;
      }
    }
    
    class EntityBuildJsonListener extends BuildJsonListener {
      final ISpecialTypeMapHandler mapHandler;
      IClassMirror currentCmirror = null;
      List cmirrorStack = [];
      
      EntityBuildJsonListener(this.mapHandler, Type modelType) {
        currentCmirror = ClassMirrorFactory.reflectClass(modelType);
      }
      
      /** Pushes the currently active container (and key, if a [Map]). */
      void pushContainer() {
        super.pushContainer();
        cmirrorStack.add(currentCmirror);
      }
    
      /** Pops the top container from the [stack], including a key if applicable. */
      void popContainer() {
        super.popContainer();
        currentCmirror = cmirrorStack.removeLast();
      }
      
      void beginObject() {
        super.beginObject();
        if (key != null) {
          IFieldType ft = currentCmirror.fieldTypes[new Symbol(key)];
          if (ft != null) {
            currentCmirror = ClassMirrorFactory.reflectClass(ft.type);
          } else {
            print('>> beginObject ${key}');
            currentCmirror = null;
          }
        }
      }
    
      void endObject() {
        Map map = currentContainer;
        ConstructorFun spCtor = mapHandler.entityCtor(currentCmirror.type);
        if (spCtor != null) {
          currentContainer = spCtor(map);
        } else {
          // Dart Beans
          IInstanceMirror imiror = currentCmirror.newInstance();
          currentCmirror.fieldTypes.forEach((_, IFieldType ft){
            ConstructorFun vCtor = mapHandler.convert(ft.type);
            var value = map[ft.name];
            imiror.getField(ft.symbol).value = (vCtor != null)?vCtor(value):value;
          });
          currentContainer = imiror.reflectee;
        }
        super.endObject();
      }
    }
    
    class EntityReviverJsonListener extends EntityBuildJsonListener {
      final _Reviver reviver;
      EntityReviverJsonListener(ISpecialTypeMapHandler mapHandler, Type modelType, reviver(key, value))
        : super(mapHandler, modelType), this.reviver = reviver;
    
      void arrayElement() {
        List list = currentContainer;
        value = reviver(list.length, value);
        super.arrayElement();
      }
    
      void propertyValue() {
        value = reviver(key, value);
        super.propertyValue();
      }
    
      get result {
        return reviver("", value);
      }
    }
    

    Tuesday, October 1, 2013

    Generic CouchDBDAO class

    I cleaned up the CouchDB handling code which essentially provides a http proxy for CouchDB. since CouchDB itself is providing Restful API, this may be seen as unnecessary duplication.



    But this is useful to avoid browser restriction(although there a some other techniques in Dart), and this can be used as a template to provide a restful API for other db.

    One interesting aspect of current implementation is such DAO class is designed as generic class.Compared to Hibernate/JPA, this approach is very simple.

    [web client]
    ICouchDbClientDAO<Expense> dao = new CouchDbClientDAO<Expense>(fromMap, fromJson, toJson);

        loadButtom = new ButtonComp(this, "Load", (_) {
          dao.fetchAll().then((List<Expense> es){ table.load(es);});
        });

        newButtom = new ButtonComp(this, "New", (_) {
          Expense e = form.create();
        });
       
        saveButtom = new ButtonComp(this, "Save", (_) {
          if (form.e != null) {
            Expense e = form.save();
            // this part is tricky..
            // since e is fill from InputText, when it is an empty text, it will assign "" instead of null..
            if (e.id == "") e.id = null;
            if (e.rev == "") e.rev = null;
            ((e.id == null)?dao.insert(e):dao.update(e)).then((Expense e0){
              e.id = e0.id;
              e.rev = e0.rev;
              table.addOrUpdate(e);
            });
          }
        });
       
        deleteButtom = new ButtonComp(this, "Delete", (_) {
          Expense e = form.e;
          if (e != null) {
            dao.delete(e).then((ok){
              if (ok) {
                form.delete();
                table.delete(e);
              }
            });
          }
        });
    Here, the argument of CouchDbClientDAO's constructor takes fromMap, fromJson, toJson. This is required since I have not provided Json binding library yet, these functions must be defined manually for each entity classes(e.g, Expense).

    [server]
    void main() {

      // register reflection factory
      initClassMirrorFactory();

      CouchDbDAO<Expense> couchDbDAO = new CouchDbDAO<Expense>(couchdb_host, couchdb_port, dbName, fromMap, toJson);
     
      CouchDbHttpServer server = new CouchDbHttpServer(couchDbDAO, fromJson, toJson);
     
      server.startHttpServer(http_server_host, http_server_port);
    }
    No other code are required to make such entity class persistent.