From c65096f16636a63b5c5de5da1bf2879d2bcac3c9 Mon Sep 17 00:00:00 2001
From: Henry <akhenry@gmail.com>
Date: Wed, 20 Jan 2016 18:49:39 -0800
Subject: [PATCH] [New Edit Mode] Added AddAction, modified
 EditableDomainObject to properly wrap inherited functions, added new
 EditableInstantiationCapability

---
 platform/commonUI/browse/bundle.js            |  14 ++
 .../commonUI/browse/src/creation/AddAction.js | 134 +++++++++++++++++
 .../browse/src/creation/AddActionProvider.js  |  87 +++++++++++
 .../browse/src/creation/CreateWizard.js       |  34 ++++-
 .../test/creation/AddActionProviderSpec.js    | 137 ++++++++++++++++++
 .../test/creation/CreateActionProviderSpec.js |  19 ++-
 .../commonUI/edit/src/actions/SaveAction.js   |  55 +------
 .../EditableInstantiationCapability.js        |  60 ++++++++
 .../capabilities/EditableLookupCapability.js  |   4 +-
 .../edit/src/capabilities/EditorCapability.js |  11 +-
 .../edit/src/objects/EditableDomainObject.js  |   3 +
 .../EditableLookupCapabilitySpec.js           |  23 +++
 .../src/controllers/swimlane/TimelineProxy.js |   2 +-
 13 files changed, 512 insertions(+), 71 deletions(-)
 create mode 100644 platform/commonUI/browse/src/creation/AddAction.js
 create mode 100644 platform/commonUI/browse/src/creation/AddActionProvider.js
 create mode 100644 platform/commonUI/browse/test/creation/AddActionProviderSpec.js
 create mode 100644 platform/commonUI/edit/src/capabilities/EditableInstantiationCapability.js

