[Edit] Utilize model cache

Utilize model cache, permitting object models in edit mode to
be reused across multiple distinct instances with unique
contexts (unique contexts are necessary to avoid ambiguity in
the Remove action, WTD-473).

To avoid infinite digest cycles as a consequence of this,
refactor context/composition capability wrappers such that the
former is idempotent (since idempotence is no longer ensured
by the EditableDomainObjectCache) to avoid infinite digest
errors in Edit mode.
This commit is contained in:
Victor Woeltjen
2015-01-27 11:52:58 -08:00
parent 431af3adbc
commit 3135174491
5 changed files with 154 additions and 60 deletions

View File

@ -2,12 +2,12 @@
define(
[],
function () {
['./EditableLookupCapability'],
function (EditableLookupCapability) {
'use strict';
/**
* Wrapper for both "context" and "composition" capabilities;
* Wrapper for the "context" capability;
* ensures that any domain objects reachable in Edit mode
* are also wrapped as EditableDomainObjects.
*
@ -21,55 +21,15 @@ define(
domainObject,
cache
) {
var capability = Object.create(contextCapability);
// Check for domain object interface. If something has these
// three methods, we assume it's a domain object.
function isDomainObject(obj) {
return obj !== undefined &&
typeof obj.getId === 'function' &&
typeof obj.getModel === 'function' &&
typeof obj.getCapability === 'function';
}
// Check an object returned by the wrapped capability; if it
// is a domain object, we want to make it editable and/or get
// it from the cache of editable domain objects. This will
// prevent changes made in edit mode from modifying the actual
// underlying domain object.
function makeEditableObject(obj) {
return isDomainObject(obj) ?
cache.getEditableObject(obj) :
obj;
}
// Wrap a returned value (see above); if it's an array, wrap
// all elements.
function makeEditable(returnValue) {
return Array.isArray(returnValue) ?
returnValue.map(makeEditableObject) :
makeEditableObject(returnValue);
}
// Wrap a returned value (see above); if it's a promise, wrap
// the resolved value.
function wrapResult(result) {
return result.then ? // promise-like
result.then(makeEditable) :
makeEditable(result);
}
// Wrap all methods; return only editable domain objects.
Object.keys(contextCapability).forEach(function (k) {
capability[k] = function () {
return wrapResult(contextCapability[k].apply(
capability,
arguments
));
};
});
return capability;
// This is a "lookup" style capability (it looks up other
// domain objects), and it should be idempotent
return new EditableLookupCapability(
contextCapability,
editableObject,
domainObject,
cache,
true // Not idempotent
);
};
}
);