Ext.data.CSV = Ext.extend(Ext.data.Config, { v: undefined, // array of change stamps constructor: function(config,callback,scope) { var changed= false; if (config) { config.config_id= 'csv'; Ext.data.CSV.superclass.constructor.call(this, config); if (config.v) { this.v= []; this.do_add(config.v); } } if (this.v===undefined) { this.v= []; changed= true; } this.writeAndCallback(changed,callback,scope); }, add: function(x,callback,scope) { var changed= this.do_add(x); this.writeAndCallback(changed,callback,scope); return this; // JCM should force use of callback? }, get: function(cs) { return this.v[cs.r]; }, setReplicaNumber: function(replica_number,callback,scope) { this.addReplicaNumbers([replica_number],callback,scope); }, addReplicaNumbers: function(x,callback,scope) { var t= []; if (x instanceof Array) { t= Ext.data.array.collect(x,function(r){return this.do_add(new Ext.data.CS({r:r}));},this); } else if (x instanceof Ext.data.CSV) { t= Ext.data.array.collect(x.v,function(cs){return this.do_add(new Ext.data.CS({r:cs.r}));},this); } var changed= Ext.data.array.includes(t,true); this.writeAndCallback(changed,callback,scope); }, do_add: function(x) { // CSV, CS, '1-2-3', [x] var changed= false; if (x instanceof Ext.data.CSV) { var t= Ext.data.array.collect(x.v,this.do_add,this); changed= Ext.data.array.includes(t,true); } else if (x instanceof Ext.data.CS) { var r= x.r; var t= this.v[r]; if (!t || x.greaterThan(t)) { this.v[r]= new Ext.data.CS({r:x.r,t:x.t,s:x.s}); changed= true; } } else if (typeof x == 'string' || x instanceof String) { changed= this.do_add(new Ext.data.CS(x)); } else if (x instanceof Array) { var t= Ext.data.array.collect(x,this.do_add,this); changed= Ext.data.array.includes(t,true); } else { throw "Error - CSV - do_add - Unknown type: "+(typeof x)+": "+x; } return changed; }, changeReplicaNumber: function(old_replica_number,new_replica_number,callback,scope) { var t= this.v[old_replica_number]; var changed= false; if (t) { t.r= new_replica_number; this.v[old_replica_number]= undefined; this.v[new_replica_number]= t; changed= true; } this.writeAndCallback(changed,function(){ callback.call(scope,this,changed); },this); }, isEmpty: function() { return this.v.length<1; }, maxChangeStamp: function() { if (!this.isEmpty()) { var r= new Ext.data.CS(); this.v.forEach(function(cs){ var t= new Ext.data.CS({t:cs.t,s:cs.s}); r= (t.greaterThan(r) ? cs : r); },this); return r; } }, dominates: function(x) { return Ext.data.array.any(this.compare(x),function(i){ return i>0; }); }, equals: function(x) { return Ext.data.array.all(this.compare(x),function(i){ return i===0; }); }, compare: function(x) { var i, cs, r; if (x instanceof Ext.data.CS) { cs= this.get(x); return [cs ? cs.compare(x) : -1]; } else if (x instanceof Ext.data.CSV) { r= []; for(i in this.v) { cs= this.v[i]; if (cs instanceof Ext.data.CS) { var cs2= x.get(cs); r.push(cs2 ? cs.compare(cs2) : 1); } } return r; } else { throw "Error - CSV - compare - Unknown type: "+(typeof x)+": "+x; } return [-1]; }, forEach: function(fn,scope) { this.v.forEach(fn,scope||this); }, encode: function() { // for the wire return Ext.data.array.collect(this.v,function(){ // JCM can we safely ignore replicas with CS of 0... except for the highest known replica number... return this.to_s(); }); }, decode: function(x) { // from the wire this.do_add(x); return this; }, to_s: function(indent) { var r= "CSV: "; this.v.forEach(function(cs){ r+= cs.to_s()+", "; },this); return r; }, as_data: function() { // for the disk var data= { v: Ext.data.array.collect(this.v,function(){return this.to_s();}) }; data[Ext.data.SyncModel.MODEL]= 'Ext.data.CSV'; return Ext.data.CSV.superclass.as_data.call(this, data); } });