[Core] Bring in core bundle from sandbox

Bring in bundle platform/core from the sandbox
branch, in preparation for clean up, tests, and
integration. WTD-573
This commit is contained in:
Victor Woeltjen
2014-11-20 12:58:21 -08:00
parent c50ca2e92b
commit 0fdce798f7
38 changed files with 2914 additions and 0 deletions

View File

@ -0,0 +1,94 @@
/*global define,Promise*/
/**
* Module defining CompositionCapability. Created by vwoeltje on 11/7/14.
*/
define(
["./ContextualDomainObject"],
function (ContextualDomainObject) {
"use strict";
/**
* Composition capability. A domain object's composition is the set of
* domain objects it contains. This is available as an array of
* identifiers in the model; the composition capability makes this
* available as an array of domain object instances, which may
* require consulting the object service (e.g. to trigger a database
* query to retrieve the nested object models.)
*
* @constructor
*/
function CompositionCapability($injector, domainObject) {
var objectService,
lastPromise,
lastModified;
// Get a reference to the object service from $injector
function injectObjectService() {
objectService = $injector.get("objectService");
return objectService;
}
// Get a reference to the object service (either cached or
// from the injector)
function getObjectService() {
return objectService || injectObjectService();
}
// Promise this domain object's composition (an array of domain
// object instances corresponding to ids in its model.)
function promiseComposition() {
var model = domainObject.getModel(),
ids;
// Then filter out non-existent objects,
// and wrap others (such that they expose a
// "context" capability)
function contextualize(objects) {
return ids.filter(function (id) {
return objects[id];
}).map(function (id) {
return new ContextualDomainObject(
objects[id],
domainObject
);
});
}
// Make a new request if we haven't made one, or if the
// object has been modified.
if (!lastPromise || lastModified !== model.modified) {
ids = model.composition || [];
lastModified = model.modified;
// Load from the underlying object service
lastPromise = getObjectService().getObjects(ids)
.then(contextualize);
}
return lastPromise;
}
return {
/**
* Request the composition of this object.
* @returns {Promise.<DomainObject[]>} a list of all domain
* objects which compose this domain object.
*/
invoke: promiseComposition
};
}
/**
* Test to determine whether or not this capability should be exposed
* by a domain object based on its model. Checks for the presence of
* a composition field, that must be an array.
* @param model the domain object model
* @returns {boolean} true if this object has a composition
*/
CompositionCapability.appliesTo = function (model) {
return Array.isArray((model || {}).composition);
};
return CompositionCapability;
}
);

View File

@ -0,0 +1,50 @@
/*global define,Promise*/
/**
* Module defining ContextCapability. Created by vwoeltje on 11/17/14.
*/
define(
[],
function () {
"use strict";
/**
*
* @constructor
*/
function ContextCapability(parentObject, domainObject) {
var self,
parentObject;
self = {
getParent: function () {
return parentObject;
},
getPath: function () {
var parentPath = [],
parentContext;
if (parentObject) {
parentContext = parentObject.getCapability("context");
parentPath = parentContext ?
parentContext.getPath() :
[parentObject];
}
return parentPath.concat([domainObject]);
},
getRoot: function () {
return self.getPath()[0];
}
};
return self;
}
ContextCapability.appliesTo = function () {
return true;
};
return ContextCapability;
}
);

View File

@ -0,0 +1,31 @@
/*global define,Promise*/
/**
* Module defining ContextualDomainObject. Created by vwoeltje on 11/18/14.
*/
define(
["./ContextCapability"],
function (ContextCapability) {
"use strict";
/**
*
* @constructor
*/
function ContextualDomainObject(domainObject, parentObject) {
var contextualObject = Object.create(domainObject),
contextCapability =
new ContextCapability(parentObject, domainObject);
contextualObject.getCapability = function (name) {
return name === "context" ?
contextCapability :
domainObject.getCapability.apply(this, arguments);
};
return contextualObject;
}
return ContextualDomainObject;
}
);

View File

