/***************************************************************************** * Open MCT Web, Copyright (c) 2014-2015, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * * Open MCT Web is licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * * Open MCT Web includes source code licensed under additional open source * licenses. See the Open Source Licenses file (LICENSES.md) included with * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ /** * Module defining ActionProvider. Created by vwoeltje on 11/7/14. */ define( [], function () { /** * An ActionProvider (implementing ActionService) provides actions * that are applicable in specific contexts, chosen from a set * of actions exposed via extension (specifically, the "actions" * category of extension.) * * @memberof platform/core * @imeplements {ActionService} * @constructor */ function ActionProvider(actions, $log) { var self = this; this.$log = $log; // Build up look-up tables this.actions = actions; this.actionsByKey = {}; this.actionsByCategory = {}; actions.forEach(function (Action) { // Get an action's category or categories var categories = Action.category || []; // Convert to an array if necessary categories = Array.isArray(categories) ? categories : [categories]; // Store action under all relevant categories categories.forEach(function (category) { self.actionsByCategory[category] = self.actionsByCategory[category] || []; self.actionsByCategory[category].push(Action); }); // Store action by ekey as well if (Action.key) { self.actionsByKey[Action.key] = self.actionsByKey[Action.key] || []; self.actionsByKey[Action.key].push(Action); } }); } ActionProvider.prototype.getActions = function (actionContext) { var context = (actionContext || {}), category = context.category, key = context.key, $log = this.$log, candidates; // Instantiate an action; invokes the constructor and // additionally fills in the action's getMetadata method // with the extension definition (if no getMetadata // method was supplied.) function instantiateAction(Action, ctxt) { var action = new Action(ctxt), metadata; // Provide a getMetadata method that echos // declarative bindings, as well as context, // unless the action has defined its own. if (!action.getMetadata) { metadata = Object.create(Action.definition || {}); metadata.context = ctxt; action.getMetadata = function () { return metadata; }; } return action; } // Filter the array of actions down to those which are // applicable in a given context, according to the static // appliesTo method of given actions (if defined), and // instantiate those applicable actions. function createIfApplicable(actions, ctxt) { function isApplicable(Action) { return Action.appliesTo ? Action.appliesTo(ctxt) : true; } function instantiate(Action) { try { return instantiateAction(Action, ctxt); } catch (e) { $log.error([ "Could not instantiate action", Action.key, "due to:", e.message ].join(" ")); return undefined; } } function isDefined(action) { return action !== undefined; } return (actions || []).filter(isApplicable) .map(instantiate) .filter(isDefined); } // Match actions to the provided context by comparing "key" // and/or "category" parameters, if specified. candidates = this.actions; if (key) { candidates = this.actionsByKey[key]; if (category) { candidates = candidates.filter(function (Action) { return Action.category === category; }); } } else if (category) { candidates = this.actionsByCategory[category]; } // Instantiate those remaining actions, with additional // filtering per any appliesTo methods defined on those // actions. return createIfApplicable(candidates, context); }; return ActionProvider; } );