From 900def94e31cf341aca82ee7c284654d17067f76 Mon Sep 17 00:00:00 2001 From: biniek Date: Thu, 4 Jan 2018 10:43:30 +0100 Subject: Moved variable name extraction to separate class. Change-Id: Ic4105f9f3557c924928321c1b27f7b0e3444bfbc Issue-ID: SO-374 Signed-off-by: biniek --- bpmn/MSOCoreBPMN/pom.xml | 6 + .../java/org/openecomp/mso/bpmn/core/BaseTask.java | 922 ++++++++++----------- .../bpmn/core/internal/VariableNameExtractor.java | 67 ++ .../core/internal/VariableNameExtractorTest.java | 86 ++ 4 files changed, 581 insertions(+), 500 deletions(-) create mode 100644 bpmn/MSOCoreBPMN/src/main/java/org/openecomp/mso/bpmn/core/internal/VariableNameExtractor.java create mode 100644 bpmn/MSOCoreBPMN/src/test/java/org/openecomp/mso/bpmn/core/internal/VariableNameExtractorTest.java (limited to 'bpmn') diff --git a/bpmn/MSOCoreBPMN/pom.xml b/bpmn/MSOCoreBPMN/pom.xml index b3eddeda41..6884c1e33b 100644 --- a/bpmn/MSOCoreBPMN/pom.xml +++ b/bpmn/MSOCoreBPMN/pom.xml @@ -167,5 +167,11 @@ status-control ${project.version} + + org.assertj + assertj-core + 3.8.0 + test + diff --git a/bpmn/MSOCoreBPMN/src/main/java/org/openecomp/mso/bpmn/core/BaseTask.java b/bpmn/MSOCoreBPMN/src/main/java/org/openecomp/mso/bpmn/core/BaseTask.java index e9da2355e4..77e418d4c3 100644 --- a/bpmn/MSOCoreBPMN/src/main/java/org/openecomp/mso/bpmn/core/BaseTask.java +++ b/bpmn/MSOCoreBPMN/src/main/java/org/openecomp/mso/bpmn/core/BaseTask.java @@ -23,510 +23,432 @@ package org.openecomp.mso.bpmn.core; import org.camunda.bpm.engine.delegate.DelegateExecution; import org.camunda.bpm.engine.delegate.Expression; import org.camunda.bpm.engine.delegate.JavaDelegate; +import org.openecomp.mso.bpmn.core.internal.VariableNameExtractor; /** * Base class for service tasks. */ public class BaseTask implements JavaDelegate { - /** - * Get the value of a required field. This method throws - * MissingInjectedFieldException if the expression is null, and - * BadInjectedFieldException if the expression evaluates to a null - * value. - * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the field value - */ - protected Object getField(Expression expression, - DelegateExecution execution, String fieldName) { - return getFieldImpl(expression, execution, fieldName, false); - } - - /** - * Gets the value of an optional field. There are three conditions - * in which this method returns null: - *

- *

    - *
  1. The expression itself is null (i.e. the field is missing - * altogether.
  2. - *
  3. The expression evaluates to a null value.
  4. - *
  5. The expression references a single variable which has not - * been set.
  6. - *
- *

- * Examples:
- * Expression ${x} when x is null: return null
- * Expression ${x} when x is unset: return null
- * Expression ${x+y} when x and/or y are unset: exception
- * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the field value, possibly null - */ - protected Object getOptionalField(Expression expression, - DelegateExecution execution, String fieldName) { - return getFieldImpl(expression, execution, fieldName, true); - } - - /** - * Get the value of a required output variable field. This method - * throws MissingInjectedFieldException if the expression is null, and - * BadInjectedFieldException if the expression produces a null or - * illegal variable name. Legal variable names contain only letters, - * numbers, and the underscore character ('_'). - * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the output variable name - */ - protected String getOutputField(Expression expression, - DelegateExecution execution, String fieldName) { - Object o = getFieldImpl(expression, execution, fieldName, false); - if (o instanceof String) { - String variable = (String) o; - if (!isLegalVariable(variable)) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "'" + variable - + "' is not a legal variable name"); - } - return variable; - } else { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "expected a variable name string" - + ", got object of type " + o.getClass().getName()); - } - } - - /** - * Get the value of an optional output variable field. This method - * throws BadInjectedFieldException if the expression produces an illegal - * variable name. Legal variable names contain only letters, numbers, - * and the underscore character ('_'). - * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the output variable name, possibly null - */ - protected String getOptionalOutputField(Expression expression, - DelegateExecution execution, String fieldName) { - Object o = getFieldImpl(expression, execution, fieldName, true); - if (o instanceof String) { - String variable = (String) o; - if (!isLegalVariable(variable)) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "'" + variable - + "' is not a legal variable name"); - } - return variable; - } else if (o == null) { - return null; - } else { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "expected a variable name string" - + ", got object of type " + o.getClass().getName()); - } - } - - /** - * Get the value of a required string field. This method throws - * MissingInjectedFieldException if the expression is null, and - * BadInjectedFieldException if the expression evaluates to a null - * value. - *

- * Note: the result is coerced to a string value, if necessary. - * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the field value - */ - protected String getStringField(Expression expression, - DelegateExecution execution, String fieldName) { - Object o = getFieldImpl(expression, execution, fieldName, false); - if (o instanceof String) { - return (String) o; - } else { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "cannot convert '" + o.toString() - + "' to Integer"); - } - } - - /** - * Gets the value of an optional string field. There are three conditions - * in which this method returns null: - *

- *

    - *
  1. The expression itself is null (i.e. the field is missing - * altogether.
  2. - *
  3. The expression evaluates to a null value.
  4. - *
  5. The expression references a single variable which has not - * been set.
  6. - *
- *

- * Examples:
- * Expression ${x} when x is null: return null
- * Expression ${x} when x is unset: return null
- * Expression ${x+y} when x and/or y are unset: exception
- *

- * Note: the result is coerced to a string value, if necessary. - * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the field value, possibly null - */ - protected String getOptionalStringField(Expression expression, - DelegateExecution execution, String fieldName) { - Object o = getFieldImpl(expression, execution, fieldName, true); - if (o instanceof String) { - return (String) o; - } else if (o == null) { - return null; - } else { - return o.toString(); - } - } - - /** - * Get the value of a required integer field. This method throws - * MissingInjectedFieldException if the expression is null, and - * BadInjectedFieldException if the expression evaluates to a null - * value or a value that cannot be coerced to an integer. - * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the field value - */ - protected Integer getIntegerField(Expression expression, - DelegateExecution execution, String fieldName) { - Object o = getFieldImpl(expression, execution, fieldName, false); - if (o instanceof Integer) { - return (Integer) o; - } else { - try { - return Integer.parseInt(o.toString()); - } catch (NumberFormatException e) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "cannot convert '" + o.toString() - + "' to Integer"); - } - } - } - - /** - * Gets the value of an optional integer field. There are three conditions - * in which this method returns null: - *

- *

    - *
  1. The expression itself is null (i.e. the field is missing - * altogether.
  2. - *
  3. The expression evaluates to a null value.
  4. - *
  5. The expression references a single variable which has not - * been set.
  6. - *
- *

- * Examples:
- * Expression ${x} when x is null: return null
- * Expression ${x} when x is unset: return null
- * Expression ${x+y} when x and/or y are unset: exception
- *

- * Note: the result is coerced to an integer value, if necessary. This - * method throws BadInjectedFieldException if the result cannot be coerced - * to an integer. - * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the field value, possibly null - */ - protected Integer getOptionalIntegerField(Expression expression, - DelegateExecution execution, String fieldName) { - Object o = getFieldImpl(expression, execution, fieldName, true); - if (o instanceof Integer) { - return (Integer) o; - } else if (o == null) { - return null; - } else { - try { - return Integer.parseInt(o.toString()); - } catch (NumberFormatException e) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "cannot convert '" + o.toString() - + "' to Integer"); - } - } - } - - /** - * Gets the value of an optional long field. There are three conditions - * in which this method returns null: - *

- *

    - *
  1. The expression itself is null (i.e. the field is missing - * altogether.
  2. - *
  3. The expression evaluates to a null value.
  4. - *
  5. The expression references a single variable which has not - * been set.
  6. - *
- *

- * Examples:
- * Expression ${x} when x is null: return null
- * Expression ${x} when x is unset: return null
- * Expression ${x+y} when x and/or y are unset: exception
- *

- * Note: the result is coerced to a long value, if necessary. This - * method throws BadInjectedFieldException if the result cannot be coerced - * to a long. - * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the field value, possibly null - */ - protected Long getOptionalLongField(Expression expression, - DelegateExecution execution, String fieldName) { - Object o = getFieldImpl(expression, execution, fieldName, true); - if (o instanceof Long) { - return (Long) o; - } else if (o == null) { - return null; - } else { - try { - return Long.parseLong(o.toString()); - } catch (NumberFormatException e) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "cannot convert '" + o.toString() - + "' to Long"); - } - } - } - - /** - * Get the value of a required long field. This method throws - * MissingInjectedFieldException if the expression is null, and - * BadInjectedFieldException if the expression evaluates to a null - * value or a value that cannot be coerced to a long. - * - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @return the field value - */ - protected Long getLongField(Expression expression, - DelegateExecution execution, String fieldName) { - Object o = getFieldImpl(expression, execution, fieldName, false); - if (o instanceof Long) { - return (Long) o; - } else { - try { - return Long.parseLong(o.toString()); - } catch (NumberFormatException e) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "cannot convert '" + o.toString() - + "' to Long"); - } - } - } - - /** - * Common implementation for field "getter" methods. - * @param expression the expression - * @param execution the execution - * @param fieldName the field name (for logging and exceptions) - * @param optional true if the field is optional - * @return the field value, possibly null - */ - private Object getFieldImpl(Expression expression, - DelegateExecution execution, String fieldName, boolean optional) { - if (expression == null) { - if (!optional) { - throw new MissingInjectedFieldException( - fieldName, getTaskName()); - } - return null; - } - - Object value; - - try { - value = expression.getValue(execution); - } catch (Exception e) { - if (!optional) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), e.getClass().getSimpleName(), e); - } - - // At this point, we have an exception that occurred while - // evaluating an expression for an optional field. A common - // problem is that the expression is a simple reference to a - // variable which has never been set, e.g. the expression is - // ${x}. The normal activiti behavior is to throw an exception, - // but we don't like that, so we have the following workaround, - // which parses the expression text to see if it is a "simple" - // variable reference, and if so, returns null. If the - // expression is anything other than a single variable - // reference, then an exception is thrown, as it would have - // been without this workaround. - - // Get the expression text so we can parse it - String s = expression.getExpressionText(); - -// if (isDebugEnabled(execution)) { -// logDebug(execution, getTaskName() + " field '" + fieldName -// + "' expression evaluation failed: " + s); -// } - - int len = s.length(); - int i = 0; - - // Skip whitespace - while (i < len && Character.isWhitespace(s.charAt(i))) { - i++; - } - - // Next character must be '$' - if (i == len || s.charAt(i++) != '$') { - throw new BadInjectedFieldException( - fieldName, getTaskName(), e.getClass().getSimpleName(), e); - } - - // Skip whitespace - while (i < len && Character.isWhitespace(s.charAt(i))) { - i++; - } - - // Next character must be '{' - if (i == len || s.charAt(i++) != '{') { - throw new BadInjectedFieldException( - fieldName, getTaskName(), e.getClass().getSimpleName(), e); - } - - // Skip whitespace - while (i < len && Character.isWhitespace(s.charAt(i))) { - i++; - } - - // Collect the variable name - StringBuilder variable = new StringBuilder(); - while (i < len && isWordCharacter(s.charAt(i))) { - variable.append(s.charAt(i)); - i++; - } - - if (variable.length() == 0) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), e.getClass().getSimpleName(), e); - } - - // Skip whitespace - while (i < len && Character.isWhitespace(s.charAt(i))) { - i++; - } - - // Next character must be '}' - if (i == len || s.charAt(i++) != '}') { - throw new BadInjectedFieldException( - fieldName, getTaskName(), e.getClass().getSimpleName(), e); - } - - // Skip whitespace - while (i < len && Character.isWhitespace(s.charAt(i))) { - i++; - } - - // Must be at end of string - if (i != len) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), e.getClass().getSimpleName(), e); - } - -// if (isDebugEnabled(execution)) { -// logDebug(execution, "Checking if variable '" -// + variable.toString() + "' exists"); -// } - - // If the variable exists then the problem was - // something else... - if (execution.hasVariable(variable.toString())) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), e.getClass().getSimpleName(), e); - } - - // The variable doesn't exist. - -// if (isDebugEnabled(execution)) { -// logDebug(execution, "Variable '" + variable.toString() -// + "' does not exist [ok]"); -// } - - value = null; - } - - if (value == null && !optional) { - throw new BadInjectedFieldException( - fieldName, getTaskName(), "required field has null value"); - } - - return value; - } - - /** - * Tests if a character is a "word" character. - * @param c the character - * @return true if the character is a "word" character. - */ - private boolean isWordCharacter(char c) { - return (Character.isLetterOrDigit(c) || c == '_'); - } - - /** - * Tests if the specified string is a legal flow variable name. - * @param name the string - * @return true if the string is a legal flow variable name - */ - private boolean isLegalVariable(String name) { - if (name == null) { - return false; - } - - int len = name.length(); - - if (len == 0) { - return false; - } - - char c = name.charAt(0); - - if (!Character.isLetter(c) && c != '_') { - return false; - } - - for (int i = 1; i < len; i++) { - c = name.charAt(i); - if (!Character.isLetterOrDigit(c) && c != '_') { - return false; - } - } - - return true; - } - - /** - * Returns the name of the task (normally the java class name). - * @return the name of the task - */ - public String getTaskName() { - return getClass().getSimpleName(); - } - - @Override - public void execute(DelegateExecution execution) throws Exception { } + /** + * Get the value of a required field. This method throws + * MissingInjectedFieldException if the expression is null, and + * BadInjectedFieldException if the expression evaluates to a null + * value. + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the field value + */ + protected Object getField(Expression expression, + DelegateExecution execution, String fieldName) { + return getFieldImpl(expression, execution, fieldName, false); + } + + /** + * Gets the value of an optional field. There are three conditions + * in which this method returns null: + *

