221 lines
8.0 KiB
JavaScript
221 lines
8.0 KiB
JavaScript
/*****************************************************************************
|
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
|
* as represented by the Administrator of the National Aeronautics and Space
|
|
* Administration. All rights reserved.
|
|
*
|
|
* Open MCT 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 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.
|
|
*****************************************************************************/
|
|
define(['zepto', '../../../../src/api/objects/object-utils.js'], function ($, objectUtils) {
|
|
|
|
/**
|
|
* The ImportAsJSONAction is available from context menus and allows a user
|
|
* to import a previously exported domain object into any domain object
|
|
* that has the composition capability.
|
|
*
|
|
* @implements {Action}
|
|
* @constructor
|
|
* @memberof platform/import-export
|
|
*/
|
|
function ImportAsJSONAction(
|
|
exportService,
|
|
identifierService,
|
|
dialogService,
|
|
openmct,
|
|
context
|
|
) {
|
|
|
|
this.openmct = openmct;
|
|
this.context = context;
|
|
this.exportService = exportService;
|
|
this.dialogService = dialogService;
|
|
this.identifierService = identifierService;
|
|
this.instantiate = openmct.$injector.get("instantiate");
|
|
}
|
|
|
|
ImportAsJSONAction.prototype.perform = function () {
|
|
this.dialogService.getUserInput(this.getFormModel(), {})
|
|
.then(function (form) {
|
|
var objectTree = form.selectFile.body;
|
|
if (this.validateJSON(objectTree)) {
|
|
this.importObjectTree(JSON.parse(objectTree));
|
|
} else {
|
|
this.displayError();
|
|
}
|
|
}.bind(this));
|
|
};
|
|
|
|
ImportAsJSONAction.prototype.importObjectTree = function (objTree) {
|
|
var parent = this.context.domainObject;
|
|
var namespace = parent.useCapability('adapter').identifier.namespace;
|
|
|
|
var tree = this.generateNewIdentifiers(objTree, namespace);
|
|
var rootId = tree.rootId;
|
|
|
|
var rootModel = tree.openmct[rootId];
|
|
delete rootModel.persisted;
|
|
|
|
var rootObj = this.instantiate(rootModel, rootId);
|
|
var newStyleParent = parent.useCapability('adapter');
|
|
var newStyleRootObj = rootObj.useCapability('adapter');
|
|
|
|
if (this.openmct.composition.checkPolicy(newStyleParent, newStyleRootObj)) {
|
|
// Instantiate all objects in tree with their newly generated ids,
|
|
// adding each to its rightful parent's composition
|
|
rootObj.getCapability("location").setPrimaryLocation(parent.getId());
|
|
this.deepInstantiate(rootObj, tree.openmct, []);
|
|
parent.getCapability("composition").add(rootObj);
|
|
} else {
|
|
var dialog = this.openmct.overlays.dialog({
|
|
iconClass: 'alert',
|
|
message: "We're sorry, but you cannot import that object type into this object.",
|
|
buttons: [
|
|
{
|
|
label: "Ok",
|
|
emphasis: true,
|
|
callback: function () {
|
|
dialog.dismiss();
|
|
}
|
|
}
|
|
]
|
|
});
|
|
}
|
|
};
|
|
|
|
ImportAsJSONAction.prototype.deepInstantiate = function (parent, tree, seen) {
|
|
// Traverses object tree, instantiates all domain object w/ new IDs and
|
|
// adds to parent's composition
|
|
if (parent.hasCapability("composition")) {
|
|
var parentModel = parent.getModel();
|
|
var newObj;
|
|
|
|
seen.push(parent.getId());
|
|
|
|
parentModel.composition.forEach(function (childId) {
|
|
let keystring = this.openmct.objects.makeKeyString(childId);
|
|
|
|
if (!tree[keystring] || seen.includes(keystring)) {
|
|
return;
|
|
}
|
|
let newModel = tree[keystring];
|
|
delete newModel.persisted;
|
|
|
|
newObj = this.instantiate(newModel, keystring);
|
|
newObj.getCapability("location")
|
|
.setPrimaryLocation(tree[keystring].location);
|
|
this.deepInstantiate(newObj, tree, seen);
|
|
}, this);
|
|
}
|
|
};
|
|
|
|
ImportAsJSONAction.prototype.generateNewIdentifiers = function (tree, namespace) {
|
|
// For each domain object in the file, generate new ID, replace in tree
|
|
Object.keys(tree.openmct).forEach(function (domainObjectId) {
|
|
let newId = {
|
|
namespace: namespace,
|
|
key: this.identifierService.generate()
|
|
};
|
|
|
|
let oldId = objectUtils.parseKeyString(domainObjectId);
|
|
|
|
tree = this.rewriteId(oldId, newId, tree);
|
|
}, this);
|
|
return tree;
|
|
};
|
|
|
|
/**
|
|
* Rewrites all instances of a given id in the tree with a newly generated
|
|
* replacement to prevent collision.
|
|
*
|
|
* @private
|
|
*/
|
|
ImportAsJSONAction.prototype.rewriteId = function (oldId, newId, tree) {
|
|
let newIdKeyString = this.openmct.objects.makeKeyString(newId);
|
|
let oldIdKeyString = this.openmct.objects.makeKeyString(oldId);
|
|
tree = JSON.stringify(tree).replace(new RegExp(oldIdKeyString, 'g'), newIdKeyString);
|
|
|
|
return JSON.parse(tree, (key, value) => {
|
|
if (Object.prototype.hasOwnProperty.call(value, 'key') &&
|
|
Object.prototype.hasOwnProperty.call(value, 'namespace') &&
|
|
value.key === oldId.key &&
|
|
value.namespace === oldId.namespace) {
|
|
return newId
|
|
} else {
|
|
return value;
|
|
}
|
|
});
|
|
};
|
|
|
|
ImportAsJSONAction.prototype.getFormModel = function () {
|
|
return {
|
|
name: "Import as JSON",
|
|
sections: [
|
|
{
|
|
name: "Import A File",
|
|
rows: [
|
|
{
|
|
name: 'Select File',
|
|
key: 'selectFile',
|
|
control: 'file-input',
|
|
required: true,
|
|
text: 'Select File'
|
|
}
|
|
]
|
|
}
|
|
]
|
|
};
|
|
};
|
|
|
|
ImportAsJSONAction.prototype.validateJSON = function (jsonString) {
|
|
var json;
|
|
try {
|
|
json = JSON.parse(jsonString);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
if (!json.openmct || !json.rootId) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
ImportAsJSONAction.prototype.displayError = function () {
|
|
var dialog,
|
|
model = {
|
|
title: "Invalid File",
|
|
actionText: "The selected file was either invalid JSON or was " +
|
|
"not formatted properly for import into Open MCT.",
|
|
severity: "error",
|
|
options: [
|
|
{
|
|
label: "Ok",
|
|
callback: function () {
|
|
dialog.dismiss();
|
|
}
|
|
}
|
|
]
|
|
};
|
|
dialog = this.dialogService.showBlockingMessage(model);
|
|
};
|
|
|
|
ImportAsJSONAction.appliesTo = function (context) {
|
|
return context.domainObject !== undefined &&
|
|
context.domainObject.hasCapability("composition");
|
|
};
|
|
|
|
return ImportAsJSONAction;
|
|
});
|