New file |
0,0 → 1,352 |
/* |
Copyright (c) 2004-2006, The Dojo Foundation |
All Rights Reserved. |
|
Licensed under the Academic Free License version 2.1 or above OR the |
modified BSD license. For more information on Dojo licensing, see: |
|
http://dojotoolkit.org/community/licensing.shtml |
*/ |
|
dojo.provide("dojo.data.core.RemoteStore"); |
dojo.require("dojo.data.core.Read"); |
dojo.require("dojo.data.core.Write"); |
dojo.require("dojo.data.core.Result"); |
dojo.require("dojo.experimental"); |
dojo.require("dojo.Deferred"); |
dojo.require("dojo.lang.declare"); |
dojo.require("dojo.json"); |
dojo.require("dojo.io.*"); |
dojo.experimental("dojo.data.core.RemoteStore"); |
dojo.lang.declare("dojo.data.core.RemoteStore", [dojo.data.core.Read, dojo.data.core.Write], {_datatypeMap:{}, _jsonRegistry:dojo.json.jsonRegistry, initializer:function (kwArgs) { |
if (!kwArgs) { |
kwArgs = {}; |
} |
this._serverQueryUrl = kwArgs.queryUrl || ""; |
this._serverSaveUrl = kwArgs.saveUrl || ""; |
this._deleted = {}; |
this._changed = {}; |
this._added = {}; |
this._results = {}; |
this._data = {}; |
this._numItems = 0; |
}, _setupQueryRequest:function (result, requestKw) { |
result.query = result.query || ""; |
requestKw.url = this._serverQueryUrl + encodeURIComponent(result.query); |
requestKw.method = "get"; |
requestKw.mimetype = "text/json"; |
}, _resultToQueryMetadata:function (serverResponseData) { |
return serverResponseData; |
}, _resultToQueryData:function (serverResponseData) { |
return serverResponseData.data; |
}, _remoteToLocalValues:function (attributes) { |
for (var key in attributes) { |
var values = attributes[key]; |
for (var i = 0; i < values.length; i++) { |
var value = values[i]; |
var type = value.datatype || value.type; |
if (type) { |
var localValue = value.value; |
if (this._datatypeMap[type]) { |
localValue = this._datatypeMap[type](value); |
} |
values[i] = localValue; |
} |
} |
} |
return attributes; |
}, _queryToQueryKey:function (query) { |
if (typeof query == "string") { |
return query; |
} else { |
return dojo.json.serialize(query); |
} |
}, _assertIsItem:function (item) { |
if (!this.isItem(item)) { |
throw new Error("dojo.data.RemoteStore: a function was passed an item argument that was not an item"); |
} |
}, get:function (item, attribute, defaultValue) { |
var valueArray = this.getValues(item, attribute); |
if (valueArray.length == 0) { |
return defaultValue; |
} |
return valueArray[0]; |
}, getValues:function (item, attribute) { |
var itemIdentity = this.getIdentity(item); |
this._assertIsItem(itemIdentity); |
var changes = this._changed[itemIdentity]; |
if (changes) { |
var newvalues = changes[attribute]; |
if (newvalues !== undefined) { |
return newvalues; |
} else { |
return []; |
} |
} |
return this._data[itemIdentity][0][attribute]; |
}, getAttributes:function (item) { |
var itemIdentity = this.getIdentity(item); |
if (!itemIdentity) { |
return undefined; |
} |
var atts = []; |
var attrDict = this._data[itemIdentity][0]; |
for (var att in attrDict) { |
atts.push(att); |
} |
return atts; |
}, hasAttribute:function (item, attribute) { |
var valueArray = this.getValues(item, attribute); |
return valueArray.length ? true : false; |
}, containsValue:function (item, attribute, value) { |
var valueArray = this.getValues(item, attribute); |
for (var i = 0; i < valueArray.length; i++) { |
if (valueArray[i] == value) { |
return true; |
} |
} |
return false; |
}, isItem:function (something) { |
if (!something) { |
return false; |
} |
var itemIdentity = something; |
if (this._deleted[itemIdentity]) { |
return false; |
} |
if (this._data[itemIdentity]) { |
return true; |
} |
if (this._added[itemIdentity]) { |
return true; |
} |
return false; |
}, find:function (keywordArgs) { |
var result = null; |
if (keywordArgs instanceof dojo.data.core.Result) { |
result = keywordArgs; |
result.store = this; |
} else { |
result = new dojo.data.core.Result(keywordArgs, this); |
} |
var query = result.query; |
var self = this; |
var bindfunc = function (type, data, evt) { |
var scope = result.scope || dj_global; |
if (type == "load") { |
result.resultMetadata = self._resultToQueryMetadata(data); |
var dataDict = self._resultToQueryData(data); |
if (result.onbegin) { |
result.onbegin.call(scope, result); |
} |
var count = 0; |
var resultData = []; |
var newItemCount = 0; |
for (var key in dataDict) { |
if (result._aborted) { |
break; |
} |
if (!self._deleted[key]) { |
var values = dataDict[key]; |
var attributeDict = self._remoteToLocalValues(values); |
var existingValue = self._data[key]; |
var refCount = 1; |
if (existingValue) { |
refCount = ++existingValue[1]; |
} else { |
newItemCount++; |
} |
self._data[key] = [attributeDict, refCount]; |
resultData.push(key); |
count++; |
if (result.onnext) { |
result.onnext.call(scope, key, result); |
} |
} |
} |
self._results[self._queryToQueryKey(query)] = resultData; |
self._numItems += newItemCount; |
result.length = count; |
if (result.saveResult) { |
result.items = resultData; |
} |
if (!result._aborted && result.oncompleted) { |
result.oncompleted.call(scope, result); |
} |
} else { |
if (type == "error" || type == "timeout") { |
dojo.debug("find error: " + dojo.json.serialize(data)); |
if (result.onerror) { |
result.onerror.call(scope, data); |
} |
} |
} |
}; |
var bindKw = keywordArgs.bindArgs || {}; |
bindKw.sync = result.sync; |
bindKw.handle = bindfunc; |
this._setupQueryRequest(result, bindKw); |
var request = dojo.io.bind(bindKw); |
result._abortFunc = request.abort; |
return result; |
}, getIdentity:function (item) { |
if (!this.isItem(item)) { |
return null; |
} |
return (item.id ? item.id : item); |
}, newItem:function (attributes, keywordArgs) { |
var itemIdentity = keywordArgs["identity"]; |
if (this._deleted[itemIdentity]) { |
delete this._deleted[itemIdentity]; |
} else { |
this._added[itemIdentity] = 1; |
} |
if (attributes) { |
for (var attribute in attributes) { |
var valueOrArrayOfValues = attributes[attribute]; |
if (dojo.lang.isArray(valueOrArrayOfValues)) { |
this.setValues(itemIdentity, attribute, valueOrArrayOfValues); |
} else { |
this.set(itemIdentity, attribute, valueOrArrayOfValues); |
} |
} |
} |
return {id:itemIdentity}; |
}, deleteItem:function (item) { |
var identity = this.getIdentity(item); |
if (!identity) { |
return false; |
} |
if (this._added[identity]) { |
delete this._added[identity]; |
} else { |
this._deleted[identity] = 1; |
} |
if (this._changed[identity]) { |
delete this._changed[identity]; |
} |
return true; |
}, setValues:function (item, attribute, values) { |
var identity = this.getIdentity(item); |
if (!identity) { |
return undefined; |
} |
var changes = this._changed[identity]; |
if (!changes) { |
changes = {}; |
this._changed[identity] = changes; |
} |
changes[attribute] = values; |
return true; |
}, set:function (item, attribute, value) { |
return this.setValues(item, attribute, [value]); |
}, unsetAttribute:function (item, attribute) { |
return this.setValues(item, attribute, []); |
}, _initChanges:function () { |
this._deleted = {}; |
this._changed = {}; |
this._added = {}; |
}, _setupSaveRequest:function (saveKeywordArgs, requestKw) { |
requestKw.url = this._serverSaveUrl; |
requestKw.method = "post"; |
requestKw.mimetype = "text/plain"; |
var deleted = []; |
for (var key in this._deleted) { |
deleted.push(key); |
} |
var saveStruct = {"changed":this._changed, "deleted":deleted}; |
var oldRegistry = dojo.json.jsonRegistry; |
dojo.json.jsonRegistry = this._jsonRegistry; |
var jsonString = dojo.json.serialize(saveStruct); |
dojo.json.jsonRegistry = oldRegistry; |
requestKw.postContent = jsonString; |
}, save:function (keywordArgs) { |
keywordArgs = keywordArgs || {}; |
var result = new dojo.Deferred(); |
var self = this; |
var bindfunc = function (type, data, evt) { |
if (type == "load") { |
if (result.fired == 1) { |
return; |
} |
var key = null; |
for (key in self._added) { |
if (!self._data[key]) { |
self._data[key] = [{}, 1]; |
} |
} |
for (key in self._changed) { |
var existing = self._data[key]; |
var changes = self._changed[key]; |
if (existing) { |
existing[0] = changes; |
} else { |
self._data[key] = [changes, 1]; |
} |
} |
for (key in self._deleted) { |
if (self._data[key]) { |
delete self._data[key]; |
} |
} |
self._initChanges(); |
result.callback(true); |
} else { |
if (type == "error" || type == "timeout") { |
result.errback(data); |
} |
} |
}; |
var bindKw = {sync:keywordArgs["sync"], handle:bindfunc}; |
this._setupSaveRequest(keywordArgs, bindKw); |
var request = dojo.io.bind(bindKw); |
result.canceller = function (deferred) { |
request.abort(); |
}; |
return result; |
}, revert:function () { |
this._initChanges(); |
return true; |
}, isDirty:function (item) { |
if (item) { |
var identity = item.id || item; |
return this._deleted[identity] || this._changed[identity]; |
} else { |
var key = null; |
for (key in this._changed) { |
return true; |
} |
for (key in this._deleted) { |
return true; |
} |
for (key in this._added) { |
return true; |
} |
return false; |
} |
}, createReference:function (idstring) { |
return {id:idstring}; |
}, getSize:function () { |
return this._numItems; |
}, forgetResults:function (query) { |
var queryKey = this._queryToQueryKey(query); |
var results = this._results[queryKey]; |
if (!results) { |
return false; |
} |
var removed = 0; |
for (var i = 0; i < results.length; i++) { |
var key = results[i]; |
var existingValue = this._data[key]; |
if (existingValue[1] <= 1) { |
delete this._data[key]; |
removed++; |
} else { |
existingValue[1] = --existingValue[1]; |
} |
} |
delete this._results[queryKey]; |
this._numItems -= removed; |
return true; |
}}); |
|