Subversion Repositories Applications.papyrus

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
        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;
}});