1
1
/*
2
2
* Breeze Labs Abstract REST DataServiceAdapter
3
3
*
4
- * v.0.2.5
4
+ * v.0.6.1
5
5
*
6
6
* Extends Breeze with a REST DataService Adapter abstract type
7
7
*
12
12
*
13
13
* A concrete REST adapter
14
14
*
15
- * - MUST replace the _createSaveRequest with a concrete implementation to enable save
15
+ * - MUST replace the _createChangeRequest with a concrete implementation to enable save
16
16
*
17
17
* - SHOULD replace the "noop" JsonResultsAdapter.
18
18
*
56
56
57
57
breeze . AbstractRestDataServiceAdapter = ctor ;
58
58
59
+ // borrow from the AbstractDataServiceAdapter
60
+ var abstractDsaProto = breeze . AbstractDataServiceAdapter . prototype ;
61
+
59
62
ctor . prototype = {
60
63
61
64
// Breeze DataService API
65
68
saveChanges : saveChanges ,
66
69
67
70
// Configuration API
71
+ ChangeRequestInterceptor : abstractDsaProto . changeRequestInterceptor , // default, no-op ctor
68
72
checkForRecomposition : checkForRecomposition ,
69
73
saveOnlyOne : false , // true if may only save one entity at a time.
70
74
ignoreDeleteNotFound : true , // true if should ignore a 404 error from a delete
71
75
72
76
// "protected" members available to derived concrete dataservice adapter types
73
77
_addToSaveContext : _addToSaveContext ,
74
78
_ajaxImpl : undefined , // see initialize()
79
+ _catchNoConnectionError : abstractDsaProto . _catchNoConnectionError ,
80
+ _changeRequestSucceeded : _changeRequestSucceeded ,
75
81
_createErrorFromResponse : _createErrorFromResponse ,
82
+ _createChangeRequest : _createChangeRequest ,
76
83
_createJsonResultsAdapter : _createJsonResultsAdapter ,
77
- _createSaveRequest : _createSaveRequest ,
78
84
_clientTypeNameToServer : _clientTypeNameToServer ,
79
85
_getEntityTypeFromMappingContext : _getEntityTypeFromMappingContext ,
80
86
_getNodeEntityType : _getNodeEntityType ,
100
106
throw new Error ( "Breeze was unable to find an 'ajax' adapter for " + adapter . name ) ;
101
107
}
102
108
103
- // Todo: hacking for Q right now; use promise adapter after Breeze makes it available
104
- // if no breeze.Q, assume Q is in global window namespace (e.g., Q.js)
105
- adapter . Q = breeze . Q ? breeze . Q : window . Q ;
109
+ adapter . Q = breeze . Q ; // adapter.Q is for backward compat
106
110
107
111
if ( ! adapter . jsonResultsAdapter ) {
108
112
adapter . jsonResultsAdapter = adapter . _createJsonResultsAdapter ( ) ;
130
134
params : mappingContext . query . parameters ,
131
135
success : querySuccess ,
132
136
error : function ( response ) {
133
- deferred . reject ( adapter . _createErrorFromResponse ( response , url ) ) ;
137
+ deferred . reject ( adapter . _createErrorFromResponse ( response , url , mappingContext ) ) ;
134
138
}
135
139
} ) ;
136
140
return deferred . promise ;
154
158
}
155
159
156
160
function saveChanges ( saveContext , saveBundle ) {
157
- var adapter = this ;
161
+ var adapter = saveContext . adapter = this ;
158
162
var Q = adapter . Q ;
159
163
160
164
try {
161
165
if ( adapter . saveOnlyOne && saveBundle . entities . length > 1 ) {
162
166
return Q . reject ( new Error ( "Only one entity may be saved at a time." ) ) ;
163
167
}
164
- saveContext . adapter = adapter ;
165
168
adapter . _addToSaveContext ( saveContext ) ;
166
169
167
- var requests = createSaveRequests ( saveContext , saveBundle ) ;
168
- var promises = sendSaveRequests ( saveContext , requests ) ;
170
+ var requests = createChangeRequests ( saveContext , saveBundle ) ;
171
+ var promises = sendChangeRequests ( saveContext , requests ) ;
169
172
var comboPromise = Q . all ( promises ) ;
170
173
return comboPromise
171
174
. then ( reviewSaveResult )
213
216
jrAdapter . clientTypeNameToServer ( typeName ) : typeName ;
214
217
}
215
218
216
- function _createErrorFromResponse ( response , url ) {
217
- var result = new Error ( ) ;
218
- result . response = response ;
219
- if ( url ) { result . url = url ; }
220
- result . message = response . message || response . error || response . statusText ;
221
- result . statusText = response . statusText ;
222
- result . status = response . status ;
219
+ function _createChangeRequest ( /* saveContext, entity, index */ ) {
220
+ throw new Error ( "Need a concrete implementation of _createChangeRequest" ) ;
221
+ }
222
+
223
+ // Create error object for both query and save responses.
224
+ // 'context' can help differentiate query and save
225
+ // 'errorEntity' only defined for save response
226
+ function _createErrorFromResponse ( response , url , context , errorEntity ) {
227
+ var err = new Error ( ) ;
228
+ err . response = response ;
229
+ if ( url ) { err . url = url ; }
230
+ err . status = response . status || '???' ;
231
+ err . statusText = response . statusText ;
232
+ err . message = response . message || response . error || response . statusText ;
233
+ fn_ . catchNoConnectionError ( err ) ;
234
+ return err ;
223
235
}
224
236
225
237
function _createJsonResultsAdapter ( /*dataServiceAdapter*/ ) {
232
244
} ) ;
233
245
}
234
246
235
- function _createSaveRequest ( /* saveContext, entity, index */ ) {
236
- throw new Error ( "Need a concrete implementation of _createSaveRequest" ) ;
237
- }
238
-
239
247
function _getEntityTypeFromMappingContext ( mappingContext ) {
240
248
var query = mappingContext . query ;
241
249
if ( ! query ) { return null ; }
281
289
return response . data ;
282
290
}
283
291
284
- function _processSavedEntity ( /*savedEntity, saveContext, response , index*/ ) {
292
+ function _processSavedEntity ( /*savedEntity, response, saveContext , index*/ ) {
285
293
// Virtual method. Override in concrete adapter if needed.
286
294
}
287
295
315
323
}
316
324
317
325
/*** private members ***/
326
+ function addKeyMapping ( saveContext , index , saved ) {
327
+ var tempKey = saveContext . tempKeys [ index ] ;
328
+ if ( tempKey ) {
329
+ // entity had a temporary key; add a temp-to-perm key mapping
330
+ var entityType = tempKey . entityType ;
331
+ var tempValue = tempKey . values [ 0 ] ;
332
+ var realKey = getRealKey ( entityType , saved ) ;
333
+ var keyMapping = {
334
+ entityTypeName : entityType . name ,
335
+ tempValue : tempValue ,
336
+ realValue : realKey . values [ 0 ]
337
+ } ;
338
+ saveContext . saveResult . keyMappings . push ( keyMapping ) ;
339
+ }
340
+ }
318
341
319
- function createSaveRequests ( saveContext , saveBundle ) {
342
+ function createChangeRequests ( saveContext , saveBundle ) {
320
343
var adapter = saveContext . adapter ;
321
344
var originalEntities = saveContext . originalEntities = saveBundle . entities ;
322
345
saveContext . tempKeys = [ ] ;
323
346
347
+ var changeRequestInterceptor =
348
+ abstractDsaProto . _createChangeRequestInterceptor ( saveContext , saveBundle ) ;
349
+
324
350
var requests = originalEntities . map ( function ( entity , index ) {
325
- return adapter . _createSaveRequest ( saveContext , entity , index ) ;
351
+ var request = adapter . _createChangeRequest ( saveContext , entity , index ) ;
352
+ return changeRequestInterceptor . getRequest ( request , entity , index ) ;
326
353
} ) ;
354
+ changeRequestInterceptor . done ( requests ) ;
327
355
return requests ;
328
356
}
329
357
332
360
breeze . DataProperty . getRawValueFromServer ) ;
333
361
}
334
362
335
- function sendSaveRequests ( saveContext , requests ) {
363
+ function sendChangeRequests ( saveContext , requests ) {
336
364
// Sends each prepared save request and processes the promised results
337
365
// returns a single "comboPromise" that waits for the individual promises to complete
338
366
// Todo: What happens when there are a gazillion async requests?
345
373
saveContext . saveResult = saveResult ;
346
374
347
375
return requests . map ( function ( request , index ) {
348
- return sendSaveRequest ( saveContext , request , index ) ;
376
+ return sendChangeRequest ( saveContext , request , index ) ;
349
377
} ) ;
350
378
}
351
379
352
- function sendSaveRequest ( saveContext , request , index ) {
380
+ function sendChangeRequest ( saveContext , request , index ) {
353
381
var adapter = saveContext . adapter ;
354
382
var deferred = adapter . Q . defer ( ) ;
355
383
var url = request . requestUri ;
370
398
if ( ( ! status ) || status >= 400 ) {
371
399
tryRequestFailed ( response ) ;
372
400
} else {
373
- var savedEntity = saveRequestSucceeded ( saveContext , response , index ) ;
374
- adapter . _processSavedEntity ( savedEntity , saveContext , response , index ) ;
401
+ var savedEntity = adapter . _changeRequestSucceeded ( saveContext , response , index ) ;
402
+ adapter . _processSavedEntity ( savedEntity , response , saveContext , index ) ;
375
403
deferred . resolve ( true ) ;
376
404
}
377
405
} catch ( e ) {
392
420
tryRequestSucceeded ( response ) ;
393
421
} else {
394
422
// Do NOT fail saveChanges at the request level
423
+ var errorEntity = saveContext . originalEntities [ index ] ;
395
424
saveContext . saveResult . entitiesWithErrors . push ( {
396
- entity : saveContext . originalEntities [ index ] ,
397
- error : adapter . _createErrorFromResponse ( response , url )
425
+ entity : errorEntity ,
426
+ error : adapter . _createErrorFromResponse ( response , url , saveContext , errorEntity )
398
427
} ) ;
399
428
deferred . resolve ( false ) ;
400
429
}
405
434
}
406
435
}
407
436
408
- function saveRequestSucceeded ( saveContext , response , index ) {
437
+ function _changeRequestSucceeded ( saveContext , response , index ) {
409
438
var saved = saveContext . adapter . _getResponseData ( response ) ;
410
439
if ( saved && typeof saved === 'object' ) {
411
440
// Have "saved entity" data; add its type (for JsonResultsAdapter) & KeyMapping
412
441
saved . $entityType = saveContext . originalEntities [ index ] . entityType ;
413
- addKeyMapping ( ) ;
442
+ addKeyMapping ( saveContext , index , saved ) ;
414
443
} else {
415
444
// No "saved entity" data; return the original entity
416
445
saved = saveContext . originalEntities [ index ] ;
417
446
}
418
447
saveContext . saveResult . entities . push ( saved ) ;
419
448
return saved ;
420
449
421
- function addKeyMapping ( ) {
422
- var tempKey = saveContext . tempKeys [ index ] ;
423
- if ( tempKey ) {
424
- // entity had a temporary key; add a temp-to-perm key mapping
425
- var entityType = tempKey . entityType ;
426
- var tempValue = tempKey . values [ 0 ] ;
427
- var realKey = getRealKey ( entityType , saved ) ;
428
- var keyMapping = {
429
- entityTypeName : entityType . name ,
430
- tempValue : tempValue ,
431
- realValue : realKey . values [ 0 ]
432
- } ;
433
- saveContext . saveResult . keyMappings . push ( keyMapping ) ;
434
- }
435
- }
450
+
436
451
}
437
452
438
453
} , this ) ) ;
0 commit comments