//@include lib_Class.js
/**
* Contains workflow related utility functions
*
* @author PZ, ELO Digital Office GmbH
* @version 1.04.000
*
* @eloix
* @eloas
* @elojc
* @requires sol.common.Config
* @requires sol.common.ConfigMixin
* @requires sol.common.ObjectUtils
* @requires sol.common.StringUtils
* @requires sol.common.SordUtils
* @requires sol.common.UserUtils
* @requires sol.common.UserProfile
* @requires sol.common.DateUtils
*
*/
sol.define("sol.common.WfUtils", {
singleton: true,
/**
* @private
*/
logger: sol.create("sol.Logger", { scope: "sol.common.WfUtils" }),
/**
* @private
* Loads the base configuration from the JSON file: `/Administration/Business Solutions/common/Configuration/base.config`
* @return {Object}
*/
loadBaseConfig: function () {
var me = this;
if (!me.baseConfig) {
me.baseConfig = sol.create("sol.common.Config", { load: "ARCPATH[(E10E1000-E100-E100-E100-E10E10E10E00)]:/Business Solutions/common/Configuration/base.config" }).config;
}
return me.baseConfig;
},
/**
* Starts a workflow.
* @param {String} templFlowId Name or ID of the template which should be started
* @param {String} flowName Name of the new workflow
* @param {String} objId Object on which the workflow should be started
* @param {Number} prio (optional) If specified, the workflow priority will be changed (0=high, 1=medium, 2=low)
* @return {Number} The ID of the started workflow
*/
startWorkflow: function (templFlowId, flowName, objId, prio) {
var me = this,
flowId;
me.logger.enter("startWorkflow", arguments);
if (!templFlowId) {
throw "Workflow template ID is empty";
}
if (flowName && flowName.length > 120) {
flowName = flowName.substr(0, 120);
}
flowId = ixConnect.ix().startWorkFlow(templFlowId, flowName, objId);
if (typeof prio !== "undefined") {
me.changeWorkflowPriority(flowId, prio);
}
me.logger.exit("startWorkflow", { flowId: flowId });
return flowId;
},
/**
* Starts the workflow defined as standard workflow for the mask or in an index field.
* If there is already an workflow, it will do nothing and return the first active one.
* @param {String} objId
* @param {Object} params (optional) Default will be the sord name
* @param {Object} params.name (optional) Default will be the sord name
* @param {Object} params.field (optional) The field to read the workflow template from
* @return {String} The workflow ID
*/
startMaskStandardWorkflow: function (objId, params) {
var me = this,
activeWorkflows, sord, templateName, templateId, maskName, docMask, name, flowId;
me.logger.enter("startMaskStandardWorkflow", arguments);
activeWorkflows = sol.common.WfUtils.getActiveWorkflows(objId);
if (activeWorkflows.length > 0) {
return activeWorkflows[0].id;
}
sord = ixConnect.ix().checkoutSord(objId, SordC.mbAllIndex, LockC.NO);
if (params && params.field) {
templateName = sol.common.SordUtils.getObjKeyValue(sord, params.field);
if (templateName) {
templateId = sol.common.WfUtils.getWorkflowTemplateId(templateName);
}
}
if (!templateId) {
maskName = sord.maskName;
docMask = sol.common.SordUtils.getDocMask(maskName);
templateId = docMask.flowId;
}
if (!templateId || templateId === -1) {
throw "mask '" + maskName + "' does not define a standard workflow";
}
name = (params && params.name) ? params.name : sord.name;
if (name && name.length > 120) {
name = name.substr(0, 120);
}
flowId = me.startWorkflow(templateId, name, objId);
me.logger.exit("startMaskStandardWorkflow", { flowId: flowId });
return flowId;
},
/**
* Returns a specific workflow.
* @param {String} flowId Flow ID
* @param {Object} params (optional)
* @param {Boolean} params.inclFinished (optional) If `true`, the workflows will be returned, even if it is already finished
* @return {de.elo.ix.client.WFDiagram}
*/
getWorkflow: function (flowId, params) {
var workflow;
try {
workflow = ixConnect.ix().checkoutWorkFlow(flowId, WFTypeC.ACTIVE, WFDiagramC.mbAll, LockC.NO);
} catch (ex) {
if (params && (params.inclFinished === true)) {
workflow = ixConnect.ix().checkoutWorkFlow(flowId, WFTypeC.FINISHED, WFDiagramC.mbAll, LockC.NO);
} else {
throw ex;
}
}
return workflow;
},
wfDiagramTypeId: 1663767661,
wfVersionTypeId: 914434915,
wfNodeTypeId: 2015686193,
wfEscalationTypeId: 633363356,
wfEscalationUserTypeId: 123879203,
/**
* Returns workflow diagram as JSON string
* @param {String} flowId Workflow ID
* @param {String} config Configuration
* @param {Boolean} [config.clearUsers=false] Clear the owner names of the template
* @param {Boolean} [config.addSubTemplateInfo=false] Add sub template information
* @return {String} JSON representation of the workflow diagram
*/
getWorkflowAsJson: function (flowId, config) {
var me = this,
fileData, workflowExportOptions, workflowTplJson, workflowTplObj;
flowId += "";
config = config || {};
if (!flowId) {
throw new Error("Flow ID is missing.");
}
if (config.addSubTemplateInfo) {
me.addSubTemplateInfo(flowId);
}
workflowExportOptions = new WorkflowExportOptions();
workflowExportOptions.flowId = flowId;
workflowExportOptions.format = WorkflowExportOptionsC.FORMAT_JSON;
workflowExportOptions.flowVersId = "0";
fileData = ixConnect.ix().exportWorkflow(workflowExportOptions);
workflowTplJson = String(new java.lang.String(fileData.data, "UTF-8"));
workflowTplObj = JSON.parse(workflowTplJson);
sol.common.ObjectUtils.traverse(workflowTplObj, function (key, obj) {
if (config.clearUsers && (obj._typeId == me.wfVersionTypeId)) {
obj.userId = 0;
obj.userName = "";
}
});
workflowTplJson = JSON.stringify(workflowTplObj);
return workflowTplJson;
},
/**
* Adds sub template info
* @param {Integer} flowId Flow ID
*/
addSubTemplateInfo: function (flowId) {
var me = this,
propertiesObj = {},
wfDiag, i, node;
flowId += "";
if (!flowId) {
return;
}
wfDiag = ixConnect.ix().checkoutWorkflowTemplate(flowId, "", WFDiagramC.mbAll, LockC.NO);
for (i = 0; i < wfDiag.nodes.length; i++) {
node = wfDiag.nodes[i];
if (node.type != WFNodeC.TYPE_CALL_SUB_WORKFLOW) {
continue;
}
try {
propertiesObj = JSON.parse(node.properties);
} catch (ignore) {
// ignore
}
propertiesObj.subTemplateName = me.getWorkflowTemplateName(node.subTemplateId);
node.properties = JSON.stringify(propertiesObj, "", 2);
me.addSubTemplateInfo(node.subTemplateId); // sub template info should also be set recursively
}
ixConnect.ix().checkinWorkflowTemplate(wfDiag, WFDiagramC.mbAll, LockC.NO);
},
/**
* Returns the workflow name
* @param {String} workflowJson Workflow JSON
* @return {String} Workflow name
*/
getWfNameFromJson: function (workflowJson) {
var me = this,
workflowObj, objectTable, i, obj, typeId;
if (!workflowJson) {
throw "Workflow JSON content is empty";
}
workflowObj = JSON.parse(workflowJson);
objectTable = workflowObj.objectTable;
for (i = 0; i < objectTable.length; i++) {
obj = objectTable[i];
if (obj) {
typeId = obj["_typeId"];
if (typeId && (typeId == me.wfDiagramTypeId)) {
return obj.name;
}
}
}
},
/**
* Returns the workflow names
* @param {String} workflowJson Workflow JSON
* @return {Array} Workflow names
*/
getAllWorkflowNamesFromJson: function (workflowJson) {
var me = this,
workflowNames = [], workflowTplObj;
if (!workflowJson) {
throw "Workflow JSON content is empty";
}
workflowTplObj = JSON.parse(workflowJson);
sol.common.ObjectUtils.traverse(workflowTplObj, function (key, obj) {
if (obj._typeId == me.wfDiagramTypeId) {
workflowNames.push(obj.name);
}
});
return workflowNames;
},
/**
* Retrieves the active workflows for an object.
* @param {String} objId
* @param {Object} filter (optional)
* @param {String} filter.template (optional) Filter results by name or ID of the workflow template
* @param {Boolean} filter.user (optional) If `true` the active workflows will be filtered by the current user
* @return {de.elo.ix.client.WFDiagram[]}
*/
getActiveWorkflows: function (objId, filter) {
var findInfo = new FindWorkflowInfo();
findInfo.objId = objId;
findInfo.type = WFTypeC.ACTIVE;
if (filter && filter.template) {
findInfo.templateId = filter.template;
}
return this.findWorkflows(findInfo, null, ((filter && filter.user === true) || (typeof ixConnectAdmin === "undefined")) ? ixConnect : ixConnectAdmin);
},
/**
* Checks, if an object has at least on active workflow.
* If a template name is defined, the function checks, if there is at least one active workflow with this template.
* @param {String} objId
* @param {String} template (optional)
* @return {Boolean}
*/
hasActiveWorkflow: function (objId, template) {
var filter;
if (template) {
filter = { template: template };
}
return (this.getActiveWorkflows(objId, filter).length > 0);
},
/**
* Returns the last active workflow for an object
* @param {String} objId Object ID
* @return {de.elo.ix.client.WFDiagram}
*/
getLastActiveWorkflow: function (objId) {
var me = this,
workflows;
if (!objId) {
throw "Object ID is empty";
}
workflows = me.getActiveWorkflows(objId);
if (workflows && (workflows.length > 0)) {
return workflows[workflows.length - 1];
}
},
/**
* Retrieves workflows with a search request.
* @param {de.elo.ix.client.FindWorkflowInfo} findWorkflowInfo Defines the search
* @param {de.elo.ix.client.WFDiagramC} [checkoutOptions=WFDiagramC.mbLean] (optional) Defines the members which will be returned in the result
* @param {de.elo.ix.client.IXConnection} [ixConn=ixConnect] (optional)
* @return {de.elo.ix.client.WFDiagram[]}
*/
findWorkflows: function (findWorkflowInfo, checkoutOptions, ixConn) {
var me = this,
max = 100,
idx = 0,
workflows = [],
findResult, i, wf;
ixConn = ixConn || ixConnect;
checkoutOptions = checkoutOptions || WFDiagramC.mbLean;
try {
findResult = ixConn.ix().findFirstWorkflows(findWorkflowInfo, max, checkoutOptions);
while (true) {
for (i = 0; i < findResult.workflows.length; i++) {
wf = findResult.workflows[i];
workflows.push(wf);
}
if (!findResult.moreResults) {
break;
}
idx += findResult.workflows.length;
findResult = ixConn.ix().findNextWorkflows(findResult.searchId, idx, max);
}
} catch (ex) {
me.logger.warn("error looking up workflows", ex);
} finally {
if (findResult) {
ixConn.ix().findClose(findResult.searchId);
}
}
return workflows;
},
/*
* Retrieves tasks for an object.
* @param {Object} filter (optional)
* @param {Boolean} filter.allUsers If `true` all tasks will be returned, not just the current users tasks
* @param {Boolean} filter.group If `true` group tasks will be included
* @param {Boolean} filter.deputy If `true` deputy tasks will be included
* @param {Boolean} filter.workflows If `true` workflow tasks will be included
* @param {String} filter.objId If set, only tasks for this object will be returned
* @return {String[]} Array of the task IDs
*
getTasks: function (filter) {
var ixConn = (filter && filter.allUsers === true) ? ixConnectAdmin : ixConnect,
findInfo = new FindTasksInfo(),
ids = [],
idx, max, findResult, i, wfNode;
findInfo.inclWorkflows = (filter && filter.workflows === true);
findInfo.inclGroup = (filter && filter.group === true);
findInfo.inclDeputy = (filter && filter.deputy === true);
findInfo.lowestPriority = UserTaskPriorityC.LOWEST;
findInfo.highestPriority = UserTaskPriorityC.HIGHEST;
if (filter && filter.objId) {
findInfo.objId = filter.objId;
}
try {
idx = 0;
max = 100;
findResult = ixConn.ix().findFirstTasks(findInfo, max);
while (true) {
for (i = 0; i < findResult.tasks.length; i++) {
wfNode = findResult.tasks[i].wfNode;
ids.push(wfNode.flowId);
}
if (!findResult.moreResults) {
break;
}
idx += findResult.tasks.length;
findResult = ixConn.ix().findNextTasks(findResult.searchId, idx, max);
}
} finally {
if (findResult !== null) {
ixConn.ix().findClose(findResult.searchId);
}
}
return ids;
},*/
/**
* Changes the priority of a workflow.
* @param {String} flowId The workflows ID
* @param {Number} prio The new priority (0=high, 1=medium, 2=low)
*/
changeWorkflowPriority: function (flowId, prio) {
var wfDiagram;
if ((typeof prio !== "undefined") && (Object.prototype.toString.call(prio) === "[object Number]") && (prio >= 0) && (prio <= 2)) {
wfDiagram = ixConnect.ix().checkoutWorkFlow(flowId, WFTypeC.ACTIVE, WFDiagramC.mbAll, LockC.NO);
if (wfDiagram.prio !== prio) {
wfDiagram.prio = prio;
ixConnect.ix().checkinWorkFlow(wfDiagram, WFDiagramC.mbAll, LockC.NO);
}
}
},
/**
* Cancels a workflow.
* @param {String} flowId
* @param {Boolean} force (optional) If `true`, the workflow will be terminated ignoring existing locks
* @param {Object} params (optional) Parameters
* @param {de.elo.ix.client.IXConnection} [params.connection=ixConnect] (optional) Index Server connection
* @return {Number} The canceled workflow ID
*/
cancelWorkflow: function (flowId, force, params) {
var conn, canceledFlowId;
params = params || {};
conn = params.connection || ixConnect;
canceledFlowId = conn.ix().terminateWorkFlow(flowId, (force) ? LockC.FORCE : LockC.YES);
return canceledFlowId;
},
/**
* Returns the Status of the workflow.
* @param {String|de.elo.ix.client.WFDiagram} flow Either a flowId or WFDiagram (to avoid loading it again)
* @return {String}
*/
getWorkflowStatus: function (flow) {
var me = this,
startNode;
if (!flow) {
throw "Flow is empty";
}
if (!flow.id) {
flow = me.getWorkflow(flow);
}
startNode = me.getNode(flow, 0);
return (startNode) ? String(startNode.yesNoCondition) : "";
},
/**
* Sets the workflow status.
* @param {de.elo.ix.client.WFDiagram} wfDiagram Workflow diagram
* @param {String} status Workflow status
*/
setWorkflowStatus: function (wfDiagram, status) {
var me = this,
startNode;
if (!wfDiagram) {
throw "Workflow diagram is empty";
}
status = status || "";
startNode = me.getNode(wfDiagram, 0);
startNode.yesNoCondition = status;
},
/**
* Retrieves the available workflow templates.
* @param {Object} params Parameters
* @param {de.elo.ix.client.WFDiagramC} [params.wfDiagramZ=WFDiagramC.mbLean] (optional) Defines the members which will be returned in the result
* @return {de.elo.ix.client.WFDiagram[]}
*/
getTemplates: function (params) {
var me = this, ixConn, result, originalProperty,
info;
params = params || {};
info = new FindWorkflowInfo();
info.type = WFTypeC.TEMPLATE;
// we need to change the connection to avoid translated workflow templates
ixConn = (typeof ixConnectAdmin === "undefined") ? ixConnect : ixConnectAdmin;
originalProperty = ixConn.getSessionOptions().getProperty(SessionOptionsC.TRANSLATE_TERMS);
ixConn.getSessionOptions().setProperty(SessionOptionsC.TRANSLATE_TERMS, "false");
ixConn.getSessionOptions().update();
result = me.findWorkflows(info, params.wfDiagramZ, ixConn);
// and now we'll change the option back to avoid untranslated terms in all the other requests
ixConn.getSessionOptions().setProperty(SessionOptionsC.TRANSLATE_TERMS, String(originalProperty));
ixConn.getSessionOptions().update();
return result;
},
/**
* Returns the template ID of a workflow
* @param {String} workflowTemplateName Name of the workflow template
* @return {String} Workflow ID
*/
getWorkflowTemplateId: function (workflowTemplateName) {
var wfDiag = ixConnect.ix().checkoutWorkflowTemplate(workflowTemplateName, "", new WFDiagramZ(WFDiagramC.mbId), LockC.NO);
return wfDiag.id;
},
/**
* Returns the template name of a workflow
* @param {String} workflowTemplateId ID of the workflow template
* @return {String} Workflow name
*/
getWorkflowTemplateName: function (workflowTemplateId) {
var wfDiag, wfName;
if (typeof workflowTemplateId == "undefined") {
return "";
}
workflowTemplateId += "";
wfDiag = ixConnect.ix().checkoutWorkflowTemplate(workflowTemplateId, "", new WFDiagramZ(WFDiagramC.mbName), LockC.NO);
if (!wfDiag) {
return "";
}
wfName = wfDiag.name + "";
return wfName;
},
/**
* Exports a workflow template into a specified file
* @param {String} workflowTemplateName Name of the workflow template
* @param {java.io.File} file Export file
* @param {Object} config Configuration
* @param {Boolean} clearAdminName Clear the administrator user name
* @return {Array} Exported workflow template names
*/
exportWorkflowTemplate: function (workflowTemplateName, file, config) {
var me = this,
workflowTemplateId, exportedWorkflowTemplateNames;
workflowTemplateId = me.getWorkflowTemplateId(workflowTemplateName);
exportedWorkflowTemplateNames = me.exportWorkflow(workflowTemplateId, file, config);
return exportedWorkflowTemplateNames;
},
/**
* Exports a workflow into a specified file
* @param {String} workflowId Workflow ID
* @param {java.io.File} file Export file
* @param {Object} config Configuration
* @param {Boolean} clearAdminName Clear the administrator user name
* @return {workflowNames} Exported workflow names
*/
exportWorkflow: function (workflowId, file, config) {
var me = this,
workflowJson, exportedWorkflowNames;
workflowJson = me.getWorkflowAsJson(workflowId, config);
Packages.org.apache.commons.io.FileUtils.writeStringToFile(file, workflowJson, "UTF-8");
exportedWorkflowNames = me.getAllWorkflowNamesFromJson(workflowJson);
return exportedWorkflowNames;
},
/**
* Imports a workflow into a specified file
* @param {String} workflowName Workflow name
* @param {java.io.File} file Import file
* @param {Object} params Parameters
* @param {Boolean} [params.replaceMissingUserByUserId=0] Replace a missing user by this user ID
* @return {Object} importResult Import result
* @return {Array} importResult.replacedSubTemplateIds Replaced sub template IDs
* @return {Integer} importResult.flowId Workflow ID
*/
importWorkflow: function (workflowName, file, params) {
var importResult = {},
workflowData, workflowImportOptions, workflowTemplateJson;
if (!workflowName) {
throw "Workflow name is empty";
}
if (!file) {
throw "Workflow file is empty";
}
params = params || {};
params.replaceMissingUserByUserId = (typeof params.replaceMissingUserByUserId == "undefined") ? "0" : params.replaceMissingUserByUserId;
workflowImportOptions = new WorkflowImportOptions();
workflowImportOptions.replaceMissingUserByUserId = params.replaceMissingUserByUserId;
workflowTemplateJson = Packages.org.apache.commons.io.FileUtils.readFileToString(file, "UTF-8") + "";
workflowData = (new java.lang.String(workflowTemplateJson)).getBytes("UTF-8");
importResult.flowId = ixConnect.ix().importWorkFlow2(workflowName, workflowData, workflowImportOptions);
return importResult;
},
/**
* Renames workflow templates
* @param {String} oldName Old name
* @param {String} newName New name
* @return {Object} Result object
*/
renameWorkflowTemplate: function (oldName, newName) {
var me = this,
wfDiag, result;
if (!oldName) {
throw "Old workflow template name is empty";
}
if (!newName) {
throw "New workflow template name is empty";
}
try {
wfDiag = me.getWorkflowTemplate(oldName);
} catch (ex) {
return;
}
wfDiag.name = newName;
ixConnect.ix().checkinWorkflowTemplate(wfDiag, WFDiagramC.mbAll, LockC.NO);
result = {
wfTplId: wfDiag.id + "",
oldName: oldName,
newName: newName
};
return result;
},
/**
* Merge workflow template
* After the workflow templateshave been imported via JSON with a timestamp suffix, they will be stored as a new working
* version of the origin workflow and than the imported workflow will be deleted.
* @param {String} workflowTemplateName Workflow template name
* @return {Object} Result object
*/
mergeWorkflowTemplate: function (workflowTemplateName) {
var me = this,
i, workflowTemplates, workflowTemplate, originWorkflowTemplate, originWorkflowTemplateNamePrefix,
currentWorkflowTemplateName, updateWorkflowTemplate, updateWorkflowTemplateId, result;
if (!workflowTemplateName) {
throw "Workflow template name is empty";
}
workflowTemplates = me.getTemplates({ wfDiagramZ: WFDiagramC.mbAll });
for (i = 0; i < workflowTemplates.length; i++) {
workflowTemplate = workflowTemplates[i];
currentWorkflowTemplateName = workflowTemplate.name + "";
originWorkflowTemplateNamePrefix = workflowTemplateName + " | origin -";
if (currentWorkflowTemplateName.indexOf(originWorkflowTemplateNamePrefix) == 0) {
originWorkflowTemplate = workflowTemplate;
originWorkflowTemplate.name = workflowTemplateName;
}
if (currentWorkflowTemplateName == workflowTemplateName) {
updateWorkflowTemplate = workflowTemplate;
updateWorkflowTemplateId = updateWorkflowTemplate.id;
}
}
if (!originWorkflowTemplate || !updateWorkflowTemplate) {
return;
}
me.addWorkflowTemplateWorkingVersion(updateWorkflowTemplate, originWorkflowTemplate);
me.deleteWorkflowTemplate(updateWorkflowTemplateId);
result = {
wfTplName: workflowTemplateName,
wfTplId: originWorkflowTemplate.id + "",
originWorkflow: {
name: originWorkflowTemplate.name + "",
wfTplId: originWorkflowTemplate.id + ""
},
updateWorkflow: {
name: updateWorkflowTemplate.name + "",
wfTplId: updateWorkflowTemplateId,
deleted: true
}
};
return result;
},
/**
* @deprecated
* @param {de.elo.ix.client.WFDiagram} fromWorkflowTemplate Source workflow template
* @param {de.elo.ix.client.WFDiagram} toWorkflowTemplate Destination workflow template
*/
addWorkflowTemplateVersions: function (fromWorkflowTemplate, toWorkflowTemplate) {
var me = this;
me.addWorkflowTemplateWorkingVersion(fromWorkflowTemplate, toWorkflowTemplate);
},
/**
* Add the working version of a workflow template as working version of another workflow template
* @param {de.elo.ix.client.WFDiagram} fromWorkflowTemplate Source workflow template
* @param {de.elo.ix.client.WFDiagram} toWorkflowTemplate Destination workflow template
*/
addWorkflowTemplateWorkingVersion: function (fromWorkflowTemplate, toWorkflowTemplate) {
var me = this,
nextWorkflowVersionNo;
if (!fromWorkflowTemplate) {
throw "Source workflow template is empty";
}
if (!toWorkflowTemplate) {
throw "Destination workflow template is empty";
}
nextWorkflowVersionNo = me.getNextWorkflowVersionNo(toWorkflowTemplate);
// save old workflow version
toWorkflowTemplate.version.id = -1;
ixConnect.ix().checkinWorkflowTemplate(toWorkflowTemplate, WFDiagramC.mbAll, LockC.NO);
// set update workflow as new working version
fromWorkflowTemplate.id = toWorkflowTemplate.id;
fromWorkflowTemplate.version.id = 0;
fromWorkflowTemplate.version.version = nextWorkflowVersionNo + ".0";
ixConnect.ix().checkinWorkflowTemplate(fromWorkflowTemplate, WFDiagramC.mbAll, LockC.NO);
},
/**
* Returns the highest workflow template version number
* @param {de.elo.ix.client.WFDiagram} workflowTemplate Workflow template
* @return {Number} Next workflow version number
*/
getNextWorkflowVersionNo: function (workflowTemplate) {
var workflowTemplateVersions, i, workflowTemplateVersion, currentWorkflowTemplateVersionNo, nextWorkflowVersionNo,
highestWorkflowTemplateVersionNo = 0;
if (!workflowTemplate) {
throw "Workflow template is empty";
}
workflowTemplateVersions = ixConnect.ix().getWorkflowTemplateVersions(workflowTemplate.id + "", false);
for (i = 0; i < workflowTemplateVersions.length; i++) {
workflowTemplateVersion = workflowTemplateVersions[i];
currentWorkflowTemplateVersionNo = parseInt(workflowTemplateVersion.version, 10);
if (currentWorkflowTemplateVersionNo > highestWorkflowTemplateVersionNo) {
highestWorkflowTemplateVersionNo = currentWorkflowTemplateVersionNo;
}
}
nextWorkflowVersionNo = highestWorkflowTemplateVersionNo + 1;
return nextWorkflowVersionNo;
},
/**
* Deletes a workflow template ID
* @param {String} workflowTemplateId Workflow template ID
*/
deleteWorkflowTemplate: function (workflowTemplateId) {
if (!workflowTemplateId) {
throw "Workflow template ID is empty";
}
ixConnect.ix().deleteWorkflowTemplate(workflowTemplateId + "", "", LockC.NO);
},
/**
* Returns the workflow template
* @param {String} workflowTemplateId Workflow template ID
* @return {String} Workflow ID
*/
getWorkflowTemplate: function (workflowTemplateId) {
if (!workflowTemplateId) {
throw "Workflow template ID is empty";
}
var wfDiag = ixConnect.ix().checkoutWorkflowTemplate(workflowTemplateId + "", "", WFDiagramC.mbAll, LockC.NO);
return wfDiag;
},
/**
* This function parses the configuration object from a nodes comment.
* The comment has to be valid JSON string.
*
* Additionally this method supports parsing the configuration from a config file (see {@link sol.common.ConfigMixin#parseConfiguration}).
*
* If $useTemplating: true is defined in the comment, the node's comment will be templated using handlebars.
*
* Should the workflow's sord be needed in templating, additionally, $useTemplateSord: true can be added to the comment.
*
* In addition there can be a variable number of string arguments for mandatory properties. If the configuration is missing one of those properties, an exception will be thrown.
*
* var config = sol.common.ix.WfUtils.parseAndCheckParams(wf, 23, "objId", ...);
*
* @param {de.elo.ix.client.WFDiagram} workflow The WFDiagram containing the workflow description
* @param {String} nodeId The ID of the node
* @return {Object}
*/
parseAndCheckParams: function (workflow, nodeId) {
var me = this,
emptyArray = [],
mandatoryProperties, node, commentString, comment, config, nodeComment;
mandatoryProperties = (arguments.length > 2) ? emptyArray.slice.call(arguments, 2) : emptyArray;
node = me.getNode(workflow, nodeId);
nodeComment = node.comment + "";
nodeComment = ((nodeComment.length > 0) && (nodeComment.trim().charAt(0) == "{")) ? nodeComment : "";
commentString = String(node.properties) || nodeComment || "{}";
try {
comment = JSON.parse(commentString);
if (comment.$useTemplating) {
commentString = me.templateMixin(commentString, (comment.$useTemplateSord && workflow.objId), workflow.id);
comment = JSON.parse(commentString);
}
config = sol.common.ConfigMixin.parseConfiguration(comment, undefined, true).config;
} catch (ex) {
me.logger.error(["error reading node config of node '{0}': {1}", node.name, commentString], ex);
throw "configuration syntax error (node='" + node.name + "'): " + ex + " - config=" + commentString;
}
mandatoryProperties.forEach(function (property) {
if (!config.hasOwnProperty(property)) {
throw "configuration error: missing parameter '" + property + "'";
}
});
return config;
},
/**
* Applies handlebars template to mixin.
* @param {Object} mixinString The config mixin string
* @param {String} objId The WFDiagram's objId
* @param {String} flowId The WFDiagram's flowId
* @return {Object} Object which resulted from templating
*/
templateMixin: function (mixinString, objId, flowId) {
var me = this, sord, templatingData = {};
if (!sol.common.TemplateUtils) {
throw "$useTemplating and $useTemplateSord can only be used with IX scripts which include lib_sol.common.Template";
}
if (objId) {
try {
sord = (typeof ixConnectAdmin !== "undefined" ? ixConnectAdmin : ixConnect).ix().checkoutSord(objId, SordC.mbAllIndex, LockC.NO);
templatingData.sord = me.getTemplateSord(sord, flowId, { formBlobs: true, asAdmin: true }).sord;
} catch (_) {
throw "could not create templatesord for templating workflowMixins.";
}
}
return sol.common.TemplateUtils.render(mixinString, templatingData, { emptyNonRendered: true });
},
/**
* Returns the node defined by the nodeId.
* @param {de.elo.ix.client.WFDiagram} workflow The WFDiagram containing the workflow description
* @param {String} id The ID of the node
* @return {de.elo.ix.client.WFNode} The node or null, if no node was found with the ID
*/
getNode: function (workflow, id) {
var node, i;
for (i = 0; i < workflow.nodes.length; i++) {
node = workflow.nodes[i];
if ((node.id == id) && (node.type != WFNodeC.TYPE_NOTHING)) {
return node;
}
}
return null;
},
/**
* Returns the name of the node.
* @param {de.elo.ix.client.WFDiagram} workflow The WFDiagram containing the workflow description
* @param {String} nodeId
* @return {String} The name of the node or null, if no node was found with the ID
*/
getNodeName: function (workflow, nodeId) {
var node = this.getNode(workflow, nodeId);
return node ? node.name : null;
},
/**
* Returns all active workflow nodes.
* @param {de.elo.ix.client.WFDiagram} workflow
* @return {de.elo.ix.client.WFNode[]}
*/
getActiveNodes: function (workflow) {
var nodes = [],
i;
for (i = 0; i < workflow.nodes.length; i++) {
if (workflow.nodes[i].enterDateIso != "" && workflow.nodes[i].exitDateIso == "") {
nodes.push(workflow.nodes[i]);
}
}
return nodes;
},
/**
* Returns all active workflow nodes with assigned users or groups.
* @param {de.elo.ix.client.WFDiagram} workflow
* @return {de.elo.ix.client.WFNode[]}
*/
getActiveUserNodes: function (workflow) {
var nodes = [],
i, node;
for (i = 0; i < workflow.nodes.length; i++) {
node = workflow.nodes[i];
if (node.enterDateIso != "" && node.exitDateIso == "" && node.userName != "") {
nodes.push(node);
}
}
return nodes;
},
/**
* Returns the node for a node name.
* If the node name is not unique, the first found node will be returned.
* @param {de.elo.ix.client.WFDiagram} workflow The WFDiagram containing the workflow description
* @param {String} name The name of the node
* @param {String} (optional) Cycle number
* @return {de.elo.ix.client.WFNode} The node or null, if no node was found with the name
*/
getNodeByName: function (workflow, name, cycleNo) {
var node, i;
if (!workflow) {
throw "Workflow diagram is empty";
}
if (!name) {
throw "Name is empty";
}
for (i = 0; i < workflow.nodes.length; i++) {
node = workflow.nodes[i];
if ((node.name == name || node.nameTranslationKey == name) && (node.type != WFNodeC.TYPE_NOTHING)) {
if (!cycleNo || sol.common.StringUtils.endsWith(node.name, "[[" + cycleNo + "]]")) {
return node;
}
}
}
return null;
},
/**
* Returns the node for a node ID.
* @param {de.elo.ix.client.WFDiagram} workflow The WFDiagram containing the workflow description
* @param {String} nodeId Node ID
* @return {de.elo.ix.client.WFNode} The node or null, if no node was found with the ID
*/
getNodeById: function (workflow, nodeId) {
var node, i;
for (i = 0; i < workflow.nodes.length; i++) {
node = workflow.nodes[i];
if ((node.id == nodeId) && (node.type != WFNodeC.TYPE_NOTHING)) {
return node;
}
}
return null;
},
/**
* Retrieves a list of nodes which are successors to the node with the spezified ID.
* The returned nodes could be filtered by type.
* @param {de.elo.ix.client.WFDiagram} workflow The WFDiagram containing the workflow description
* @param {String} nodeId The ID of the node
* @param {Number} filterType (optional) The number of the type (use de.elo.ix.client.WFNodeC.TYPE_* for the types)
* @return {de.elo.ix.client.WFNode[]}
*/
getSuccessorNodes: function (workflow, nodeId, filterType) {
var me = this,
assocs = workflow.matrix.assocs,
succNodes = [];
assocs.forEach(function (assoc) {
var node;
if (assoc.nodeFrom == nodeId) {
node = me.getNode(workflow, assoc.nodeTo);
if (!filterType || filterType == node.type) {
succNodes.push(node);
}
}
});
return succNodes;
},
/**
* Returns the successor node
* @param {de.elo.ix.client.WFDiagram} workflow The WFDiagram containing the workflow description
* @param {String} nodeId The ID of the node
* @param {Object} filterConfig Filte configuration
* @param {Array} filterConfig.nameTranslationKeys Translation keys
* @param {Array} filterConfig.iconNames Icon names
* @return {de.elo.ix.client.WFNode}
*/
getSuccessorNode: function (workflow, nodeId, filterConfig) {
var me = this,
succNodes;
succNodes = me.getSuccessorNodes2(workflow, nodeId, filterConfig);
if (succNodes.length > 1) {
throw "More than one successor node found.";
}
if (succNodes.length == 1) {
return succNodes[0];
}
},
/**
* Returns the successor nodes
* @param {de.elo.ix.client.WFDiagram} workflow The WFDiagram containing the workflow description
* @param {String} nodeId The ID of the node
* @param {Object} filterConfig Filter configuration
* @param {Array} filterConfig.nameTranslationKeys Translation keys
* @param {Array} filterConfig.iconNames Icon names
* @return {de.elo.ix.client.WFNode[]}
*/
getSuccessorNodes2: function (workflow, nodeId, filterConfig) {
var me = this,
succNodes = [],
assocs, assoc, i, j, node,
nameTranslationKeys, nameTranslationKey,
iconNames, iconGuid;
assocs = workflow.matrix.assocs;
for (i = 0; i < assocs.length; i++) {
assoc = assocs[i];
if (assoc.nodeFrom == nodeId) {
node = me.getNode(workflow, assoc.nodeTo);
if (filterConfig) {
if (filterConfig.nameTranslationKeys) {
nameTranslationKeys = filterConfig.nameTranslationKeys;
for (j = 0; j < nameTranslationKeys.length; j++) {
nameTranslationKey = nameTranslationKeys[j];
if (node.nameTranslationKey == nameTranslationKey) {
succNodes.push(node);
continue;
}
}
}
if (filterConfig.iconNames) {
iconNames = filterConfig.iconNames;
for (j = 0; j < iconNames.length; j++) {
iconGuid = me.getWorkflowIconGuid(iconNames[j]);
if (iconGuid && (node.iconId == iconGuid)) {
succNodes.push(node);
}
}
}
} else {
succNodes.push(node);
}
}
}
return me.getUniqueNodes(succNodes);
},
/**
* Returns the guid of a workflow icon
* @param {String} iconName Icon name
* @return {String} Workflow icon GUID
*/
getWorkflowIconGuid: function (iconName) {
var me = this,
guid;
if (!me.workflowIconGuids) {
me.readWorkflowIconGuids();
}
guid = me.workflowIconGuids[iconName];
return guid;
},
/**
* Activates associations
* @param {de.elo.ix.client.WFNodeAssoc[]} assocs Associations
*/
activateAssocs: function (assocs) {
var me = this;
if (!assocs || (assocs.length == 0)) {
return;
}
assocs.forEach(function (assoc) {
me.logger.debug(["Activate association: nodeFrom={0}, nodeTo={1}, assocType={2}", assoc.nodeFrom, assoc.nodeTo, assoc.type]);
assoc.done = true;
});
},
workflowIconFolderGuid: "(E10E1000-E100-E100-E100-E10E10E10EE0)",
/**
* Reads the workflow icon IDs
* @private
*/
readWorkflowIconGuids: function () {
var me = this,
wfIconGuids = {},
sords;
sords = sol.common.RepoUtils.findChildren(me.workflowIconFolderGuid, { includeDocuments: true, includeReferences: true, sordZ: SordC.mbMin });
sords.forEach(function (sord) {
wfIconGuids[sord.name] = sord.guid;
});
me.workflowIconGuids = wfIconGuids;
},
/**
* Returns a list of unique workflow nodes
* @param {Array} nodes Workflow nodes
* @returns {Array} Unique workflow nodes
*/
getUniqueNodes: function (nodes) {
var key,
nodesObj = {},
filteredNodes = [];
if (!nodes) {
throw "Nodes array must be given";
}
nodes.forEach(function (node) {
nodesObj[String(node.id)] = node;
});
for (key in nodesObj) {
if (nodesObj.hasOwnProperty(key)) {
filteredNodes.push(nodesObj[key]);
}
}
return filteredNodes;
},
/**
* Forward a workflow
* @param {String} flowId Flow ID
* @param {String} currentNodeId Current node ID
* @param {Array} destinationNodeIds Destination node ID
*/
forwardWorkflow: function (flowId, currentNodeId, destinationNodeIds) {
var me = this;
if (!flowId) {
throw "Flow ID is empty";
}
if (!currentNodeId) {
throw "Current node ID is empty";
}
if (!destinationNodeIds) {
throw "Destination node IDs are empty";
}
ixConnect.ix().beginEditWorkFlowNode(flowId, currentNodeId, LockC.YES);
ixConnect.ix().endEditWorkFlowNode(flowId, currentNodeId, false, false, null, null, destinationNodeIds);
me.logger.debug(["Workflow forwarded (flowId={0}, currentNodeId={1}, destinationNodeIds={2})", flowId, currentNodeId, destinationNodeIds]);
},
/**
* Changes the user of a node.
* @param {de.elo.ix.client.WFNode} node The node to be changed
* @param {String} user The user which should be set
* @param {Object} params Parameters
* @param {Boolean} [params.changeDesignDepartment=false] Change also the property `designDepartment`
*/
changeNodeUser: function (node, user, params) {
var me = this,
userInfo;
params = params || {};
if (node) {
if (node.userName != user) {
me.logger.debug(["changeNodeUser: node.name={0}, node.userName={1}", node.name, user]);
node.userName = user;
node.userId = -1;
if (params.changeDesignDepartment) {
userInfo = sol.common.UserUtils.getUserInfo(user);
if (userInfo) {
me.logger.debug(["changeNodeUser: node.name={0}, node.designDepartment={1}, node.designDepartmentName={2}", node.name, userInfo.id, userInfo.name]);
node.designDepartment = userInfo.id;
}
}
}
} else {
this.logger.warn("'node' cannot be empty, no user set.");
}
},
/**
* Sets node escalations
* @param {de.elo.ix.client.WFNode} node The node to be changed
* @param {Object[]} nodeEscalations Node escalations
* @param {Object} nodeEscalations.user Node escalation user
* @param {String} nodeEscalations.user.value Node escalation user name
* @param {Boolean} nodeEscalations.user.supervisor Escalate to the users supervisor
* @param {Number} nodeEscalations.timeLimitMinutes Node escalation minutes
*
* Example:
* [
* { "timeLimitMinutes": 1, "user": { "value": "User1" } }
* ]
*
* @param {String} defaultUserName Default user name
*
*/
setNodeEscalations: function (node, nodeEscalations, defaultUserName) {
var me = this,
i, nodeEscalation, userName;
nodeEscalations = nodeEscalations || [];
if (!node) {
throw "Node is empty";
}
if (!nodeEscalations || !nodeEscalations.length) {
return;
}
for (i = 0; i < 2; i++) {
nodeEscalation = nodeEscalations[i];
if (!nodeEscalation) {
continue;
}
userName = (nodeEscalation.user && (typeof nodeEscalation.user.value != "undefined")) ? nodeEscalation.user.value : defaultUserName;
if (nodeEscalation.user && (nodeEscalation.user.supervisor === true)) {
userName = sol.common.UserUtils.getSupervisor(userName);
}
node.timeLimitEscalations[i].userId = -1;
node.timeLimitEscalations[i].userName = userName;
if (typeof nodeEscalation.timeLimitMinutes != "undefined") {
node.timeLimitEscalations[i].timeLimit = nodeEscalation.timeLimitMinutes;
}
me.logger.debug(["Set escalation {0}: node.name={1}, userName={2}", i + "", node.name + "", userName + ""]);
}
},
/**
* Changes the name of a node.
* @param {de.elo.ix.client.WFNode} node The node to be changed
* @param {String} name The new node name
*/
changeNodeName: function (node, name) {
if (node) {
node.name = name;
} else {
this.logger.warn("'node' cannot be empty, name not changed.");
}
},
* Appends a String to a nodes comment field.
* @param {de.elo.ix.client.WFNode} node The node to be changed
* @param {String} comment
* @param {Boolean} override (optional) If `true`, an existing comment will be overridden
*/
appendNodeComment: function (node, comment, override) {
comment = comment || "";
if (override) {
node.comment = comment;
return;
}
if (node.comment && node.comment.length() > 0) {
node.comment += "\n";
}
node.comment += comment;
},
/**
* Finds the first active node of a specific object and workflow
* and returns the node ID and the URL.
* @param {String} objId Object ID
* @param {String} flowId Flow ID
* @return {Object} nodeId, url. Node ID and URL
*/
findFirstActiveNodeWithUrl: function (objId, flowId) {
var me = this,
wfCollectNode, url;
wfCollectNode = me.findFirstActiveNode(objId, flowId);
if (wfCollectNode) {
url = me.getFormUrl(wfCollectNode);
return { nodeId: wfCollectNode.nodeId, url: url };
}
},
/**
* Finds the first active Node of a specific object and workflow
* @param {String} objId Object ID
* @param {String} flowId Flow ID
* @return {de.elo.ix.client.WFCollectNode} wfCollectNode. Found active node.
*/
findFirstActiveNode: function (objId, flowId) {
var me = this,
findTasksInfo, idx, findResult, tasks, i, wfCollectNode;
me.logger.enter("findFirstActiveNode", { objId: objId, flowId: flowId });
findTasksInfo = new FindTasksInfo();
findTasksInfo.inclWorkflows = true;
findTasksInfo.lowestPriority = UserTaskPriorityC.LOWEST;
findTasksInfo.highestPriority = UserTaskPriorityC.HIGHEST;
findTasksInfo.objId = objId;
idx = 0;
findResult = ixConnect.ix().findFirstTasks(findTasksInfo, 100);
while (true) {
tasks = findResult.tasks;
for (i = 0; i < tasks.length; i++) {
wfCollectNode = tasks[i].wfNode;
if ((wfCollectNode.flowId == flowId) || (wfCollectNode.parentFlowId == flowId)) {
me.logger.debug(["found active node for workflow (flowId={0}, nodeName={1}, nodeId={2})", wfCollectNode.flowId, wfCollectNode.nodeName, wfCollectNode.nodeId]);
me.logger.exit("findFirstActiveNode");
return wfCollectNode;
}
}
if (!findResult.isMoreResults()) {
break;
}
idx += findResult.tasks.length;
findResult = ixConnect.ix().findNextTasks(findResult.searchId, idx, 100);
}
if (findResult) {
ixConnect.ix().findClose(findResult.searchId);
}
me.logger.debug(["no active node found for flowId={0}", flowId]);
me.logger.exit("findFirstActiveNode");
return null;
},
/**
* Returns the ELOwf form URL of a specified node
* @param {de.elo.ix.client.WFCollectNode} wfCollectNode
* @return {String} url URL of the ELOwf form
*/
getFormUrl: function (wfCollectNode) {
var me = this,
formName, baseUrl, url,
urlParams = [];
urlParams.push("wfid=" + wfCollectNode.flowId);
urlParams.push("nodeid=" + wfCollectNode.nodeId);
urlParams.push("ticket=" + ixConnect.loginResult.clientInfo.ticket);
urlParams.push("lang=" + ixConnect.loginResult.clientInfo.language);
formName = me.getFormName(wfCollectNode);
baseUrl = me.getWfBaseUrl();
if (!formName || !baseUrl) {
return "";
}
url = baseUrl + "/" + formName + ".jsp?" + urlParams.join("&");
return url;
},
/**
* Returns the ELOwf base URL
* @return {String} url. ELOwf base URL.
*/
getWfBaseUrl: function () {
var me = this,
ixVersion, ixUrl, globalProfile;
if (!me.wfBaseUrl) {
ixVersion = ixConnect.implVersion + "";
// For ELO versions 2x (20, 21 etc.) the proxy WF URL should be used
if (ixVersion.substring(0, 1) == "2") {
ixUrl = sol.common.RepoUtils.getIxOption("publicUrlBase");
if (!ixUrl) {
ixUrl = ixConnect.endpointUrl + "";
}
me.wfBaseUrl = ixUrl.substring(0, ixUrl.length - 3) + "/plugin/de.elo.ix.plugin.proxy/wf";
return me.wfBaseUrl;
}
globalProfile = sol.create("sol.common.UserProfile", { userId: UserProfileC.USERID_ALL });
me.wfBaseUrl = String(globalProfile.getOption("Client.1398.1.0.Options.EloWfUrl.")).replace(/\/$/, "");
}
return me.wfBaseUrl;
},
/**
* Checks wether the ELOwf is running
* @return {Object}
* @return {Boolean} httpResponse.isRunning
*/
checkWfIsRunning: function () {
var me = this,
wfStatusUrl, httpResponse;
wfStatusUrl = me.getWfBaseUrl() + "/wf?__cmd__=status";
httpResponse = sol.common.HttpUtils.sendRequest({ url: wfStatusUrl, resolve: false, connectTimeout: 3000, readTimeout: 10000 });
if (httpResponse.responseOk && (httpResponse.content.indexOf(">ELOwf Status Report<") > -1) && (httpResponse.content.indexOf(">Running<") > -1)) {
httpResponse.isRunning = true;
} else {
httpResponse.isRunning = false;
}
return httpResponse;
},
/**
* Returns form name of a specified node
* @param {de.elo.ix.client.WFCollectNode} wfCollectNode
* @return {String} formName. Form name.
*/
getFormName: function (wfCollectNode) {
var me = this,
formStartPos, formEndPos,
formSpec = String(wfCollectNode.formSpec);
if (!formSpec) {
me.logger.warn("Property 'formSpec' is empty: node.name=" + wfCollectNode.name);
return "";
}
formStartPos = formSpec.indexOf("[") + 1;
formEndPos = formSpec.indexOf("(");
return formSpec.substring(formStartPos, formEndPos);
},
/**
* Creates a template workflow node from a WFDiagram (see {@link sol.common.ObjectFormatter.TemplateWfDiagramNode TemplateWfDiagramNode}).
* @param {de.elo.ix.client.WFDiagram} wfDiagram
* @param {Number} nodeId
* @return {Object}
*/
getTemplateWfDiagramNode: function (wfDiagram, nodeId) {
if (!wfDiagram) {
throw "wfDiagram is empty";
}
if (!nodeId) {
throw "Node ID is empty";
}
return sol.common.ObjectFormatter.format({
node: {
formatter: "sol.common.ObjectFormatter.TemplateWfDiagramNode",
data: wfDiagram,
config: {
flowId: wfDiagram.id,
nodeId: nodeId
}
}
});
},
/**
* Retrieves a map value from a workflow.
* @param {String} flowId Flow ID
* @param {String} key Map key
* @return {String} value
*/
getWfMapValue: function (flowId, key) {
var tmpValue,
value = "";
tmpValue = ixConnect.ix().checkoutMap(MapDomainC.DOMAIN_WORKFLOW_ACTIVE, flowId, [key], LockC.NO).items;
if (tmpValue && tmpValue.length == 1) {
value = tmpValue[0].value;
}
return value;
},
/**
* Sets a map value from a workflow.
* @param {Number} objId Flow ID
* @param {String} flowId Flow ID
* @param {String} key Map key
* @param {String|Array} values Value
*/
setWfMapValue: function (objId, flowId, key, values) {
var i,
keyValues = [];
if (!objId) {
throw "Object ID is empty";
}
if (!flowId) {
throw "Flow ID is empty";
}
if (!key) {
throw "Map key is empty";
}
values = values || "";
objId = parseInt(objId, 10);
if (sol.common.ObjectUtils.isArray(values)) {
for (i = 1; i <= values.length; i++) {
keyValues.push(new KeyValue(key + i, values[i - 1]));
}
keyValues.push(new KeyValue(key + i, ""));
} else {
keyValues.push(new KeyValue(key, values));
}
ixConnect.ix().checkinMap(MapDomainC.DOMAIN_WORKFLOW_ACTIVE, flowId, objId, keyValues, LockC.NO);
},
/**
* Get node User
* @param {de.elo.ix.client.WFDiagram} wfDiagram Workflow diagram
* @param {String} nodeId Node ID
* @param {Object} config Configuration
* @param {Boolean} config.useSessionUserAlternatively
* @return {String} Node user
*/
getNodeUser: function (wfDiagram, nodeId, config) {
var me = this,
wfNode,
nodeUser = "";
config = config || {};
if (wfDiagram && nodeId) {
wfNode = me.getNode(wfDiagram, nodeId);
nodeUser = String(wfNode.userName);
}
if (!nodeUser && config.useSessionUserAlternatively) {
nodeUser = String(ixConnect.loginResult.user.name);
}
return nodeUser;
},
/**
* Returns the cycle number
* @param {String} nodeName Node name
* @return {String}
*/
getCycleNumber: function (nodeName) {
var matches;
matches = String(nodeName).match(/(\[\[)(\d+)(\]\]$)/);
if (matches && (matches.length == 4)) {
return matches[2];
}
},
/**
* Appends the cycle number to a node name
* @param {String} nodeName Node name
* @param {String} cycleNo Cycle number
* @return {String}
*/
appendCycleNumber: function (nodeName, cycleNo) {
return cycleNo ? nodeName + " [[" + cycleNo + "]]" : nodeName;
},
/**
* Retrieves the prefix for service workflows from the `serviceWfPrefix` property from `base.config` file.
* @return {String}
*/
getServiceWfPrefix: function () {
var me = this;
return me.loadBaseConfig().serviceWfPrefix;
},
/**
* Checks, if the workflow template was created of a user with main admin rights.
* @param {de.elo.ix.client.WFDiagram} wfDiagram
*/
checkMainAdminWf: function (wfDiagram) {
var creator;
creator = (wfDiagram && wfDiagram.version) ? wfDiagram.version.userId : "";
if (creator == -1) {
throw "Workflow creator ID is not valid: userId=" + creator;
}
if (!sol.common.UserUtils.isMainAdmin(creator)) {
throw "This workflow uses an admin function node. Hence this workflow template has to be created by an administrative user. It was created by '" + +(creator) + "'";
}
},
/**
* Checks, if a workflow was started from a service.
*
* Currently this is determined by the prefix at the workflow name retrieved by {@link #getServiceWfPrefix}.
* @param {de.elo.ix.client.WFDiagram} wfDiagram
* @return {Boolean}
*/
isServiceWf: function (wfDiagram) {
var me = this,
prefix, wfName, isServiceWf;
me.logger.enter("isServiceWf", arguments);
prefix = me.getServiceWfPrefix();
wfName = wfDiagram.name;
isServiceWf = sol.common.StringUtils.startsWith(wfName, prefix);
me.logger.exit("isServiceWf", { isServiceWf: isServiceWf });
return isServiceWf;
},
/**
* Creates the name for a service workflow from a given name.
*
* Currently this is implemented by using the value retrieved by {@link #getServiceWfPrefix} as prefix.
* @param {String} wfName
* @return {String}
*/
createServiceWfName: function (wfName) {
var me = this,
prefix;
me.logger.enter("createServiceWfName", arguments);
prefix = me.getServiceWfPrefix();
if (prefix) {
wfName = prefix + wfName;
}
me.logger.exit("createServiceWfName", { wfName: wfName });
return wfName;
},
/**
* Sets the session option ´Start docmask workflows´
* @param {Boolean} startDocMaskWorkflows Start doc mask workflows
*/
setSessionOptionStartDocMaskWorkflows: function (startDocMaskWorkflows) {
var sessionOptions;
if (typeof startDocMaskWorkflows !== "boolean") {
return;
}
sessionOptions = {};
sessionOptions[SessionOptionsC.START_DOCMASK_WORKFLOWS] = startDocMaskWorkflows ? "true" : "false";
sol.common.RepoUtils.setSessionOptions(sessionOptions);
},
/**
* Returns a template sord including wfMap data
* @param {de.elo.ix.client.Sord} sord sord for object formatter
* @param {String} flowId Workflow id of workflow map
* @param {Object} options Options
* @param {Boolean} options.asAdmin As admin
* @return {Object} Template Sord
*/
getTemplateSord: function (sord, flowId, options) {
var me = this,
templateSord;
me.logger.enter("getTemplateSord", arguments);
templateSord = sol.common.ObjectFormatter.format({
sord: {
formatter: "sol.common.ObjectFormatter.WfMap",
data: sord,
config: {
sordKeys: ["id", "guid", "maskName", "name", "desc", "IDateIso", "XDateIso", "ownerName"],
allMapFields: true,
allFormBlobFields: (options && options.formBlobs === true),
flowId: flowId,
asAdmin: (options && options.asAdmin) || false
}
}
});
me.logger.exit("getTemplateSord");
return templateSord;
},
/**
* Creates a new reminder.
* @since 1.04.000
* @param {String} objId
* @param {Object} params (optional) Additional parameters
* @param {String[]} params.userIds (optional) The user ids of the reminder receivers. Default is the IX connection user.
* @param {String} params.name (optional) The name for the reminder. Default is `sord.name`.
* @param {String} params.promptDateIso (optional) The date (as ISO string) when the reminder will be set visible for the user. Defualt is the current date.
* @return {Number[]} The reminder ids. There will be one reminderfor each user in `params.userIds` if defined or one reminder for the current user.
*/
createReminder: function (objId, params) {
var me = this,
name, promptDate, receiverIds, reminder, reminderIds;
name = (params && params.name) ? params.name : ixConnect.ix().checkoutSord(objId, SordC.mbMin, LockC.NO).name;
promptDate = (params && params.promptDateIso) ? params.promptDateIso : sol.common.DateUtils.dateToIso(new Date());
receiverIds = (params && params.userIds) ? params.userIds : [ixConnect.loginResult.user.id];
reminder = ixConnect.ix().createReminder(objId);
reminder.name = name;
reminder.promptDateIso = promptDate;
reminderIds = ixConnect.ix().checkinReminder(reminder, receiverIds, false, LockC.NO);
me.logger.info(["reminder created: objId={0}, users={1}", objId, receiverIds.join(",")]);
return reminderIds;
},
/**
* Checks if the passed node is from type WFNodeC.TYPE_CALL_SUB_WORKFLOW
* @param {de.elo.ix.client.WFNode} node which should be checked
*/
isSubworkflowNode: function (node) {
return node && node.type === WFNodeC.TYPE_CALL_SUB_WORKFLOW;
}
});