1 | define([ |
---|
2 | "../_base/lang", "../_base/declare", "../Deferred", "../_base/array", |
---|
3 | "./util/QueryResults", "./util/SimpleQueryEngine" /*=====, "./api/Store" =====*/ |
---|
4 | ], function(lang, declare, Deferred, array, QueryResults, SimpleQueryEngine /*=====, Store =====*/){ |
---|
5 | |
---|
6 | // module: |
---|
7 | // dojo/store/DataStore |
---|
8 | |
---|
9 | |
---|
10 | // No base class, but for purposes of documentation, the base class is dojo/store/api/Store |
---|
11 | var base = null; |
---|
12 | /*===== base = Store; =====*/ |
---|
13 | |
---|
14 | return declare("dojo.store.DataStore", base, { |
---|
15 | // summary: |
---|
16 | // This is an adapter for using Dojo Data stores with an object store consumer. |
---|
17 | // You can provide a Dojo data store and use this adapter to interact with it through |
---|
18 | // the Dojo object store API |
---|
19 | |
---|
20 | target: "", |
---|
21 | constructor: function(options){ |
---|
22 | // options: Object? |
---|
23 | // This provides any configuration information that will be mixed into the store, |
---|
24 | // including a reference to the Dojo data store under the property "store". |
---|
25 | lang.mixin(this, options); |
---|
26 | if(!"idProperty" in options){ |
---|
27 | var idAttribute; |
---|
28 | try{ |
---|
29 | idAttribute = this.store.getIdentityAttributes(); |
---|
30 | }catch(e){ |
---|
31 | // some store are not requiring an item instance to give us the ID attributes |
---|
32 | // but some other do and throw errors in that case. |
---|
33 | } |
---|
34 | // if no idAttribute we have implicit id |
---|
35 | this.idProperty = (!idAttribute || !idAttributes[0]) || this.idProperty; |
---|
36 | } |
---|
37 | var features = this.store.getFeatures(); |
---|
38 | // check the feature set and null out any methods that shouldn't be available |
---|
39 | if(!features["dojo.data.api.Read"]){ |
---|
40 | this.get = null; |
---|
41 | } |
---|
42 | if(!features["dojo.data.api.Identity"]){ |
---|
43 | this.getIdentity = null; |
---|
44 | } |
---|
45 | if(!features["dojo.data.api.Write"]){ |
---|
46 | this.put = this.add = null; |
---|
47 | } |
---|
48 | }, |
---|
49 | // idProperty: String |
---|
50 | // The object property to use to store the identity of the store items. |
---|
51 | idProperty: "id", |
---|
52 | // store: |
---|
53 | // The object store to convert to a data store |
---|
54 | store: null, |
---|
55 | // queryEngine: Function |
---|
56 | // Defines the query engine to use for querying the data store |
---|
57 | queryEngine: SimpleQueryEngine, |
---|
58 | |
---|
59 | _objectConverter: function(callback){ |
---|
60 | var store = this.store; |
---|
61 | var idProperty = this.idProperty; |
---|
62 | function convert(item){ |
---|
63 | var object = {}; |
---|
64 | var attributes = store.getAttributes(item); |
---|
65 | for(var i = 0; i < attributes.length; i++){ |
---|
66 | var attribute = attributes[i]; |
---|
67 | var values = store.getValues(item, attribute); |
---|
68 | if(values.length > 1){ |
---|
69 | for(var j = 0; j < values.length; j++){ |
---|
70 | var value = values[j]; |
---|
71 | if(typeof value == 'object' && store.isItem(value)){ |
---|
72 | values[j] = convert(value); |
---|
73 | } |
---|
74 | } |
---|
75 | value = values; |
---|
76 | }else{ |
---|
77 | var value = store.getValue(item, attribute); |
---|
78 | if(typeof value == 'object' && store.isItem(value)){ |
---|
79 | value = convert(value); |
---|
80 | } |
---|
81 | } |
---|
82 | object[attributes[i]] = value; |
---|
83 | } |
---|
84 | if(!(idProperty in object) && store.getIdentity){ |
---|
85 | object[idProperty] = store.getIdentity(item); |
---|
86 | } |
---|
87 | return object; |
---|
88 | } |
---|
89 | return function(item){ |
---|
90 | return callback(convert(item)); |
---|
91 | }; |
---|
92 | }, |
---|
93 | get: function(id, options){ |
---|
94 | // summary: |
---|
95 | // Retrieves an object by it's identity. This will trigger a fetchItemByIdentity |
---|
96 | // id: Object? |
---|
97 | // The identity to use to lookup the object |
---|
98 | var returnedObject, returnedError; |
---|
99 | var deferred = new Deferred(); |
---|
100 | this.store.fetchItemByIdentity({ |
---|
101 | identity: id, |
---|
102 | onItem: this._objectConverter(function(object){ |
---|
103 | deferred.resolve(returnedObject = object); |
---|
104 | }), |
---|
105 | onError: function(error){ |
---|
106 | deferred.reject(returnedError = error); |
---|
107 | } |
---|
108 | }); |
---|
109 | if(returnedObject){ |
---|
110 | // if it was returned synchronously |
---|
111 | return returnedObject; |
---|
112 | } |
---|
113 | if(returnedError){ |
---|
114 | throw returnedError; |
---|
115 | } |
---|
116 | return deferred.promise; |
---|
117 | }, |
---|
118 | put: function(object, options){ |
---|
119 | // summary: |
---|
120 | // Stores an object by its identity. |
---|
121 | // object: Object |
---|
122 | // The object to store. |
---|
123 | // options: Object? |
---|
124 | // Additional metadata for storing the data. Includes a reference to an id |
---|
125 | // that the object may be stored with (i.e. { id: "foo" }). |
---|
126 | var id = options && typeof options.id != "undefined" || this.getIdentity(object); |
---|
127 | var store = this.store; |
---|
128 | var idProperty = this.idProperty; |
---|
129 | if(typeof id == "undefined"){ |
---|
130 | store.newItem(object); |
---|
131 | store.save(); |
---|
132 | }else{ |
---|
133 | store.fetchItemByIdentity({ |
---|
134 | identity: id, |
---|
135 | onItem: function(item){ |
---|
136 | if(item){ |
---|
137 | for(var i in object){ |
---|
138 | if(i != idProperty && // don't copy id properties since they are immutable and should be omitted for implicit ids |
---|
139 | store.getValue(item, i) != object[i]){ |
---|
140 | store.setValue(item, i, object[i]); |
---|
141 | } |
---|
142 | } |
---|
143 | }else{ |
---|
144 | store.newItem(object); |
---|
145 | } |
---|
146 | store.save(); |
---|
147 | } |
---|
148 | }); |
---|
149 | } |
---|
150 | }, |
---|
151 | remove: function(id){ |
---|
152 | // summary: |
---|
153 | // Deletes an object by its identity. |
---|
154 | // id: Object |
---|
155 | // The identity to use to delete the object |
---|
156 | var store = this.store; |
---|
157 | this.store.fetchItemByIdentity({ |
---|
158 | identity: id, |
---|
159 | onItem: function(item){ |
---|
160 | store.deleteItem(item); |
---|
161 | store.save(); |
---|
162 | } |
---|
163 | }); |
---|
164 | }, |
---|
165 | query: function(query, options){ |
---|
166 | // summary: |
---|
167 | // Queries the store for objects. |
---|
168 | // query: Object |
---|
169 | // The query to use for retrieving objects from the store |
---|
170 | // options: Object? |
---|
171 | // Optional options object as used by the underlying dojo.data Store. |
---|
172 | // returns: dojo/store/api/Store.QueryResults |
---|
173 | // A query results object that can be used to iterate over results. |
---|
174 | var fetchHandle; |
---|
175 | var deferred = new Deferred(function(){ fetchHandle.abort && fetchHandle.abort(); }); |
---|
176 | deferred.total = new Deferred(); |
---|
177 | var converter = this._objectConverter(function(object){return object;}); |
---|
178 | fetchHandle = this.store.fetch(lang.mixin({ |
---|
179 | query: query, |
---|
180 | onBegin: function(count){ |
---|
181 | deferred.total.resolve(count); |
---|
182 | }, |
---|
183 | onComplete: function(results){ |
---|
184 | deferred.resolve(array.map(results, converter)); |
---|
185 | }, |
---|
186 | onError: function(error){ |
---|
187 | deferred.reject(error); |
---|
188 | } |
---|
189 | }, options)); |
---|
190 | return QueryResults(deferred); |
---|
191 | }, |
---|
192 | getIdentity: function(object){ |
---|
193 | // summary: |
---|
194 | // Fetch the identity for the given object. |
---|
195 | // object: Object |
---|
196 | // The data object to get the identity from. |
---|
197 | // returns: Number |
---|
198 | // The id of the given object. |
---|
199 | return object[this.idProperty]; |
---|
200 | } |
---|
201 | }); |
---|
202 | }); |
---|