/*
	Copyright (c) 2004-2009, The Dojo Foundation All Rights Reserved.
	Available via Academic Free License >= 2.1 OR the modified BSD license.
	see: http://dojotoolkit.org/license for details
*/


if(!dojo._hasResource["dojo.data.ItemFileWriteStore"]){
dojo._hasResource["dojo.data.ItemFileWriteStore"]=true;
dojo.provide("dojo.data.ItemFileWriteStore");
dojo.require("dojo.data.ItemFileReadStore");
dojo.declare("dojo.data.ItemFileWriteStore",dojo.data.ItemFileReadStore,{constructor:function(_1){
this._features["dojo.data.api.Write"]=true;
this._features["dojo.data.api.Notification"]=true;
this._pending={_newItems:{},_modifiedItems:{},_deletedItems:{}};
if(!this._datatypeMap["Date"].serialize){
this._datatypeMap["Date"].serialize=function(_2){
return dojo.date.stamp.toISOString(_2,{zulu:true});
};
}
if(_1&&(_1.referenceIntegrity===false)){
this.referenceIntegrity=false;
}
this._saveInProgress=false;
},referenceIntegrity:true,_assert:function(_3){
if(!_3){
throw new Error("assertion failed in ItemFileWriteStore");
}
},_getIdentifierAttribute:function(){
var _4=this.getFeatures()["dojo.data.api.Identity"];
return _4;
},newItem:function(_5,_6){
this._assert(!this._saveInProgress);
if(!this._loadFinished){
this._forceLoad();
}
if(typeof _5!="object"&&typeof _5!="undefined"){
throw new Error("newItem() was passed something other than an object");
}
var _7=null;
var _8=this._getIdentifierAttribute();
if(_8===Number){
_7=this._arrayOfAllItems.length;
}else{
_7=_5[_8];
if(typeof _7==="undefined"){
throw new Error("newItem() was not passed an identity for the new item");
}
if(dojo.isArray(_7)){
throw new Error("newItem() was not passed an single-valued identity");
}
}
if(this._itemsByIdentity){
this._assert(typeof this._itemsByIdentity[_7]==="undefined");
}
this._assert(typeof this._pending._newItems[_7]==="undefined");
this._assert(typeof this._pending._deletedItems[_7]==="undefined");
var _9={};
_9[this._storeRefPropName]=this;
_9[this._itemNumPropName]=this._arrayOfAllItems.length;
if(this._itemsByIdentity){
this._itemsByIdentity[_7]=_9;
_9[_8]=[_7];
}
this._arrayOfAllItems.push(_9);
var _a=null;
if(_6&&_6.parent&&_6.attribute){
_a={item:_6.parent,attribute:_6.attribute,oldValue:undefined};
var _b=this.getValues(_6.parent,_6.attribute);
if(_b&&_b.length>0){
var _c=_b.slice(0,_b.length);
if(_b.length===1){
_a.oldValue=_b[0];
}else{
_a.oldValue=_b.slice(0,_b.length);
}
_c.push(_9);
this._setValueOrValues(_6.parent,_6.attribute,_c,false);
_a.newValue=this.getValues(_6.parent,_6.attribute);
}else{
this._setValueOrValues(_6.parent,_6.attribute,_9,false);
_a.newValue=_9;
}
}else{
_9[this._rootItemPropName]=true;
this._arrayOfTopLevelItems.push(_9);
}
this._pending._newItems[_7]=_9;
for(var _d in _5){
if(_d===this._storeRefPropName||_d===this._itemNumPropName){
throw new Error("encountered bug in ItemFileWriteStore.newItem");
}
var _e=_5[_d];
if(!dojo.isArray(_e)){
_e=[_e];
}
_9[_d]=_e;
if(this.referenceIntegrity){
for(var i=0;i<_e.length;i++){
var _f=_e[i];
if(this.isItem(_f)){
this._addReferenceToMap(_f,_9,_d);
}
}
}
}
this.onNew(_9,_a);
return _9;
},_removeArrayElement:function(_10,_11){
var _12=dojo.indexOf(_10,_11);
if(_12!=-1){
_10.splice(_12,1);
return true;
}
return false;
},deleteItem:function(_13){
this._assert(!this._saveInProgress);
this._assertIsItem(_13);
var _14=_13[this._itemNumPropName];
var _15=this.getIdentity(_13);
if(this.referenceIntegrity){
var _16=this.getAttributes(_13);
if(_13[this._reverseRefMap]){
_13["backup_"+this._reverseRefMap]=dojo.clone(_13[this._reverseRefMap]);
}
dojo.forEach(_16,function(_17){
dojo.forEach(this.getValues(_13,_17),function(_18){
if(this.isItem(_18)){
if(!_13["backupRefs_"+this._reverseRefMap]){
_13["backupRefs_"+this._reverseRefMap]=[];
}
_13["backupRefs_"+this._reverseRefMap].push({id:this.getIdentity(_18),attr:_17});
this._removeReferenceFromMap(_18,_13,_17);
}
},this);
},this);
var _19=_13[this._reverseRefMap];
if(_19){
for(var _1a in _19){
var _1b=null;
if(this._itemsByIdentity){
_1b=this._itemsByIdentity[_1a];
}else{
_1b=this._arrayOfAllItems[_1a];
}
if(_1b){
for(var _1c in _19[_1a]){
var _1d=this.getValues(_1b,_1c)||[];
var _1e=dojo.filter(_1d,function(_1f){
return !(this.isItem(_1f)&&this.getIdentity(_1f)==_15);
},this);
this._removeReferenceFromMap(_13,_1b,_1c);
if(_1e.length<_1d.length){
this._setValueOrValues(_1b,_1c,_1e,true);
}
}
}
}
}
}
this._arrayOfAllItems[_14]=null;
_13[this._storeRefPropName]=null;
if(this._itemsByIdentity){
delete this._itemsByIdentity[_15];
}
this._pending._deletedItems[_15]=_13;
if(_13[this._rootItemPropName]){
this._removeArrayElement(this._arrayOfTopLevelItems,_13);
}
this.onDelete(_13);
return true;
},setValue:function(_20,_21,_22){
return this._setValueOrValues(_20,_21,_22,true);
},setValues:function(_23,_24,_25){
return this._setValueOrValues(_23,_24,_25,true);
},unsetAttribute:function(_26,_27){
return this._setValueOrValues(_26,_27,[],true);
},_setValueOrValues:function(_28,_29,_2a,_2b){
this._assert(!this._saveInProgress);
this._assertIsItem(_28);
this._assert(dojo.isString(_29));
this._assert(typeof _2a!=="undefined");
var _2c=this._getIdentifierAttribute();
if(_29==_2c){
throw new Error("ItemFileWriteStore does not have support for changing the value of an item's identifier.");
}
var _2d=this._getValueOrValues(_28,_29);
var _2e=this.getIdentity(_28);
if(!this._pending._modifiedItems[_2e]){
var _2f={};
for(var key in _28){
if((key===this._storeRefPropName)||(key===this._itemNumPropName)||(key===this._rootItemPropName)){
_2f[key]=_28[key];
}else{
if(key===this._reverseRefMap){
_2f[key]=dojo.clone(_28[key]);
}else{
_2f[key]=_28[key].slice(0,_28[key].length);
}
}
}
this._pending._modifiedItems[_2e]=_2f;
}
var _30=false;
if(dojo.isArray(_2a)&&_2a.length===0){
_30=delete _28[_29];
_2a=undefined;
if(this.referenceIntegrity&&_2d){
var _31=_2d;
if(!dojo.isArray(_31)){
_31=[_31];
}
for(var i=0;i<_31.length;i++){
var _32=_31[i];
if(this.isItem(_32)){
this._removeReferenceFromMap(_32,_28,_29);
}
}
}
}else{
var _33;
if(dojo.isArray(_2a)){
var _34=_2a;
_33=_2a.slice(0,_2a.length);
}else{
_33=[_2a];
}
if(this.referenceIntegrity){
if(_2d){
var _31=_2d;
if(!dojo.isArray(_31)){
_31=[_31];
}
var map={};
dojo.forEach(_31,function(_35){
if(this.isItem(_35)){
var id=this.getIdentity(_35);
map[id.toString()]=true;
}
},this);
dojo.forEach(_33,function(_36){
if(this.isItem(_36)){
var id=this.getIdentity(_36);
if(map[id.toString()]){
delete map[id.toString()];
}else{
this._addReferenceToMap(_36,_28,_29);
}
}
},this);
for(var rId in map){
var _37;
if(this._itemsByIdentity){
_37=this._itemsByIdentity[rId];
}else{
_37=this._arrayOfAllItems[rId];
}
this._removeReferenceFromMap(_37,_28,_29);
}
}else{
for(var i=0;i<_33.length;i++){
var _32=_33[i];
if(this.isItem(_32)){
this._addReferenceToMap(_32,_28,_29);
}
}
}
}
_28[_29]=_33;
_30=true;
}
if(_2b){
this.onSet(_28,_29,_2d,_2a);
}
return _30;
},_addReferenceToMap:function(_38,_39,_3a){
var _3b=this.getIdentity(_39);
var _3c=_38[this._reverseRefMap];
if(!_3c){
_3c=_38[this._reverseRefMap]={};
}
var _3d=_3c[_3b];
if(!_3d){
_3d=_3c[_3b]={};
}
_3d[_3a]=true;
},_removeReferenceFromMap:function(_3e,_3f,_40){
var _41=this.getIdentity(_3f);
var _42=_3e[this._reverseRefMap];
var _43;
if(_42){
for(_43 in _42){
if(_43==_41){
delete _42[_43][_40];
if(this._isEmpty(_42[_43])){
delete _42[_43];
}
}
}
if(this._isEmpty(_42)){
delete _3e[this._reverseRefMap];
}
}
},_dumpReferenceMap:function(){
var i;
for(i=0;i<this._arrayOfAllItems.length;i++){
var _44=this._arrayOfAllItems[i];
if(_44&&_44[this._reverseRefMap]){
}
}
},_getValueOrValues:function(_45,_46){
var _47=undefined;
if(this.hasAttribute(_45,_46)){
var _48=this.getValues(_45,_46);
if(_48.length==1){
_47=_48[0];
}else{
_47=_48;
}
}
return _47;
},_flatten:function(_49){
if(this.isItem(_49)){
var _4a=_49;
var _4b=this.getIdentity(_4a);
var _4c={_reference:_4b};
return _4c;
}else{
if(typeof _49==="object"){
for(var _4d in this._datatypeMap){
var _4e=this._datatypeMap[_4d];
if(dojo.isObject(_4e)&&!dojo.isFunction(_4e)){
if(_49 instanceof _4e.type){
if(!_4e.serialize){
throw new Error("ItemFileWriteStore:  No serializer defined for type mapping: ["+_4d+"]");
}
return {_type:_4d,_value:_4e.serialize(_49)};
}
}else{
if(_49 instanceof _4e){
return {_type:_4d,_value:_49.toString()};
}
}
}
}
return _49;
}
},_getNewFileContentString:function(){
var _4f={};
var _50=this._getIdentifierAttribute();
if(_50!==Number){
_4f.identifier=_50;
}
if(this._labelAttr){
_4f.label=this._labelAttr;
}
_4f.items=[];
for(var i=0;i<this._arrayOfAllItems.length;++i){
var _51=this._arrayOfAllItems[i];
if(_51!==null){
var _52={};
for(var key in _51){
if(key!==this._storeRefPropName&&key!==this._itemNumPropName&&key!==this._reverseRefMap&&key!==this._rootItemPropName){
var _53=key;
var _54=this.getValues(_51,_53);
if(_54.length==1){
_52[_53]=this._flatten(_54[0]);
}else{
var _55=[];
for(var j=0;j<_54.length;++j){
_55.push(this._flatten(_54[j]));
_52[_53]=_55;
}
}
}
}
_4f.items.push(_52);
}
}
var _56=true;
return dojo.toJson(_4f,_56);
},_isEmpty:function(_57){
var _58=true;
if(dojo.isObject(_57)){
var i;
for(i in _57){
_58=false;
break;
}
}else{
if(dojo.isArray(_57)){
if(_57.length>0){
_58=false;
}
}
}
return _58;
},save:function(_59){
this._assert(!this._saveInProgress);
this._saveInProgress=true;
var _5a=this;
var _5b=function(){
_5a._pending={_newItems:{},_modifiedItems:{},_deletedItems:{}};
_5a._saveInProgress=false;
if(_59&&_59.onComplete){
var _5c=_59.scope||dojo.global;
_59.onComplete.call(_5c);
}
};
var _5d=function(err){
_5a._saveInProgress=false;
if(_59&&_59.onError){
var _5e=_59.scope||dojo.global;
_59.onError.call(_5e,err);
}
};
if(this._saveEverything){
var _5f=this._getNewFileContentString();
this._saveEverything(_5b,_5d,_5f);
}
if(this._saveCustom){
this._saveCustom(_5b,_5d);
}
if(!this._saveEverything&&!this._saveCustom){
_5b();
}
},revert:function(){
this._assert(!this._saveInProgress);
var _60;
for(_60 in this._pending._modifiedItems){
var _61=this._pending._modifiedItems[_60];
var _62=null;
if(this._itemsByIdentity){
_62=this._itemsByIdentity[_60];
}else{
_62=this._arrayOfAllItems[_60];
}
_61[this._storeRefPropName]=this;
for(key in _62){
delete _62[key];
}
dojo.mixin(_62,_61);
}
var _63;
for(_60 in this._pending._deletedItems){
_63=this._pending._deletedItems[_60];
_63[this._storeRefPropName]=this;
var _64=_63[this._itemNumPropName];
if(_63["backup_"+this._reverseRefMap]){
_63[this._reverseRefMap]=_63["backup_"+this._reverseRefMap];
delete _63["backup_"+this._reverseRefMap];
}
this._arrayOfAllItems[_64]=_63;
if(this._itemsByIdentity){
this._itemsByIdentity[_60]=_63;
}
if(_63[this._rootItemPropName]){
this._arrayOfTopLevelItems.push(_63);
}
}
for(_60 in this._pending._deletedItems){
_63=this._pending._deletedItems[_60];
if(_63["backupRefs_"+this._reverseRefMap]){
dojo.forEach(_63["backupRefs_"+this._reverseRefMap],function(_65){
var _66;
if(this._itemsByIdentity){
_66=this._itemsByIdentity[_65.id];
}else{
_66=this._arrayOfAllItems[_65.id];
}
this._addReferenceToMap(_66,_63,_65.attr);
},this);
delete _63["backupRefs_"+this._reverseRefMap];
}
}
for(_60 in this._pending._newItems){
var _67=this._pending._newItems[_60];
_67[this._storeRefPropName]=null;
this._arrayOfAllItems[_67[this._itemNumPropName]]=null;
if(_67[this._rootItemPropName]){
this._removeArrayElement(this._arrayOfTopLevelItems,_67);
}
if(this._itemsByIdentity){
delete this._itemsByIdentity[_60];
}
}
this._pending={_newItems:{},_modifiedItems:{},_deletedItems:{}};
return true;
},isDirty:function(_68){
if(_68){
var _69=this.getIdentity(_68);
return new Boolean(this._pending._newItems[_69]||this._pending._modifiedItems[_69]||this._pending._deletedItems[_69]).valueOf();
}else{
if(!this._isEmpty(this._pending._newItems)||!this._isEmpty(this._pending._modifiedItems)||!this._isEmpty(this._pending._deletedItems)){
return true;
}
return false;
}
},onSet:function(_6a,_6b,_6c,_6d){
},onNew:function(_6e,_6f){
},onDelete:function(_70){
},close:function(_71){
if(this.clearOnClose){
if(!this.isDirty()){
this.inherited(arguments);
}else{
throw new Error("dojo.data.ItemFileWriteStore: There are unsaved changes present in the store.  Please save or revert the changes before invoking close.");
}
}
}});
}
