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.onap.so.bpmn.core;
23 import org.camunda.bpm.engine.delegate.DelegateExecution;
24 import org.camunda.bpm.engine.delegate.Expression;
25 import org.camunda.bpm.engine.delegate.JavaDelegate;
26 import org.onap.so.bpmn.core.internal.VariableNameExtractor;
29 * Base class for service tasks.
31 public class BaseTask implements JavaDelegate {
34 * Get the value of a required field. This method throws MissingInjectedFieldException if the expression is null,
35 * and BadInjectedFieldException if the expression evaluates to a null value.
37 * @param expression the expression
38 * @param execution the execution
39 * @param fieldName the field name (for logging and exceptions)
40 * @return the field value
42 protected Object getField(Expression expression, DelegateExecution execution, String fieldName) {
43 return getFieldImpl(expression, execution, fieldName, false);
47 * Gets the value of an optional field. There are three conditions in which this method returns null:
50 * <li>The expression itself is null (i.e. the field is missing altogether.</li>
51 * <li>The expression evaluates to a null value.</li>
52 * <li>The expression references a single variable which has not been set.</li>
56 * Expression ${x} when x is null: return null<br>
57 * Expression ${x} when x is unset: return null<br>
58 * Expression ${x+y} when x and/or y are unset: exception<br>
60 * @param expression the expression
61 * @param execution the execution
62 * @param fieldName the field name (for logging and exceptions)
63 * @return the field value, possibly null
65 protected Object getOptionalField(Expression expression, DelegateExecution execution, String fieldName) {
66 return getFieldImpl(expression, execution, fieldName, true);
70 * Get the value of a required output variable field. This method throws MissingInjectedFieldException if the
71 * expression is null, and BadInjectedFieldException if the expression produces a null or illegal variable name.
72 * Legal variable names contain only letters, numbers, and the underscore character ('_').
74 * @param expression the expression
75 * @param execution the execution
76 * @param fieldName the field name (for logging and exceptions)
77 * @return the output variable name
79 protected String getOutputField(Expression expression, DelegateExecution execution, String fieldName) {
80 Object o = getFieldImpl(expression, execution, fieldName, false);
81 if (o instanceof String) {
82 String variable = (String) o;
83 if (!isLegalVariable(variable)) {
84 throw new BadInjectedFieldException(fieldName, getTaskName(),
85 "'" + variable + "' is not a legal variable name");
89 throw new BadInjectedFieldException(fieldName, getTaskName(),
90 "expected a variable name string" + ", got object of type " + o.getClass().getName());
95 * Get the value of an optional output variable field. This method throws BadInjectedFieldException if the
96 * expression produces an illegal variable name. Legal variable names contain only letters, numbers, and the
97 * underscore character ('_').
99 * @param expression the expression
100 * @param execution the execution
101 * @param fieldName the field name (for logging and exceptions)
102 * @return the output variable name, possibly null
104 protected String getOptionalOutputField(Expression expression, DelegateExecution execution, String fieldName) {
105 Object o = getFieldImpl(expression, execution, fieldName, true);
106 if (o instanceof String) {
107 String variable = (String) o;
108 if (!isLegalVariable(variable)) {
109 throw new BadInjectedFieldException(fieldName, getTaskName(),
110 "'" + variable + "' is not a legal variable name");
113 } else if (o == null) {
116 throw new BadInjectedFieldException(fieldName, getTaskName(),
117 "expected a variable name string" + ", got object of type " + o.getClass().getName());
122 * Get the value of a required string field. This method throws MissingInjectedFieldException if the expression is
123 * null, and BadInjectedFieldException if the expression evaluates to a null value.
125 * Note: the result is coerced to a string value, if necessary.
127 * @param expression the expression
128 * @param execution the execution
129 * @param fieldName the field name (for logging and exceptions)
130 * @return the field value
132 protected String getStringField(Expression expression, DelegateExecution execution, String fieldName) {
133 Object o = getFieldImpl(expression, execution, fieldName, false);
134 if (o instanceof String) {
137 throw new BadInjectedFieldException(fieldName, getTaskName(),
138 "cannot convert '" + o.toString() + "' to Integer");
143 * Gets the value of an optional string field. There are three conditions in which this method returns null:
146 * <li>The expression itself is null (i.e. the field is missing altogether.</li>
147 * <li>The expression evaluates to a null value.</li>
148 * <li>The expression references a single variable which has not been set.</li>
152 * Expression ${x} when x is null: return null<br>
153 * Expression ${x} when x is unset: return null<br>
154 * Expression ${x+y} when x and/or y are unset: exception<br>
156 * Note: the result is coerced to a string value, if necessary.
158 * @param expression the expression
159 * @param execution the execution
160 * @param fieldName the field name (for logging and exceptions)
161 * @return the field value, possibly null
163 protected String getOptionalStringField(Expression expression, DelegateExecution execution, String fieldName) {
164 Object o = getFieldImpl(expression, execution, fieldName, true);
165 if (o instanceof String) {
167 } else if (o == null) {
175 * Get the value of a required integer field. This method throws MissingInjectedFieldException if the expression is
176 * null, and BadInjectedFieldException if the expression evaluates to a null value or a value that cannot be coerced
179 * @param expression the expression
180 * @param execution the execution
181 * @param fieldName the field name (for logging and exceptions)
182 * @return the field value
184 protected Integer getIntegerField(Expression expression, DelegateExecution execution, String fieldName) {
185 Object o = getFieldImpl(expression, execution, fieldName, false);
186 if (o instanceof Integer) {
190 return Integer.parseInt(o.toString());
191 } catch (NumberFormatException e) {
192 throw new BadInjectedFieldException(fieldName, getTaskName(),
193 "cannot convert '" + o.toString() + "' to Integer");
199 * Gets the value of an optional integer field. There are three conditions in which this method returns null:
202 * <li>The expression itself is null (i.e. the field is missing altogether.</li>
203 * <li>The expression evaluates to a null value.</li>
204 * <li>The expression references a single variable which has not been set.</li>
208 * Expression ${x} when x is null: return null<br>
209 * Expression ${x} when x is unset: return null<br>
210 * Expression ${x+y} when x and/or y are unset: exception<br>
212 * Note: the result is coerced to an integer value, if necessary. This method throws BadInjectedFieldException if
213 * the result cannot be coerced to an integer.
215 * @param expression the expression
216 * @param execution the execution
217 * @param fieldName the field name (for logging and exceptions)
218 * @return the field value, possibly null
220 protected Integer getOptionalIntegerField(Expression expression, DelegateExecution execution, String fieldName) {
221 Object o = getFieldImpl(expression, execution, fieldName, true);
222 if (o instanceof Integer) {
224 } else if (o == null) {
228 return Integer.parseInt(o.toString());
229 } catch (NumberFormatException e) {
230 throw new BadInjectedFieldException(fieldName, getTaskName(),
231 "cannot convert '" + o.toString() + "' to Integer");
237 * Gets the value of an optional long field. There are three conditions in which this method returns null:
240 * <li>The expression itself is null (i.e. the field is missing altogether.</li>
241 * <li>The expression evaluates to a null value.</li>
242 * <li>The expression references a single variable which has not been set.</li>
246 * Expression ${x} when x is null: return null<br>
247 * Expression ${x} when x is unset: return null<br>
248 * Expression ${x+y} when x and/or y are unset: exception<br>
250 * Note: the result is coerced to a long value, if necessary. This method throws BadInjectedFieldException if the
251 * result cannot be coerced to a long.
253 * @param expression the expression
254 * @param execution the execution
255 * @param fieldName the field name (for logging and exceptions)
256 * @return the field value, possibly null
258 protected Long getOptionalLongField(Expression expression, DelegateExecution execution, String fieldName) {
259 Object o = getFieldImpl(expression, execution, fieldName, true);
260 if (o instanceof Long) {
262 } else if (o == null) {
266 return Long.parseLong(o.toString());
267 } catch (NumberFormatException e) {
268 throw new BadInjectedFieldException(fieldName, getTaskName(),
269 "cannot convert '" + o.toString() + "' to Long");
275 * Get the value of a required long field. This method throws MissingInjectedFieldException if the expression is
276 * null, and BadInjectedFieldException if the expression evaluates to a null value or a value that cannot be coerced
279 * @param expression the expression
280 * @param execution the execution
281 * @param fieldName the field name (for logging and exceptions)
282 * @return the field value
284 protected Long getLongField(Expression expression, DelegateExecution execution, String fieldName) {
285 Object o = getFieldImpl(expression, execution, fieldName, false);
286 if (o instanceof Long) {
290 return Long.parseLong(o.toString());
291 } catch (NumberFormatException e) {
292 throw new BadInjectedFieldException(fieldName, getTaskName(),
293 "cannot convert '" + o.toString() + "' to Long");
299 * Common implementation for field "getter" methods.
301 * @param expression the expression
302 * @param execution the execution
303 * @param fieldName the field name (for logging and exceptions)
304 * @param optional true if the field is optional
305 * @return the field value, possibly null
307 private Object getFieldImpl(Expression expression, DelegateExecution execution, String fieldName,
309 if (expression == null) {
311 throw new MissingInjectedFieldException(fieldName, getTaskName());
319 value = expression.getValue(execution);
320 } catch (Exception e) {
322 throw new BadInjectedFieldException(fieldName, getTaskName(), e.getClass().getSimpleName(), e);
325 // At this point, we have an exception that occurred while
326 // evaluating an expression for an optional field. A common
327 // problem is that the expression is a simple reference to a
328 // variable which has never been set, e.g. the expression is
329 // ${x}. The normal activiti behavior is to throw an exception,
330 // but we don't like that, so we have the following workaround,
331 // which parses the expression text to see if it is a "simple"
332 // variable reference, and if so, returns null. If the
333 // expression is anything other than a single variable
334 // reference, then an exception is thrown, as it would have
335 // been without this workaround.
337 // Get the expression text so we can parse it
338 String s = expression.getExpressionText();
339 new VariableNameExtractor(s).extract().ifPresent(name -> {
340 if (execution.hasVariable(name)) {
341 throw new BadInjectedFieldException(fieldName, getTaskName(), e.getClass().getSimpleName(), e);
346 if (value == null && !optional) {
347 throw new BadInjectedFieldException(fieldName, getTaskName(), "required field has null value");
354 * Tests if a character is a "word" character.
356 * @param c the character
357 * @return true if the character is a "word" character.
359 private static boolean isWordCharacter(char c) {
360 return (Character.isLetterOrDigit(c) || c == '_');
364 * Tests if the specified string is a legal flow variable name.
366 * @param name the string
367 * @return true if the string is a legal flow variable name
369 private boolean isLegalVariable(String name) {
374 int len = name.length();
380 char c = name.charAt(0);
382 if (!Character.isLetter(c) && c != '_') {
386 for (int i = 1; i < len; i++) {
388 if (!Character.isLetterOrDigit(c) && c != '_') {
397 * Returns the name of the task (normally the java class name).
399 * @return the name of the task
401 public String getTaskName() {
402 return getClass().getSimpleName();
406 public void execute(DelegateExecution execution) throws Exception {}