You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
259 lines
7.7 KiB
259 lines
7.7 KiB
define([ |
|
"../_base/lang", "../_base/declare", "../Deferred", "../_base/array", |
|
"./util/QueryResults", "./util/SimpleQueryEngine" /*=====, "./api/Store" =====*/ |
|
], function(lang, declare, Deferred, array, QueryResults, SimpleQueryEngine /*=====, Store =====*/){ |
|
|
|
// module: |
|
// dojo/store/DataStore |
|
|
|
|
|
// No base class, but for purposes of documentation, the base class is dojo/store/api/Store |
|
var base = null; |
|
/*===== base = Store; =====*/ |
|
|
|
return declare("dojo.store.DataStore", base, { |
|
// summary: |
|
// This is an adapter for using Dojo Data stores with an object store consumer. |
|
// You can provide a Dojo data store and use this adapter to interact with it through |
|
// the Dojo object store API |
|
|
|
target: "", |
|
constructor: function(options){ |
|
// options: Object? |
|
// This provides any configuration information that will be mixed into the store, |
|
// including a reference to the Dojo data store under the property "store". |
|
lang.mixin(this, options); |
|
if(!("idProperty" in options)){ |
|
var idAttribute; |
|
try{ |
|
idAttribute = this.store.getIdentityAttributes(); |
|
}catch(e){ |
|
// some store are not requiring an item instance to give us the ID attributes |
|
// but some other do and throw errors in that case. |
|
} |
|
// if no idAttribute we have implicit id |
|
this.idProperty = (lang.isArray(idAttribute) ? idAttribute[0] : idAttribute) || this.idProperty; |
|
} |
|
var features = this.store.getFeatures(); |
|
// check the feature set and null out any methods that shouldn't be available |
|
if(!features["dojo.data.api.Read"]){ |
|
this.get = null; |
|
} |
|
if(!features["dojo.data.api.Identity"]){ |
|
this.getIdentity = null; |
|
} |
|
if(!features["dojo.data.api.Write"]){ |
|
this.put = this.add = null; |
|
} |
|
}, |
|
// idProperty: String |
|
// The object property to use to store the identity of the store items. |
|
idProperty: "id", |
|
// store: |
|
// The object store to convert to a data store |
|
store: null, |
|
// queryEngine: Function |
|
// Defines the query engine to use for querying the data store |
|
queryEngine: SimpleQueryEngine, |
|
|
|
_objectConverter: function(callback){ |
|
var store = this.store; |
|
var idProperty = this.idProperty; |
|
function convert(item){ |
|
var object = {}; |
|
var attributes = store.getAttributes(item); |
|
for(var i = 0; i < attributes.length; i++){ |
|
var attribute = attributes[i]; |
|
var values = store.getValues(item, attribute); |
|
if(values.length > 1){ |
|
for(var j = 0; j < values.length; j++){ |
|
var value = values[j]; |
|
if(typeof value == 'object' && store.isItem(value)){ |
|
values[j] = convert(value); |
|
} |
|
} |
|
value = values; |
|
}else{ |
|
var value = store.getValue(item, attribute); |
|
if(typeof value == 'object' && store.isItem(value)){ |
|
value = convert(value); |
|
} |
|
} |
|
object[attributes[i]] = value; |
|
} |
|
if(!(idProperty in object) && store.getIdentity){ |
|
object[idProperty] = store.getIdentity(item); |
|
} |
|
return object; |
|
} |
|
return function(item){ |
|
return callback(item && convert(item)); |
|
}; |
|
}, |
|
get: function(id, options){ |
|
// summary: |
|
// Retrieves an object by it's identity. This will trigger a fetchItemByIdentity |
|
// id: Object? |
|
// The identity to use to lookup the object |
|
var returnedObject, returnedError; |
|
var deferred = new Deferred(); |
|
this.store.fetchItemByIdentity({ |
|
identity: id, |
|
onItem: this._objectConverter(function(object){ |
|
deferred.resolve(returnedObject = object); |
|
}), |
|
onError: function(error){ |
|
deferred.reject(returnedError = error); |
|
} |
|
}); |
|
if(returnedObject !== undefined){ |
|
// if it was returned synchronously |
|
return returnedObject == null ? undefined : returnedObject; |
|
} |
|
if(returnedError){ |
|
throw returnedError; |
|
} |
|
return deferred.promise; |
|
}, |
|
put: function(object, options){ |
|
// summary: |
|
// Stores an object by its identity. |
|
// object: Object |
|
// The object to store. |
|
// options: Object? |
|
// Additional metadata for storing the data. Includes a reference to an id |
|
// that the object may be stored with (i.e. { id: "foo" }). |
|
options = options || {}; |
|
var id = typeof options.id != "undefined" ? options.id : this.getIdentity(object); |
|
var store = this.store; |
|
var idProperty = this.idProperty; |
|
var deferred = new Deferred(); |
|
if(typeof id == "undefined"){ |
|
var item = store.newItem(object); |
|
store.save({ |
|
onComplete: function(){ |
|
deferred.resolve(item); |
|
}, |
|
onError: function(error){ |
|
deferred.reject(error); |
|
} |
|
}); |
|
}else{ |
|
store.fetchItemByIdentity({ |
|
identity: id, |
|
onItem: function(item){ |
|
if(item){ |
|
if(options.overwrite === false){ |
|
return deferred.reject(new Error("Overwriting existing object not allowed")); |
|
} |
|
for(var i in object){ |
|
if(i != idProperty && // don't copy id properties since they are immutable and should be omitted for implicit ids |
|
object.hasOwnProperty(i) && // don't want to copy methods and inherited properties |
|
store.getValue(item, i) != object[i]){ |
|
store.setValue(item, i, object[i]); |
|
} |
|
} |
|
}else{ |
|
if(options.overwrite === true){ |
|
return deferred.reject(new Error("Creating new object not allowed")); |
|
} |
|
var item = store.newItem(object); |
|
} |
|
store.save({ |
|
onComplete: function(){ |
|
deferred.resolve(item); |
|
}, |
|
onError: function(error){ |
|
deferred.reject(error); |
|
} |
|
}); |
|
}, |
|
onError: function(error){ |
|
deferred.reject(error); |
|
} |
|
}); |
|
} |
|
return deferred.promise; |
|
}, |
|
add: function(object, options){ |
|
// summary: |
|
// Creates an object, throws an error if the object already exists |
|
// object: Object |
|
// The object to store. |
|
// options: dojo/store/api/Store.PutDirectives? |
|
// Additional metadata for storing the data. Includes an "id" |
|
// property if a specific id is to be used. |
|
// returns: Number |
|
(options = options || {}).overwrite = false; |
|
// call put with overwrite being false |
|
return this.put(object, options); |
|
}, |
|
remove: function(id){ |
|
// summary: |
|
// Deletes an object by its identity. |
|
// id: Object |
|
// The identity to use to delete the object |
|
var store = this.store; |
|
var deferred = new Deferred(); |
|
|
|
this.store.fetchItemByIdentity({ |
|
identity: id, |
|
onItem: function(item){ |
|
try{ |
|
if(item == null){ |
|
// no item found, return false |
|
deferred.resolve(false); |
|
}else{ |
|
// delete and save the change |
|
store.deleteItem(item); |
|
store.save(); |
|
deferred.resolve(true); |
|
} |
|
}catch(error){ |
|
deferred.reject(error); |
|
} |
|
}, |
|
onError: function(error){ |
|
deferred.reject(error); |
|
} |
|
}); |
|
return deferred.promise; |
|
}, |
|
query: function(query, options){ |
|
// summary: |
|
// Queries the store for objects. |
|
// query: Object |
|
// The query to use for retrieving objects from the store |
|
// options: Object? |
|
// Optional options object as used by the underlying dojo.data Store. |
|
// returns: dojo/store/api/Store.QueryResults |
|
// A query results object that can be used to iterate over results. |
|
var fetchHandle; |
|
var deferred = new Deferred(function(){ fetchHandle.abort && fetchHandle.abort(); }); |
|
deferred.total = new Deferred(); |
|
var converter = this._objectConverter(function(object){return object;}); |
|
fetchHandle = this.store.fetch(lang.mixin({ |
|
query: query, |
|
onBegin: function(count){ |
|
deferred.total.resolve(count); |
|
}, |
|
onComplete: function(results){ |
|
deferred.resolve(array.map(results, converter)); |
|
}, |
|
onError: function(error){ |
|
deferred.reject(error); |
|
} |
|
}, options)); |
|
return QueryResults(deferred); |
|
}, |
|
getIdentity: function(object){ |
|
// summary: |
|
// Fetch the identity for the given object. |
|
// object: Object |
|
// The data object to get the identity from. |
|
// returns: Number |
|
// The id of the given object. |
|
return object[this.idProperty]; |
|
} |
|
}); |
|
});
|
|
|