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