blob: dfc687509f85d38199958199a354106b21a1655a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
import Ember from 'ember';
import CommonUtils from "../utils/common-utils";
import {Workflow} from '../domain/workflow';
import {WorkflowXmlMapper} from '../domain/workflow_xml_mapper';
import SchemaVersions from '../domain/schema-versions';
import Constants from '../utils/constants';
var WorkflowImporter= Ember.Object.extend({
workflowMapper:null,
x2js : new X2JS(),
schemaVersions : SchemaVersions.create({}),
importWorkflow(workflowXml){
var workflow=Workflow.create({});
var errors=[];
workflow.initialize();
this.workflowMapper=WorkflowXmlMapper.create({schemaVersions:workflow.schemaVersions});
return this.processWorkflowXml(workflowXml,workflow, errors);
},
processWorkflowXml(workflowXml,workflow, errors){
var xmlDoc= Ember.$.parseXML( workflowXml );
if (xmlDoc && xmlDoc.getElementsByTagName('action').length>Constants.flowGraphMaxNodeCount){
errors.push({message: "Workflow is too large to be imported",dismissable:true});
return {workflow:null, errors: errors};
}
var workflowJson= this.get("x2js").xml_str2json(workflowXml);
if (!workflowJson || !workflowJson["workflow-app"]){
errors.push({message: "Could not import invalid workflow",dismissable:true});
return {workflow:null, errors: errors};
}
var workflowAppJson=workflowJson["workflow-app"];
var workflowVersion=CommonUtils.extractSchemaVersion(workflowAppJson._xmlns);
var maxWorkflowVersion = Math.max.apply(Math, this.get('schemaVersions').getSupportedVersions('workflow'));
if (workflowVersion > maxWorkflowVersion) {
errors.push({message: "Unsupported workflow version - " + workflowVersion});
} else {
workflow.schemaVersions.workflowVersion = workflowVersion;
}
this.processWorkflowActionVersions(workflowAppJson, workflow, errors);
if (workflowAppJson.info && workflowAppJson.info.__prefix==="sla") {
workflow.slaEnabled=true;
this.workflowMapper.handleSLAImport(workflow,workflowAppJson.info);
}
this.workflowMapper.handleCredentialImport(workflow,workflowAppJson.credentials);
this.workflowMapper.handleParametersImport(workflow,workflowAppJson.parameters);
var nodeMap=this.setupNodeMap(workflowAppJson,workflow,Ember.$(xmlDoc));
this.setupTransitions(workflowAppJson,nodeMap);
workflow.set("startNode",nodeMap.get("start").node);
let globalProperties = workflowJson["workflow-app"].global.configuration.property;
if(workflowJson["workflow-app"].global) {
if(Ember.isArray(globalProperties)) {
workflow.set("globalSetting", workflowJson["workflow-app"].global);
} else {
workflow.set("globalSetting", {configuration : { property:[globalProperties] }} );
}
}
this.populateKillNodes(workflow,nodeMap);
return {workflow: workflow, errors: errors};
},
processWorkflowActionVersions(workflowAppJson, workflow, errors) {
var importedWfActionVersions = Ember.Map.create();
var actions=workflowAppJson.action ? (workflowAppJson.action.length?workflowAppJson.action:[workflowAppJson.action]):[];
actions.forEach(function(wfAction) {
var wfActionType = Object.keys(wfAction)[0];
var wfActionXmlns = wfAction[wfActionType]._xmlns;
if (!wfActionXmlns) {
return;
}
var wfActionVersion = CommonUtils.extractSchemaVersion(wfActionXmlns);
if (importedWfActionVersions.get(wfActionType)) {
importedWfActionVersions.get(wfActionType).push(wfActionVersion);
} else {
importedWfActionVersions.set(wfActionType, [wfActionVersion]);
}
});
importedWfActionVersions._keys.forEach(function(wfActionType){
if(!CommonUtils.isSupportedAction(wfActionType)){
return;
}
var maxImportedActionVersion = Math.max.apply(null,importedWfActionVersions.get(wfActionType));
var supportedVersions = this.get('schemaVersions').getSupportedVersions(wfActionType);
importedWfActionVersions.get(wfActionType).forEach((version)=>{
if(supportedVersions.indexOf(version) === -1){
errors.push({message: "Unsupported " + wfActionType + " version - " + maxImportedActionVersion});
}else{
workflow.schemaVersions.actionVersions.set(wfActionType, maxImportedActionVersion);
}
}, this);
}, this);
},
processActionNode(nodeMap,action){
var actionMapper=this.get("workflowMapper").getNodeHandler("action");
var actionNode=actionMapper.handleImportNode(action);
nodeMap.set(actionNode.getName(),actionNode);
},
setupNodeMap(workflowAppJson,workflow,xmlDoc){
var self=this;
workflow.set("name",workflowAppJson["_name"]);
var nodeMap=new Map();
Object.keys(workflowAppJson).forEach(function (key) {
var nodeHandler=self.workflowMapper.getNodeHandler(key);
if (nodeHandler){
if (Ember.isArray(workflowAppJson[key])){
workflowAppJson[key].forEach(function(jsonObj){
var actionDom = xmlDoc.find("action[name='" + jsonObj._name + "']");
var node = nodeHandler.handleImportNode(key,jsonObj,workflow,actionDom);
nodeMap.set(jsonObj._name,{json:jsonObj,node:node});
});
}else{
if ('action'===key){//action handler.
var actionDom=xmlDoc.find("action[name='"+workflowAppJson[key]._name+ "']");
}
var node=nodeHandler.handleImportNode(key,workflowAppJson[key],workflow,actionDom);
if (!workflowAppJson[key]._name){
nodeMap.set(key,{json:workflowAppJson[key],node:node});
}else{
nodeMap.set(workflowAppJson[key]._name,{json:workflowAppJson[key],node:node});
}
}
}
});
return nodeMap;
},
setupTransitions(workflowAppJson,nodeMap){
var self=this;
nodeMap.forEach(function(entry,key){
var node=entry.node;
if (!node){
console.error("could not process:",key);//TODO error handling...
return;
}
var json=entry.json;
var nodeHandler=self.workflowMapper.getNodeHandler(node.get("type"));
if (!nodeHandler){
console.error("could not process:",node.get("type"));//TODO error handling...
}
nodeHandler.handleImportTransitions(node,json,nodeMap);
});
},
getNodeIds(nodeMap){
var ids=[];
nodeMap.forEach(function(entry){
var node=entry.node;
ids.push(node.id);
});
return ids;
},
getNodeNames(nodeMap){
var names=[];
nodeMap.forEach(function(entry){
var node=entry.node;
names.push(node.id);
});
return names;
},
populateKillNodes(workflow,nodeMap){
if (this.containsKillNode(nodeMap)){
workflow.resetKillNodes();
}
nodeMap.forEach(function(entry){
var node=entry.node;
if (node.isKillNode()){
workflow.get("killNodes").pushObject(node);
}
});
},
containsKillNode(nodeMap){
var containsKillNode=false;
nodeMap.forEach(function(entry){
var node=entry.node;
if (node.isKillNode()){
containsKillNode=true;
}
});
return containsKillNode;
}
});
export {WorkflowImporter};