diff --git a/platform/commonUI/browse/bundle.js b/platform/commonUI/browse/bundle.js
index 21aba14b91..4b8f8dd850 100644
--- a/platform/commonUI/browse/bundle.js
+++ b/platform/commonUI/browse/bundle.js
@@ -34,6 +34,7 @@ define([
     "./src/windowing/NewTabAction",
     "./src/windowing/FullscreenAction",
     "./src/creation/CreateActionProvider",
+    "./src/creation/AddActionProvider",
     "./src/creation/CreationService",
     "./src/windowing/WindowTitler",
     'legacyRegistry'
@@ -50,6 +51,7 @@ define([
     NewTabAction,
     FullscreenAction,
     CreateActionProvider,
+    AddActionProvider,
     CreationService,
     WindowTitler,
     legacyRegistry
@@ -271,6 +273,18 @@ define([
                         "policyService"
                     ]
                 },
+                {
+                    "key": "AddActionProvider",
+                    "provides": "actionService",
+                    "type": "provider",
+                    "implementation": AddActionProvider,
+                    "depends": [
+                        "$q",
+                        "typeService",
+                        "dialogService",
+                        "policyService"
+                    ]
+                },
                 {
                     "key": "CreationService",
                     "provides": "creationService",
diff --git a/platform/commonUI/browse/src/creation/AddAction.js b/platform/commonUI/browse/src/creation/AddAction.js
new file mode 100644
index 0000000000..31d158e7bd
--- /dev/null
+++ b/platform/commonUI/browse/src/creation/AddAction.js
@@ -0,0 +1,134 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+/*global define,Promise*/
+
+/**
+ * Module defining CreateAction. Created by vwoeltje on 11/10/14.
+ */
+define(
+    [
+        './CreateWizard'
+    ],
+    function (CreateWizard) {
+        "use strict";
+
+        /**
+         * The Add Action is performed to create new instances of
+         * domain objects of a specific type that are subobjects of an
+         * object being edited. This is the action that is performed when a
+         * user uses the Add menu option.
+         *
+         * @memberof platform/commonUI/browse
+         * @implements {Action}
+         * @constructor
+         *
+         * @param {Type} type the type of domain object to create
+         * @param {DomainObject} parent the domain object that should
+         *        act as a container for the newly-created object
+         *        (note that the user will have an opportunity to
+         *        override this)
+         * @param {ActionContext} context the context in which the
+         *        action is being performed
+         * @param {DialogService} dialogService
+         */
+        function AddAction(type, parent, context, $q, dialogService, policyService) {
+            this.metadata = {
+                key: 'add',
+                glyph: type.getGlyph(),
+                name: type.getName(),
+                type: type.getKey(),
+                description: type.getDescription(),
+                context: context
+            };
+
+            this.type = type;
+            this.parent = parent;
+            this.$q = $q;
+            this.dialogService = dialogService;
+            this.policyService = policyService;
+        }
+        /**
+         * Create a new object of the given type.
+         * This will prompt for user input first.
+         */
+        AddAction.prototype.perform = function () {
+            var newModel = this.type.getInitialModel(),
+                newObject,
+                parentObject = this.parent,
+                wizard;
+
+            newModel.type = this.type.getKey();
+            newObject = parentObject.getCapability('instantiation').instantiate(newModel);
+            newObject.useCapability('mutation', function(model){
+                model.location = parentObject.getId();
+            });
+
+            wizard = new CreateWizard(newObject, this.parent, this.policyService);
+
+            function populateObjectFromInput (formValue) {
+                return wizard.populateObjectFromInput(formValue, newObject);
+            }
+
+            function addToParent (populatedObject) {
+                parentObject.getCapability('composition').add(populatedObject);
+                return parentObject.getCapability('persistence').persist().then(function(){
+                    return parentObject;
+                });
+            }
+
+            function save(object) {
+                /*
+                It's necessary to persist the new sub-object in order
+                 that it can be retrieved for composition in the parent.
+                 Future refactoring that allows temporary objects to be
+                 retrieved from object services will make this unnecessary.
+                 */
+                return object.getCapability('editor').save(true);
+            }
+
+            return this.dialogService
+                .getUserInput(wizard.getFormStructure(), wizard.getInitialFormValue())
+                .then(populateObjectFromInput)
+                .then(save)
+                .then(addToParent)
+
+        };
+
+
+        /**
+         * Metadata associated with a Add action.
+         * @typedef {ActionMetadata} AddActionMetadata
+         * @property {string} type the key for the type of domain object
+         *           to be created
+         */
+
+        /**
+         * Get metadata about this action.
+         * @returns {AddActionMetadata} metadata about this action
+         */
+        AddAction.prototype.getMetadata = function () {
+           return this.metadata;
+        };
+
+        return AddAction;
+    }
+);
diff --git a/platform/commonUI/browse/src/creation/AddActionProvider.js b/platform/commonUI/browse/src/creation/AddActionProvider.js
new file mode 100644
index 0000000000..6f799b8d9b
--- /dev/null
+++ b/platform/commonUI/browse/src/creation/AddActionProvider.js
@@ -0,0 +1,87 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+/*global define,Promise*/
+
+/**
+ * Module defining CreateActionProvider.js. Created by vwoeltje on 11/10/14.
+ */
+define(
+    ["./AddAction"],
+    function (AddAction) {
+        "use strict";
+
+        /**
+         * The AddActionProvider is an ActionProvider which introduces
+         * an Add action for creating sub objects.
+         *
+         * @memberof platform/commonUI/browse
+         * @constructor
+         * @implements {ActionService}
+         *
+         * @param {TypeService} typeService the type service, used to discover
+         *        available types
+         * @param {DialogService} dialogService the dialog service, used by
+         *        specific Create actions to get user input to populate the
+         *        model of the newly-created domain object.
+         * @param {CreationService} creationService the creation service (also
+         *        introduced in this bundle), responsible for handling actual
+         *        object creation.
+         */
+        function AddActionProvider($q, typeService, dialogService, policyService) {
+            this.typeService = typeService;
+            this.dialogService = dialogService;
+            this.$q = $q;
+            this.policyService = policyService;
+        }
+
+        AddActionProvider.prototype.getActions = function (actionContext) {
+            var context = actionContext || {},
+                key = context.key,
+                destination = context.domainObject,
+                self = this;
+
+            // We only provide Add actions, and we need a
+            // domain object to serve as the container for the
+            // newly-created object (although the user may later
+            // make a different selection)
+            if (key !== 'add' || !destination) {
+                return [];
+            }
+
+            // Introduce one create action per type
+            return this.typeService.listTypes().filter(function (type) {
+                return self.policyService.allow("creation", type) && self.policyService.allow("composition", destination.getCapability('type'), type);
+            }).map(function (type) {
+                return new AddAction(
+                    type,
+                    destination,
+                    context,
+                    self.$q,
+                    self.dialogService,
+                    self.policyService
+                );
+            });
+        };
+
+        return AddActionProvider;
+    }
+);
diff --git a/platform/commonUI/browse/src/creation/CreateWizard.js b/platform/commonUI/browse/src/creation/CreateWizard.js
index caa60c6150..8bf4c5a2f1 100644
--- a/platform/commonUI/browse/src/creation/CreateWizard.js
+++ b/platform/commonUI/browse/src/creation/CreateWizard.js
@@ -26,18 +26,21 @@ define(
         'use strict';
 
         /**
-         * Construct a new CreateWizard.
+         * A class for capturing user input data from an object creation
+         * dialog, and populating a domain object with that data.
          *
-         * @param {TypeImpl} type the type of domain object to be created
+         * @param {DomainObject} domainObject the newly created object to
+         * populate with user input
          * @param {DomainObject} parent the domain object to serve as
          *        the initial parent for the created object, in the dialog
          * @memberof platform/commonUI/browse
          * @constructor
          */
-        function CreateWizard(type, parent, policyService, initialModel) {
-            this.type = type;
-            this.model = initialModel || type.getInitialModel();
-            this.properties = type.getProperties();
+        function CreateWizard(domainObject, parent, policyService) {
+            this.type = domainObject.getCapability('type');
+            this.model = domainObject.getModel();
+            this.domainObject = domainObject;
+            this.properties = this.type.getProperties();
             this.parent = parent;
             this.policyService = policyService;
         }
@@ -97,6 +100,23 @@ define(
             };
         };
 
+        /**
+         * Given some form input values and a domain object, populate the
+         * domain object used to create this wizard from the given form values.
+         * @param formValue
+         * @returns {DomainObject}
+         */
+        CreateWizard.prototype.populateObjectFromInput = function(formValue) {
+            var parent = this.getLocation(formValue),
+                formModel = this.createModel(formValue);
+
+            formModel.location = parent.getId();
+            this.domainObject.useCapability("mutation", function(){
+                return formModel;
+            });
+            return this.domainObject;
+        }
+
         /**
          * Get the initial value for the form being described.
          * This will include the values for all properties described
@@ -120,6 +140,7 @@ define(
         /**
          * Based on a populated form, get the domain object which
          * should be used as a parent for the newly-created object.
+         * @private
          * @return {DomainObject}
          */
         CreateWizard.prototype.getLocation = function (formValue) {
@@ -129,6 +150,7 @@ define(
         /**
          * Create the domain object model for a newly-created object,
          * based on user input read from a formModel.
+         * @private
          * @return {object} the domain object model
          */
         CreateWizard.prototype.createModel = function (formValue) {
diff --git a/platform/commonUI/browse/test/creation/AddActionProviderSpec.js b/platform/commonUI/browse/test/creation/AddActionProviderSpec.js
new file mode 100644
index 0000000000..938067e72a
--- /dev/null
+++ b/platform/commonUI/browse/test/creation/AddActionProviderSpec.js
@@ -0,0 +1,137 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine,xit,xdescribe*/
+
+/**
+ * MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
+ */
+define(
+    ["../../src/creation/AddActionProvider"],
+    function (AddActionProvider) {
+        "use strict";
+
+        describe("The add action provider", function () {
+            var mockTypeService,
+                mockDialogService,
+                mockPolicyService,
+                mockCreationPolicy,
+                mockCompositionPolicy,
+                mockPolicyMap = {},
+                mockTypes,
+                mockDomainObject,
+                mockQ,
+                provider;
+
+            function createMockType(name) {
+                var mockType = jasmine.createSpyObj(
+                    "type" + name,
+                    [
+                        "getKey",
+                        "getGlyph",
+                        "getName",
+                        "getDescription",
+                        "getProperties",
+                        "getInitialModel",
+                        "hasFeature"
+                    ]
+                );
+                mockType.hasFeature.andReturn(true);
+                mockType.getName.andReturn(name);
+                return mockType;
+            }
+
+            beforeEach(function () {
+                mockTypeService = jasmine.createSpyObj(
+                    "typeService",
+                    [ "listTypes" ]
+                );
+                mockDialogService = jasmine.createSpyObj(
+                    "dialogService",
+                    [ "getUserInput" ]
+                );
+                mockPolicyService = jasmine.createSpyObj(
+                    "policyService",
+                    [ "allow" ]
+                );
+
+                mockDomainObject = jasmine.createSpyObj(
+                    "domainObject",
+                    [ "getCapability" ]
+                );
+
+                //Mocking getCapability because AddActionProvider uses the
+                // type capability of the destination object.
+                mockDomainObject.getCapability.andReturn({});
+
+                mockTypes = [ "A", "B", "C" ].map(createMockType);
+
+                mockTypes.forEach(function(type){
+                    mockPolicyMap[type.getName()] = true;
+                });
+
+                mockCreationPolicy = function(type){
+                    return mockPolicyMap[type.getName()];
+                };
+
+                mockCompositionPolicy = function(){
+                    return true;
+                };
+
+                mockPolicyService.allow.andReturn(true);
+
+                mockTypeService.listTypes.andReturn(mockTypes);
+
+                provider = new AddActionProvider(
+                    mockQ,
+                    mockTypeService,
+                    mockDialogService,
+                    mockPolicyService
+                );
+            });
+
+            it("checks for creatability", function () {
+                provider.getActions({
+                    key: "add",
+                    domainObject: mockDomainObject
+                });
+                // Make sure it was creation which was used to check
+                expect(mockPolicyService.allow)
+                    .toHaveBeenCalledWith("creation", mockTypes[0]);
+            });
+
+            it("checks for composability of type", function () {
+                provider.getActions({
+                    key: "add",
+                    domainObject: mockDomainObject
+                });
+
+                expect(mockPolicyService.allow).toHaveBeenCalledWith(
+                    "composition",
+                    jasmine.any(Object),
+                    jasmine.any(Object)
+                );
+
+                expect(mockDomainObject.getCapability).toHaveBeenCalledWith('type');
+            });
+        });
+    }
+);
\ No newline at end of file
diff --git a/platform/commonUI/browse/test/creation/CreateActionProviderSpec.js b/platform/commonUI/browse/test/creation/CreateActionProviderSpec.js
index f49c394dc9..857b29fe4e 100644
--- a/platform/commonUI/browse/test/creation/CreateActionProviderSpec.js
+++ b/platform/commonUI/browse/test/creation/CreateActionProviderSpec.js
@@ -32,11 +32,12 @@ define(
         describe("The create action provider", function () {
             var mockTypeService,
                 mockDialogService,
-                mockCreationService,
+                mockNavigationService,
                 mockPolicyService,
                 mockCreationPolicy,
                 mockPolicyMap = {},
                 mockTypes,
+                mockQ,
                 provider;
 
             function createMockType(name) {
@@ -66,9 +67,9 @@ define(
                     "dialogService",
                     [ "getUserInput" ]
                 );
-                mockCreationService = jasmine.createSpyObj(
-                    "creationService",
-                    [ "createObject" ]
+                mockNavigationService = jasmine.createSpyObj(
+                    "navigationService",
+                    [ "setNavigation" ]
                 );
                 mockPolicyService = jasmine.createSpyObj(
                     "policyService",
@@ -92,15 +93,14 @@ define(
                 mockTypeService.listTypes.andReturn(mockTypes);
 
                 provider = new CreateActionProvider(
+                    mockQ,
                     mockTypeService,
-                    mockDialogService,
-                    mockCreationService,
+                    mockNavigationService,
                     mockPolicyService
                 );
             });
 
-            //TODO: Disabled for NEM Beta
-            xit("exposes one create action per type", function () {
+            it("exposes one create action per type", function () {
                 expect(provider.getActions({
                     key: "create",
                     domainObject: {}
@@ -114,8 +114,7 @@ define(
                 }).length).toEqual(0);
             });
 
-            //TODO: Disabled for NEM Beta
-            xit("does not expose non-creatable types", function () {
+            it("does not expose non-creatable types", function () {
                 // One of the types won't have the creation feature...
                 mockPolicyMap[mockTypes[0].getName()] = false;
                 // ...so it should have been filtered out.
diff --git a/platform/commonUI/edit/src/actions/SaveAction.js b/platform/commonUI/edit/src/actions/SaveAction.js
index 13fde582d7..4cc71e56ee 100644
--- a/platform/commonUI/edit/src/actions/SaveAction.js
+++ b/platform/commonUI/edit/src/actions/SaveAction.js
@@ -79,63 +79,18 @@ define(
 
             function doWizardSave(parent) {
                 var context = domainObject.getCapability("context"),
-                    wizard = new CreateWizard(domainObject.useCapability('type'), parent, self.policyService, domainObject.getModel());
-
-                function mergeObjects(fromObject, toObject){
-                    Object.keys(fromObject).forEach(function(key) {
-                        toObject[key] = fromObject[key];
-                    });
-                }
-
-                // Create and persist the new object, based on user
-                // input.
-                function buildObjectFromInput(formValue) {
-                    var parent = wizard.getLocation(formValue),
-                        formModel = wizard.createModel(formValue);
-
-                        formModel.location = parent.getId();
-                        //Replace domain object model with model collected
-                        // from user form.
-                        domainObject.useCapability("mutation", function(){
-                            //Replace object model with the model from the form
-                            return formModel;
-                        });
-                        return domainObject;
-                }
-
-                function getAllComposees(domainObject){
-                    return domainObject.useCapability('composition');
-                }
-
-                function addComposeesToObject(object){
-                    return function(composees){
-                        return self.$q.all(composees.map(function (composee) {
-                            return object.getCapability('composition').add(composee);
-                        })).then(resolveWith(object));
-                    };
-                }
-
-                /**
-                 * Add the composees of the 'virtual' object to the
-                 * persisted object
-                 * @param object
-                 * @returns {*}
-                 */
-                function composeNewObject(object){
-                    if (self.$q.when(object.hasCapability('composition') && domainObject.hasCapability('composition'))) {
-                        return getAllComposees(domainObject)
-                            .then(addComposeesToObject(object));
-                    }
-                }
+                    wizard = new CreateWizard(domainObject, parent, self.policyService);
 
                 return self.dialogService
                     .getUserInput(wizard.getFormStructure(), wizard.getInitialFormValue())
-                    .then(buildObjectFromInput);
+                    .then(function(formValue){
+                        wizard.populateObjectFromInput(formValue, domainObject)
+                    });
             }
 
 
             function persistObject(object){
-                return  ((object.hasCapability('editor') && object.getCapability('editor').save(true)) ||
+                return  ((object.hasCapability('editor') && object.getCapability('editor').save()) ||
                         object.getCapability('persistence').persist())
                         .then(resolveWith(object));
             }
diff --git a/platform/commonUI/edit/src/capabilities/EditableInstantiationCapability.js b/platform/commonUI/edit/src/capabilities/EditableInstantiationCapability.js
new file mode 100644
index 0000000000..6a0392476b
--- /dev/null
+++ b/platform/commonUI/edit/src/capabilities/EditableInstantiationCapability.js
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+/*global define*/
+
+
+define(
+    ['./EditableLookupCapability'],
+    function (EditableLookupCapability) {
+        'use strict';
+
+        /**
+         * Wrapper for the "instantiation" capability;
+         * ensures that any domain objects instantiated in Edit mode
+         * are also wrapped as EditableDomainObjects.
+         *
+         * Meant specifically for use by EditableDomainObject and the
+         * associated cache; the constructor signature is particular
+         * to a pattern used there and may contain unused arguments.
+         * @constructor
+         * @memberof platform/commonUI/edit
+         * @implements {CompositionCapability}
+         */
+        return function EditableInstantiationCapability(
+            contextCapability,
+            editableObject,
+            domainObject,
+            cache
+        ) {
+            // This is a "lookup" style capability (it looks up other
+            // domain objects), but we do not want to return the same
+            // specific value every time (composition may change)
+            return new EditableLookupCapability(
+                contextCapability,
+                editableObject,
+                domainObject,
+                cache,
+                false // Not idempotent
+            );
+        };
+    }
+);
diff --git a/platform/commonUI/edit/src/capabilities/EditableLookupCapability.js b/platform/commonUI/edit/src/capabilities/EditableLookupCapability.js
index c92495dc3f..8193b0182d 100644
--- a/platform/commonUI/edit/src/capabilities/EditableLookupCapability.js
+++ b/platform/commonUI/edit/src/capabilities/EditableLookupCapability.js
@@ -114,7 +114,9 @@ define(
             }
 
             // Wrap all methods; return only editable domain objects.
-            Object.keys(contextCapability).forEach(wrapMethod);
+            for (var method in contextCapability){
+                wrapMethod(method);
+            }
 
             return capability;
         };
diff --git a/platform/commonUI/edit/src/capabilities/EditorCapability.js b/platform/commonUI/edit/src/capabilities/EditorCapability.js
index ec43bf298a..97fc2f9a56 100644
--- a/platform/commonUI/edit/src/capabilities/EditorCapability.js
+++ b/platform/commonUI/edit/src/capabilities/EditorCapability.js
@@ -81,7 +81,8 @@ define(
             var domainObject = this.domainObject,
                 editableObject = this.editableObject,
                 self = this,
-                cache = this.cache;
+                cache = this.cache,
+                returnPromise;
 
             // Update the underlying, "real" domain object's model
             // with changes made to the copy used for editing.
@@ -99,14 +100,18 @@ define(
             editableObject.getCapability("status").set("editing", false);
 
             if (nonrecursive) {
-                return resolvePromise(doMutate())
+                returnPromise = resolvePromise(doMutate())
                     .then(doPersist)
                     .then(function(){
                         self.cancel();
                     });
             } else {
-                return resolvePromise(cache.saveAll());
+                returnPromise = resolvePromise(cache.saveAll());
             }
+            //Return the original (non-editable) object
+            return returnPromise.then(function() {
+                return domainObject;
+            })
         };
 
         /**
diff --git a/platform/commonUI/edit/src/objects/EditableDomainObject.js b/platform/commonUI/edit/src/objects/EditableDomainObject.js
index 2b764f7de7..253947181d 100644
--- a/platform/commonUI/edit/src/objects/EditableDomainObject.js
+++ b/platform/commonUI/edit/src/objects/EditableDomainObject.js
@@ -36,6 +36,7 @@ define(
         '../capabilities/EditableContextCapability',
         '../capabilities/EditableCompositionCapability',
         '../capabilities/EditableRelationshipCapability',
+        '../capabilities/EditableInstantiationCapability',
         '../capabilities/EditorCapability',
         '../capabilities/EditableActionCapability',
         './EditableDomainObjectCache'
@@ -45,6 +46,7 @@ define(
         EditableContextCapability,
         EditableCompositionCapability,
         EditableRelationshipCapability,
+        EditableInstantiationCapability,
         EditorCapability,
         EditableActionCapability,
         EditableDomainObjectCache
@@ -56,6 +58,7 @@ define(
             context: EditableContextCapability,
             composition: EditableCompositionCapability,
             relationship: EditableRelationshipCapability,
+            instantiation: EditableInstantiationCapability,
             editor: EditorCapability
         };
 
diff --git a/platform/commonUI/edit/test/capabilities/EditableLookupCapabilitySpec.js b/platform/commonUI/edit/test/capabilities/EditableLookupCapabilitySpec.js
index 24b68b6fd9..16bcee88b1 100644
--- a/platform/commonUI/edit/test/capabilities/EditableLookupCapabilitySpec.js
+++ b/platform/commonUI/edit/test/capabilities/EditableLookupCapabilitySpec.js
@@ -118,6 +118,29 @@ define(
                 expect(mockContext.getDomainObject.calls.length).toEqual(2);
             });
 
+            it("wraps inherited methods", function () {
+                var CapabilityClass = function(){
+                };
+                CapabilityClass.prototype.inheritedMethod=function () {
+                    return "an inherited method";
+                };
+
+                mockContext = new CapabilityClass();
+
+                capability = new EditableLookupCapability(
+                    mockContext,
+                    mockEditableObject,
+                    mockDomainObject,
+                    factory,
+                    false
+                );
+                expect(capability.inheritedMethod()).toEqual("an inherited method");
+                expect(capability.hasOwnProperty('inheritedMethod')).toBe(true);
+                // The presence of an own property indicates that the method
+                // has been wrapped on the object itself and this is a valid
+                // test that the inherited method has been wrapped.
+            });
+
         });
     }
 );
\ No newline at end of file
diff --git a/platform/features/timeline/src/controllers/swimlane/TimelineProxy.js b/platform/features/timeline/src/controllers/swimlane/TimelineProxy.js
index 3174659a63..7f74f59de0 100644
--- a/platform/features/timeline/src/controllers/swimlane/TimelineProxy.js
+++ b/platform/features/timeline/src/controllers/swimlane/TimelineProxy.js
@@ -39,7 +39,7 @@ define(
             function populateActionMap(domainObject) {
                 var actionCapability = domainObject.getCapability('action'),
                     actions = actionCapability ?
-                            actionCapability.getActions('create') : [];
+                            actionCapability.getActions('add') : [];
                 actions.forEach(function (action) {
                     actionMap[action.getMetadata().type] = action;
                 });