blob: 6e809f4ed739d9f6e3e40d8ddfd39167977da15c [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.
*/
'use strict';
/*global $:false */
/*global vkbeautify:false */
/**
* @ngdoc service
* @name angApp.InstanceService
* @description
* # InstanceService
* Service in the angApp.
*/
angular.module('odeConsole')
.factory('InstanceService', function ($log, $q, xmlFilter, SoapService, IMAPI_ENDPOINT) {
var PMAPI_NS = 'http://www.apache.org/ode/pmapi';
/** private functions **/
var nsResolver = function (prefix) {
var ns = {
'ns' : 'http://www.apache.org/ode/pmapi/types/2006/08/02/',
'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
'pmapi' : 'http://www.apache.org/ode/pmapi'
};
return ns[prefix] || null;
};
var mapInstanceInfo = function (instanceInfoElement) {
var processNameEl = instanceInfoElement.xpath('ns:process-name', nsResolver),
rootScopeEl = instanceInfoElement.xpath('ns:root-scope', nsResolver),
iObj = {
iid: instanceInfoElement.xpath('ns:iid', nsResolver).text(),
pid: instanceInfoElement.xpath('ns:pid', nsResolver).text(),
processNameShort: processNameEl.text(),
processNameFull: SoapService.qnameToString(SoapService.createQNameObj(processNameEl.text(), processNameEl[0])),
processQName: SoapService.createQNameObj(processNameEl.text(), processNameEl[0]),
status: instanceInfoElement.xpath('ns:status', nsResolver).text(),
started: instanceInfoElement.xpath('ns:dt-started', nsResolver).text(),
lastActive: instanceInfoElement.xpath('ns:dt-last-active', nsResolver).text(),
rootScope: {id: rootScopeEl.attr('siid'),
name: rootScopeEl.attr('name'),
status: rootScopeEl.attr('status'),
modelId: rootScopeEl.attr('modelId')}
};
if (instanceInfoElement.xpath('ns:fault-info', nsResolver).length !== 0) {
var faultNameEl = instanceInfoElement.xpath('ns:fault-info/ns:name', nsResolver);
iObj.fault = {
name: SoapService.createQNameObj(faultNameEl.text(), faultNameEl[0]),
explanation: instanceInfoElement.xpath('ns:fault-info/ns:explanation', nsResolver).text(),
lineNumber: instanceInfoElement.xpath('ns:fault-info/ns:line-number', nsResolver).text(),
aiid: instanceInfoElement.xpath('ns:fault-info/ns:aiid', nsResolver).text()
};
}
if (instanceInfoElement.xpath('ns:failures', nsResolver).length !== 0) {
iObj.failures = {
failure: instanceInfoElement.xpath('ns:failures/ns:dt-failure', nsResolver).text(),
count: instanceInfoElement.xpath('ns:failures/ns:count', nsResolver).text()
};
}
if (instanceInfoElement.xpath('ns:correlation-properties/ns:correlation-property', nsResolver).length !== 0) {
var cProps = instanceInfoElement.xpath('ns:correlation-properties/ns:correlation-property', nsResolver);
iObj.correlationProperties = [];
for (var j = 0; j < cProps.length; j++) {
var propEl = angular.element(cProps[j]);
iObj.correlationProperties.push(
{ name: SoapService.createQNameObj(propEl.attr('propertyName'), propEl[0]),
value: propEl.text()
});
}
}
return iObj;
};
var mapScopeInfo = function (scopeInfoElement) {
var si = {};
si.siid = scopeInfoElement.xpath('ns:siid', nsResolver).text();
si.name = scopeInfoElement.xpath('ns:name', nsResolver).text();
si.status = scopeInfoElement.xpath('ns:status', nsResolver).text();
// variables
si.variables = [];
scopeInfoElement.xpath('ns:variables/ns:variable-ref', nsResolver).each(function() {
var vr = {};
vr.iid = Number($(this).attr('iid'));
vr.siid = Number($(this).attr('siid'));
vr.name = $(this).attr('name');
vr.scope = { name: si.name, status: si.status };
si.variables.push(vr);
});
// endpoints
si.endpoints = [];
scopeInfoElement.xpath('ns:endpoints/ns:endpoint-ref', nsResolver).each(function() {
var er = {};
er.siid = si.siid;
er.partnerLink = $(this).attr('partner-link');
er.partnerRole = $(this).attr('partner-role');
er.scope = { name: si.name, status: si.status };
er.value = vkbeautify.xml($(this).first().html().trim(), 2);
si.endpoints.push(er);
});
// activities
si.activities = [];
scopeInfoElement.xpath('ns:activities/ns:activity-info', nsResolver).each(function() {
var act = {};
act.name = $(this).xpath('ns:name', nsResolver).text();
act.type = $(this).xpath('ns:type', nsResolver).text();
act.status = $(this).xpath('ns:status', nsResolver).text();
act.enabled = $(this).xpath('ns:dt-enabled', nsResolver).text();
act.started = $(this).xpath('ns:dt-started', nsResolver).text();
act.completed = $(this).xpath('ns:dt-completed', nsResolver).text();
act.aiid = Number($(this).xpath('ns:aiid', nsResolver).text());
var scope = $(this).xpath('ns:scope', nsResolver);
act.scope = {siid : Number(scope.attr('siid')), name: scope.attr('name'), modelId: Number(scope.attr('modelId')), status: si.status };
si.activities.push(act);
var failure = $(this).xpath('ns:failure', nsResolver);
if (failure.length > 0) {
act.failure = {};
act.failure.failure = failure.xpath('ns:dt-failure', nsResolver).text();
act.failure.retries = failure.xpath('ns:retries', nsResolver).text();
act.failure.reason = failure.xpath('ns:reason', nsResolver).text();
act.failure.actions = failure.xpath('ns:actions', nsResolver).text().split(' ');
}
});
// children
si.children = [];
// add child references
scopeInfoElement.xpath('ns:children/ns:child-ref', nsResolver).each(function() {
var cr = {};
cr.siid = Number($(this).attr('siid'));
cr.name = $(this).attr('name');
cr.status = $(this).attr('status');
cr.modelId = Number($(this).attr('modelId'));
cr.isRef = true;
si.children.push(cr);
});
return si;
};
/** public functions **/
var is = {};
/**
* List instances and only return summary information about the instance,
* combined with all correlation properties.
*
* The request identifies the process instances using a filter that can
* select instances with a given name, status, property values, etc.
* Without a filter, the operation returns all process instances up to a
* specified <code>limit<.code>. The request also indicates which key fields
* to use for ordering the results.
* </p>
*
* <p>
* The filter element can be used to narrow down the list of process definitions
* by applying selection criteria. There are six filters that can be applied:
* <ul>
* <li><p>name -- Only process instances with this local name.</p></li>
* <li><p>namespace -- Only process instances with this namespace URI.</p></li>
* <li><p>status -- Only process instances with these status code(s).</p></li>
* <li><p>started -- Only process instances started relative to this date/time.</p></li>
* <li><p> last-active -- Only process instances last active relative to this date/time.</p></li>
* <li><p>$property -- Only process instances with a correlation property equal to the
* specified value.</p></li>
* </ul>
*
* </p>
* <p>
* The name and namespace filters can do full or partial name matching. Partial matching
* occurs if either filter ends with an asterisk (*). These filters are not case sensitive,
* for example name=my* will match MyProcess and my-process. If unspecified, the default
* filter is name=* namespace=*.
* </p>
*
* <p>
* The status filter can be used to filter all process definitions based on six status codes:
* <ul>
* <li><p>active -- All currently active process instances (excludes instances in any other
* state).</p></li>
* <li><p>suspended -- All process instances that have not completed, but are currently
* suspended.</p></li>
* <li><p>error -- All process instances that have not completed, but are currently indicate an
* error condition.</p></li>
* <li><p>completed -- All successfully completed process instances (excludes instances in any
* other state). </p></li>
* <li><p>terminated -- All process instances that were terminated.
* <li><p>faulted -- All process instances that encountered a fault (in the global scope).
* </ul>
* <p>
* The started filter can be used to filter all process instances started on or after a
* particular date or date/time instant. The value of this filter is either an ISO-8601
* date or ISO-8601 date/time. For example, to find all process instances started on or
* after September 1, 2005, use started>=20050901. Similarly, the last-active filter can
* be used to filter all process instances based on their last active time. The last
* active time records when the process last completed performing work, and either
* completed or is now waiting to receive a message, a timeout or some other event.
* </p>
*
* <p>
* Each process instance has one or more properties that are set its instantiation, that
* can be used to distinguish it from other process instances. In this version of the
* specification, we only support properties instantiated as part of correlation sets
* defined in the global scope of the process. For example, if a process instantiates a
* correlation set that uses the property order-id, it is possible to filter that process
* instance based on the value of that property.
* </p>
*
* <p>
* The property name is identified by the prefix $. If the property name is an NCName,
* the filter will match all properties with that local name. If the property name is
* {namespace}local, the filter will match all properties with the specified namespace URI
* and local name. For example, to retrieve a list of all active process instances with a
* property order-id that has the value 456, use status=active $order-id=456.
* </p>
*
* <p>
* By default the response returns process instances in no particular order. The order
* element can be used to order the results by specifying a space-separated list of keys.
* Each key can be prefixed with a plus sign '+' to specify ascending order, or a '-'
* minus sign to specify descending order. Without a sign the default behavior is to
* return process instances in ascending order. The currently supported odering keys are:
* <ul>
* <li><p>pid</p></li> -- Order based on the process identifier.
* <li><p>name</p></li> -- Order based on the local name of the process instance.
* <li><p>namespace</p></li> -- Order based on the namespace URI of the process instance.
* <li><p>version</p></li> -- Order based on the version number.
* <li><p>status</p></li> -- Order based on the status of the process instance.
* <li><p>started</p></li> -- Order based on the process instance start date/time.
* <li><p>last-active</p></li> -- Order based on the process instance last active date/time.
* </ul>
*
* @param {string} filter See listInstances' filter argument
* @param {string} order See listInstances' order argument
* @param {number} limit maximum number of instances to return
* @returns list of matching instances
*/
is.listInstancesSummary = function (filter, order, limit) {
filter = filter || '';
order = order || '';
limit = limit || 0;
var deferred = $q.defer();
SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'listInstancesSummary', namespaceURI: PMAPI_NS},
{filter: filter, order: order, limit: limit})
.then(function(response) {
var instances = [],
els = response.xpath('//ns:instance-info', nsResolver),
instance,
i;
for (i = 0; i < els.length; i += 1) {
instance = angular.element(els[i]);
instances.push(mapInstanceInfo(instance));
}
deferred.resolve(instances);
}, function(fault) {
deferred.reject(fault);
});
return deferred.promise;
};
/**
* Get an instance by id.
* @param {number} iid
* @returns information about a specific instance
*/
is.getInstanceInfo = function (iid) {
var deferred = $q.defer();
SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'getInstanceInfo', namespaceURI: PMAPI_NS},
{iid: iid})
.then(function(response) {
deferred.resolve(mapInstanceInfo(response.xpath('//instance-info', nsResolver)));
}, function(fault) {
deferred.reject(fault);
});
return deferred.promise;
};
/** Get info about a scope instance by id, optionally including activity info.
* @param {number} siid scope instance identifier
* @param {boolean} activityInfo if <code>true</code>, include activity info
* @returns information about a specific scope instance
*/
is.getScopeInfoWithActivity = function (siid, activityInfo) {
var deferred = $q.defer();
SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'getScopeInfoWithActivity', namespaceURI: PMAPI_NS},
{sid: siid, activityInfo: activityInfo})
.then(function(response) {
deferred.resolve(mapScopeInfo(response.xpath('//scope-info')));
}, function(fault) {
deferred.reject(fault);
});
return deferred.promise;
};
/**
* Delete a process instances with the given IID.
* @param iid InstanceID.
* @returns collection of instances identfiers, corresponding to deleted
* instances
*/
is.delete = function (iid) {
return SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'delete', namespaceURI: PMAPI_NS},
{filter: 'iid = ' + iid});
};
/**
* Delete the process instances matching the given filter.
* @param filter instance filter (see listInstancesSummary ).
* @returns collection of instances identfiers, corresponding to deleted
* instances
*/
is.deleteFilter = function (filter) {
return SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'delete', namespaceURI: PMAPI_NS},
{filter: filter});
};
/**
* Causes the process instance to terminate immediately, without a chance to
* perform any fault handling or compensation. The process transitions to the
* terminated state. It only affects process instances that are in the active,
* suspended or error states.
* @param iid instance id
* @returns post-change instance information
*/
is.terminate = function (iid) {
return SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'terminate', namespaceURI: PMAPI_NS},
{iid: iid});
};
/**
* Changes the process state from active to suspended. this affects process instances that
* are in the active or error states.
* @param iid instance id
* @returns post-change instance information
*/
is.suspend = function (iid) {
return SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'suspend', namespaceURI: PMAPI_NS},
{iid: iid});
};
/**
* Resume the (previously suspended) instance. This operation only affects process instances
* that are in the suspended state.
* @param iid instance id
* @returns post-change instance information
*/
is.resume = function (iid) {
return SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'resume', namespaceURI: PMAPI_NS},
{iid: iid});
};
/**
* Performs an activity recovery action.
* @param iid instance id (process)
* @param aid instance id (activity)
* @param action recovery action (e.g. retry, fault)
* @returns post-change instance information
*/
is.recoverActivity = function (iid, aid, action) {
return SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'recoverActivity', namespaceURI: PMAPI_NS},
{iid: iid, aid: aid, action: action});
};
/**
* Get info about a variable.
* @param siid scope identifier
* @param varName variable name
* @returns information about variable (basically the value)
*/
is.getVariableInfo = function (siid, varName) {
var deferred = $q.defer();
SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'getVariableInfo', namespaceURI: PMAPI_NS},
{sid: siid, varName: varName})
.then(function(response) {
var res = {};
var selfEl = response.xpath('//variable-info/ns:self', nsResolver);
res.name = selfEl.attr('name');
res.iid = selfEl.attr('iid');
res.siid = selfEl.attr('siid');
res.value = response.xpath('//variable-info/ns:value', nsResolver).html().trim();
deferred.resolve(res);
}, function(fault) {
deferred.reject(fault);
});
return deferred.promise;
};
is.setVariable = function (siid, varName, value) {
return SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'setVariable', namespaceURI: PMAPI_NS},
{sid: siid, varName: varName, value: value});
};
/**
* Retrieve a timeline of BPEL events.
*
* @param instanceFilter instance filter (if set,return only events for matching instances)
* @param eventFilter event filter (event type and data range)
* @returns list of stringified dates (in ISO format)
*/
is.getEventTimeline = function (instanceFilter, eventFilter) {
instanceFilter = instanceFilter || '';
eventFilter = eventFilter || '';
return SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'getEventTimeline', namespaceURI: PMAPI_NS},
{instanceFilter: instanceFilter, eventFilter: eventFilter});
//TODO
};
/**
* Retrieve BPEL events. One may specify an "instance filter" and an "event filter" to
* limit the number of events returned. The instance filter takes the exact same syntax
* as for the {@link #listInstances(String, String, int)} method. The "event filter" employs
* a similar syntax; the following properties may be filtered: <ol>
* <li><em>type</em> - the event type</li>
* <li><em>tstamp</em> - the event timestamp</li>
* </ol>
* @param instanceFilter instance filter (if set,return only events for matching instances)
* @param eventFilter event filter (event type and data range)
* @returns list of events
*/
is.listEvents = function (instanceFilter, eventFilter, maxCount) {
instanceFilter = instanceFilter || '';
eventFilter = eventFilter || '';
return SoapService.callSOAP(IMAPI_ENDPOINT,
{localName: 'getEventTimeline', namespaceURI: PMAPI_NS},
{instanceFilter: instanceFilter, eventFilter: eventFilter, maxCount: maxCount});
//TODO
};
return is;
});