mirror of
https://github.com/nasa/openmct.git
synced 2025-02-07 11:30:28 +00:00
[Containment] Add general policy for containment rules
Add general policy for supporting containment rules, WTD-962.
This commit is contained in:
parent
3c3dd0ad17
commit
3c00eb86ea
2
platform/containment/README.md
Normal file
2
platform/containment/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Implements support for rules which determine which objects are allowed
|
||||||
|
to contain other objects, typically by type.
|
53
platform/containment/src/CapabilityTable.js
Normal file
53
platform/containment/src/CapabilityTable.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*global define*/
|
||||||
|
|
||||||
|
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a table indicating which types are expected to expose
|
||||||
|
* which capabilities.
|
||||||
|
*/
|
||||||
|
function CapabilityTable(typeService, capabilityService) {
|
||||||
|
var table = {};
|
||||||
|
|
||||||
|
// Build an initial model for a type
|
||||||
|
function buildModel(type) {
|
||||||
|
var model = Object.create(type.getInitialModel() || {});
|
||||||
|
model.type = type.getKey();
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get capabilities expected for this type
|
||||||
|
function getCapabilities(type) {
|
||||||
|
return capabilityService.getCapabilities(buildModel(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the lookup table for this type's capabilities
|
||||||
|
function addToTable(type) {
|
||||||
|
var typeKey = type.getKey();
|
||||||
|
Object.keys(getCapabilities(type)).forEach(function (key) {
|
||||||
|
table[key] = table[key] || {};
|
||||||
|
table[key][typeKey] = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the table
|
||||||
|
(typeService.listTypes() || []).forEach(addToTable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Check if a type is expected to expose a specific
|
||||||
|
* capability.
|
||||||
|
*/
|
||||||
|
hasCapability: function (typeKey, capabilityKey) {
|
||||||
|
return (table[capabilityKey] || {})[typeKey];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return CapabilityTable;
|
||||||
|
}
|
||||||
|
);
|
29
platform/containment/src/CompositionPolicy.js
Normal file
29
platform/containment/src/CompositionPolicy.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*global define*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
['./ContainmentTable'],
|
||||||
|
function (ContainmentTable) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines composition policy as driven by type metadata.
|
||||||
|
*/
|
||||||
|
function CompositionPolicy(typeService, capabilityService) {
|
||||||
|
// We're really just wrapping the containment table and rephrasing
|
||||||
|
// it as a policy decision.
|
||||||
|
var table = new ContainmentTable(typeService, capabilityService);
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Is the type identified by the candidate allowed to
|
||||||
|
* contain the type described by the context?
|
||||||
|
*/
|
||||||
|
allow: function (candidate, context) {
|
||||||
|
return table.canContain(candidate, context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompositionPolicy;
|
||||||
|
}
|
||||||
|
);
|
98
platform/containment/src/ContainmentTable.js
Normal file
98
platform/containment/src/ContainmentTable.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*global define*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
['./CapabilityTable'],
|
||||||
|
function (CapabilityTable) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Symbolic value for the type table for cases when any type
|
||||||
|
// is allowed to be contained.
|
||||||
|
var ANY = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supports composition policy by maintaining a table of
|
||||||
|
* domain object types, to determine if they can contain
|
||||||
|
* other domain object types. This is determined at application
|
||||||
|
* start time (plug-in support means this cannot be determined
|
||||||
|
* prior to that, but we don't want to redo these calculations
|
||||||
|
* every time policy is checked.)
|
||||||
|
*/
|
||||||
|
function ContainmentTable(typeService, capabilityService) {
|
||||||
|
var types = typeService.listTypes(),
|
||||||
|
capabilityTable = new CapabilityTable(typeService, capabilityService),
|
||||||
|
table = {};
|
||||||
|
|
||||||
|
// Check if one type can contain another
|
||||||
|
function canContain(containerType, containedType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add types which have all these capabilities to the set
|
||||||
|
// of allowed types
|
||||||
|
function addToSetByCapability(set, has) {
|
||||||
|
has = Array.isArray(has) ? has : [has];
|
||||||
|
types.forEach(function (type) {
|
||||||
|
var typeKey = type.getKey();
|
||||||
|
set[typeKey] = has.map(function (capabilityKey) {
|
||||||
|
return capabilityTable.hasCapability(typeKey, capabilityKey);
|
||||||
|
}).reduce(function (a, b) {
|
||||||
|
return a && b;
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this type (or type description) to the set of allowed types
|
||||||
|
function addToSet(set, type) {
|
||||||
|
// Is this a simple case of an explicit type identifier?
|
||||||
|
if (typeof type === 'string') {
|
||||||
|
// If so, add it to the set of allowed types
|
||||||
|
set[type] = true;
|
||||||
|
} else {
|
||||||
|
// Otherwise, populate that set based on capabilities
|
||||||
|
addToSetByCapability(set, (type || {}).has || []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to the lookup table for this type
|
||||||
|
function addToTable(type) {
|
||||||
|
var key = type.getKey(),
|
||||||
|
definition = type.getDefinition() || {},
|
||||||
|
contains = definition.contains;
|
||||||
|
|
||||||
|
// Check for defined containment restrictions
|
||||||
|
if (contains === undefined) {
|
||||||
|
// If not, accept anything
|
||||||
|
table[key] = ANY;
|
||||||
|
} else {
|
||||||
|
// Start with an empty set...
|
||||||
|
table[key] = {};
|
||||||
|
// ...cast accepted types to array if necessary...
|
||||||
|
contains = Array.isArray(contains) ? contains : [contains];
|
||||||
|
// ...and add all containment rules to that set
|
||||||
|
contains.forEach(function (c) {
|
||||||
|
addToSet(table[key], c);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the table
|
||||||
|
types.forEach(addToTable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Check if domain objects of one type can contain domain
|
||||||
|
* objects of another type.
|
||||||
|
* @returns {boolean} true if allowable
|
||||||
|
*/
|
||||||
|
canContain: function (containerType, containedType) {
|
||||||
|
var set = table[containerType.getKey()] || {};
|
||||||
|
// Recognize either the symbolic value for "can contain
|
||||||
|
// anything", or lookup the specific type from the set.
|
||||||
|
return (set === ANY) || set[containedType.getKey()];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ContainmentTable;
|
||||||
|
}
|
||||||
|
);
|
Loading…
x
Reference in New Issue
Block a user