Diffstat (limited to 'frontend/delta/js/Clipperz/PM/DataModel/Record.js') (more/less context) (show whitespace changes)
-rw-r--r-- | frontend/delta/js/Clipperz/PM/DataModel/Record.js | 891 |
1 files changed, 891 insertions, 0 deletions
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/Record.js b/frontend/delta/js/Clipperz/PM/DataModel/Record.js new file mode 100644 index 0000000..379872a --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/Record.js | |||
@@ -0,0 +1,891 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2013 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz, the online password manager. | ||
6 | For further information about its features and functionalities please | ||
7 | refer to http://www.clipperz.com. | ||
8 | |||
9 | * Clipperz is free software: you can redistribute it and/or modify it | ||
10 | under the terms of the GNU Affero General Public License as published | ||
11 | by the Free Software Foundation, either version 3 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | * Clipperz is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
17 | See the GNU Affero General Public License for more details. | ||
18 | |||
19 | * You should have received a copy of the GNU Affero General Public | ||
20 | License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||
21 | |||
22 | */ | ||
23 | |||
24 | if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||
25 | if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } | ||
26 | if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } | ||
27 | |||
28 | |||
29 | Clipperz.PM.DataModel.Record = function(args) { | ||
30 | Clipperz.PM.DataModel.Record.superclass.constructor.apply(this, arguments); | ||
31 | |||
32 | this._updateDate = (args.updateDate ? Clipperz.PM.Date.parse(args.updateDate) : Clipperz.Base.exception.raise('MandatoryParameter')); | ||
33 | |||
34 | this._retrieveIndexDataFunction = args.retrieveIndexDataFunction|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
35 | this._updateIndexDataFunction = args.updateIndexDataFunction || Clipperz.Base.exception.raise('MandatoryParameter'); | ||
36 | |||
37 | this._retrieveDirectLoginIndexDataFunction = args.retrieveDirectLoginIndexDataFunction|| null; | ||
38 | this._setDirectLoginIndexDataFunction = args.setDirectLoginIndexDataFunction || null; | ||
39 | this._removeDirectLoginIndexDataFunction = args.removeDirectLoginIndexDataFunction|| null; | ||
40 | |||
41 | this._createNewDirectLoginFunction = args.createNewDirectLoginFunction || null; | ||
42 | |||
43 | this._directLogins = {}; | ||
44 | |||
45 | this._versions = {}; | ||
46 | |||
47 | this._currentRecordVersion = null; | ||
48 | if (this.isBrandNew()) { | ||
49 | var newVersion; | ||
50 | |||
51 | this.setNotes(''); | ||
52 | newVersion = new Clipperz.PM.DataModel.Record.Version({ | ||
53 | 'retrieveKeyFunction':MochiKit.Base.method(this, 'getVersionKey'), | ||
54 | 'getVersion': MochiKit.Base.method(this, 'getVersion') | ||
55 | |||
56 | }); | ||
57 | this._versions[newVersion.reference()] = newVersion; | ||
58 | this._currentVersionReference = newVersion.reference(); | ||
59 | // this.setLabel(''); | ||
60 | } | ||
61 | |||
62 | return this; | ||
63 | } | ||
64 | |||
65 | |||
66 | Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.EncryptedRemoteObject, { | ||
67 | |||
68 | 'toString': function() { | ||
69 | return "Record (" + this.reference() + ")"; | ||
70 | }, | ||
71 | |||
72 | //------------------------------------------------------------------------- | ||
73 | |||
74 | 'reference': function () { | ||
75 | return this._reference; | ||
76 | }, | ||
77 | |||
78 | //========================================================================= | ||
79 | |||
80 | 'getIndexData': function () { | ||
81 | return this._retrieveIndexDataFunction(this.reference()); | ||
82 | }, | ||
83 | |||
84 | //......................................................................... | ||
85 | |||
86 | 'getIndexDataForKey': function (aKey) { | ||
87 | return Clipperz.Async.callbacks("Record.getIndexDataForKey", [ | ||
88 | MochiKit.Base.method(this, 'getIndexData'), | ||
89 | MochiKit.Base.itemgetter(aKey) | ||
90 | ], {trace:false}); | ||
91 | }, | ||
92 | |||
93 | //------------------------------------------------------------------------- | ||
94 | |||
95 | 'setIndexDataForKey': function (aKey, aValue) { | ||
96 | // return this._updateIndexDataFunction(this.reference(), aKey, aValue); | ||
97 | |||
98 | var deferredResult; | ||
99 | |||
100 | deferredResult = new Clipperz.Async.Deferred("Record.setIndexDataForKey", {trace:false}); | ||
101 | deferredResult.addMethod(this, 'getIndexDataForKey', aKey); | ||
102 | deferredResult.addCallback(MochiKit.Base.bind(function (aCurrentValue) { | ||
103 | var result; | ||
104 | var originalValue; | ||
105 | |||
106 | originalValue = this.transientState().getValue('originalValues.indexData.' + aKey); | ||
107 | if (originalValue == null) { | ||
108 | originalValue = this.transientState().setValue('originalValues.indexData.' + aKey, aCurrentValue); | ||
109 | } | ||
110 | |||
111 | if (aCurrentValue != aValue) { | ||
112 | if (originalValue != aValue) { | ||
113 | this.transientState().setValue('hasPendingChanges.indexData.' + aKey, true); | ||
114 | } else { | ||
115 | this.transientState().setValue('hasPendingChanges.indexData.' + aKey, false); | ||
116 | } | ||
117 | |||
118 | result = this._updateIndexDataFunction(this.reference(), aKey, aValue); | ||
119 | } else { | ||
120 | result = MochiKit.Async.succeed(aValue); | ||
121 | } | ||
122 | |||
123 | return result; | ||
124 | }, this)); | ||
125 | |||
126 | deferredResult.callback(); | ||
127 | |||
128 | return deferredResult; | ||
129 | }, | ||
130 | |||
131 | //========================================================================= | ||
132 | /* | ||
133 | 'key': function () { | ||
134 | return this.getIndexDataForKey('key'); | ||
135 | }, | ||
136 | */ | ||
137 | //========================================================================= | ||
138 | |||
139 | 'label': function () { | ||
140 | return this.getIndexDataForKey('label'); | ||
141 | }, | ||
142 | |||
143 | //......................................................................... | ||
144 | |||
145 | 'setLabel': function (aValue) { | ||
146 | return this.setIndexDataForKey('label', aValue); | ||
147 | }, | ||
148 | |||
149 | //========================================================================= | ||
150 | |||
151 | 'headerNotes': function () { | ||
152 | return this.getIndexDataForKey('notes'); | ||
153 | }, | ||
154 | |||
155 | //------------------------------------------------------------------------- | ||
156 | |||
157 | 'notes': function () { | ||
158 | return Clipperz.Async.callbacks("Record.notes", [ | ||
159 | MochiKit.Base.method(this, 'headerNotes'), | ||
160 | MochiKit.Base.bind(function (someHeaderNotes) { | ||
161 | var result; | ||
162 | |||
163 | if ((someHeaderNotes == null) || (typeof(someHeaderNotes) == 'undefined')) { | ||
164 | result = this.getValue('notes'); | ||
165 | } else { | ||
166 | result = MochiKit.Async.succeed(someHeaderNotes); | ||
167 | } | ||
168 | |||
169 | return result; | ||
170 | }, this) | ||
171 | ], {trace:false}); | ||
172 | }, | ||
173 | |||
174 | //......................................................................... | ||
175 | |||
176 | 'setNotes': function (aValue) { | ||
177 | return this.setValue('notes', aValue); | ||
178 | }, | ||
179 | |||
180 | //========================================================================= | ||
181 | |||
182 | 'updateDate': function () { | ||
183 | return MochiKit.Async.succeed(this._updateDate); | ||
184 | }, | ||
185 | |||
186 | //========================================================================= | ||
187 | |||
188 | 'favicon': function () { | ||
189 | var result; | ||
190 | var directLogins; | ||
191 | |||
192 | directLogins = MochiKit.Base.values(this.directLogins()); | ||
193 | if (directLogins.length > 0) { | ||
194 | result = directLogins[0].favicon(); | ||
195 | // } else if (/* is there an URL to use for searching a favicon */){ | ||
196 | } else { | ||
197 | result = null; //MochiKit.Async.succeed(Clipperz.PM.Strings['defaultFaviconUrl']); | ||
198 | } | ||
199 | |||
200 | return result; | ||
201 | }, | ||
202 | |||
203 | //------------------------------------------------------------------------- | ||
204 | |||
205 | 'searchableContent': function () { | ||
206 | var deferredResult; | ||
207 | |||
208 | deferredResult = new Clipperz.Async.Deferred("Record.searchableContent", {trace:false}); | ||
209 | |||
210 | deferredResult.collectResults({ | ||
211 | 'recordLabel': MochiKit.Base.method(this, 'label'), | ||
212 | 'directLoginLabels': [ | ||
213 | MochiKit.Base.method(this, 'directLoginReferences'), | ||
214 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.itemgetter('label')) | ||
215 | ] | ||
216 | }) | ||
217 | deferredResult.addCallback(function (someValues) { | ||
218 | return someValues['recordLabel'] + ' ' + someValues['directLoginLabels'].join(' '); | ||
219 | }); | ||
220 | deferredResult.callback(); | ||
221 | |||
222 | return deferredResult; | ||
223 | }, | ||
224 | |||
225 | //------------------------------------------------------------------------- | ||
226 | |||
227 | 'isMatching': function (aRegExp) { | ||
228 | return Clipperz.Async.callbacks("deferredFilterFunction", [ | ||
229 | MochiKit.Base.method(this, 'searchableContent'), | ||
230 | MochiKit.Base.method(aRegExp, 'test'), | ||
231 | function (doesItMatch) { | ||
232 | var result; | ||
233 | |||
234 | if (doesItMatch) { | ||
235 | result = MochiKit.Async.succeed('match'); | ||
236 | } else { | ||
237 | result = MochiKit.Async.fail('miss'); | ||
238 | } | ||
239 | |||
240 | return result; | ||
241 | } | ||
242 | ], {trace:false}); | ||
243 | }, | ||
244 | |||
245 | //========================================================================= | ||
246 | |||
247 | 'content': function () { | ||
248 | var deferredResult; | ||
249 | varresult; | ||
250 | |||
251 | result = { | ||
252 | 'fields': [], | ||
253 | 'directLogins': [] | ||
254 | }; | ||
255 | |||
256 | deferredResult = new Clipperz.Async.Deferred("Record.content", {trace:false}); | ||
257 | deferredResult.addMethod(this, 'reference'); | ||
258 | deferredResult.addCallback(function (aValue) { result['reference'] = aValue; }); | ||
259 | deferredResult.addMethod(this, 'label'); | ||
260 | deferredResult.addCallback(function (aValue) { result['title'] = aValue; }); | ||
261 | deferredResult.addMethod(this, 'notes'); | ||
262 | deferredResult.addCallback(function (aValue) { result['notes'] = aValue; }); | ||
263 | |||
264 | deferredResult.addMethod(this, 'fields'); | ||
265 | deferredResult.addCallback(MochiKit.Base.values); | ||
266 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('content')); | ||
267 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
268 | deferredResult.addCallback(MochiKit.Base.map, function (aValue) { result['fields'].push(aValue); }); | ||
269 | |||
270 | deferredResult.addMethod(this, 'directLogins'); | ||
271 | deferredResult.addCallback(MochiKit.Base.values); | ||
272 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('content')); | ||
273 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
274 | deferredResult.addCallback(MochiKit.Base.map, function (aValue) { result['directLogins'].push(aValue); }); | ||
275 | deferredResult.addCallback(function () { return result; }); | ||
276 | |||
277 | deferredResult.callback(); | ||
278 | |||
279 | return deferredResult; | ||
280 | }, | ||
281 | |||
282 | //========================================================================= | ||
283 | |||
284 | 'directLogins': function () { | ||
285 | return this._directLogins; | ||
286 | }, | ||
287 | |||
288 | 'addDirectLogin': function (aDirectLogin) { | ||
289 | this._directLogins[aDirectLogin.reference()] = aDirectLogin; | ||
290 | }, | ||
291 | |||
292 | 'directLoginWithReference': function (aDirectLoginReference) { | ||
293 | return this._directLogins[aDirectLoginReference]; | ||
294 | }, | ||
295 | |||
296 | 'createNewDirectLoginFunction': function () { | ||
297 | return this._createNewDirectLoginFunction; | ||
298 | }, | ||
299 | |||
300 | 'saveOriginalDirectLoginStatusToTransientState': function () { | ||
301 | if (this.transientState().getValue('directLogins') == null) { | ||
302 | // this.transientState().setValue('directLogins', this._directLogins) | ||
303 | MochiKit.Iter.forEach(MochiKit.Base.keys(this._directLogins), MochiKit.Base.bind(function(aKey) { | ||
304 | this.transientState().setValue('directLogins' + '.' + aKey, this._directLogins[aKey]) | ||
305 | }, this)) | ||
306 | } | ||
307 | }, | ||
308 | |||
309 | 'createNewDirectLogin': function () { | ||
310 | this.saveOriginalDirectLoginStatusToTransientState(); | ||
311 | |||
312 | return this.createNewDirectLoginFunction()(this); | ||
313 | }, | ||
314 | |||
315 | 'removeDirectLogin': function(aDirectLogin) { | ||
316 | this.saveOriginalDirectLoginStatusToTransientState(); | ||
317 | |||
318 | return Clipperz.Async.callbacks("Record.removeDirectLogin", [ | ||
319 | MochiKit.Base.method(this, 'removeValue', 'directLogins' + '.' + aDirectLogin.reference()), | ||
320 | MochiKit.Base.bind(function () { | ||
321 | delete this._directLogins[aDirectLogin.reference()] | ||
322 | }, this) | ||
323 | ], {trace:false}); | ||
324 | |||
325 | }, | ||
326 | |||
327 | 'directLoginReferences': function () { | ||
328 | var result; | ||
329 | |||
330 | result = Clipperz.Async.callbacks("Record.directLoginReferences", [ | ||
331 | MochiKit.Base.method(this, 'directLogins'), | ||
332 | MochiKit.Base.values, | ||
333 | function (someDirectLogins) { | ||
334 | var result; | ||
335 | var i,c; | ||
336 | |||
337 | result = []; | ||
338 | c = someDirectLogins.length; | ||
339 | for (i=0; i<c; i++) { | ||
340 | result.push(Clipperz.Async.collectResults("Record.directLoginReferences - collectResults", { | ||
341 | '_rowObject': MochiKit.Async.succeed, | ||
342 | '_reference': MochiKit.Base.methodcaller('reference'), | ||
343 | 'label': MochiKit.Base.methodcaller('label'), | ||
344 | 'favicon': MochiKit.Base.methodcaller('favicon') | ||
345 | }, {trace:false})(someDirectLogins[i])); | ||
346 | }; | ||
347 | |||
348 | return result; | ||
349 | }, | ||
350 | Clipperz.Async.collectAll | ||
351 | ], {trace:false}); | ||
352 | |||
353 | return result; | ||
354 | }, | ||
355 | |||
356 | //========================================================================= | ||
357 | |||
358 | 'unpackRemoteData': function (someData) { | ||
359 | var result; | ||
360 | |||
361 | /* | ||
362 | this._currentRecordVersion = new Clipperz.PM.DataModel.Record.Version({ | ||
363 | 'reference': someData['currentVersion']['reference'], | ||
364 | 'retrieveKeyFunction': MochiKit.Base.method(this, 'getCurrentRecordVersionKey'), | ||
365 | 'remoteData': someData['currentVersion'], | ||
366 | }); | ||
367 | */ | ||
368 | var versionKey; | ||
369 | |||
370 | for (versionKey in someData['versions']) { | ||
371 | this._versions[versionKey] = new Clipperz.PM.DataModel.Record.Version({ | ||
372 | 'reference': versionKey, | ||
373 | 'retrieveKeyFunction':MochiKit.Base.method(this, 'getVersionKey'), | ||
374 | 'remoteData': someData['versions'][versionKey], | ||
375 | 'getVersion': MochiKit.Base.method(this, 'getVersion') | ||
376 | }) | ||
377 | } | ||
378 | |||
379 | // this._currentVersionReference = someData['currentVersion']['reference']; | ||
380 | this._currentVersionReference = someData['currentVersion']; | ||
381 | |||
382 | result = Clipperz.PM.DataModel.Record.superclass.unpackRemoteData.apply(this, arguments); | ||
383 | |||
384 | return result; | ||
385 | }, | ||
386 | |||
387 | //------------------------------------------------------------------------- | ||
388 | |||
389 | 'unpackData': function (someData) { | ||
390 | var result; | ||
391 | |||
392 | result = Clipperz.PM.DataModel.Record.superclass.unpackData.apply(this, arguments); | ||
393 | |||
394 | if (MochiKit.Base.isUndefinedOrNull(result['notes'])) { | ||
395 | result['notes'] = '' | ||
396 | } | ||
397 | |||
398 | return result; | ||
399 | }, | ||
400 | |||
401 | //------------------------------------------------------------------------- | ||
402 | |||
403 | 'prepareRemoteDataWithKey': function (aKey) { | ||
404 | var deferredResult; | ||
405 | varnewVersionKey; | ||
406 | var result; | ||
407 | |||
408 | newVersionKey = Clipperz.PM.Crypto.randomKey(); | ||
409 | result = {}; | ||
410 | |||
411 | deferredResult = new Clipperz.Async.Deferred("Record.prepareRemoteDataWithKey", {trace:false}); | ||
412 | deferredResult.addCallbackList([ | ||
413 | Clipperz.Async.collectResults("Record.prepareRemoteDataWithKey - collect results", { | ||
414 | 'isBrandNew': MochiKit.Base.method(this, 'isBrandNew'), | ||
415 | 'versionHasPendingChanges':[ | ||
416 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
417 | // MochiKit.Base.methodcaller('hasPendingChanges') | ||
418 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges') | ||
419 | ] | ||
420 | }), | ||
421 | Clipperz.Async.or, | ||
422 | |||
423 | Clipperz.Async.deferredIf("Current Version has pending changes", [ | ||
424 | MochiKit.Base.method(this, 'createNewRecordVersion'), | ||
425 | MochiKit.Base.methodcaller('prepareRemoteDataWithKey', newVersionKey), | ||
426 | MochiKit.Base.partial(Clipperz.Async.setItem, result, 'currentRecordVersion'), | ||
427 | MochiKit.Base.method(this, 'setCurrentRecordVersionKey', newVersionKey) | ||
428 | ], []), | ||
429 | |||
430 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.prepareRemoteDataWithKey, this, aKey), | ||
431 | MochiKit.Base.partial(Clipperz.Async.setItem, result, 'record'), | ||
432 | |||
433 | MochiKit.Base.partial(MochiKit.Async.succeed, result) | ||
434 | ]); | ||
435 | |||
436 | deferredResult.callback(); | ||
437 | |||
438 | return deferredResult; | ||
439 | }, | ||
440 | |||
441 | //========================================================================= | ||
442 | |||
443 | 'fields': function () { | ||
444 | return this.invokeCurrentRecordVersionMethod('fields'); | ||
445 | }, | ||
446 | |||
447 | 'addField': function (someParameters) { | ||
448 | return this.invokeCurrentRecordVersionMethod('addField', someParameters); | ||
449 | }, | ||
450 | |||
451 | 'removeField': function (someParameters) { | ||
452 | return this.invokeCurrentRecordVersionMethod('removeField', someParameters); | ||
453 | }, | ||
454 | |||
455 | //'sortFieldReference': function (someSortedFieldReferences) { | ||
456 | // return this.invokeCurrentRecordVersionMethod('sortFieldReference', someSortedFieldReferences); | ||
457 | //}, | ||
458 | |||
459 | 'getFieldsValues': function () { | ||
460 | return this.invokeCurrentRecordVersionMethod('getFieldsValues'); | ||
461 | }, | ||
462 | |||
463 | 'fieldWithLabel': function (aLabel) { | ||
464 | return Clipperz.Async.callbacks("Record.fieldWithLabel", [ | ||
465 | MochiKit.Base.method(this, 'fields'), | ||
466 | MochiKit.Base.values, | ||
467 | MochiKit.Base.partial(Clipperz.Async.deferredFilter, function (aField) { | ||
468 | return Clipperz.Async.callbacks("Record.fieldWithLabel - check field label", [ | ||
469 | MochiKit.Base.methodcaller('label'), | ||
470 | MochiKit.Base.partial(MochiKit.Base.operator.eq, aLabel) | ||
471 | ], {trace:false}, aField); | ||
472 | }), | ||
473 | function (someFilteredResults) { | ||
474 | var result; | ||
475 | |||
476 | switch (someFilteredResults.length) { | ||
477 | case 0: | ||
478 | result = null; | ||
479 | break; | ||
480 | case 1: | ||
481 | result = someFilteredResults[0]; | ||
482 | break; | ||
483 | default: | ||
484 | WTF = TODO; | ||
485 | break; | ||
486 | } | ||
487 | |||
488 | return result; | ||
489 | } | ||
490 | ], {trace:false}); | ||
491 | }, | ||
492 | |||
493 | //========================================================================= | ||
494 | |||
495 | 'getVersion': function (aVersionReference) { | ||
496 | return Clipperz.Async.callbacks("Record.getVersion", [ | ||
497 | MochiKit.Base.method(this, 'getVersions'), | ||
498 | MochiKit.Base.itemgetter(aVersionReference) | ||
499 | ], {trace:false}); | ||
500 | }, | ||
501 | |||
502 | //------------------------------------------------------------------------- | ||
503 | |||
504 | 'getVersionKey': function (aVersionReference) { | ||
505 | vardeferredResult; | ||
506 | var transientStateKey; | ||
507 | |||
508 | transientStateKey = 'versionKeys' + '.' + aVersionReference; | ||
509 | if (this.transientState().getValue(transientStateKey) != null) { | ||
510 | deferredResult = MochiKit.Async.succeed(this.transientState().getValue(transientStateKey)); | ||
511 | } else { | ||
512 | deferredResult = Clipperz.Async.callbacks("Record.getVersionKey", [ | ||
513 | MochiKit.Base.method(this, 'getVersions'), | ||
514 | MochiKit.Base.partial(MochiKit.Base.operator.eq, aVersionReference, this.currentVersionReference()), | ||
515 | Clipperz.Async.deferredIf("getVersionKey for current version", [ | ||
516 | MochiKit.Base.method(this, 'getCurrentRecordVersionKey'), | ||
517 | MochiKit.Base.method(this.transientState(), 'setValue', transientStateKey) | ||
518 | ],[ | ||
519 | MochiKit.Async.fail | ||
520 | ]) | ||
521 | ], {trace:false}); | ||
522 | } | ||
523 | |||
524 | return deferredResult; | ||
525 | }, | ||
526 | |||
527 | //------------------------------------------------------------------------- | ||
528 | |||
529 | 'versions': function () { | ||
530 | return this._versions; | ||
531 | }, | ||
532 | |||
533 | 'getVersions': function () { | ||
534 | return Clipperz.Async.callbacks("Record.versions", [ | ||
535 | MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'), | ||
536 | MochiKit.Base.bind(function () { return this._versions; }, this) | ||
537 | ], {trace:false}); | ||
538 | }, | ||
539 | |||
540 | //------------------------------------------------------------------------- | ||
541 | |||
542 | 'getCurrentRecordVersion': function () { | ||
543 | return Clipperz.Async.callbacks("Record.getCurrentRecordVersion", [ | ||
544 | // MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'), | ||
545 | // MochiKit.Base.bind(function () { return this._currentRecordVersion; }, this) | ||
546 | |||
547 | MochiKit.Base.method(this, 'versions'), | ||
548 | MochiKit.Base.itemgetter(this.currentVersionReference()), | ||
549 | Clipperz.Async.deferredIf("The current version is available", [ | ||
550 | MochiKit.Async.succeed | ||
551 | ], [ | ||
552 | MochiKit.Base.method(this, 'getVersions'), | ||
553 | MochiKit.Base.bind(function (someVersions) { return someVersions[this.currentVersionReference()]}, this) | ||
554 | ]) | ||
555 | ], {trace:false}); | ||
556 | }, | ||
557 | |||
558 | 'setCurrentRecordVersion': function (aRecordVersion) { | ||
559 | this._currentVersionReference = aRecordVersion.reference(); | ||
560 | }, | ||
561 | |||
562 | //......................................................................... | ||
563 | |||
564 | 'currentVersionReference': function () { | ||
565 | return this._currentVersionReference; | ||
566 | }, | ||
567 | |||
568 | //------------------------------------------------------------------------- | ||
569 | |||
570 | 'createNewRecordVersion': function () { | ||
571 | var deferredResult; | ||
572 | |||
573 | if (this.isBrandNew()) { | ||
574 | deferredResult = this.getCurrentRecordVersion(); | ||
575 | } else { | ||
576 | var newVersion; | ||
577 | |||
578 | newVersion = new Clipperz.PM.DataModel.Record.Version({ | ||
579 | // 'reference': versionKey, | ||
580 | 'retrieveKeyFunction':MochiKit.Base.method(this, 'getVersionKey'), | ||
581 | // 'remoteData': {}, | ||
582 | 'getVersion': MochiKit.Base.method(this, 'getVersion') | ||
583 | }) | ||
584 | this._versions[newVersion.reference()] = newVersion; | ||
585 | |||
586 | deferredResult = Clipperz.Async.callbacks("Record.createNewRecordVersion", [ | ||
587 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
588 | // MochiKit.Base.methodcaller('values'), | ||
589 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'values'), | ||
590 | MochiKit.Base.method(newVersion, 'setValues'), | ||
591 | |||
592 | Clipperz.Async.collectResults("Record.createNewRecordVersion [collect results]", { | ||
593 | 'reference':MochiKit.Base.method(this, 'currentVersionReference'), | ||
594 | 'key': MochiKit.Base.method(this, 'getCurrentRecordVersionKey') | ||
595 | }, {trace:false}), | ||
596 | MochiKit.Base.method(newVersion, 'setPreviousVersionReferenceAndKey'), | ||
597 | |||
598 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
599 | // MochiKit.Base.method(this, 'revertChanges'), | ||
600 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'), | ||
601 | |||
602 | MochiKit.Base.method(this, 'setCurrentRecordVersion', newVersion), | ||
603 | MochiKit.Base.partial(MochiKit.Async.succeed, newVersion) | ||
604 | ], {trace:false}); | ||
605 | } | ||
606 | |||
607 | return deferredResult; | ||
608 | }, | ||
609 | |||
610 | //------------------------------------------------------------------------- | ||
611 | |||
612 | 'getCurrentRecordVersionKey': function () { | ||
613 | return Clipperz.Async.callbacks("Record.getCurrentRecordVersionKey", [ | ||
614 | MochiKit.Base.method(this, 'getValue', 'currentVersionKey'), | ||
615 | Clipperz.Async.deferredIf("currentVersionKey is NOT null", [ | ||
616 | MochiKit.Async.succeed | ||
617 | ], [ | ||
618 | MochiKit.Base.method(this, 'getKey') | ||
619 | ]) | ||
620 | ], {trace:false}); | ||
621 | }, | ||
622 | |||
623 | 'setCurrentRecordVersionKey': function (aValue) { | ||
624 | //TODO: triple check this method! | ||
625 | return Clipperz.Async.callbacks("Record.setCurrentRecordVersionKey", [ | ||
626 | MochiKit.Base.method(this, 'setValue', 'currentVersionKey', aValue) | ||
627 | ], {trace:false}); | ||
628 | }, | ||
629 | |||
630 | //------------------------------------------------------------------------- | ||
631 | |||
632 | 'invokeCurrentRecordVersionMethod': function (aMethodName, someValues) { | ||
633 | return Clipperz.Async.callbacks("Record.invokeCurrentRecordVersionMethod", [ | ||
634 | MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
635 | MochiKit.Base.methodcaller(aMethodName, someValues) | ||
636 | ], {trace:false}); | ||
637 | }, | ||
638 | |||
639 | |||
640 | 'lazilyinvokeCurrentRecordVersionMethod': function (aMethodName, someValues, defaultResult) { | ||
641 | return Clipperz.Async.callbacks("Record.lazilyinvokeCurrentRecordVersionMethod", [ | ||
642 | MochiKit.Base.method(this, 'currentVersionReference'), | ||
643 | Clipperz.Async.deferredIf("versions has been loaded", [ | ||
644 | MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
645 | MochiKit.Base.methodcaller(aMethodName, someValues), | ||
646 | ], [ | ||
647 | MochiKit.Base.partial(MochiKit.Async.succeed, defaultResult), | ||
648 | ]) | ||
649 | ], {trace:false}); | ||
650 | }, | ||
651 | |||
652 | //========================================================================= | ||
653 | |||
654 | 'hasPendingChanges': function () { | ||
655 | var deferredResult; | ||
656 | |||
657 | if (this.hasInitiatedObjectDataStore()) { | ||
658 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChanges", {trace:false}); | ||
659 | deferredResult.collectResults({ | ||
660 | 'super': MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasPendingChanges, this), | ||
661 | 'currentVersion': [ | ||
662 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
663 | // MochiKit.Base.methodcaller('hasPendingChanges') | ||
664 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges') | ||
665 | ], | ||
666 | 'directLogins': [ | ||
667 | MochiKit.Base.method(this, 'directLogins'), | ||
668 | MochiKit.Base.values, | ||
669 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')), | ||
670 | Clipperz.Async.collectAll, | ||
671 | Clipperz.Async.or | ||
672 | // function(someValues) { | ||
673 | // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
674 | // } | ||
675 | ] | ||
676 | }); | ||
677 | deferredResult.addCallback(MochiKit.Base.values); | ||
678 | deferredResult.addCallback(MochiKit.Base.bind(function(someValues) { | ||
679 | var result; | ||
680 | result = MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
681 | |||
682 | if ((result == false) && (this.isBrandNew() == false)) { | ||
683 | result = MochiKit.Iter.some(MochiKit.Base.values(this.transientState().getValue('hasPendingChanges.indexData')), MochiKit.Base.operator.identity); | ||
684 | } | ||
685 | |||
686 | return result; | ||
687 | }, this)); | ||
688 | |||
689 | deferredResult.callback(); | ||
690 | } else { | ||
691 | deferredResult = Clipperz.Async.callbacks("Recrod.hasPendingChanges [hasInitiatedObjectDataStore == false]", [ | ||
692 | MochiKit.Base.method(this, 'directLogins'), | ||
693 | MochiKit.Base.values, | ||
694 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')), | ||
695 | Clipperz.Async.collectAll, | ||
696 | Clipperz.Async.or | ||
697 | // function(someValues) { | ||
698 | // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
699 | // } | ||
700 | ], {trace:false}) | ||
701 | } | ||
702 | |||
703 | return deferredResult; | ||
704 | }, | ||
705 | |||
706 | //------------------------------------------------------------------------- | ||
707 | |||
708 | 'hasPendingChangesWhenBrandNew': function () { | ||
709 | var deferredResult; | ||
710 | |||
711 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChangesWhenBrandNew", {trace:false}); | ||
712 | deferredResult.collectResults({ | ||
713 | 'label': [ | ||
714 | MochiKit.Base.method(this, 'label'), | ||
715 | MochiKit.Base.partial(MochiKit.Base.operator.ne, '') | ||
716 | ], | ||
717 | 'notes': [ | ||
718 | MochiKit.Base.method(this, 'notes'), | ||
719 | MochiKit.Base.partial(MochiKit.Base.operator.ne, '') | ||
720 | ] | ||
721 | }); | ||
722 | // deferredResult.addCallback(MochiKit.Base.values); | ||
723 | // deferredResult.addCallback(function(someValues) { | ||
724 | // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
725 | // }); | ||
726 | deferredResult.addCallback(Clipperz.Async.or); | ||
727 | |||
728 | deferredResult.callback(); | ||
729 | |||
730 | return deferredResult; | ||
731 | }, | ||
732 | |||
733 | //------------------------------------------------------------------------- | ||
734 | |||
735 | 'isBrandNewWithNoPendingChanges': function () { | ||
736 | vardeferredResult; | ||
737 | |||
738 | if (this.isBrandNew() == false) { | ||
739 | deferredResult = MochiKit.Async.succeed(false); | ||
740 | } else { | ||
741 | deferredResult = Clipperz.Async.callbacks("Record.isBrandNewWithNoPendingChanges", [ | ||
742 | MochiKit.Base.method(this, 'hasPendingChanges'), | ||
743 | MochiKit.Base.operator.lognot | ||
744 | ], {trace:false}); | ||
745 | } | ||
746 | |||
747 | return deferredResult; | ||
748 | }, | ||
749 | |||
750 | //========================================================================= | ||
751 | |||
752 | 'revertChanges': function () { | ||
753 | var deferredResult; | ||
754 | |||
755 | if (this.isBrandNew() == false) { | ||
756 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.revertChanges", {trace:false}); | ||
757 | deferredResult.addMethod(this, 'hasPendingChanges'); | ||
758 | deferredResult.addIf([ | ||
759 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
760 | // MochiKit.Base.methodcaller('revertChanges'), | ||
761 | MochiKit.Base.method(this,'invokeCurrentRecordVersionMethod', 'revertChanges'), | ||
762 | |||
763 | MochiKit.Base.method(this, 'directLogins'), | ||
764 | MochiKit.Base.values, | ||
765 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')), | ||
766 | |||
767 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this) | ||
768 | ], [ | ||
769 | MochiKit.Async.succeed | ||
770 | ]); | ||
771 | deferredResult.callback(); | ||
772 | } else { | ||
773 | // this.deleteAllCleanTextData(); | ||
774 | deferredResult = MochiKit.Async.succeed(); | ||
775 | } | ||
776 | |||
777 | return deferredResult; | ||
778 | }, | ||
779 | |||
780 | //------------------------------------------------------------------------- | ||
781 | |||
782 | 'resetTransientState': function (isCommitting) { | ||
783 | // if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) { | ||
784 | // this._directLogins = this.transientState().getValue('directLogins'); | ||
785 | // } | ||
786 | |||
787 | return Clipperz.Async.callbacks("Record.resetTransientState", [ | ||
788 | //- MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
789 | //- MochiKit.Base.methodcaller('resetTransientState'), | ||
790 | // MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'resetTransientState'), | ||
791 | MochiKit.Base.method(this, 'lazilyinvokeCurrentRecordVersionMethod', 'resetTransientState'), | ||
792 | |||
793 | MochiKit.Base.method(this, 'directLogins'), | ||
794 | MochiKit.Base.values, | ||
795 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('resetTransientState')), | ||
796 | |||
797 | MochiKit.Base.bind(function () { | ||
798 | if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) { | ||
799 | this._directLogins = this.transientState().getValue('directLogins'); | ||
800 | } | ||
801 | }, this), | ||
802 | |||
803 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.resetTransientState, this, isCommitting) | ||
804 | ], {trace:false}) | ||
805 | }, | ||
806 | |||
807 | //------------------------------------------------------------------------- | ||
808 | |||
809 | 'commitTransientState': function () { | ||
810 | var deferredResult; | ||
811 | |||
812 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.commitTransientState", {trace:false}); | ||
813 | deferredResult.addMethod(this, 'hasPendingChanges'); | ||
814 | deferredResult.addIf([ | ||
815 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.commitTransientState, this), | ||
816 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
817 | // MochiKit.Base.methodcaller('commitTransientState'), | ||
818 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'commitTransientState'), | ||
819 | MochiKit.Base.method(this, 'directLogins'), | ||
820 | MochiKit.Base.values, | ||
821 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('commitTransientState')) | ||
822 | ], [ | ||
823 | MochiKit.Async.succeed | ||
824 | ]); | ||
825 | deferredResult.callback(); | ||
826 | |||
827 | return deferredResult; | ||
828 | }, | ||
829 | |||
830 | //========================================================================= | ||
831 | |||
832 | 'retrieveDirectLoginIndexDataFunction': function () { | ||
833 | return this._retrieveDirectLoginIndexDataFunction; | ||
834 | }, | ||
835 | |||
836 | 'setDirectLoginIndexDataFunction': function () { | ||
837 | return this._setDirectLoginIndexDataFunction; | ||
838 | }, | ||
839 | |||
840 | 'removeDirectLoginIndexDataFunction': function () { | ||
841 | return this._removeDirectLoginIndexDataFunction; | ||
842 | }, | ||
843 | |||
844 | //========================================================================= | ||
845 | |||
846 | 'deleteAllCleanTextData': function () { | ||
847 | // return Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData.apply(this, arguments); | ||
848 | |||
849 | return Clipperz.Async.callbacks("Record.deleteAllCleanTextData", [ | ||
850 | MochiKit.Base.method(this, 'versions'), | ||
851 | MochiKit.Base.values, | ||
852 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')), | ||
853 | |||
854 | MochiKit.Base.method(this, 'directLogins'), | ||
855 | MochiKit.Base.values, | ||
856 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')), | ||
857 | |||
858 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData, this) | ||
859 | ], {trace:false}); | ||
860 | }, | ||
861 | |||
862 | 'hasAnyCleanTextData': function () { | ||
863 | // return Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData.apply(this, arguments); | ||
864 | |||
865 | return Clipperz.Async.callbacks("Record.hasAnyCleanTextData", [ | ||
866 | Clipperz.Async.collectResults("Record.hasAnyCleanTextData [collect results]", { | ||
867 | 'versions':[ | ||
868 | MochiKit.Base.method(this, 'versions'), | ||
869 | MochiKit.Base.values, | ||
870 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')), | ||
871 | Clipperz.Async.collectAll | ||
872 | ], | ||
873 | 'directLogins': [ | ||
874 | MochiKit.Base.method(this, 'directLogins'), | ||
875 | MochiKit.Base.values, | ||
876 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')), | ||
877 | Clipperz.Async.collectAll | ||
878 | ], | ||
879 | 'super': [ | ||
880 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData, this) | ||
881 | ] | ||
882 | }, {trace:false}), | ||
883 | Clipperz.Async.or | ||
884 | ]) | ||
885 | }, | ||
886 | |||
887 | //========================================================================= | ||
888 | __syntaxFix__: "syntax fix" | ||
889 | }); | ||
890 | |||
891 | |||