+ *

    + *
  1. The expression itself is null (i.e. the field is missing + * altogether.
  2. + *
  3. The expression evaluates to a null value.
  4. + *
  5. The expression references a single variable which has not + * been set.
  6. + *
+ *

+ * Examples:
+ * Expression ${x} when x is null: return null
+ * Expression ${x} when x is unset: return null
+ * Expression ${x+y} when x and/or y are unset: exception
+ * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the field value, possibly null + */ + protected Object getOptionalField(Expression expression, + DelegateExecution execution, String fieldName) { + return getFieldImpl(expression, execution, fieldName, true); + } + + /** + * Get the value of a required output variable field. This method + * throws MissingInjectedFieldException if the expression is null, and + * BadInjectedFieldException if the expression produces a null or + * illegal variable name. Legal variable names contain only letters, + * numbers, and the underscore character ('_'). + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the output variable name + */ + protected String getOutputField(Expression expression, + DelegateExecution execution, String fieldName) { + Object o = getFieldImpl(expression, execution, fieldName, false); + if (o instanceof String) { + String variable = (String) o; + if (!isLegalVariable(variable)) { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "'" + variable + + "' is not a legal variable name"); + } + return variable; + } else { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "expected a variable name string" + + ", got object of type " + o.getClass().getName()); + } + } + + /** + * Get the value of an optional output variable field. This method + * throws BadInjectedFieldException if the expression produces an illegal + * variable name. Legal variable names contain only letters, numbers, + * and the underscore character ('_'). + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the output variable name, possibly null + */ + protected String getOptionalOutputField(Expression expression, + DelegateExecution execution, String fieldName) { + Object o = getFieldImpl(expression, execution, fieldName, true); + if (o instanceof String) { + String variable = (String) o; + if (!isLegalVariable(variable)) { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "'" + variable + + "' is not a legal variable name"); + } + return variable; + } else if (o == null) { + return null; + } else { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "expected a variable name string" + + ", got object of type " + o.getClass().getName()); + } + } + + /** + * Get the value of a required string field. This method throws + * MissingInjectedFieldException if the expression is null, and + * BadInjectedFieldException if the expression evaluates to a null + * value. + *

+ * Note: the result is coerced to a string value, if necessary. + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the field value + */ + protected String getStringField(Expression expression, + DelegateExecution execution, String fieldName) { + Object o = getFieldImpl(expression, execution, fieldName, false); + if (o instanceof String) { + return (String) o; + } else { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "cannot convert '" + o.toString() + + "' to Integer"); + } + } + + /** + * Gets the value of an optional string field. There are three conditions + * in which this method returns null: + *

+ *

    + *
  1. The expression itself is null (i.e. the field is missing + * altogether.
  2. + *
  3. The expression evaluates to a null value.
  4. + *
  5. The expression references a single variable which has not + * been set.
  6. + *
+ *

+ * Examples:
+ * Expression ${x} when x is null: return null
+ * Expression ${x} when x is unset: return null
+ * Expression ${x+y} when x and/or y are unset: exception
+ *

+ * Note: the result is coerced to a string value, if necessary. + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the field value, possibly null + */ + protected String getOptionalStringField(Expression expression, + DelegateExecution execution, String fieldName) { + Object o = getFieldImpl(expression, execution, fieldName, true); + if (o instanceof String) { + return (String) o; + } else if (o == null) { + return null; + } else { + return o.toString(); + } + } + + /** + * Get the value of a required integer field. This method throws + * MissingInjectedFieldException if the expression is null, and + * BadInjectedFieldException if the expression evaluates to a null + * value or a value that cannot be coerced to an integer. + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the field value + */ + protected Integer getIntegerField(Expression expression, + DelegateExecution execution, String fieldName) { + Object o = getFieldImpl(expression, execution, fieldName, false); + if (o instanceof Integer) { + return (Integer) o; + } else { + try { + return Integer.parseInt(o.toString()); + } catch (NumberFormatException e) { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "cannot convert '" + o.toString() + + "' to Integer"); + } + } + } + + /** + * Gets the value of an optional integer field. There are three conditions + * in which this method returns null: + *

+ *

    + *
  1. The expression itself is null (i.e. the field is missing + * altogether.
  2. + *
  3. The expression evaluates to a null value.
  4. + *
  5. The expression references a single variable which has not + * been set.
  6. + *
+ *

+ * Examples:
+ * Expression ${x} when x is null: return null
+ * Expression ${x} when x is unset: return null
+ * Expression ${x+y} when x and/or y are unset: exception
+ *

+ * Note: the result is coerced to an integer value, if necessary. This + * method throws BadInjectedFieldException if the result cannot be coerced + * to an integer. + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the field value, possibly null + */ + protected Integer getOptionalIntegerField(Expression expression, + DelegateExecution execution, String fieldName) { + Object o = getFieldImpl(expression, execution, fieldName, true); + if (o instanceof Integer) { + return (Integer) o; + } else if (o == null) { + return null; + } else { + try { + return Integer.parseInt(o.toString()); + } catch (NumberFormatException e) { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "cannot convert '" + o.toString() + + "' to Integer"); + } + } + } + + /** + * Gets the value of an optional long field. There are three conditions + * in which this method returns null: + *

+ *

    + *
  1. The expression itself is null (i.e. the field is missing + * altogether.
  2. + *
  3. The expression evaluates to a null value.
  4. + *
  5. The expression references a single variable which has not + * been set.
  6. + *
+ *

+ * Examples:
+ * Expression ${x} when x is null: return null
+ * Expression ${x} when x is unset: return null
+ * Expression ${x+y} when x and/or y are unset: exception
+ *

+ * Note: the result is coerced to a long value, if necessary. This + * method throws BadInjectedFieldException if the result cannot be coerced + * to a long. + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the field value, possibly null + */ + protected Long getOptionalLongField(Expression expression, + DelegateExecution execution, String fieldName) { + Object o = getFieldImpl(expression, execution, fieldName, true); + if (o instanceof Long) { + return (Long) o; + } else if (o == null) { + return null; + } else { + try { + return Long.parseLong(o.toString()); + } catch (NumberFormatException e) { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "cannot convert '" + o.toString() + + "' to Long"); + } + } + } + + /** + * Get the value of a required long field. This method throws + * MissingInjectedFieldException if the expression is null, and + * BadInjectedFieldException if the expression evaluates to a null + * value or a value that cannot be coerced to a long. + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @return the field value + */ + protected Long getLongField(Expression expression, + DelegateExecution execution, String fieldName) { + Object o = getFieldImpl(expression, execution, fieldName, false); + if (o instanceof Long) { + return (Long) o; + } else { + try { + return Long.parseLong(o.toString()); + } catch (NumberFormatException e) { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "cannot convert '" + o.toString() + + "' to Long"); + } + } + } + + /** + * Common implementation for field "getter" methods. + * + * @param expression the expression + * @param execution the execution + * @param fieldName the field name (for logging and exceptions) + * @param optional true if the field is optional + * @return the field value, possibly null + */ + private Object getFieldImpl(Expression expression, + DelegateExecution execution, String fieldName, boolean optional) { + if (expression == null) { + if (!optional) { + throw new MissingInjectedFieldException( + fieldName, getTaskName()); + } + return null; + } + + Object value = null; + + try { + value = expression.getValue(execution); + } catch (Exception e) { + if (!optional) { + throw new BadInjectedFieldException( + fieldName, getTaskName(), e.getClass().getSimpleName(), e); + } + + // At this point, we have an exception that occurred while + // evaluating an expression for an optional field. A common + // problem is that the expression is a simple reference to a + // variable which has never been set, e.g. the expression is + // ${x}. The normal activiti behavior is to throw an exception, + // but we don't like that, so we have the following workaround, + // which parses the expression text to see if it is a "simple" + // variable reference, and if so, returns null. If the + // expression is anything other than a single variable + // reference, then an exception is thrown, as it would have + // been without this workaround. + + // Get the expression text so we can parse it + String s = expression.getExpressionText(); + new VariableNameExtractor(s).extract().ifPresent(name -> { + if (execution.hasVariable(name)) { + throw new BadInjectedFieldException( + fieldName, getTaskName(), e.getClass().getSimpleName(), e); + } + }); + } + + if (value == null && !optional) { + throw new BadInjectedFieldException( + fieldName, getTaskName(), "required field has null value"); + } + + return value; + } + + /** + * Tests if a character is a "word" character. + * + * @param c the character + * @return true if the character is a "word" character. + */ + private static boolean isWordCharacter(char c) { + return (Character.isLetterOrDigit(c) || c == '_'); + } + + /** + * Tests if the specified string is a legal flow variable name. + * + * @param name the string + * @return true if the string is a legal flow variable name + */ + private boolean isLegalVariable(String name) { + if (name == null) { + return false; + } + + int len = name.length(); + + if (len == 0) { + return false; + } + + char c = name.charAt(0); + + if (!Character.isLetter(c) && c != '_') { + return false; + } + + for (int i = 1; i < len; i++) { + c = name.charAt(i); + if (!Character.isLetterOrDigit(c) && c != '_') { + return false; + } + } + + return true; + } + + /** + * Returns the name of the task (normally the java class name). + * + * @return the name of the task + */ + public String getTaskName() { + return getClass().getSimpleName(); + } + + @Override + public void execute(DelegateExecution execution) throws Exception { + } } diff --git a/bpmn/MSOCoreBPMN/src/main/java/org/openecomp/mso/bpmn/core/internal/VariableNameExtractor.java b/bpmn/MSOCoreBPMN/src/main/java/org/openecomp/mso/bpmn/core/internal/VariableNameExtractor.java new file mode 100644 index 0000000000..e1aaba74da --- /dev/null +++ b/bpmn/MSOCoreBPMN/src/main/java/org/openecomp/mso/bpmn/core/internal/VariableNameExtractor.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.mso.bpmn.core.internal; + +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Extracts variable name from expression if entire expression is just + * one variable, for example "${x}". + * + * Ignores all whitespaces, except inside variable name. + * + * Examples: + * "${x}", extracted variable name is "x" + * " ${\t weird_NAME }", extracted variable name is "weird_NAME" + * "${incorrect name}", no extracted name + * "${two}+${two}", no extracted name + */ +public class VariableNameExtractor { + + private static final Pattern VARIABLE_NAME_PATTERN = Pattern + .compile("^\\s*\\$\\s*\\{\\s*([a-zA-Z0-9_]+)\\s*\\}\\s*$"); + + private final String expression; + + + /** + * Creates new VariableNameExtractor + * @param expression expression to be parsed + */ + public VariableNameExtractor(String expression) { + this.expression = expression; + } + + /** + * Extracts variable name from expression given in constructor + * @return Optional of variable name, empty if expression wasn't single variable + */ + public Optional extract() { + Matcher matcher = VARIABLE_NAME_PATTERN.matcher(expression); + if (!matcher.matches()) { + return Optional.empty(); + } + return Optional.of(matcher.group(1)); + } + +} diff --git a/bpmn/MSOCoreBPMN/src/test/java/org/openecomp/mso/bpmn/core/internal/VariableNameExtractorTest.java b/bpmn/MSOCoreBPMN/src/test/java/org/openecomp/mso/bpmn/core/internal/VariableNameExtractorTest.java new file mode 100644 index 0000000000..57f479f7cb --- /dev/null +++ b/bpmn/MSOCoreBPMN/src/test/java/org/openecomp/mso/bpmn/core/internal/VariableNameExtractorTest.java @@ -0,0 +1,86 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.mso.bpmn.core.internal; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Optional; +import org.junit.Test; + +public class VariableNameExtractorTest { + + @Test + public void shouldExtractVariableName() throws Exception { + // given + String name = "A_different_NAME123"; + String variable = "${A_different_NAME123}"; + VariableNameExtractor extractor = new VariableNameExtractor(variable); + // when + Optional extracted = extractor.extract(); + // then + assertThat(extracted).isPresent().contains(name); + } + + @Test + public void shouldExtractVariableNameFromWhitespaces() throws Exception { + // given + String name = "name"; + String variable = " \n\t$ \n\t{ \n\tname \n\t} \n\t"; + VariableNameExtractor extractor = new VariableNameExtractor(variable); + // when + Optional extracted = extractor.extract(); + // then + assertThat(extracted).isPresent().contains(name); + } + + @Test + public void shouldReturnEmptyIfThereIsMoreThanVariable() throws Exception { + // given + String variable = "a ${test}"; + VariableNameExtractor extractor = new VariableNameExtractor(variable); + // when + Optional extracted = extractor.extract(); + // then + assertThat(extracted).isNotPresent(); + } + + @Test + public void shouldReturnEmptyIfVariableNameIsIncorrect() throws Exception { + // given + String variable = "${name with space}"; + VariableNameExtractor extractor = new VariableNameExtractor(variable); + // when + Optional extracted = extractor.extract(); + // then + assertThat(extracted).isNotPresent(); + } + + @Test + public void shouldReturnEmptyIfTwoVariablesPresent() throws Exception { + // given + String variable = "${var1} ${var2}"; + VariableNameExtractor extractor = new VariableNameExtractor(variable); + // when + Optional extracted = extractor.extract(); + // then + assertThat(extracted).isNotPresent(); + } +} \ No newline at end of file -- cgit 1.2.3-korg