@ -0,0 +1,63 @@
/*global define,Promise*/
/**
* Module defining CoreCapabilityProvider. Created by vwoeltje on 11/7/14.
*/
define(
[],
function () {
"use strict";
/**
* Provides capabilities based on extension definitions.
* @constructor
*/
function CoreCapabilityProvider(capabilities) {
// Filter by invoking the capability's appliesTo method
function filterCapabilities(model) {
return capabilities.filter(function (capability) {
return capability.appliesTo ?
capability.appliesTo(model) :
true;
});
}
// Package capabilities as key-value pairs
function packageCapabilities(capabilities) {
var result = {};
capabilities.forEach(function (capability) {
result[capability.key] = capability;
});
return result;
}
function getCapabilities(model) {
return packageCapabilities(filterCapabilities(model));
}
return {
/**
* Get all capabilities associated with a given domain
* object.
*
* This returns a promise for an object containing key-value
* pairs, where keys are capability names and values are
* either:
*
* * Capability instances
* * Capability constructors (which take a domain object
* as their argument.)
*
*
* @param {*} model the object model
* @returns {Object.<string,function|Capability>} all
* capabilities known to be valid for this model, as
* key-value pairs
*/
getCapabilities: getCapabilities
};
}
return CoreCapabilityProvider;
}
);

View File

@ -0,0 +1,57 @@
/*global define,Promise*/
/**
* Module defining DelegationCapability. Created by vwoeltje on 11/18/14.
*/
define(
[],
function () {
'use strict';
function DelegationCapability(domainObject) {
var delegateCapabilities = {},
type = domainObject.getCapability("type");
function filterObjectsWithCapability(capability) {
return function (objects) {
return objects.filter(function (obj) {
return obj.hasCapability(capability);
});
};
}
function promiseChildren() {
return domainObject.useCapability('composition');
}
function doesDelegate(key) {
return delegateCapabilities[key] || false;
}
function getDelegates(capability) {
return doesDelegate(capability) ?
promiseChildren().then(
filterObjectsWithCapability(capability)
) :
[];
}
// Generate set for easy lookup of capability delegation
if (type && type.getDefinition) {
(type.getDefinition().delegates || []).forEach(function (key) {
delegateCapabilities[key] = true;
});
}
return {
invoke: getDelegates,
getDelegates: getDelegates,
doesDelegateCapability: doesDelegate
};
}
return DelegationCapability;
}
);

View File

@ -0,0 +1,63 @@
/*global define,Promise*/
/**
* Module defining MutationCapability. Created by vwoeltje on 11/12/14.
*/
define(
[],
function () {
"use strict";
// Utility function to overwrite a destination object
// with the contents of a source object.
function copyValues(destination, source) {
// First, remove all previously-existing keys
Object.keys(destination).forEach(function (k) {
delete destination[k];
});
// Second, write all new keys
Object.keys(source).forEach(function (k) {
destination[k] = source[k];
});
}
function MutationCapability($q, domainObject) {
function mutate(mutator) {
// Get the object's model and clone it, so the
// mutator function has a temporary copy to work with.
var model = domainObject.getModel(),
clone = JSON.parse(JSON.stringify(model));
// Function to handle copying values to the actual
function handleMutation(mutationResult) {
// If mutation result was undefined, just use
// the clone; this allows the mutator to omit return
// values and just change the model directly.
var result = mutationResult || clone;
// Allow mutators to change their mind by
// returning false.
if (mutationResult !== false) {
copyValues(model, result);
model.modified = Date.now();
}
// Report the result of the mutation
return mutationResult !== false;
}
// Invoke the provided mutator, then make changes to
// the underlying model (if applicable.)
return $q.when(mutator(clone))
.then(handleMutation);
}
return {
invoke: mutate
};
}
return MutationCapability;
}
);

View File

@ -0,0 +1,38 @@
/*global define*/
/**
* Defines the "persistence" capability, used to indicate
* that changes to an object should be written to some
* underlying store.
*
* Current implementation is a stub that simply triggers
* a refresh on modified views, which is a necessary
* side effect of persisting the object.
*/
define(
function () {
'use strict';
function PersistenceCapability(persistenceService, SPACE, domainObject) {
var self = {
persist: function () {
return persistenceService.updateObject(
SPACE,
domainObject.getId(),
domainObject.getModel()
);
},
getSpace: function () {
return SPACE;
},
invoke: function () {
return self;
}
};
return self;
}
return PersistenceCapability;
}
);