Commits

vadimtsushko committed af4ea1f

11

Comments (0)

Files changed (10)

lib/objectory/.children

+WebsocketClient.dart
+objectory_server.dart
+ObjectoryLib_vm.dart
+ObjectoryLib_ws.dart

lib/objectory/.project

+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>objectory</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.google.dart.tools.core.dartBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.google.dart.tools.core.dartNature</nature>
+	</natures>
+</projectDescription>

lib/objectory/Objectory.dart

 interface Objectory{  
   void registerClass(ClassSchema schema);
   PersistentObject newInstance(String className);
+  PersistentObject map2Object(String className, Map map);  
   Future<PersistentObject> findOne(String className,[Map selector]);
   Future<List<PersistentObject>> find(String className,[Map selector]);
   void save(PersistentObject persistentObject);
   void remove(PersistentObject persistentObject);
-  Future<bool> open(String database, [String url]);
+  Future<bool> open([String database, String url]);
   Future<bool> dropDb();
   ClassSchema getSchema(String className);
 }
     throw "Class $className have not been registered in Objectory";
   }
   PersistentObject map2Object(String className, Map map){
-    PersistentObject result = newInstance(className);
+    var result = newInstance(className);
     result.map = map;
     if (result.isRoot()){
       result.id = map["_id"];    
       //  print(property);
         ObjectId linkId = map[property];
         if (linkId !== null){
-          PersistentObject link = newInstance(linkClass);
+          RootPersistentObject link = newInstance(linkClass);
           link.id = linkId;
           result.setProperty(property,link);
           result.clearDirtyStatus();

lib/objectory/ObjectoryDirectConnectionImpl.dart

 class ObjectoryDirectConnectionImpl extends ObjectorySingleton{
   ObjectoryDirectConnectionImpl._internal():super._internal();
   Db db;
-  Future<bool> open(String database, [String url]){
+  Future<bool> open([String database, String url]){
     db = new Db(database);
     return db.open();
   }
-  void save(PersistentObject persistentObject){
-    db.collection(persistentObject.type).save(persistentObject);
+  void save(RootPersistentObject persistentObject){
+    db.collection(persistentObject.type).save(persistentObject.map);
     persistentObject.id = persistentObject["_id"];
   }
-  void remove(PersistentObject persistentObject){
+  void remove(RootPersistentObject persistentObject){
     if (persistentObject.id === null){
       return;
     }
     db.collection(className)
       .find(selector)
       .each((map){
-        PersistentObject obj = objectory.map2Object(className,map);
+        RootPersistentObject obj = objectory.map2Object(className,map);
         result.add(obj);
       }).then((_) => completer.complete(result));
     return completer.future;  

lib/objectory/ObjectoryLib_ws.dart

+#library("objectory");
+#import("dart:io");
+#import("../bson/bson.dart");
+#source("PersistentObject.dart");
+#source("Objectory.dart");
+#source("ObjectoryWebSocketImpl.dart");
+#source("../helpers/SelectorBuilder.dart");
+#source("..//helpers/MapProxy.dart");

lib/objectory/ObjectoryWebSocketImpl.dart

+Objectory get objectory() => new ObjectorySingleton._singleton();
+abstract class ObjectorySingleton extends ObjectoryBaseImpl{
+  static Objectory _objectory;
+  ObjectorySingleton._internal();
+  factory ObjectorySingleton._singleton(){
+    if (_objectory === null){
+      _objectory = new ObjectoryWebSocketImpl._internal();
+    }
+    return _objectory;
+  }
+}
+class ObjectoryWebSocketImpl extends ObjectorySingleton{
+  ObjectoryWebSocketImpl._internal():super._internal();
+  WebSocket webSocket;
+  String socketId; 
+  Completer onMessageCompleter;
+  Future<bool> open([String database, String url]){
+    Completer completer = new Completer();    
+    if (database !== null){
+      throw "Database paramater is not supported in WebSocket objectory implementation";
+    }
+    if (url === null){
+      throw "Url paramater is mandatory in WebSocket objectory implementation";
+    }
+    webSocket = new WebSocket(url);
+    onMessageCompleter = new Completer();
+    webSocket.onopen = (){
+      webSocket.send("Objectory opened");    
+      completer.complete(true);          
+      webSocket.onmessage = processMessage;
+    };        
+    return completer.future;    
+  }
+  Future get onMessageFuture() => onMessageCompleter.future;
+  void processMessage(message){
+    var data = message.data;
+    print("in process message $data");
+    if (data is String){
+      socketId = data;
+      print("socketId  $socketId");
+    }
+    else{    
+      Binary buffer = new Binary.from(data);    
+      BsonMap command = new BsonMap(null);
+      command.unpackValue(buffer);
+      print(command.data);    
+    }
+    onMessageCompleter.complete(true);
+  }  
+  Binary sendMessage(String command, Map obj, [String collecion]){
+    Map map = {};
+    map["command"] = command;
+    map["object"] = obj;
+    map["socketId"] = socketId;
+    BsonMap bmap = new BsonMap(map);
+    Binary message = new Binary(bmap.byteLength());
+    bmap.packValue(message);
+    webSocket.send(message.byteList);        
+  }
+  void save(RootPersistentObject persistentObject){    
+    String command = 'update';
+    if (persistentObject.id === null){
+       command = 'insert';
+       persistentObject.id = new ObjectId();
+       persistentObject.map["_id"] = persistentObject.id;
+    }
+    sendMessage(command,persistentObject.map,persistentObject.type);
+  }
+  void remove(RootPersistentObject persistentObject){
+
+    if (persistentObject.id === null){
+      return;
+    }
+    sendMessage("remove",{"_id":persistentObject.id},persistentObject.type);
+  }
+/*  Future<List<PersistentObject>> find(String className,[Map selector]){
+    Completer completer = new Completer();
+    List<PersistentObject> result = new List<PersistentObject>();
+    db.collection(className)
+      .find(selector)
+      .each((map){
+        RootPersistentObject obj = objectory.map2Object(className,map);
+        result.add(obj);
+      }).then((_) => completer.complete(result));
+    return completer.future;  
+  }
+  Future<PersistentObject> findOne(String className,[Map selector]){
+    Completer completer = new Completer();    
+    db.collection(className)
+      .findOne(selector)
+      .then((map){              
+        PersistentObject obj = objectory.map2Object(className,map);
+        completer.complete(obj);
+      });
+    return completer.future;  
+  }
+  
+  Future<bool> dropDb(){
+    db.drop();
+  }
+*/  
+}

lib/objectory/PersistentObject.dart

   void clearDirtyStatus();
   Future fetchLink(String property);
   Future fetchLinks();
+  bool isRoot();
+  Map map;
 }
 abstract class PersistentObjectBase extends MapProxy implements PersistentObject{  
   bool setupMode;
     noSuchMethod('set:$property',[value]);
   }
   Dynamic get(String property){
-    return noSuchMethod('get:$property');
+    return noSuchMethod('get:$property',[]);
   }  
   String toString()=>"$type($map)";
   void init(){}  
-  abstract String get type();
-  abstract bool isRoot();
+  abstract String get type();  
   Future<PersistentObject> fetchLink(String property, [Map links]){
     var completer = new Completer<PersistentObject>();
     if (links === null){

lib/objectory/WebsocketClient.dart

+#import("dart:io");
+
+void main() {  
+  WebSocket webSocket;
+  webSocket = new WebSocket("ws://localhost:8080/");
+  webSocket.onopen = (){
+    webSocket.send("Objectory opened");
+    webSocket.send([123,234,23,34,45]);
+    webSocket.close(123,"Normal closing");
+  };
+}

lib/objectory/objectory_server.dart

+#import('dart:io');
+#import("../mongo.dart");
+#import("../bson/bson.dart");
+
+Map<String, String> contentTypes = const {
+  "html": "text/html; charset=UTF-8",
+  "dart": "application/dart",
+  "js": "application/javascript", 
+};
+
+List<WebSocketConnection> connections;
+void processMessage(message){
+  print("in process message $message");
+  if (message is String){
+    print(message);    
+  }
+  else{    
+    Binary buffer = new Binary.from(message);    
+    BsonMap command = new BsonMap(null);
+    command.unpackValue(buffer);
+    print(command.data);    
+  }
+}
+void main() {
+  connections = new List();
+  
+  WebSocketHandler wsHandler = new WebSocketHandler();
+  wsHandler.onOpen = (WebSocketConnection conn) {
+    print("Connection opened. Connections total: ${connections.length}");
+    connections.add(conn);    
+    conn.onClosed = (a, b) => removeConnection(conn);
+    conn.onError = (_) => removeConnection(conn);
+    conn.send("234234234");    
+    conn.onMessage = processMessage;
+    
+  };
+
+  HttpServer server = new HttpServer();
+  server.addRequestHandler((_) => true, wsHandler.onRequest);   
+
+  server.listen("127.0.0.1", 8080);  
+}
+void removeConnection(WebSocketConnection conn) {
+  int index = connections.indexOf(conn);
+  if (index > -1) {
+    connections.removeRange(index, 1);
+  }
+}

tests/objectory/ObjectoryImplWsTest.dart

+#library("ObjectoryWS");
+#import("../../lib/objectory/ObjectoryLib_ws.dart");
+#import("../../lib/bson/bson.dart");
+#import('../../third_party/testing/unittest/unittest_vm.dart');
+#source("DomainModel.dart");
+Future<bool> setUpObjectory(){
+  var res = new Completer();
+//  objectory.clearFactories();
+  objectory.open(url:"ws://localhost:8080").then((_){    
+//    objectory.dropDb();
+    print("I'm here");
+    registerClasses();
+    res.complete(true);
+  });    
+  return res.future;
+}
+void testInsertionAndUpdate(){
+  Author author = new Author();  
+  author.name = 'Dan';
+  author.age = 3;
+  author.email = 'who@cares.net';  
+  objectory.save(author); // First insert;
+  author.age = 4;
+  objectory.save(author); // Then update;
+  objectory.find('Author').then((coll){
+    expect(coll.length).equals(1);
+    Author authFromMongo = coll[0];
+    expect(authFromMongo.age).equals(4);    
+    callbackDone();
+  });
+}
+testNewInstanceMethod(){
+  Author author = objectory.newInstance('Author');
+  expect(author is Author).isTrue();
+}
+testMap2ObjectMethod(){
+  Map map = {
+    "name": "Vadim",
+    "age": 300,
+    "email": "nobody@know.it"};
+  Author author = objectory.map2Object("Author",map);
+  // Not converted to upperCase because setter has not been invoked
+  expect(author.name).equals("Vadim"); 
+  expect(author.age).equals(300);
+  expect(author.email).equals("nobody@know.it");
+  map = {
+    "streetName": "333",
+    "cityName": "44444"
+    };
+  Address address = objectory.map2Object("Address",map);  
+  expect(address.cityName).equals("44444");   
+}
+testCompoundObject(){
+  Person person = new Person();  
+  person.address.cityName = 'Tyumen';
+  person.address.streetName = 'Elm';  
+  person.firstName = 'Dick';
+  objectory.save(person); ;
+  objectory.findOne('Person',query().id(person.id)).then((savedPerson){
+    expect(savedPerson.firstName).equals('Dick');
+    expect(savedPerson.address.streetName).equals('Elm');
+    expect(savedPerson.address.cityName).equals('Tyumen');
+    callbackDone();
+  });
+}
+testObjectWithLinks(){
+  Person father = new Person();  
+  father.firstName = 'Father';
+  objectory.save(father);
+  Person son = new Person();  
+  son.firstName = 'Son';
+  son.father = father;
+  objectory.save(son);  
+  objectory.findOne('Person',query().id(son.id)).then((sonFromObjectory){
+    // Links must be fetched before use.
+    Expect.throws(()=>sonFromObjectory.father.firstName);
+    expect(sonFromObjectory.mother).equals(null);
+    sonFromObjectory.fetchLinks().then((_){
+      expect(sonFromObjectory.father.firstName).equals("Father");
+      expect(sonFromObjectory.mother).equals(null);
+      callbackDone();
+    });    
+  });
+}
+main(){  
+  setUpObjectory().then((_) {    
+    objectory.onMessageFuture.then((_){
+      print("Now here ${objectory.socketId}");
+      objectory.save(new Person());    
+      Person person = new Person();
+      person.id = new ObjectId();
+      objectory.remove(person);
+//    print("End ${objectory.webSocket.bufferedAmount}");
+      objectory.webSocket.send("closing");
+      objectory.webSocket.close(123,"Normal closing");      
+      return;
+      });
+    return;
+    group("ObjectoryVM", ()  {
+      asyncTest("testCompoundObject",1,testCompoundObject);   
+      asyncTest("testInsertionAndUpdate",1,testInsertionAndUpdate);         
+      asyncTest("testObjectWithLinks",1,testObjectWithLinks);               
+      test("testNewInstanceMethod",testNewInstanceMethod);   
+      test("testMap2ObjectMethod",testMap2ObjectMethod);       
+    });  
+  });    
+}