Author: jmorliaguet
Date: Sat Feb  4 12:22:35 2006
New Revision: 2281

Modified:
   cpsskins/branches/jmo-perspectives/ui/framework/cpsskins.js
Log:

- saving work:

  - models now have their own schema based on the initial data present in the
  model.

  - added low-level read / write / merge functions that are responsible for
    protecting the model against data corruption.

    - it is impossible for data setter to modify the type of the data fields

    - new fields cannot be added once the model has been instanciated.

  this makes it possible to combine models / storages while preserving the
  data structures of each model.




Modified: cpsskins/branches/jmo-perspectives/ui/framework/cpsskins.js
==============================================================================
--- cpsskins/branches/jmo-perspectives/ui/framework/cpsskins.js (original)
+++ cpsskins/branches/jmo-perspectives/ui/framework/cpsskins.js Sat Feb  4 
12:22:35 2006
@@ -617,13 +617,16 @@
   initialize: function(node, def) {
     this.node = this.node;
     this.def = def;
+    // set the schema
+    this.schema = this._setSchema();
     // set the storage adapter
-    this._setStorageAdapter();
+    this.storage = this._setStorageAdapter();
   },
 
+  // high-level I/O
   getData: function() {
     this.storage.requestData(); /* asynchronous call */
-    return this.def.data;
+    return this.read();
   },
 
   setData: function(data) {
@@ -632,8 +635,34 @@
 
   // TODO: to rewrite: this might not work if called asynchronously.
   updateData: function(data) {
-    Object.extend(data, this.def.data || new Object());
-    this.setData(data);
+    var current_data = this.def.data || new Object();
+    new_data = $H(current_data).merge(data);
+    this.setData(new_data);
+  },
+
+  // low-level I/O
+  read: function() {
+    return this.def.data;
+  },
+
+  write: function(data) {
+    // filter out fields with the wrong data type
+    var schema = this.schema;
+    var filtered_data = new Object();
+    this.schema.each(function(f) {
+      var field = f[0];
+      var value = data[field];
+      if (value != null && typeof value == f[1]) {
+        filtered_data[field] = value;
+      }
+    });
+    this.def.data = filtered_data;
+  },
+
+  merge: function(data) {
+    var current_data = this.read();
+    var new_data = $H(current_data).merge(data);
+    this.write(new_data);
   },
 
   addObserver: function(view) {
@@ -655,13 +684,23 @@
     CPSSkins.unsubscribe('modified', {'subscriber': view, 'target': model});
   },
 
+  /* Private API */
+  _setSchema: function() {
+    var initial_data = this.def.data;
+    var schema = $H({});
+    $H(initial_data).each(function(f) {
+      var field = f[0];
+      var value = f[1];
+      schema[field] = typeof value;
+    });
+    return schema;
+  },
+
   _setStorageAdapter: function() {
     var storage_def = this.def.storage;
     if (!storage_def) {
       storage_def = {"type": "volatile"};
     }
-    this.storage = Storages[storage_def.type](this);
-
     var model = this;
     // the model reacts to events on the storage and notifies observers
     CPSSkins.registerEventHandler('stored', model, function(event) {
@@ -669,7 +708,7 @@
     });
 
     CPSSkins.subscribe('stored', {'subscriber': model, 'target': 
this.storage});
-
+    return Storages[storage_def.type](this);
   }
 
 }
@@ -721,31 +760,33 @@
 
   setup: function() {
     var models = $A([]);
+    var storage = this;
     $A(this.model.def.storage.partitions).each(function(p) {
-      models.push(CPSSkins.getModelById(p));
+      var model = CPSSkins.getModelById(p);
+      models.push(model);
+      CPSSkins.subscribe('stored',
+        {'subscriber': storage, 'target': model.storage}
+      );
     });
     this.models = models;
+
+    // TODO: add a handler that will data from the different storages.
+    //  var data = m.read();
+    //  model.merge(data);
+
   },
 
   requestData: function() {
     var model = this.model;
     $A(this.models).each(function(m) {
       m.storage.requestData();
-      Object.extend(model.def.data, m.def.data)
     });
   },
 
   storeData: function(data) {
     var model = this.model;
     $A(this.models).each(function(m) {
-      var partition_data = m.def.data;
-      $H(data).each(function(d) {
-        var key = d[0];
-        if (partition_data[key]) {
-          partition_data[key] = data[key];
-        }
-      });
-      m.storage.storeData(partition_data);
+      m.storage.storeData(data);
     });
   }
 });
@@ -760,7 +801,7 @@
 
   storeData: function(data) {
     /* Store the data directly */
-    this.model.def.data = data;
+    this.model.write(data);
     CPSSkins.notify('stored', this);
   }
 
@@ -778,7 +819,7 @@
     new Ajax.Request(url, {
       onComplete: function(req) {
         var data = JSON.parse(req.responseText);
-        model.def.data = data;
+        model.write(data);
         CPSSkins.notify('stored', storage);
       }
     });
@@ -797,7 +838,7 @@
         }).toQueryString(),
       onComplete: function(req) {
         var data = JSON.parse(req.responseText);
-        model.def.data = data;
+        model.write(data);
         CPSSkins.notify('stored', storage);
       }
     });
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to