2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.mso.bpmn.core;
23 import java.util.Objects;
25 import org.camunda.bpm.engine.ProcessEngineException;
26 import org.camunda.bpm.engine.delegate.DelegateExecution;
27 import org.camunda.bpm.engine.delegate.Expression;
28 import org.camunda.bpm.engine.delegate.JavaDelegate;
31 * Base class for service tasks.
33 public abstract class BaseTask implements JavaDelegate {
36 * Get the value of a required field. This method throws
37 * MissingInjectedFieldException if the expression is null, and
38 * BadInjectedFieldException if the expression evaluates to a null
41 * @param expression the expression
42 * @param execution the execution
43 * @param fieldName the field name (for logging and exceptions)
44 * @return the field value
46 protected Object getField(Expression expression,
47 DelegateExecution execution, String fieldName) {
48 return getFieldImpl(expression, execution, fieldName, false);
52 * Gets the value of an optional field. There are three conditions
53 * in which this method returns null:
56 * <li> The expression itself is null (i.e. the field is missing
58 * <li>The expression evaluates to a null value.</li>
59 * <li>The expression references a single variable which has not
64 * Expression ${x} when x is null: return null<br>
65 * Expression ${x} when x is unset: return null<br>
66 * Expression ${x+y} when x and/or y are unset: exception<br>
68 * @param expression the expression
69 * @param execution the execution
70 * @param fieldName the field name (for logging and exceptions)
71 * @return the field value, possibly null
73 protected Object getOptionalField(Expression expression,
74 DelegateExecution execution, String fieldName) {
75 return getFieldImpl(expression, execution, fieldName, true);
79 * Get the value of a required output variable field. This method
80 * throws MissingInjectedFieldException if the expression is null, and
81 * BadInjectedFieldException if the expression produces a null or
82 * illegal variable name. Legal variable names contain only letters,
83 * numbers, and the underscore character ('_').
85 * @param expression the expression
86 * @param execution the execution
87 * @param fieldName the field name (for logging and exceptions)
88 * @return the output variable name
90 protected String getOutputField(Expression expression,
91 DelegateExecution execution, String fieldName) {
92 Object o = getFieldImpl(expression, execution, fieldName, false);
93 if (o instanceof String) {
94 String variable = (String) o;
95 if (!isLegalVariable(variable)) {
96 throw new BadInjectedFieldException(
97 fieldName, getTaskName(), "'" + variable
98 + "' is not a legal variable name");
102 throw new BadInjectedFieldException(
103 fieldName, getTaskName(), "expected a variable name string"
104 + ", got object of type " + o.getClass().getName());
109 * Get the value of an optional output variable field. This method
110 * throws BadInjectedFieldException if the expression produces an illegal
111 * variable name. Legal variable names contain only letters, numbers,
112 * and the underscore character ('_').
114 * @param expression the expression
115 * @param execution the execution
116 * @param fieldName the field name (for logging and exceptions)
117 * @return the output variable name, possibly null
119 protected String getOptionalOutputField(Expression expression,
120 DelegateExecution execution, String fieldName) {
121 Object o = getFieldImpl(expression, execution, fieldName, true);
122 if (o instanceof String) {
123 String variable = (String) o;
124 if (!isLegalVariable(variable)) {
125 throw new BadInjectedFieldException(
126 fieldName, getTaskName(), "'" + variable
127 + "' is not a legal variable name");
130 } else if (o == null) {
133 throw new BadInjectedFieldException(
134 fieldName, getTaskName(), "expected a variable name string"
135 + ", got object of type " + o.getClass().getName());
140 * Get the value of a required string field. This method throws
141 * MissingInjectedFieldException if the expression is null, and
142 * BadInjectedFieldException if the expression evaluates to a null
145 * Note: the result is coerced to a string value, if necessary.
147 * @param expression the expression
148 * @param execution the execution
149 * @param fieldName the field name (for logging and exceptions)
150 * @return the field value
152 protected String getStringField(Expression expression,
153 DelegateExecution execution, String fieldName) {
154 Object o = getFieldImpl(expression, execution, fieldName, false);
155 if (o instanceof String) {
158 throw new BadInjectedFieldException(
159 fieldName, getTaskName(), "cannot convert '" + o.toString()
165 * Gets the value of an optional string field. There are three conditions
166 * in which this method returns null:
169 * <li> The expression itself is null (i.e. the field is missing
171 * <li>The expression evaluates to a null value.</li>
172 * <li>The expression references a single variable which has not
177 * Expression ${x} when x is null: return null<br>
178 * Expression ${x} when x is unset: return null<br>
179 * Expression ${x+y} when x and/or y are unset: exception<br>
181 * Note: the result is coerced to a string value, if necessary.
183 * @param expression the expression
184 * @param execution the execution
185 * @param fieldName the field name (for logging and exceptions)
186 * @return the field value, possibly null
188 protected String getOptionalStringField(Expression expression,
189 DelegateExecution execution, String fieldName) {
190 Object o = getFieldImpl(expression, execution, fieldName, true);
191 return Objects.toString(o, null);
195 * Get the value of a required integer field. This method throws
196 * MissingInjectedFieldException if the expression is null, and
197 * BadInjectedFieldException if the expression evaluates to a null
198 * value or a value that cannot be coerced to an integer.
200 * @param expression the expression
201 * @param execution the execution
202 * @param fieldName the field name (for logging and exceptions)
203 * @return the field value
205 protected Integer getIntegerField(Expression expression,
206 DelegateExecution execution, String fieldName) {
207 Object o = getFieldImpl(expression, execution, fieldName, false);
208 if (o instanceof Integer) {
212 return Integer.parseInt(o.toString());
213 } catch (NumberFormatException e) {
214 throw new BadInjectedFieldException(
215 fieldName, getTaskName(), "cannot convert '" + o.toString()
222 * Gets the value of an optional integer field. There are three conditions
223 * in which this method returns null:
226 * <li> The expression itself is null (i.e. the field is missing
228 * <li>The expression evaluates to a null value.</li>
229 * <li>The expression references a single variable which has not
234 * Expression ${x} when x is null: return null<br>
235 * Expression ${x} when x is unset: return null<br>
236 * Expression ${x+y} when x and/or y are unset: exception<br>
238 * Note: the result is coerced to an integer value, if necessary. This
239 * method throws BadInjectedFieldException if the result cannot be coerced
242 * @param expression the expression
243 * @param execution the execution
244 * @param fieldName the field name (for logging and exceptions)
245 * @return the field value, possibly null
247 protected Integer getOptionalIntegerField(Expression expression,
248 DelegateExecution execution, String fieldName) {
249 Object o = getFieldImpl(expression, execution, fieldName, true);
250 if (o instanceof Integer) {
252 } else if (o == null) {
256 return Integer.parseInt(o.toString());
257 } catch (NumberFormatException e) {
258 throw new BadInjectedFieldException(
259 fieldName, getTaskName(), "cannot convert '" + o.toString()
266 * Gets the value of an optional long field. There are three conditions
267 * in which this method returns null:
270 * <li> The expression itself is null (i.e. the field is missing
272 * <li>The expression evaluates to a null value.</li>
273 * <li>The expression references a single variable which has not
278 * Expression ${x} when x is null: return null<br>
279 * Expression ${x} when x is unset: return null<br>
280 * Expression ${x+y} when x and/or y are unset: exception<br>
282 * Note: the result is coerced to a long value, if necessary. This
283 * method throws BadInjectedFieldException if the result cannot be coerced
286 * @param expression the expression
287 * @param execution the execution
288 * @param fieldName the field name (for logging and exceptions)
289 * @return the field value, possibly null
291 protected Long getOptionalLongField(Expression expression,
292 DelegateExecution execution, String fieldName) {
293 Object o = getFieldImpl(expression, execution, fieldName, true);
294 if (o instanceof Long) {
296 } else if (o == null) {
300 return Long.parseLong(o.toString());
301 } catch (NumberFormatException e) {
302 throw new BadInjectedFieldException(
303 fieldName, getTaskName(), "cannot convert '" + o.toString()
310 * Get the value of a required long field. This method throws
311 * MissingInjectedFieldException if the expression is null, and
312 * BadInjectedFieldException if the expression evaluates to a null
313 * value or a value that cannot be coerced to a long.
315 * @param expression the expression
316 * @param execution the execution
317 * @param fieldName the field name (for logging and exceptions)
318 * @return the field value
320 protected Long getLongField(Expression expression,
321 DelegateExecution execution, String fieldName) {
322 Object o = getFieldImpl(expression, execution, fieldName, false);
323 if (o instanceof Long) {
327 return Long.parseLong(o.toString());
328 } catch (NumberFormatException e) {
329 throw new BadInjectedFieldException(
330 fieldName, getTaskName(), "cannot convert '" + o.toString()
337 * Common implementation for field "getter" methods.
338 * @param expression the expression
339 * @param execution the execution
340 * @param fieldName the field name (for logging and exceptions)
341 * @param optional true if the field is optional
342 * @return the field value, possibly null
344 private Object getFieldImpl(Expression expression,
345 DelegateExecution execution, String fieldName, boolean optional) {
346 if (expression == null) {
348 throw new MissingInjectedFieldException(
349 fieldName, getTaskName());
357 value = expression.getValue(execution);
358 } catch (Exception e) {
360 throw new BadInjectedFieldException(
361 fieldName, getTaskName(), e.getClass().getSimpleName(), e);
364 // At this point, we have an exception that occurred while
365 // evaluating an expression for an optional field. A common
366 // problem is that the expression is a simple reference to a
367 // variable which has never been set, e.g. the expression is
368 // ${x}. The normal activiti behavior is to throw an exception,
369 // but we don't like that, so we have the following workaround,
370 // which parses the expression text to see if it is a "simple"
371 // variable reference, and if so, returns null. If the
372 // expression is anything other than a single variable
373 // reference, then an exception is thrown, as it would have
374 // been without this workaround.
376 // Get the expression text so we can parse it
377 String s = expression.getExpressionText();
379 // if (isDebugEnabled(execution)) {
380 // logDebug(execution, getTaskName() + " field '" + fieldName
381 // + "' expression evaluation failed: " + s);
384 int len = s.length();
388 while (i < len && Character.isWhitespace(s.charAt(i))) {
392 // Next character must be '$'
393 if (i == len || s.charAt(i++) != '$') {
394 throw new BadInjectedFieldException(
395 fieldName, getTaskName(), e.getClass().getSimpleName(), e);
399 while (i < len && Character.isWhitespace(s.charAt(i))) {
403 // Next character must be '{'
404 if (i == len || s.charAt(i++) != '{') {
405 throw new BadInjectedFieldException(
406 fieldName, getTaskName(), e.getClass().getSimpleName(), e);
410 while (i < len && Character.isWhitespace(s.charAt(i))) {
414 // Collect the variable name
415 StringBuilder variable = new StringBuilder();
416 while (i < len && isWordCharacter(s.charAt(i))) {
417 variable.append(s.charAt(i));
421 if (variable.length() == 0) {
422 throw new BadInjectedFieldException(
423 fieldName, getTaskName(), e.getClass().getSimpleName(), e);
427 while (i < len && Character.isWhitespace(s.charAt(i))) {
431 // Next character must be '}'
432 if (i == len || s.charAt(i++) != '}') {
433 throw new BadInjectedFieldException(
434 fieldName, getTaskName(), e.getClass().getSimpleName(), e);
438 while (i < len && Character.isWhitespace(s.charAt(i))) {
442 // Must be at end of string
444 throw new BadInjectedFieldException(
445 fieldName, getTaskName(), e.getClass().getSimpleName(), e);
448 // if (isDebugEnabled(execution)) {
449 // logDebug(execution, "Checking if variable '"
450 // + variable.toString() + "' exists");
453 // If the variable exists then the problem was
455 if (execution.hasVariable(variable.toString())) {
456 throw new BadInjectedFieldException(
457 fieldName, getTaskName(), e.getClass().getSimpleName(), e);
460 // The variable doesn't exist.
462 // if (isDebugEnabled(execution)) {
463 // logDebug(execution, "Variable '" + variable.toString()
464 // + "' does not exist [ok]");
470 if (value == null && !optional) {
471 throw new BadInjectedFieldException(
472 fieldName, getTaskName(), "required field has null value");
479 * Tests if a character is a "word" character.
480 * @param c the character
481 * @return true if the character is a "word" character.
483 private boolean isWordCharacter(char c) {
484 return (Character.isLetterOrDigit(c) || c == '_');
488 * Tests if the specified string is a legal flow variable name.
489 * @param name the string
490 * @return true if the string is a legal flow variable name
492 private boolean isLegalVariable(String name) {
497 int len = name.length();
503 char c = name.charAt(0);
505 if (!Character.isLetter(c) && c != '_') {
509 for (int i = 1; i < len; i++) {
511 if (!Character.isLetterOrDigit(c) && c != '_') {
520 * Returns the name of the task (normally the java class name).
521 * @return the name of the task
523 public String getTaskName() {
524 return getClass().getSimpleName();
529 * Check if shouldFail variable is set to true.
533 protected boolean shouldFail(DelegateExecution execution) {
534 Boolean shouldFail = (Boolean) execution.getVariable("shouldFail");
535 return shouldFail != null && shouldFail;