mongo-dart / lib / objectory / PersistentObject.dart

// noSuchMethod() borrowed from Chris Buckett (
interface PersistentObject{
  noSuchMethod(String function_name, List args);
  void setProperty(String property, value);
  void init();
  String get type();
  void clearDirtyStatus();
  Future fetchLink(String property);
  Future fetchLinks();
  bool isRoot();
  Map map;
abstract class PersistentObjectBase extends MapProxy implements PersistentObject{  
  bool setupMode;
  Set<String> dirtyFields;
    if (isRoot()){
      map["_id"] = null;
    dirtyFields = new Set<String>();
  void setDirty(String fieldName){
    if (dirtyFields === null){
void clearDirtyStatus(){
  onValueChanging(String fieldName, newValue){
    return !dirtyFields.isEmpty();
  noSuchMethod(String function_name, List args) {
    ClassSchema schema = objectory.getSchema(type);
    if (schema === null){
      throw "Class $type have not been registered in Objectory";
    if (args.length == 0 && function_name.startsWith("get:")) {
      //synthetic getter
      var property = function_name.replaceFirst("get:", "");
      if ( {
        return this[property];
        super.noSuchMethod(function_name, args);
    else if (args.length == 1 && function_name.startsWith("set:")) {
      //synthetic setter
      var value = args[0];
      var property = function_name.replaceFirst("set:", "");      
      if ( {
        if (schema.links !== null){
          if (schema.links.containsKey(property)){
            if ( === null){
              throw "Error setting link property $property. Link object must have not null id";
            value =;
        onValueChanging(property, value);
        this[property] = value;
        if (value is InnerPersistentObject){
          value.pathToMe = property;
          value.parent = this;
        return this[property];
      else {       
        super.noSuchMethod(function_name, args);
    //if we get here, then we've not found it - throw.
    super.noSuchMethod(function_name, args);
  void setProperty(String property, value){
  Dynamic get(String property){
    return noSuchMethod('get:$property',[]);
  String toString()=>"$type($map)";
  void init(){}  
  abstract String get type();  
  Future<PersistentObject> fetchLink(String property, [Map links]){
    var completer = new Completer<PersistentObject>();
    if (links === null){
      links = objectory.getSchema(type).links;
    if (links === null || !links.containsKey(property)){
      throw "Link $property is not registered on class $type";
    var value = map[property];    
    if (value !== null){
        map[property] = res;
    return completer.future;
  Future fetchLinks(){
    var links = objectory.getSchema(type).links;
    if (links === null ){
      throw "Links are not registered on class $type";
    var futures = new List<Future>();
    for (var link in links.getKeys()){
    return Futures.wait(futures);

abstract class RootPersistentObject extends PersistentObjectBase{
   ObjectId id;
   bool isRoot()=>true;
abstract class InnerPersistentObject extends PersistentObjectBase{
  PersistentObject parent;
  String pathToMe;
  bool isRoot()=>false;
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.