diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/marshalling/ExpressionEditorMessageJSONMarshaller.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/marshalling/ExpressionEditorMessageJSONMarshaller.java new file mode 100644 index 0000000000..7f2d063639 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/marshalling/ExpressionEditorMessageJSONMarshaller.java @@ -0,0 +1,102 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor.marshalling; + +import org.codehaus.jackson.JsonEncoding; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonGenerator; +import org.jbpm.designer.expressioneditor.model.Condition; +import org.jbpm.designer.expressioneditor.model.ExpressionEditorMessage; +import org.jbpm.designer.expressioneditor.model.ConditionExpression; + +import java.io.ByteArrayOutputStream; + +public class ExpressionEditorMessageJSONMarshaller { + + public ExpressionEditorMessageJSONMarshaller() { + + } + + public String marshall(ExpressionEditorMessage message) throws Exception { + + if (message == null) return null; + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + JsonFactory jsonFactory = new JsonFactory(); + JsonGenerator generator = jsonFactory.createJsonGenerator(outputStream, JsonEncoding.UTF8); + + generator.writeStartObject(); + + if (message.getExpression() == null) message.setExpression(new ConditionExpression()); + + if (message.getExpression() != null) { + + generator.writeFieldName(ExpressionEditorMessageTokens.OPERATOR_TOKEN); + if (message.getExpression().getOperator() != null) { + generator.writeString(message.getExpression().getOperator()); + } else { + generator.writeNull(); + } + + generator.writeArrayFieldStart(ExpressionEditorMessageTokens.CONDITIONS_TOKEN); + if (message.getExpression().getConditions().size() > 0) { + for (Condition condition : message.getExpression().getConditions()) { + generator.writeStartObject(); + generator.writeFieldName(ExpressionEditorMessageTokens.CONDITION_TOKEN); + generator.writeString(condition.getFunction()); + if (condition.getParameters().size() > 0) { + generator.writeArrayFieldStart(ExpressionEditorMessageTokens.PARAMETERS_TOKEN); + for (String param : condition.getParameters()) { + generator.writeString(param); + } + generator.writeEndArray(); + } + generator.writeEndObject(); + } + } + generator.writeEndArray(); + } + + generator.writeFieldName(ExpressionEditorMessageTokens.SCRIPT_TOKEN); + if (message.getScript() != null) { + generator.writeString(message.getScript()); + } else { + generator.writeNull(); + } + + generator.writeFieldName(ExpressionEditorMessageTokens.ERROR_CODE_TOKEN); + if (message.getErrorCode() != null) { + generator.writeString(message.getErrorCode()); + } else { + generator.writeNull(); + } + + generator.writeFieldName(ExpressionEditorMessageTokens.ERROR_MESSAGE_TOKEN); + if (message.getErrorMessage() != null) { + generator.writeString(message.getErrorMessage()); + } else { + generator.writeNull(); + } + + generator.writeEndObject(); + + generator.close(); + return outputStream.toString(); + + } + +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/marshalling/ExpressionEditorMessageJSONUnmarshaller.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/marshalling/ExpressionEditorMessageJSONUnmarshaller.java new file mode 100644 index 0000000000..5e52cf3a81 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/marshalling/ExpressionEditorMessageJSONUnmarshaller.java @@ -0,0 +1,144 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor.marshalling; + +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonToken; +import org.jbpm.designer.expressioneditor.model.Condition; +import org.jbpm.designer.expressioneditor.model.ExpressionEditorMessage; +import org.jbpm.designer.expressioneditor.model.ConditionExpression; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + + +public class ExpressionEditorMessageJSONUnmarshaller { + + private static final Logger logger = LoggerFactory.getLogger(ExpressionEditorMessageJSONUnmarshaller.class); + + public ExpressionEditorMessageJSONUnmarshaller() { + } + + public ExpressionEditorMessage unmarshall(String jsonMessage) throws Exception { + JsonFactory jsonFactory = new JsonFactory(); + JsonParser parser = null; + try { + parser = jsonFactory.createJsonParser(jsonMessage); + } catch (Exception e) { + logger.error("It was not possible to create a json parser for the jsonMessage: " + jsonMessage, e); + throw e; + } + return unmarshall(parser); + } + + public ExpressionEditorMessage unmarshall(InputStream inputStream) throws Exception { + JsonFactory jsonFactory = new JsonFactory(); + JsonParser parser = null; + try { + parser = jsonFactory.createJsonParser(inputStream); + } catch (Exception e) { + logger.error("It was not possible to create the a json parser for the inputStream: " + inputStream, e); + throw e; + } + return unmarshall(parser); + } + + + private ExpressionEditorMessage unmarshall(JsonParser parser) throws Exception { + ExpressionEditorMessage message = new ExpressionEditorMessage(); + ConditionExpression expression = new ConditionExpression(); + + try { + String currentField; + + while (parser.nextToken() != JsonToken.END_OBJECT) { + + currentField = parser.getCurrentName(); + + if (ExpressionEditorMessageTokens.OPERATOR_TOKEN.equals(currentField)) { + parser.nextToken(); + expression.setOperator(parseText(parser)); + message.setExpression(expression); + } else if (ExpressionEditorMessageTokens.CONDITIONS_TOKEN.equals(currentField)) { + List conditions = parseConditions(parser); + if (conditions.size() > 0) { + expression.setConditions(conditions); + message.setExpression(expression); + } + } else if (ExpressionEditorMessageTokens.SCRIPT_TOKEN.equals(currentField)) { + parser.nextToken(); + message.setScript(parseText(parser)); + } else if (ExpressionEditorMessageTokens.ERROR_CODE_TOKEN.equals(currentField)) { + parser.nextToken(); + message.setErrorCode(parseText(parser)); + } else if (ExpressionEditorMessageTokens.ERROR_MESSAGE_TOKEN.equals(currentField)) { + parser.nextToken(); + message.setErrorMessage(parseText(parser)); + } + } + } catch (IOException e) { + logger.error("An error was produced during json message parsing. " + e); + throw e; + } + return message; + } + + private String parseText(JsonParser parser) throws IOException, JsonParseException { + return parser.getText(); + } + + private List parseConditions(JsonParser parser) throws IOException, JsonParseException { + List result = new ArrayList(); + Condition condition; + + if (parser.nextToken() == JsonToken.START_ARRAY) { + while (parser.nextToken() != JsonToken.END_ARRAY) { + if ((condition = parseCondition(parser)) != null) { + result.add(condition); + } + } + } + return result; + } + + private Condition parseCondition(JsonParser parser) throws IOException, JsonParseException { + Condition condition = null; + if (parser.getCurrentToken() == JsonToken.START_OBJECT && parser.nextToken() != JsonToken.END_OBJECT) { + condition = new Condition(); + if (ExpressionEditorMessageTokens.CONDITION_TOKEN.equals(parser.getCurrentName())) { + parser.nextToken(); + condition.setFunction(parseText(parser)); + } + if (parser.nextToken() != JsonToken.END_OBJECT && ExpressionEditorMessageTokens.PARAMETERS_TOKEN.equals(parser.getCurrentName())) { + //parser the parameters + if (parser.nextToken() == JsonToken.START_ARRAY) { + while (parser.nextToken() != JsonToken.END_ARRAY) { + condition.addParam(parseText(parser)); + } + } + } + } + return condition; + } + +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/marshalling/ExpressionEditorMessageTokens.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/marshalling/ExpressionEditorMessageTokens.java new file mode 100644 index 0000000000..b9b8a9f2b4 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/marshalling/ExpressionEditorMessageTokens.java @@ -0,0 +1,13 @@ +package org.jbpm.designer.expressioneditor.marshalling; + +public interface ExpressionEditorMessageTokens { + + static final String OPERATOR_TOKEN = "operator"; + static final String CONDITION_TOKEN = "condition"; + static final String CONDITIONS_TOKEN = "conditions"; + static final String PARAMETERS_TOKEN = "parameters"; + static final String SCRIPT_TOKEN = "script"; + static final String ERROR_CODE_TOKEN = "errorCode"; + static final String ERROR_MESSAGE_TOKEN = "errorMessage"; + +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/model/Condition.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/model/Condition.java new file mode 100644 index 0000000000..c5a5a0a8a7 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/model/Condition.java @@ -0,0 +1,55 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor.model; + +import java.util.ArrayList; +import java.util.List; + +public class Condition { + + private String function; + + private List parameters = new ArrayList(); + + public Condition() { + } + + public Condition(String function) { + this.function = function; + } + + public String getFunction() { + return function; + } + + public void setFunction(String function) { + this.function = function; + } + + public List getParameters() { + return parameters; + } + + public void setParameters(List parameters) { + this.parameters = parameters; + } + + public void addParam(String param) { + parameters.add(param); + } + +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/model/ConditionExpression.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/model/ConditionExpression.java new file mode 100644 index 0000000000..9cede1e125 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/model/ConditionExpression.java @@ -0,0 +1,54 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor.model; + +import java.util.ArrayList; +import java.util.List; + +public class ConditionExpression { + + public static final String AND_OPERATOR = "AND"; + + public static final String OR_OPERATOR = "OR"; + + private String operator; + + private List conditions = new ArrayList(); + + public ConditionExpression() { + } + + public ConditionExpression(String operator) { + this.operator = operator; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } + + public List getConditions() { + return conditions; + } + + public void setConditions(List conditions) { + this.conditions = conditions; + } +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/model/ExpressionEditorMessage.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/model/ExpressionEditorMessage.java new file mode 100644 index 0000000000..c77e56a53a --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/model/ExpressionEditorMessage.java @@ -0,0 +1,63 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor.model; + +public class ExpressionEditorMessage { + + private String errorCode; + + private String errorMessage; + + private ConditionExpression expression; + + private String script; + + public ExpressionEditorMessage() { + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public ConditionExpression getExpression() { + return expression; + } + + public void setExpression(ConditionExpression expression) { + this.expression = expression; + } + + public String getScript() { + return script; + } + + public void setScript(String script) { + this.script = script; + } +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/ExpressionParser.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/ExpressionParser.java new file mode 100644 index 0000000000..b9c0e5ed67 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/ExpressionParser.java @@ -0,0 +1,393 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor.parser; + +import org.jbpm.designer.expressioneditor.model.Condition; +import org.jbpm.designer.expressioneditor.model.ConditionExpression; + +import java.text.MessageFormat; +import java.text.ParseException; +import java.util.Map; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ExpressionParser { + + private static final String VARIABLE_NAME_PARAM_REGEX = "[$_a-zA-Z][$_a-zA-Z0-9]*"; + + public static final String KIE_FUNCTIONS = "KieFunctions."; + + private static Map functionsRegistry = new TreeMap(); + + private int parseIndex = 0; + + private String expression; + + private String functionName = null; + + public static final String FUNCTION_NAME_NOT_RECOGNIZED_ERROR = "The function name \'{0}\' is not recognized by system."; + + public static final String FUNCTION_CALL_NOT_FOUND_ERROR = "Function call was not found, a token like \'" + KIE_FUNCTIONS + "functionName(variable, params)\' is expected."; + + public static final String VALID_FUNCTION_CALL_NOT_FOUND_ERROR = "The \'" + KIE_FUNCTIONS + "\' keyword must be followed by one of the following function names: \'{0}\'"; + + public static final String FUNCTION_CALL_NOT_CLOSED_PROPERLY_ERROR = "Function call \'{0}\' is not closed properly, character \')\' is expected."; + + public static final String SENTENCE_NOT_CLOSED_PROPERLY_ERROR = "Script not closed properly, character \';\' is expected."; + + public static final String VARIABLE_NAME_EXPECTED_ERROR = "Variable name not found, a valid process variable name is expected."; + + public static final String PARAMETER_DELIMITER_EXPECTED_ERROR = "Parameter delimiter \',\' is expected."; + + public static final String STRING_PARAMETER_EXPECTED_ERROR = "String parameter value like \"some value\" is expected."; + + public static final String RETURN_SENTENCE_EXPECTED_ERROR = "Sentence \'{0}\' is expected."; + + public static final String BLANK_AFTER_RETURN_EXPECTED_ERROR = "Sentence \'{0}\' must be followed by a blank space or a line break."; + + private static String functionNames = null; + + static { + + //Operators for all types: + + FunctionDef isNull = new FunctionDef("isNull"); + isNull.addParam("param1", Object.class); + functionsRegistry.put(isNull.getName(), isNull); + + //Global operators: + + FunctionDef equalsTo = new FunctionDef("equalsTo"); + equalsTo.addParam("param1", Object.class); + equalsTo.addParam("param2", String.class); + functionsRegistry.put(equalsTo.getName(), equalsTo); + + //Operators for String type: + + FunctionDef isEmpty = new FunctionDef("isEmpty"); + isEmpty.addParam("param1", Object.class); + functionsRegistry.put(isEmpty.getName(), isEmpty); + + FunctionDef contains = new FunctionDef("contains"); + contains.addParam("param1", Object.class); + contains.addParam("param2", String.class); + functionsRegistry.put(contains.getName(), contains); + + FunctionDef startsWith = new FunctionDef("startsWith"); + startsWith.addParam("param1", Object.class); + startsWith.addParam("param2", String.class); + functionsRegistry.put(startsWith.getName(), startsWith); + + FunctionDef endsWith = new FunctionDef("endsWith"); + endsWith.addParam("param1", Object.class); + endsWith.addParam("param2", String.class); + functionsRegistry.put(endsWith.getName(), endsWith); + + // Operators for Numeric types: + + FunctionDef greaterThan = new FunctionDef("greaterThan"); + greaterThan.addParam("param1", Object.class); + greaterThan.addParam("param2", String.class); + functionsRegistry.put(greaterThan.getName(), greaterThan); + + FunctionDef greaterOrEqualThan = new FunctionDef("greaterOrEqualThan"); + greaterOrEqualThan.addParam("param1", Object.class); + greaterOrEqualThan.addParam("param2", String.class); + functionsRegistry.put(greaterOrEqualThan.getName(), greaterOrEqualThan); + + FunctionDef lessThan = new FunctionDef("lessThan"); + lessThan.addParam("param1", Object.class); + lessThan.addParam("param2", String.class); + functionsRegistry.put(lessThan.getName(), lessThan); + + FunctionDef lessOrEqualThan = new FunctionDef("lessOrEqualThan"); + lessOrEqualThan.addParam("param1", Object.class); + lessOrEqualThan.addParam("param2", String.class); + functionsRegistry.put(lessOrEqualThan.getName(), lessOrEqualThan); + + FunctionDef between = new FunctionDef("between"); + between.addParam("param1", Object.class); + between.addParam("param2", String.class); + between.addParam("param3", String.class); + functionsRegistry.put(between.getName(), between); + + // Operators for Boolean type: + + FunctionDef isTrue = new FunctionDef("isTrue"); + isTrue.addParam("param1", Object.class); + functionsRegistry.put(isTrue.getName(), isTrue); + + + FunctionDef isFalse = new FunctionDef("isFalse"); + isFalse.addParam("param1", Object.class); + functionsRegistry.put(isFalse.getName(), isFalse); + + StringBuilder functionNamesBuilder = new StringBuilder(); + functionNamesBuilder.append("{"); + boolean first = true; + for (String functionName : functionsRegistry.keySet()) { + if (!first) functionNamesBuilder.append(", "); + functionNamesBuilder.append(functionName); + first = false; + } + functionNamesBuilder.append("}"); + functionNames = functionNamesBuilder.toString(); + } + + public ExpressionParser(String expression) { + this.expression = expression; + this.parseIndex = expression != null ? 0 : -1; + } + + public ConditionExpression parse() throws ParseException { + + ConditionExpression conditionExpression = new ConditionExpression(); + Condition condition = null; + FunctionDef functionDef = null; + + parseReturnSentence(); + + functionName = parseFunctionName(); + functionName = functionName.substring(KIE_FUNCTIONS.length(), functionName.length()); + functionDef = functionsRegistry.get(functionName); + + if (functionDef == null) throw new ParseException(errorMessage(FUNCTION_NAME_NOT_RECOGNIZED_ERROR, functionName), parseIndex); + + conditionExpression.setOperator(ConditionExpression.AND_OPERATOR); + condition = new Condition(functionName); + conditionExpression.getConditions().add(condition); + + String param = null; + boolean first = true; + + for (ParamDef paramDef : functionDef.getParams()) { + if (first) { + first = false; + } else { + parseParamDelimiter(); + } + + if (Object.class.getName().equals(paramDef.getType().getName())) { + param = parseVariableName(); + } else { + param = parseStringParameter(); + } + condition.addParam(param); + } + + //all parameters were consumed + parseFunctionClose(); + parseSentenceClose(); + + + return conditionExpression; + } + + private String parseReturnSentence() throws ParseException { + + int index = nextNonBlank(); + if (index < 0) throw new ParseException(errorMessage(RETURN_SENTENCE_EXPECTED_ERROR, "return"), parseIndex); + + if (!expression.startsWith("return", index)) { + //the expression does not start with return. + throw new ParseException(errorMessage(RETURN_SENTENCE_EXPECTED_ERROR, "return"), parseIndex); + } + + parseIndex = index + "return".length(); + + //next character after return must be a \n or a " " + if (!isBlank(expression.charAt(parseIndex))) throw new ParseException(errorMessage(BLANK_AFTER_RETURN_EXPECTED_ERROR, "return"), parseIndex); + + return "return"; + } + + private String parseFunctionName() throws ParseException { + + int index = nextNonBlank(); + if (index < 0) throw new ParseException(errorMessage(FUNCTION_CALL_NOT_FOUND_ERROR), parseIndex); + String functionName = null; + + if (!expression.startsWith(KIE_FUNCTIONS, index)) throw new ParseException(errorMessage(FUNCTION_CALL_NOT_FOUND_ERROR), parseIndex); + + for(FunctionDef functionDef : functionsRegistry.values()) { + if (expression.startsWith(KIE_FUNCTIONS+functionDef.getName()+"(", index)) { + functionName = KIE_FUNCTIONS+functionDef.getName(); + break; + } + } + + if (functionName == null) throw new ParseException(errorMessage(VALID_FUNCTION_CALL_NOT_FOUND_ERROR, functionNames()), parseIndex); + + parseIndex = index + functionName.length() +1; + + return functionName; + } + + private String parseFunctionClose() throws ParseException { + int index = nextNonBlank(); + if (index < 0) throw new ParseException(errorMessage(FUNCTION_CALL_NOT_CLOSED_PROPERLY_ERROR, functionName), parseIndex); + + if (expression.charAt(index) != ')') throw new ParseException(errorMessage(FUNCTION_CALL_NOT_CLOSED_PROPERLY_ERROR, functionName), parseIndex); + + parseIndex = index +1; + return ")"; + } + + private String parseSentenceClose() throws ParseException { + int index = nextNonBlank(); + if (index < 0) throw new ParseException(errorMessage(SENTENCE_NOT_CLOSED_PROPERLY_ERROR), parseIndex); + + if (expression.charAt(index) != ';') throw new ParseException(errorMessage(SENTENCE_NOT_CLOSED_PROPERLY_ERROR), parseIndex); + + parseIndex = index +1; + while (parseIndex < expression.length()) { + if (!isBlank(expression.charAt(parseIndex))) throw new ParseException(errorMessage(SENTENCE_NOT_CLOSED_PROPERLY_ERROR), parseIndex); + parseIndex++; + } + + return ";"; + } + + private String parseVariableName() throws ParseException { + int index = nextNonBlank(); + if (index < 0) throw new ParseException(errorMessage(VARIABLE_NAME_EXPECTED_ERROR), parseIndex); + + Pattern variableNameParam = Pattern.compile(VARIABLE_NAME_PARAM_REGEX); + Matcher variableMatcher = variableNameParam.matcher(expression.substring(index, expression.length())); + + if (!Pattern.matches(VARIABLE_NAME_PARAM_REGEX, String.valueOf(expression.charAt(index)))) throw new ParseException(errorMessage(VARIABLE_NAME_EXPECTED_ERROR), parseIndex); + + String variableName = null; + if (variableMatcher.find()) { + variableName = variableMatcher.group(); + } else { + throw new ParseException(errorMessage(VARIABLE_NAME_EXPECTED_ERROR), parseIndex); + } + + parseIndex = index + variableName.length(); + + return variableName; + } + + private String parseParamDelimiter() throws ParseException { + int index = nextNonBlank(); + if (index < 0) throw new ParseException(errorMessage(PARAMETER_DELIMITER_EXPECTED_ERROR), parseIndex); + + if (expression.charAt(index) != ',') { + throw new ParseException(errorMessage(PARAMETER_DELIMITER_EXPECTED_ERROR), parseIndex); + } + + parseIndex = index + 1; + return ","; + } + + private String parseStringParameter() throws ParseException { + int index = nextNonBlank(); + if (index < 0) throw new ParseException(STRING_PARAMETER_EXPECTED_ERROR, parseIndex); + + if (expression.charAt(index) != '"') { + throw new ParseException(STRING_PARAMETER_EXPECTED_ERROR, parseIndex); + } + + int shift = 1; + Character scapeChar = Character.valueOf('\\'); + Character last = null; + boolean strReaded = false; + StringBuilder param = new StringBuilder(); + for (int i = index+1; i < expression.length(); i++) { + if (expression.charAt(i) == '\\') { + if (scapeChar.equals(last)) { + shift += 2; + param.append('\\'); + last = null; + } else { + last = expression.charAt(i); + } + } else if (expression.charAt(i) == '"') { + if (scapeChar.equals(last)) { + shift += 2; + param.append('"'); + last = null; + } else { + shift++; + strReaded = true; + break; + } + } else if (expression.charAt(i) == 'n') { + if (scapeChar.equals(last)) { + shift += 2; + param.append('\n'); + } else { + shift += 1; + param.append(expression.charAt(i)); + } + last = null; + } else { + if (last != null) { + shift++; + param.append(last); + } + last = null; + shift++; + param.append(expression.charAt(i)); + } + + } + + if (!strReaded) throw new ParseException(STRING_PARAMETER_EXPECTED_ERROR, parseIndex); + + parseIndex = index + shift; + return param.toString(); + } + + private int nextNonBlank() { + if (parseIndex < 0) return -1; + + for (int i = parseIndex; i < expression.length(); i++) { + if (!isBlank(expression.charAt(i))) { + return i; + } + } + + return -1; + } + + private int nextBlank() { + if (parseIndex < 0) return -1; + + for (int i = parseIndex; i < expression.length(); i++) { + if (isBlank(expression.charAt(i))) { + return i; + } + } + + return -1; + } + + private boolean isBlank(Character character) { + return character != null && (character.equals('\n') || character.equals(' ')); + } + + private String errorMessage(String message, Object ... params) { + return MessageFormat.format(message, params); + } + + private String functionNames() { + return functionNames; + } +} \ No newline at end of file diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/ExpressionScriptGenerator.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/ExpressionScriptGenerator.java new file mode 100644 index 0000000000..7368ae127c --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/ExpressionScriptGenerator.java @@ -0,0 +1,124 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor.parser; + +import org.jbpm.designer.expressioneditor.model.Condition; +import org.jbpm.designer.expressioneditor.model.ConditionExpression; +import org.jbpm.designer.expressioneditor.server.ExpressionEditorErrors; + +import java.util.List; + + +public class ExpressionScriptGenerator { + + + public String generateScript(ConditionExpression expression, List errors) { + + StringBuilder script = new StringBuilder(); + String operator = null; + int validTerms = 0; + + //First version implementation. At the moment we don't need a more elaborated programming or templates + //to generate the script. + //For version 6.1 we can provide a more elaborated generation if needed. + + if ("OR".equals(expression.getOperator())) { + operator = "||"; + } else if ("AND".equals(expression.getOperator())) { + operator = "&&"; + } else if (expression.getConditions().size() > 1) { + //we have multiple conditions and the operator is not defined. + //the default operator will be AND + operator = "&&"; + } + + for (Condition condition : expression.getConditions()) { + if (addConditionToScript(condition, script, operator, validTerms, errors) > 0) { + validTerms++; + } else { + //we have an invalid condition. + //at the moment the approach is that all the generation fails. + errors.add(ExpressionEditorErrors.INVALID_CONDITION_ERROR); + return null; + } + } + + return "return " + script.toString() + ";"; + } + + private int addConditionToScript(final Condition condition, final StringBuilder script, final String operator, final int validTerms, final List errors) { + if (condition == null) return 0; + if (!isValidFunction(condition.getFunction())) { + errors.add("Invalid function : " + condition.getFunction()); + return 0; + } + //TODO evaluate if we put more validations. + if (validTerms > 0) { + script.append(" " + operator + " "); + } else { + script.append(" "); + } + script.append(ExpressionParser.KIE_FUNCTIONS + condition.getFunction().trim()); + script.append("("); + boolean first = true; + for (String param : condition.getParameters()) { + if (first) { + //first parameter is always a process variable name. + script.append(param); + first = false; + } else { + //the other parameters are always string parameters. + //TODO escape " and line break charactrers. + script.append(", "); + script.append("\""+escapeStringParam(param)+"\""); + } + } + script.append(")"); + return 1; + } + + private String escapeStringParam(String param) { + if (param == null) return null; + StringBuilder escapedParam = new StringBuilder(param.length() * 2); + char c; + for (int i = 0; i < param.length(); i++) { + c = param.charAt(i); + switch (c) { + case '"' : + escapedParam.append('\\'); + escapedParam.append('"'); + break; + case '\n' : + escapedParam.append('\\'); + escapedParam.append('n'); + break; + case '\\' : + escapedParam.append('\\'); + escapedParam.append('\\'); + break; + default: + escapedParam.append(c); + + } + } + return escapedParam.toString(); + } + + private boolean isValidFunction(String function) { + return function != null && !"".equals(function.trim()); + } +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/FunctionDef.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/FunctionDef.java new file mode 100644 index 0000000000..629d096a05 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/FunctionDef.java @@ -0,0 +1,56 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor.parser; + +import java.util.ArrayList; +import java.util.List; + +public class FunctionDef { + + private String name; + + private List params = new ArrayList(); + + public FunctionDef(String name) { + this.name = name; + } + + public FunctionDef(String name, List params) { + this.name = name; + this.params = params; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + + public void addParam(String name, Class type) { + params.add(new ParamDef(name, type)); + } +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/ParamDef.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/ParamDef.java new file mode 100644 index 0000000000..fa9bc6f476 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/parser/ParamDef.java @@ -0,0 +1,45 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor.parser; + +public class ParamDef { + + private String name; + + private Class type; + + public ParamDef(String name, Class type) { + this.name = name; + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Class getType() { + return type; + } + + public void setType(Class type) { + this.type = type; + } +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/server/ExpressionEditorErrors.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/server/ExpressionEditorErrors.java new file mode 100644 index 0000000000..5195e5a1e4 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/server/ExpressionEditorErrors.java @@ -0,0 +1,29 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ +package org.jbpm.designer.expressioneditor.server; + + +public interface ExpressionEditorErrors { + + static final String INVALID_MESSAGE_ERROR = "INVALID_MESSAGE_ERROR"; + + static final String INVALID_CONDITION_ERROR = "INVALID_CONDITION_ERROR"; + + static final String SCRIPT_PARSING_ERROR = "SCRIPT_PARSING_ERROR"; + + static final String SCRIPT_GENERATION_ERROR = "SCRIPT_GENERATION_ERROR"; + +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/server/ExpressionEditorProcessor.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/server/ExpressionEditorProcessor.java new file mode 100644 index 0000000000..16f9e7dac9 --- /dev/null +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/expressioneditor/server/ExpressionEditorProcessor.java @@ -0,0 +1,178 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ +package org.jbpm.designer.expressioneditor.server; + +import org.jbpm.designer.expressioneditor.marshalling.ExpressionEditorMessageJSONMarshaller; +import org.jbpm.designer.expressioneditor.marshalling.ExpressionEditorMessageJSONUnmarshaller; +import org.jbpm.designer.expressioneditor.model.ConditionExpression; +import org.jbpm.designer.expressioneditor.model.ExpressionEditorMessage; +import org.jbpm.designer.expressioneditor.parser.ExpressionParser; +import org.jbpm.designer.expressioneditor.parser.ExpressionScriptGenerator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +public class ExpressionEditorProcessor { + + private static final Logger logger = LoggerFactory.getLogger(ExpressionEditorProcessor.class); + + private static final String PARSE_COMMAND = "parseScript"; + + private static final String GENERATE_COMMAND = "generateScript"; + + public static final String MESSAGE_PARAM = "expression_editor_message"; + + public static final String COMMAND_PARAM = "expression_editor_command"; + + public ExpressionEditorProcessor() { + } + + public void doProcess(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { + res.setContentType("application/json"); + try { + + ExpressionEditorMessageJSONMarshaller marshaller = new ExpressionEditorMessageJSONMarshaller(); + ExpressionEditorMessageJSONUnmarshaller unmarshaller = new ExpressionEditorMessageJSONUnmarshaller(); + ExpressionEditorMessage requestMessage = null; + ExpressionEditorMessage responseMessage = null; + + PrintWriter out = res.getWriter(); + + String command = req.getParameter(COMMAND_PARAM); + String message = req.getParameter(MESSAGE_PARAM); + + if (logger.isDebugEnabled()) { + logger.debug("Processing request for parameters, command: " + command + ", message: " + message); + } + + if (!isValidCommand(command)) { + logger.error("Invalid command: " + command + " was sent to the ExpressionsEditorProcessor, " + + "request will be discarded."); + return; + } + + try { + requestMessage = unmarshaller.unmarshall(message); + } catch (Exception e) { + logger.error("It was not possible to unmarshall json message, request will be discarded. message: " + message, e); + return; + } + + if (GENERATE_COMMAND.equals(command)) { + responseMessage = doGenerateScript(requestMessage); + } else if (PARSE_COMMAND.equals(command)) { + responseMessage = doParseScript(requestMessage); + } + + if (responseMessage != null) { + try { + String jsonResponse = marshaller.marshall(responseMessage); + if (logger.isDebugEnabled()) { + logger.debug("sending response message: " + jsonResponse); + } + out.write(jsonResponse); + } catch (Exception e) { + //unexpected error. + logger.error("It was not possible to marshal the responseMessage: " + responseMessage, e); + } + } + } catch (Exception e) { + logger.error("Unexpected error during request processing.", e); + } + } + + private ExpressionEditorMessage doParseScript(ExpressionEditorMessage requestMessage) { + + //TODO add more fine grained controls. + String script = requestMessage.getScript(); + ConditionExpression conditionExpression = null; + + if (logger.isDebugEnabled()) logger.debug("parsing script: " + script); + + try { + ExpressionParser parser = new ExpressionParser(script); + conditionExpression = parser.parse(); + requestMessage.setExpression(conditionExpression); + requestMessage.setErrorCode(null); + requestMessage.setErrorMessage(null); + } catch (ParseException e) { + logger.error("Script sent to server couldn't be parsed: " + script + " due to the following error: " + e.getMessage(), e); + requestMessage.setErrorCode(ExpressionEditorErrors.SCRIPT_PARSING_ERROR); + requestMessage.setErrorMessage(e.getMessage()); + requestMessage.setExpression(new ConditionExpression()); + } + return requestMessage; + } + + private ExpressionEditorMessage doGenerateScript(ExpressionEditorMessage requestMessage) { + ExpressionEditorMessage responseMessage = new ExpressionEditorMessage(); + List errors = new ArrayList(); + ExpressionScriptGenerator generator = new ExpressionScriptGenerator(); + + if (isValidMessageForCommand(GENERATE_COMMAND, requestMessage)) { + ConditionExpression expression = requestMessage.getExpression(); + String script = generator.generateScript(expression, errors); + + if (script == null) { + //process the errors. + requestMessage.setErrorCode(ExpressionEditorErrors.SCRIPT_GENERATION_ERROR); + responseMessage.setErrorMessage(concat(errors)); + } + responseMessage.setScript(script); + + } else { + responseMessage.setErrorCode(ExpressionEditorErrors.INVALID_MESSAGE_ERROR); + } + return responseMessage; + } + + private boolean isValidMessageForCommand(String command, ExpressionEditorMessage message) { + if (GENERATE_COMMAND.equals(command)) { + if (message.getExpression() == null) { + logger.error("No expression is present in message: " + message); + return false; + } + } + + return true; + } + + private boolean isValidCommand(String command) { + return PARSE_COMMAND.equals(command) || GENERATE_COMMAND.equals(command); + } + + private String concat(List values) { + StringBuilder result = new StringBuilder(); + if (values == null || values.size() == 0) return result.toString(); + boolean first = true; + for (String value : values) { + if (!first) { + result.append(", "); + } + result.append(value); + first = false; + } + return result.toString(); + } +} diff --git a/jbpm-designer-backend/src/main/java/org/jbpm/designer/web/server/CustomEditorsServlet.java b/jbpm-designer-backend/src/main/java/org/jbpm/designer/web/server/CustomEditorsServlet.java index 03a4e69f07..b3e35a1d1f 100644 --- a/jbpm-designer-backend/src/main/java/org/jbpm/designer/web/server/CustomEditorsServlet.java +++ b/jbpm-designer-backend/src/main/java/org/jbpm/designer/web/server/CustomEditorsServlet.java @@ -1,5 +1,6 @@ package org.jbpm.designer.web.server; +import org.jbpm.designer.expressioneditor.server.ExpressionEditorProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.jbpm.designer.repository.Asset; @@ -47,17 +48,25 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) String profileName = req.getParameter("profile"); String uuid = req.getParameter("uuid"); - if (profile == null) { - profile = _profileService.findProfile(req, profileName); + if (isExpressionEditorRequest(req)) { + //do the processing for the expression editor. + ExpressionEditorProcessor expressionEditorProcessor = new ExpressionEditorProcessor(); + expressionEditorProcessor.doProcess(req, resp); + + } else { + //do the normal processing of this servlet. + if (profile == null) { + profile = _profileService.findProfile(req, profileName); + } + String customEditorsJSON = getCustomEditorsJSON(profile, getServletContext(), uuid); + PrintWriter pw = resp.getWriter(); + resp.setContentType("text/plain"); + resp.setCharacterEncoding("UTF-8"); + pw.write(customEditorsJSON); } - String customEditorsJSON = getCustomEditorsJSON(profile, getServletContext(), uuid); - PrintWriter pw = resp.getWriter(); - resp.setContentType("text/plain"); - resp.setCharacterEncoding("UTF-8"); - pw.write(customEditorsJSON); } - - private String getCustomEditorsJSON(IDiagramProfile profile, ServletContext servletContext, String uuid) { + + private String getCustomEditorsJSON(IDiagramProfile profile, ServletContext servletContext, String uuid) { String retStr = ""; Repository repository = profile.getRepository(); @@ -72,4 +81,9 @@ private String getCustomEditorsJSON(IDiagramProfile profile, ServletContext serv return retStr; } -} + + private boolean isExpressionEditorRequest(HttpServletRequest req) { + return req.getParameter(ExpressionEditorProcessor.COMMAND_PARAM) != null && req.getParameter(ExpressionEditorProcessor.MESSAGE_PARAM) != null; + } + +} \ No newline at end of file diff --git a/jbpm-designer-backend/src/test/java/org/jbpm/designer/expressioneditor/ExpressionEditorMessageMarshallingTest.java b/jbpm-designer-backend/src/test/java/org/jbpm/designer/expressioneditor/ExpressionEditorMessageMarshallingTest.java new file mode 100644 index 0000000000..ce05f5ac12 --- /dev/null +++ b/jbpm-designer-backend/src/test/java/org/jbpm/designer/expressioneditor/ExpressionEditorMessageMarshallingTest.java @@ -0,0 +1,109 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor; + +import org.jbpm.designer.expressioneditor.marshalling.ExpressionEditorMessageJSONMarshaller; +import org.jbpm.designer.expressioneditor.marshalling.ExpressionEditorMessageJSONUnmarshaller; +import org.jbpm.designer.expressioneditor.model.Condition; +import org.jbpm.designer.expressioneditor.model.ConditionExpression; +import org.jbpm.designer.expressioneditor.model.ExpressionEditorMessage; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; + + +public class ExpressionEditorMessageMarshallingTest { + + @Test + public void testUnmarshalling() throws Exception { + + ExpressionEditorMessageJSONUnmarshaller unmarshaller = new ExpressionEditorMessageJSONUnmarshaller(); + ExpressionEditorMessage message = unmarshaller.unmarshall(ExpressionEditorMessageMarshallingTest.class.getResourceAsStream("condition_editor_message.json")); + + assertNotNull("json message was not marshalled", message); + assertNotNull("condition expression was not marshalled", message.getExpression()); + + assertEquals("OR", message.getExpression().getOperator()); + assertEquals(2, message.getExpression().getConditions().size()); + + assertEquals("isEquals", message.getExpression().getConditions().get(0).getFunction()); + assertEquals("variableName1", message.getExpression().getConditions().get(0).getParameters().get(0)); + assertEquals("param1.1", message.getExpression().getConditions().get(0).getParameters().get(1)); + + assertEquals("isBetween", message.getExpression().getConditions().get(1).getFunction()); + assertEquals("variableName2", message.getExpression().getConditions().get(1).getParameters().get(0)); + assertEquals("param2.1", message.getExpression().getConditions().get(1).getParameters().get(1)); + assertEquals("param2.2", message.getExpression().getConditions().get(1).getParameters().get(2)); + + assertEquals("return true;", message.getScript()); + assertEquals("The error code", message.getErrorCode()); + assertEquals("The error message", message.getErrorMessage()); + + } + + @Test + public void testMarshalling() throws Exception { + ExpressionEditorMessageJSONMarshaller marshaller = new ExpressionEditorMessageJSONMarshaller(); + + ExpressionEditorMessage message = new ExpressionEditorMessage(); + + ConditionExpression expression = new ConditionExpression("OR"); + message.setExpression(expression); + + Condition condition1 = new Condition(); + condition1.setFunction("isEquals"); + condition1.getParameters().add("variableName1"); + condition1.getParameters().add("param1.1"); + + expression.getConditions().add(condition1); + + + Condition condition2 = new Condition(); + condition2.setFunction("isBetween"); + condition2.getParameters().add("variableName2"); + condition2.getParameters().add("param2.1"); + condition2.getParameters().add("param2.2"); + + expression.getConditions().add(condition2); + + message.setScript("return true;"); + message.setErrorCode("The error code"); + message.setErrorMessage("The error message"); + + String expectedResult = "{\"operator\":\"OR\"," + + "\"conditions\":[" + + "{" + + "\"condition\":\"isEquals\"," + + "\"parameters\":[\"variableName1\",\"param1.1\"]" + + "}," + + "{" + + "\"condition\":\"isBetween\"," + + "\"parameters\":[\"variableName2\",\"param2.1\",\"param2.2\"]" + + "}" + + "]," + + "\"script\":\"return true;\"," + + "\"errorCode\":\"The error code\"," + + "\"errorMessage\":\"The error message\"" + + "}"; + + String result = marshaller.marshall(message); + + assertEquals(expectedResult, result); + + } +} diff --git a/jbpm-designer-backend/src/test/java/org/jbpm/designer/expressioneditor/ExpressionParserTest.java b/jbpm-designer-backend/src/test/java/org/jbpm/designer/expressioneditor/ExpressionParserTest.java new file mode 100644 index 0000000000..68c66e93be --- /dev/null +++ b/jbpm-designer-backend/src/test/java/org/jbpm/designer/expressioneditor/ExpressionParserTest.java @@ -0,0 +1,161 @@ +/** + * Copyright 2012 JBoss Inc + * + * 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. + */ + +package org.jbpm.designer.expressioneditor; + +import org.jbpm.designer.expressioneditor.model.Condition; +import org.jbpm.designer.expressioneditor.model.ConditionExpression; +import org.jbpm.designer.expressioneditor.parser.ExpressionParser; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; + + +public class ExpressionParserTest { + + Logger logger = LoggerFactory.getLogger(ExpressionParserTest.class); + + @Test + //@Ignore + public void testOneScriptPerLine() throws Exception { + + /* + return between(a, "o\"ne" , "two" ) ; + return isNull(variable1) ; + return greaterThan(variable2 , " the value " ); + return isNull( a); + return greaterOrEqualThan(v, "one", " two"); + */ + + LineNumberReader lineReader = new LineNumberReader(new InputStreamReader(ExpressionEditorMessageMarshallingTest.class.getResourceAsStream("OneScriptPerLine.txt") )); + String line = null; + + List expectedExpressions = new ArrayList(); + + ConditionExpression expression = new ConditionExpression(ConditionExpression.AND_OPERATOR); + Condition condition = new Condition("between"); + condition.addParam("a"); + condition.addParam("o\"ne"); + condition.addParam("two"); + expression.getConditions().add(condition); + expectedExpressions.add(expression); + + expression = new ConditionExpression(ConditionExpression.AND_OPERATOR); + condition = new Condition("isNull"); + condition.addParam("variable1"); + expression.getConditions().add(condition); + expectedExpressions.add(expression); + + expression = new ConditionExpression(ConditionExpression.AND_OPERATOR); + condition = new Condition("greaterThan"); + condition.addParam("variable2"); + condition.addParam(" the value "); + expression.getConditions().add(condition); + expectedExpressions.add(expression); + + expression = new ConditionExpression(ConditionExpression.AND_OPERATOR); + condition = new Condition("isNull"); + condition.addParam("a"); + expression.getConditions().add(condition); + expectedExpressions.add(expression); + + expression = new ConditionExpression(ConditionExpression.AND_OPERATOR); + condition = new Condition("greaterOrEqualThan"); + condition.addParam("v"); + condition.addParam("one"); + expression.getConditions().add(condition); + expectedExpressions.add(expression); + + + while ((line = lineReader.readLine()) != null) { + + logger.debug("line(" + lineReader.getLineNumber() + ") :" + line); + + ExpressionParser parser = new ExpressionParser(line); + + ConditionExpression conditionExpression = parser.parse(); + assertEqualsExpression(expectedExpressions.get(lineReader.getLineNumber()-1) , conditionExpression); + } + + } + + String readFile(String fileName) throws IOException { + + BufferedReader reader = new LineNumberReader(new InputStreamReader(ExpressionEditorMessageMarshallingTest.class.getResourceAsStream(fileName) )); + StringBuilder result = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + result.append(line); + result.append("\n"); + } + return result.toString(); + } + + + @Test + public void testScript1() throws Exception { + + String script = readFile("Script1.txt"); + + ConditionExpression expectedExpression = new ConditionExpression(ConditionExpression.AND_OPERATOR); + Condition expectedCondition = new Condition("greaterOrEqualThan"); + expectedCondition.addParam("variable"); + expectedCondition.addParam("o\\náéö great! \"\n áéíóúñÑ @|#~!·$%&/()=?¿"); + expectedExpression.getConditions().add(expectedCondition); + + ExpressionParser parser = new ExpressionParser(script); + ConditionExpression actualExpression = parser.parse(); + + System.out.println(actualExpression.getOperator()); + for (Condition condition : actualExpression.getConditions()) { + System.out.println("condition: " + condition.getFunction()); + for (String param : condition.getParameters()) { + System.out.println("\""+param+"\""); + } + } + + assertEqualsExpression(expectedExpression, actualExpression); + } + + public void assertEqualsExpression(ConditionExpression expected, ConditionExpression actual) { + assertNotNull(actual); + assertEquals(expected.getOperator(), actual.getOperator()); + assertEquals(expected.getConditions().size(), actual.getConditions().size()); + for (int i = 0; i < expected.getConditions().size(); i++) { + assertEqualsCondition(expected.getConditions().get(i), actual.getConditions().get(i)); + } + } + + public void assertEqualsCondition(Condition expected, Condition actual) { + assertNotNull(actual); + assertEquals(expected.getFunction(), actual.getFunction()); + assertEquals(expected.getParameters().size(), actual.getParameters().size()); + for (int i = 0; i < expected.getParameters().size(); i++) { + assertEquals(expected.getParameters().get(i), actual.getParameters().get(i)); + } + } +} diff --git a/jbpm-designer-backend/src/test/resources/org/jbpm/designer/expressioneditor/OneScriptPerLine.txt b/jbpm-designer-backend/src/test/resources/org/jbpm/designer/expressioneditor/OneScriptPerLine.txt new file mode 100644 index 0000000000..e26ed160af --- /dev/null +++ b/jbpm-designer-backend/src/test/resources/org/jbpm/designer/expressioneditor/OneScriptPerLine.txt @@ -0,0 +1,5 @@ + return KieFunctions.between(a, "o\"ne" , "two" ) ; + return KieFunctions.isNull(variable1) ; +return KieFunctions.greaterThan(variable2, " the value "); +return KieFunctions.isNull( a); + return KieFunctions.greaterOrEqualThan(v, "one"); \ No newline at end of file diff --git a/jbpm-designer-backend/src/test/resources/org/jbpm/designer/expressioneditor/Script1.txt b/jbpm-designer-backend/src/test/resources/org/jbpm/designer/expressioneditor/Script1.txt new file mode 100644 index 0000000000..bd76a1c49b --- /dev/null +++ b/jbpm-designer-backend/src/test/resources/org/jbpm/designer/expressioneditor/Script1.txt @@ -0,0 +1,32 @@ + + + + + + + + return +KieFunctions.greaterOrEqualThan( +variable +, + + "o\\náéö great! \"\n áéíóúñÑ @|#~!·$%&/()=?¿" + +) + +; + + + + + + + + + + + + + + + diff --git a/jbpm-designer-backend/src/test/resources/org/jbpm/designer/expressioneditor/condition_editor_message.json b/jbpm-designer-backend/src/test/resources/org/jbpm/designer/expressioneditor/condition_editor_message.json new file mode 100644 index 0000000000..07a2d9463c --- /dev/null +++ b/jbpm-designer-backend/src/test/resources/org/jbpm/designer/expressioneditor/condition_editor_message.json @@ -0,0 +1,16 @@ +{ + "operator" : "OR", + "conditions" : [ + { + "condition" : "isEquals", + "parameters" : [ "variableName1", "param1.1" ] + }, + { + "condition" : "isBetween", + "parameters" : [ "variableName2", "param2.1", "param2.2" ] + } + ], + "script" : "return true;", + "errorCode": "The error code", + "errorMessage": "The error message" +} \ No newline at end of file diff --git a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_de.js b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_de.js index 10cf036e9e..4a1c13847b 100644 --- a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_de.js +++ b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_de.js @@ -378,6 +378,35 @@ ORYX.I18N.PropertyWindow.ok = "Ok"; ORYX.I18N.PropertyWindow.cancel = "Abbrechen"; ORYX.I18N.PropertyWindow.dateFormat = "d/m/y"; +if (!ORYX.I18N.ConditionExpressionEditorField) ORYX.I18N.ConditionExpressionEditorField = {}; + +ORYX.I18N.ConditionExpressionEditorField.simpleTitle = "Expression Editor - Press [Ctrl-Z] to activate auto-completion"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowTitle = "Sequence Flow Conditions"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowFullTitle = "Sequence Flow Conditions - Press [Ctrl-Z] to activate auto-completion"; +ORYX.I18N.ConditionExpressionEditorField.scriptTab = "Script"; +ORYX.I18N.ConditionExpressionEditorField.editorTab = "Editor"; +ORYX.I18N.ConditionExpressionEditorField.editorDescription = "Run sequence flow if the following conditions are met." +ORYX.I18N.ConditionExpressionEditorField.processVariable = "Process variable:" +ORYX.I18N.ConditionExpressionEditorField.condition = "Condition:" +ORYX.I18N.ConditionExpressionEditorField.between = "between"; +ORYX.I18N.ConditionExpressionEditorField.contains = "contains"; +ORYX.I18N.ConditionExpressionEditorField.endsWith = "ends with"; +ORYX.I18N.ConditionExpressionEditorField.equalsTo = "is equal to"; +ORYX.I18N.ConditionExpressionEditorField.greaterThan = "is greater than"; +ORYX.I18N.ConditionExpressionEditorField.greaterThanOrEqual = "is greater than or equal to"; +ORYX.I18N.ConditionExpressionEditorField.isEmpty = "is empty"; +ORYX.I18N.ConditionExpressionEditorField.isFalse = "is false"; +ORYX.I18N.ConditionExpressionEditorField.isNull = "is null"; +ORYX.I18N.ConditionExpressionEditorField.isTrue = "is true"; +ORYX.I18N.ConditionExpressionEditorField.lessThan = "is less than"; +ORYX.I18N.ConditionExpressionEditorField.lessThanOrEqual = "is less than or equal to"; +ORYX.I18N.ConditionExpressionEditorField.startsWith = "starts with"; +ORYX.I18N.ConditionExpressionEditorField.paramsError = "Unable to generate Script expression, please fill correctly the form params."; +ORYX.I18N.ConditionExpressionEditorField.saveError = "Unable to save property value, please check the value and try again."; +ORYX.I18N.ConditionExpressionEditorField.scriptParseError = "Error found parsing script:
{0}

Press OK to go to the Expression Editor screen and loose the current Script or Cancel to go back to the Script Editor."; +ORYX.I18N.ConditionExpressionEditorField.scriptGenerationError = "Error found generating script:
{0}

Please check the data entered on the Expression Editor."; +ORYX.I18N.ConditionExpressionEditorField.nonExistingVariable = "The process does not contain any variable called '{0}'."; + if(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; ORYX.I18N.ShapeMenuPlugin.drag = "Ziehen"; diff --git a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_en.js b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_en.js index 9993dc9fe4..525aef156c 100644 --- a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_en.js +++ b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_en.js @@ -404,6 +404,35 @@ ORYX.I18N.PropertyWindow.ok = "Ok"; ORYX.I18N.PropertyWindow.cancel = "Cancel"; ORYX.I18N.PropertyWindow.dateFormat = "m/d/y"; +if (!ORYX.I18N.ConditionExpressionEditorField) ORYX.I18N.ConditionExpressionEditorField = {}; + +ORYX.I18N.ConditionExpressionEditorField.simpleTitle = "Expression Editor - Press [Ctrl-Z] to activate auto-completion"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowTitle = "Sequence Flow Conditions"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowFullTitle = "Sequence Flow Conditions - Press [Ctrl-Z] to activate auto-completion"; +ORYX.I18N.ConditionExpressionEditorField.scriptTab = "Script"; +ORYX.I18N.ConditionExpressionEditorField.editorTab = "Editor"; +ORYX.I18N.ConditionExpressionEditorField.editorDescription = "Run sequence flow if the following conditions are met." +ORYX.I18N.ConditionExpressionEditorField.processVariable = "Process variable:" +ORYX.I18N.ConditionExpressionEditorField.condition = "Condition:" +ORYX.I18N.ConditionExpressionEditorField.between = "between"; +ORYX.I18N.ConditionExpressionEditorField.contains = "contains"; +ORYX.I18N.ConditionExpressionEditorField.endsWith = "ends with"; +ORYX.I18N.ConditionExpressionEditorField.equalsTo = "is equal to"; +ORYX.I18N.ConditionExpressionEditorField.greaterThan = "is greater than"; +ORYX.I18N.ConditionExpressionEditorField.greaterThanOrEqual = "is greater than or equal to"; +ORYX.I18N.ConditionExpressionEditorField.isEmpty = "is empty"; +ORYX.I18N.ConditionExpressionEditorField.isFalse = "is false"; +ORYX.I18N.ConditionExpressionEditorField.isNull = "is null"; +ORYX.I18N.ConditionExpressionEditorField.isTrue = "is true"; +ORYX.I18N.ConditionExpressionEditorField.lessThan = "is less than"; +ORYX.I18N.ConditionExpressionEditorField.lessThanOrEqual = "is less than or equal to"; +ORYX.I18N.ConditionExpressionEditorField.startsWith = "starts with"; +ORYX.I18N.ConditionExpressionEditorField.paramsError = "Unable to generate Script expression, please fill correctly the form params."; +ORYX.I18N.ConditionExpressionEditorField.saveError = "Unable to save property value, please check the value and try again."; +ORYX.I18N.ConditionExpressionEditorField.scriptParseError = "Error found parsing script:
{0}

Press OK to go to the Expression Editor screen and loose the current Script or Cancel to go back to the Script Editor."; +ORYX.I18N.ConditionExpressionEditorField.scriptGenerationError = "Error found generating script:
{0}

Please check the data entered on the Expression Editor."; +ORYX.I18N.ConditionExpressionEditorField.nonExistingVariable = "The process does not contain any variable called '{0}'."; + if(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; ORYX.I18N.ShapeMenuPlugin.drag = "Drag"; diff --git a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_es.js b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_es.js index bafb5c810d..e4424a4921 100644 --- a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_es.js +++ b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_es.js @@ -288,6 +288,35 @@ ORYX.I18N.PropertyWindow.ok = "Ok"; ORYX.I18N.PropertyWindow.cancel = "Cancelar"; ORYX.I18N.PropertyWindow.dateFormat = "dia/mes/año"; +if (!ORYX.I18N.ConditionExpressionEditorField) ORYX.I18N.ConditionExpressionEditorField = {}; + +ORYX.I18N.ConditionExpressionEditorField.simpleTitle = "Editor de Expresiones - Pulse [Ctrl-Z] para activar auto-completar"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowTitle = "Sequence Flow Conditions"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowFullTitle = "Sequence Flow Conditions - Pulse [Ctrl-Z] para activar auto-completar"; +ORYX.I18N.ConditionExpressionEditorField.scriptTab = "Script"; +ORYX.I18N.ConditionExpressionEditorField.editorTab = "Editor"; +ORYX.I18N.ConditionExpressionEditorField.editorDescription = "Ejecuta flujo si se cumplen las siguientes condiciones." +ORYX.I18N.ConditionExpressionEditorField.processVariable = "Variable del proceso::" +ORYX.I18N.ConditionExpressionEditorField.condition = "Condición:" +ORYX.I18N.ConditionExpressionEditorField.between = "Entre"; +ORYX.I18N.ConditionExpressionEditorField.contains = "Contiene"; +ORYX.I18N.ConditionExpressionEditorField.endsWith = "Termina con"; +ORYX.I18N.ConditionExpressionEditorField.equalsTo = "Es igual a"; +ORYX.I18N.ConditionExpressionEditorField.greaterThan = "Mayor que"; +ORYX.I18N.ConditionExpressionEditorField.greaterThanOrEqual = "Mayor o igual que"; +ORYX.I18N.ConditionExpressionEditorField.isEmpty = "Está vacío"; +ORYX.I18N.ConditionExpressionEditorField.isFalse = "Es falso"; +ORYX.I18N.ConditionExpressionEditorField.isNull = "Es nulo"; +ORYX.I18N.ConditionExpressionEditorField.isTrue = "Es verdadero"; +ORYX.I18N.ConditionExpressionEditorField.lessThan = "Menor que"; +ORYX.I18N.ConditionExpressionEditorField.lessThanOrEqual = "Menor o igual que"; +ORYX.I18N.ConditionExpressionEditorField.startsWith = "Empieza con"; +ORYX.I18N.ConditionExpressionEditorField.paramsError = "No se ha podido generar la expresión, por favor rellene los campos correctamente."; +ORYX.I18N.ConditionExpressionEditorField.saveError = "No se ha podido guardar la propiedad, por favor revise el valor configurado y pruebe otra vez"; +ORYX.I18N.ConditionExpressionEditorField.scriptParseError = "Se ha encontrado un error parseando el script:
{0}

Pulse OK para quedarse en el Editor de Expresiones y perder el Script o Cancelar para volver al Editor de Scripts."; +ORYX.I18N.ConditionExpressionEditorField.scriptGenerationError = "Se ha encontrado un error generando el script:
{0}

Por favor revise los datos insertados en el Editor de Expresiones."; +ORYX.I18N.ConditionExpressionEditorField.nonExistingVariable = "El proceso no contiene ninguna variable llamada '{0}'."; + if(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; ORYX.I18N.ShapeMenuPlugin.drag = "Tirar"; diff --git a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_ja.js b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_ja.js index a41898a185..60188e5b6c 100644 --- a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_ja.js +++ b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_ja.js @@ -398,6 +398,35 @@ ORYX.I18N.PropertyWindow.ok = "OK"; ORYX.I18N.PropertyWindow.cancel = "キャンセル"; ORYX.I18N.PropertyWindow.dateFormat = "m/d/y"; +if (!ORYX.I18N.ConditionExpressionEditorField) ORYX.I18N.ConditionExpressionEditorField = {}; + +ORYX.I18N.ConditionExpressionEditorField.simpleTitle = "Expression Editor - Press [Ctrl-Z] to activate auto-completion"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowTitle = "Sequence Flow Conditions"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowFullTitle = "Sequence Flow Conditions - Press [Ctrl-Z] to activate auto-completion"; +ORYX.I18N.ConditionExpressionEditorField.scriptTab = "Script"; +ORYX.I18N.ConditionExpressionEditorField.editorTab = "Editor"; +ORYX.I18N.ConditionExpressionEditorField.editorDescription = "Run sequence flow if the following conditions are met." +ORYX.I18N.ConditionExpressionEditorField.processVariable = "Process variable:" +ORYX.I18N.ConditionExpressionEditorField.condition = "Condition:" +ORYX.I18N.ConditionExpressionEditorField.between = "between"; +ORYX.I18N.ConditionExpressionEditorField.contains = "contains"; +ORYX.I18N.ConditionExpressionEditorField.endsWith = "ends with"; +ORYX.I18N.ConditionExpressionEditorField.equalsTo = "is equal to"; +ORYX.I18N.ConditionExpressionEditorField.greaterThan = "is greater than"; +ORYX.I18N.ConditionExpressionEditorField.greaterThanOrEqual = "is greater than or equal to"; +ORYX.I18N.ConditionExpressionEditorField.isEmpty = "is empty"; +ORYX.I18N.ConditionExpressionEditorField.isFalse = "is false"; +ORYX.I18N.ConditionExpressionEditorField.isNull = "is null"; +ORYX.I18N.ConditionExpressionEditorField.isTrue = "is true"; +ORYX.I18N.ConditionExpressionEditorField.lessThan = "is less than"; +ORYX.I18N.ConditionExpressionEditorField.lessThanOrEqual = "is less than or equal to"; +ORYX.I18N.ConditionExpressionEditorField.startsWith = "starts with"; +ORYX.I18N.ConditionExpressionEditorField.paramsError = "Unable to generate Script expression, please fill correctly the form params."; +ORYX.I18N.ConditionExpressionEditorField.saveError = "Unable to save property value, please check the value and try again."; +ORYX.I18N.ConditionExpressionEditorField.scriptParseError = "Error found parsing script:
{0}

Press OK to go to the Expression Editor screen and loose the current Script or Cancel to go back to the Script Editor."; +ORYX.I18N.ConditionExpressionEditorField.scriptGenerationError = "Error found generating script:
{0}

Please check the data entered on the Expression Editor."; +ORYX.I18N.ConditionExpressionEditorField.nonExistingVariable = "The process does not contain any variable called '{0}'."; + if(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; ORYX.I18N.ShapeMenuPlugin.drag = "ドラッグ"; diff --git a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_ru.js b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_ru.js index a60bf30415..ac0c0a9a89 100644 --- a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_ru.js +++ b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/i18n/translation_ru.js @@ -294,6 +294,35 @@ ORYX.I18N.PropertyWindow.ok = "Ок"; ORYX.I18N.PropertyWindow.cancel = "Отменить"; ORYX.I18N.PropertyWindow.dateFormat = "m/d/y"; +if (!ORYX.I18N.ConditionExpressionEditorField) ORYX.I18N.ConditionExpressionEditorField = {}; + +ORYX.I18N.ConditionExpressionEditorField.simpleTitle = "Expression Editor - Press [Ctrl-Z] to activate auto-completion"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowTitle = "Sequence Flow Conditions"; +ORYX.I18N.ConditionExpressionEditorField.sequenceFlowFullTitle = "Sequence Flow Conditions - Press [Ctrl-Z] to activate auto-completion"; +ORYX.I18N.ConditionExpressionEditorField.scriptTab = "Script"; +ORYX.I18N.ConditionExpressionEditorField.editorTab = "Editor"; +ORYX.I18N.ConditionExpressionEditorField.editorDescription = "Run sequence flow if the following conditions are met." +ORYX.I18N.ConditionExpressionEditorField.processVariable = "Process variable:" +ORYX.I18N.ConditionExpressionEditorField.condition = "Condition:" +ORYX.I18N.ConditionExpressionEditorField.between = "between"; +ORYX.I18N.ConditionExpressionEditorField.contains = "contains"; +ORYX.I18N.ConditionExpressionEditorField.endsWith = "ends with"; +ORYX.I18N.ConditionExpressionEditorField.equalsTo = "is equal to"; +ORYX.I18N.ConditionExpressionEditorField.greaterThan = "is greater than"; +ORYX.I18N.ConditionExpressionEditorField.greaterThanOrEqual = "is greater than or equal to"; +ORYX.I18N.ConditionExpressionEditorField.isEmpty = "is empty"; +ORYX.I18N.ConditionExpressionEditorField.isFalse = "is false"; +ORYX.I18N.ConditionExpressionEditorField.isNull = "is null"; +ORYX.I18N.ConditionExpressionEditorField.isTrue = "is true"; +ORYX.I18N.ConditionExpressionEditorField.lessThan = "is less than"; +ORYX.I18N.ConditionExpressionEditorField.lessThanOrEqual = "is less than or equal to"; +ORYX.I18N.ConditionExpressionEditorField.startsWith = "starts with"; +ORYX.I18N.ConditionExpressionEditorField.paramsError = "Unable to generate Script expression, please fill correctly the form params."; +ORYX.I18N.ConditionExpressionEditorField.saveError = "Unable to save property value, please check the value and try again."; +ORYX.I18N.ConditionExpressionEditorField.scriptParseError = "Error found parsing script:
{0}

Press OK to go to the Expression Editor screen and loose the current Script or Cancel to go back to the Script Editor."; +ORYX.I18N.ConditionExpressionEditorField.scriptGenerationError = "Error found generating script:
{0}

Please check the data entered on the Expression Editor."; +ORYX.I18N.ConditionExpressionEditorField.nonExistingVariable = "The process does not contain any variable called '{0}'."; + if(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; ORYX.I18N.ShapeMenuPlugin.drag = "Тянуть"; diff --git a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/js/Plugins/propertywindow.js b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/js/Plugins/propertywindow.js index 66547572bc..ac6f0c2161 100644 --- a/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/js/Plugins/propertywindow.js +++ b/jbpm-designer-client/src/main/resources/org/jbpm/designer/public/js/Plugins/propertywindow.js @@ -957,13 +957,15 @@ ORYX.Plugins.PropertyWindow = { break; case ORYX.CONFIG.TYPE_EXPRESSION: - var cf = new Ext.form.ComplexExpressionField({ - allowBlank: pair.optional(), - dataSource:this.dataSource, - grid:this.grid, - row:index, - facade:this.facade - }); + + var cf = new Ext.form.ConditionExpressionEditorField({ + allowBlank: pair.optional(), + dataSource:this.dataSource, + grid:this.grid, + row:index, + facade:this.facade + }); + cf.on('dialogClosed', this.dialogClosed, {scope:this, row:index, col:1,field:cf}); editorGrid = new Ext.Editor(cf); break; @@ -3618,82 +3620,629 @@ Ext.form.ComplexGlobalsField = Ext.extend(Ext.form.NameTypeEditor, { addButtonLabel : 'Add Global' }); - -Ext.form.ComplexExpressionField = Ext.extend(Ext.form.TriggerField, { - onTriggerClick : function(){ - if(this.disabled){ +Ext.form.ConditionExpressionEditorField = Ext.extend(Ext.form.TriggerField, { + onTriggerClick: function(){ + if(this.disabled){ return; } - var ceta = new Ext.form.TextArea({ + + function setFieldValueAndClose(value) { + input.setValue(value); + input.dataSource.getAt(input.row).set('value', value); + input.dataSource.commitChanges(); + dialog.hide() + } + + var isJavaCondition = false; + + Ext.each(this.dataSource.data.items, function(item){ + if (item.data.gridProperties.propId == "oryx-conditionexpressionlanguage" && item.data['value'] == "java") isJavaCondition = true; + }); + + var input = this; + var isSimpleEditor = true; + var initScreen = true; + + var contentPanel; + + var scriptEditor = new Ext.form.TextArea({ id: Ext.id(), fieldLabel: "Expression Editor", value: this.value.replace(/\\n/g,"\n"), autoScroll: true + }); + var sourceEditor; + var hlLine; + + if (!isJavaCondition) { + contentPanel = new Ext.Panel({ + border:false, + items: [scriptEditor] }); - - var sourceEditor; - var hlLine; - - var dialog = new Ext.Window({ - layout : 'anchor', - autoCreate : true, - title : 'Expression Editor - Press [Ctrl-Z] to activate auto-completion', - height : 430, - width : 550, - modal : true, - collapsible : false, - fixedcenter : true, - shadow : true, - resizable : true, - proxyDrag : true, - autoScroll : true, - keys:[{ - key : 27, - fn : function(){ - dialog.hide() - }.bind(this) - }], - items :[ceta], - listeners :{ - hide: function(){ - this.fireEvent('dialogClosed', this.value); - dialog.destroy(); - }.bind(this) - }, - buttons : [{ + + } else { + // definde the input panels for each action type + var currentInputRecord; + + var stringPanel = new Ext.Panel({ + layout:'column', border:false, + style: 'margin-left:10px;display:block;', + items:[new Ext.form.TextField({name: "stringValue"})] + }); + var floatPanel = new Ext.Panel({ + layout:'column', border:false, + style: 'margin-left:10px;display:block;', + items:[new Ext.form.NumberField({name: "floatValue", allowDecimals: true})] + }); + var floatPanelRange = new Ext.Panel({ + layout:'column', border:false, + style: 'margin-left:10px;display:block;', + items:[new Ext.form.NumberField({name: "floatFrom", allowDecimals: true}), + new Ext.form.NumberField({name: "floatTo", allowDecimals: true, style: 'margin-left:10px;display:block;'})] + }); + var integerPanel = new Ext.Panel({ + layout:'column', border:false, + style: 'margin-left:10px;display:block;', + items:[new Ext.form.NumberField({name: "intValue", allowDecimals: false})] + }); + var integerPanelRange = new Ext.Panel({ + layout:'column', border:false, + style: 'margin-left:10px;display:block;', + items:[new Ext.form.NumberField({name: "intForm", allowDecimals: false}), + new Ext.form.NumberField({name: "intTo", allowDecimals: false, style: 'margin-left:10px;display:block;'})] + }); + + var stringActions = []; + stringActions.push(["contains", ORYX.I18N.ConditionExpressionEditorField.contains, stringPanel, [0]]); + stringActions.push(["endsWith", ORYX.I18N.ConditionExpressionEditorField.endsWith, stringPanel, [0]]); + stringActions.push(["equalsTo", ORYX.I18N.ConditionExpressionEditorField.equalsTo, stringPanel, [0]]); + stringActions.push(["isEmpty", ORYX.I18N.ConditionExpressionEditorField.isEmpty, null, null]); + stringActions.push(["isNull", ORYX.I18N.ConditionExpressionEditorField.isNull, null, null]); + stringActions.push(["startsWith", ORYX.I18N.ConditionExpressionEditorField.startsWith, stringPanel, [0]]); + + var sActionStore = new Ext.data.SimpleStore({ + fields: [{name: 'value'},{name: 'title'},{name: 'panel'}, {name: 'inputs'}], + data : stringActions + }); + + var floatActions = []; + floatActions.push(["between", ORYX.I18N.ConditionExpressionEditorField.between, floatPanelRange, [0, 1]]); + floatActions.push(["equalsTo", ORYX.I18N.ConditionExpressionEditorField.equalsTo, floatPanel, [0]]); + floatActions.push(["greaterThan", ORYX.I18N.ConditionExpressionEditorField.greaterThan, floatPanel, [0]]); + floatActions.push(["greaterOrEqualThan", ORYX.I18N.ConditionExpressionEditorField.greaterThanOrEqual, floatPanel, [0]]); + floatActions.push(["isNull", ORYX.I18N.ConditionExpressionEditorField.isNull, null, null]); + floatActions.push(["lessThan", ORYX.I18N.ConditionExpressionEditorField.lessThan, floatPanel, [0]]); + floatActions.push(["lessOrEqualThan", ORYX.I18N.ConditionExpressionEditorField.lessThanOrEqual, floatPanel, [0]]); + + var fActionStore = new Ext.data.SimpleStore({ + fields: [{name: 'value'},{name: 'title'},{name: 'panel'}, {name: 'inputs'}], + data : floatActions + }); + + var integerActions = []; + integerActions.push(["between", ORYX.I18N.ConditionExpressionEditorField.between, integerPanelRange, [0, 1]]); + integerActions.push(["equalsTo", ORYX.I18N.ConditionExpressionEditorField.equalsTo, integerPanel, [0]]); + integerActions.push(["greaterThan", ORYX.I18N.ConditionExpressionEditorField.greaterThan, integerPanel, [0]]); + integerActions.push(["greaterOrEqualThan", ORYX.I18N.ConditionExpressionEditorField.greaterThanOrEqual, integerPanel, [0]]); + integerActions.push(["isNull", ORYX.I18N.ConditionExpressionEditorField.isNull, null, null]); + integerActions.push(["lessThan", ORYX.I18N.ConditionExpressionEditorField.lessThan, integerPanel, [0]]); + integerActions.push(["lessOrEqualThan", ORYX.I18N.ConditionExpressionEditorField.lessThanOrEqual, integerPanel, [0]]); + + var iActionStore = new Ext.data.SimpleStore({ + fields: [{name: 'value'},{name: 'title'},{name: 'panel'}, {name: 'inputs'}], + data : integerActions + }); + + var booleanActions = []; + booleanActions.push(["isFalse", ORYX.I18N.ConditionExpressionEditorField.isFalse, null, null]); + booleanActions.push(["isNull", ORYX.I18N.ConditionExpressionEditorField.isNull, null, null]); + booleanActions.push(["isTrue", ORYX.I18N.ConditionExpressionEditorField.isTrue, null, null]); + + var bActionStore = new Ext.data.SimpleStore({ + fields: [{name: 'value'},{name: 'title'},{name: 'panel'}, {name: 'inputs'}], + data : booleanActions + }); + + var objectActions = []; + objectActions.push(["isNull", ORYX.I18N.ConditionExpressionEditorField.isNull, null, null]); + + var oActionStore = new Ext.data.SimpleStore({ + fields: [{name: 'value'},{name: 'title'},{name: 'panel'}, {name: 'inputs'}], + data : objectActions + }); + + stringPanel.hide(); + floatPanel.hide(); + floatPanelRange.hide(); + integerPanel.hide(); + integerPanelRange.hide(); + + var processJSON = ORYX.EDITOR.getSerializedJSON(); + var vardefs = jsonPath(processJSON.evalJSON(), "$.properties.vardefs"); + + var processVars = []; + + if(vardefs) { + vardefs.forEach(function(item){ + if(item.length > 0) { + var valueParts = item.split(","); + for(var i=0; i < valueParts.length; i++) { + var nextPart = valueParts[i]; + if(nextPart.indexOf(":") > 0) { + var innerParts = nextPart.split(":"); + switch (innerParts[1]) { + case "String": + case "java.lang.String": processVars.push([innerParts[0], innerParts[1], sActionStore]); + break; + case "Integer": + case "java.lang.Integer": + case "java.math.BigInteger": + case "java.lang.Short": + case "java.lang.Long": processVars.push([innerParts[0], innerParts[1], iActionStore]); + break; + case "Float": + case "java.math.BigDecimal": + case "java.lang.Float": + case "java.lang.Double": processVars.push([innerParts[0], innerParts[1], fActionStore]); + break; + case "Boolean": + case "java.lang.Boolean": processVars.push([innerParts[0], innerParts[1], bActionStore]); + break; + default: processVars.push([innerParts[0], innerParts[1], oActionStore]); + } + } + } + } + }); + } + + var varsStore = new Ext.data.SimpleStore({ + fields: [{name: 'value'},{name: 'type'}, {name: 'store'}], + data : processVars + }); + + var actionsCombo = new Ext.form.ComboBox({ + editable: false, + displayField:'title', + valueField: 'value', + typeAhead: true, + mode: 'local', + triggerAction: 'all', + selectOnFocus: true, + listeners: { + 'select': function(combo, record, index){ + cleanCurrentInput(); + currentInputRecord = record; + var panel = currentInputRecord.get("panel") + if (panel != null) { + panel.show(); + } + } + } + }); + + var varsCombo = new Ext.form.ComboBox({ + editable: false, + store: varsStore, + displayField:'value', + valueField: 'value', + typeAhead: true, + mode: 'local', + triggerAction: 'all', + selectOnFocus:true, + listeners: { + 'select': function(combo, record, index) { + actionsCombo.clearValue(); + cleanCurrentInput(); + actionsCombo.bindStore(record.get("store")) + } + } + }); + + var expressionEditorLayout = new Ext.form.FormPanel({ + layout:'table', + title: ORYX.I18N.ConditionExpressionEditorField.editorTab, + layoutConfig: { + columns: 3 + }, + defaults: { + border:false + }, + items: [ + {colspan: 3, items:[{ + style: 'font-size:12px;margin:10px;display:block;', + anchor: '100%', + xtype: 'label', + html: ORYX.I18N.ConditionExpressionEditorField.editorDescription} + ]}, + { + style: 'font-size:12px;margin:10px;display:block;', + anchor: '100%', + xtype: 'label', + html: ORYX.I18N.ConditionExpressionEditorField.processVariable}, {colspan: 2, items:[varsCombo]}, + { + style: 'font-size:12px;margin:10px;display:block;', + anchor: '100%', + xtype: 'label', + html: ORYX.I18N.ConditionExpressionEditorField.condition}, actionsCombo, {layout: 'column', items: [stringPanel, floatPanel, floatPanelRange, integerPanel, integerPanelRange]}] + }); + + var scriptEditorLayout = new Ext.Panel({ + title: ORYX.I18N.ConditionExpressionEditorField.scriptTab, + layout:'anchor', + defaults: { + border:false + }, + items:[scriptEditor] + }); + + function showParseError(errorMessage) { + var fullMessage = ORYX.I18N.ConditionExpressionEditorField.scriptParseError; + fullMessage = fullMessage.replace("{0}", errorMessage); + Ext.MessageBox.show({ + msg : fullMessage, + icon: Ext.MessageBox.WARNING, + buttons: { + ok: ORYX.I18N.PropertyWindow.ok, + cancel: ORYX.I18N.PropertyWindow.cancel + }, + fn: function(btn){ + if(btn == "ok") { + showSimpleEditor(true, true); + } else { + showScriptEditor(false, false); + } + } + }); + } + + function showScriptGenerationError(errorMessage) { + var fullMessage = ORYX.I18N.ConditionExpressionEditorField.scriptGenerationError; + fullMessage = fullMessage.replace("{0}", errorMessage); + Ext.MessageBox.show({ + msg : fullMessage, + icon: Ext.MessageBox.WARNING, + buttons: { + ok: ORYX.I18N.PropertyWindow.ok + } + }); + } + + var onsuccessParseScript = function(response) { + if(response.responseText.length > 0) { + var responseJson = Ext.decode(response.responseText); + if (responseJson.errorMessage) { + if (!initScreen) { + showParseError(responseJson.errorMessage); + return; + } else { + isSimpleEditor = false; + } + } else { + var action; + var variable; + var params = []; + responseJson.conditions.forEach(function(condition){ + action = condition.condition; + condition.parameters.forEach(function(parameter) { + if (variable == null) variable = parameter; + else params.push(parameter) + }); + }); + var index = varsStore.find('value', variable); + if (index == -1) { + var errorMessage = ORYX.I18N.ConditionExpressionEditorField.nonExistingVariable; + errorMessage = errorMessage.replace("{0}", variable); + showParseError(errorMessage); + return; + } else { + varsCombo.setValue(variable); + var varRecord = varsStore.getAt(index); + varsCombo.fireEvent('select', varsCombo, varRecord); + + actionsCombo.setValue(action); + var actionStore = varRecord.get("store"); + + index = actionStore.find('value', action); + var actionRecord = actionStore.getAt(index); + actionsCombo.fireEvent('select', actionsCombo, actionRecord); + + var panel = actionRecord.get("panel"); + + if (panel != null) { + var inputs = actionRecord.get("inputs"); + if (inputs != null && inputs.length == params.length) { + var i; + for (i = 0; i< inputs.length; i++) { + var value = panel.getComponent(inputs[i]).setValue(params[i]); + } + } + } + isSimpleEditor = true; + } + } + } + initScreen = false; + if (isSimpleEditor) { + showSimpleEditor(true, false); + } else { + showScriptEditor(false, false); + } + } + + var onfailureParseScript = function () { + showScriptEditor(false, false); + } + + function showScriptEditor(state, resetSource, expression) { + if (sourceEditor) { + sourceEditor.toTextArea(); + sourceEditor = null; + } + if (resetSource) scriptEditor.setValue(expression); + isSimpleEditor = state; + contentPanel.setActiveTab(scriptEditorLayout); + dialog.setTitle(ORYX.I18N.ConditionExpressionEditorField.sequenceFlowFullTitle); + initCodeEditor(); + } + + function showSimpleEditor(state, cleanEditor) { + if (cleanEditor) clearExpressionEditor(); + isSimpleEditor = state; + contentPanel.setActiveTab(expressionEditorLayout); + dialog.setTitle(ORYX.I18N.ConditionExpressionEditorField.sequenceFlowTitle); + } + + contentPanel = new Ext.TabPanel({ + renderTo: Ext.getBody(), + activeTab: 0, + defaults: { + border: false + }, + items: [expressionEditorLayout, scriptEditorLayout], + listeners: { + 'tabchange': function (tabpanel, tab) { + if (tab.title == ORYX.I18N.ConditionExpressionEditorField.scriptTab) { + if (isSimpleEditor) { + if (varsCombo.getValue() == "" || (varsCombo.getValue() != "" && actionsCombo.getValue() == "")) { + showScriptEditor(false, true, ''); + } else { + var onsuccess = function(response) { + isSimpleEditor = true; + if(response.responseText.length > 0) { + var responseJson = Ext.decode(response.responseText); + if (responseJson.errorMessage) { + showScriptGenerationError(responseJson.errorMessage); + showSimpleEditor(true, false); + } else { + showScriptEditor(false, true, responseJson.script); + } + } + } + var onfailure = function () { + showSimpleEditor(true, false); + } + var result = generateScript(onsuccess, onfailure); + if (result == false) { + showSimpleEditor(true, false); + } + } + } + } else { + if (!isSimpleEditor) { + if (sourceEditor.getValue() == null || sourceEditor.getValue().trim() == "") { + showSimpleEditor(true, true); + } else { + scriptEditor.setValue(sourceEditor.getValue()); + parseScript({script: sourceEditor.getValue()}); + } + } + } + } + } + }); + + function clearExpressionEditor() { + varsCombo.clearValue(); + actionsCombo.clearValue(); + cleanCurrentInput(); + } + + function cleanCurrentInput () { + if (currentInputRecord != null) { + var panel = currentInputRecord.get("panel"); + if (panel) { + var currentInputs = currentInputRecord.get("inputs"); + if (currentInputs != null) { + currentInputs.forEach(function(index){ + panel.getComponent(index).setValue(null); + }); + } + panel.hide(); + } + currentInputRecord = null; + } + } + + function checkCurrentInputRecord() { + if (!currentInputRecord) return false; + var panel = currentInputRecord.get("panel"); + if (panel == null) return true; + var currentInputs = currentInputRecord.get("inputs"); + if (currentInputs != null) { + var actionParams = []; + currentInputs.forEach(function(index) { + var value = panel.getComponent(index).getValue(); + if (value == null || value == "") return false; + actionParams.push(value) + }); + if (actionParams.length != currentInputs.length) return false; + if (actionParams.length == 2) { + return actionParams[1] > actionParams[0]; + } + } + return true; + } + + function generateScriptParams() { + var varValue = varsCombo.getValue(); + + if (!varValue || !checkCurrentInputRecord()) { + return null; + } + var actionParams = []; + actionParams.push(varValue); + + var panel = currentInputRecord.get("panel"); + if (panel != null) { + var currentInputs = currentInputRecord.get("inputs"); + if (currentInputs != null) { + currentInputs.forEach(function(index) { + actionParams.push(panel.getComponent(index).getValue()) + }); + } + } + var param = { + operator: "AND", + conditions: [{ + condition: actionsCombo.getValue(), + parameters: actionParams + }] + }; + return param; + } + + function ajaxRequest(command, jsonParam, onsuccess, onfailure) { + Ext.Ajax.request({ + url: ORYX.PATH + 'customeditors', + method: 'POST', + params: { + expression_editor_command: command, + expression_editor_message: Ext.util.JSON.encode(jsonParam) + }, + success: function(response) { + onsuccess(response); + }.bind(this), + failure: function() { + onfailure(); + } + }); + } + + function parseScript(jsonParam) { + ajaxRequest("parseScript", jsonParam, onsuccessParseScript, onfailureParseScript); + } + + function generateScript(onsuccess, onfailure) { + var param = generateScriptParams(); + if (!param) { + showScriptGenerationError(ORYX.I18N.ConditionExpressionEditorField.paramsError); + return false; + } + ajaxRequest("generateScript", param, onsuccess, onfailure); + return true; + } + + var onsuccessSave = function(response) { + if(response.responseText.length > 0) { + var responseJson = Ext.decode(response.responseText); + if (responseJson.errorMessage) { + showScriptGenerationError(responseJson.errorMessage); + } else { + setFieldValueAndClose(responseJson.script) + } + } + } + + var onfailureSave = function() { + showScriptGenerationError(ORYX.I18N.ConditionExpressionEditorField.saveError) + } + } + + var dialog = new Ext.Window({ + layout : 'anchor', + autoCreate : true, + height : 430, + width : 680, + modal : true, + collapsible : false, + fixedcenter : true, + shadow : true, + resizable : true, + proxyDrag : true, + autoScroll : true, + keys:[{ + key : 27, + fn : function(){ + dialog.hide() + }.bind(this) + }], + items :[contentPanel], + listeners :{ + hide: function(){ + this.fireEvent('dialogClosed', this.value); + dialog.destroy(); + }.bind(this) + }, + buttons : [{ text: ORYX.I18N.PropertyWindow.ok, - handler: function(){ - this.setValue(sourceEditor.getValue().replace(/\r\n|\r|\n/g,"\\n")); - this.dataSource.getAt(this.row).set('value', sourceEditor.getValue()); - this.dataSource.commitChanges(); - dialog.hide() + handler: function() { + if (isJavaCondition) { + if (isSimpleEditor) { + generateScript(onsuccessSave, onfailureSave); + } else { + setFieldValueAndClose(sourceEditor.getValue().replace(/\r\n|\r|\n/g,"\\n")); + } + } else { + setFieldValueAndClose(sourceEditor.getValue().replace(/\r\n|\r|\n/g,"\\n")); + } }.bind(this) }, { text: ORYX.I18N.PropertyWindow.cancel, handler: function(){ - this.setValue(this.value); - dialog.hide() + this.setValue(this.value); + dialog.hide() }.bind(this) }] - }); - dialog.show(); - this.foldFunc = CodeMirror.newFoldFunction(CodeMirror.braceRangeFinder); - sourceEditor = CodeMirror.fromTextArea(document.getElementById(ceta.getId()), { - mode: "text/x-java", - lineNumbers: true, - lineWrapping: true, - matchBrackets: true, - onGutterClick: this.foldFunc, - extraKeys: {"Ctrl-Z": function(cm) {CodeMirror.hint(cm, CodeMirror.jbpmHint, dialog);}}, - onCursorActivity: function() { - sourceEditor.setLineClass(hlLine, null, null); - hlLine = sourceEditor.setLineClass(sourceEditor.getCursor().line, null, "activeline"); - }.bind(this) - }); - hlLine = sourceEditor.setLineClass(0, "activeline"); - this.grid.stopEditing(); - } + }); + + function initCodeEditor() { + this.foldFunc = CodeMirror.newFoldFunction(CodeMirror.braceRangeFinder); + sourceEditor = CodeMirror.fromTextArea(document.getElementById(scriptEditor.getId()), { + mode: "text/x-java", + lineNumbers: true, + lineWrapping: true, + matchBrackets: true, + onGutterClick: this.foldFunc, + extraKeys: {"Ctrl-Z": function(cm) {CodeMirror.hint(cm, CodeMirror.jbpmHint, dialog);}}, + onCursorActivity: function() { + sourceEditor.setLineClass(hlLine, null, null); + hlLine = sourceEditor.setLineClass(sourceEditor.getCursor().line, null, "activeline"); + }.bind(this) + }); + hlLine = sourceEditor.setLineClass(0, "activeline"); + } + + if (isJavaCondition) { + if (this.getValue() != null && this.getValue() != "") { + parseScript({script:this.getValue()}); + } else { + showSimpleEditor(true, false); + initScreen = false; + } + } else { + dialog.setTitle(ORYX.I18N.ConditionExpressionEditorField.simpleTitle); + } + + dialog.show(); + + contentPanel.setHeight(dialog.getInnerHeight()) + if (!isJavaCondition) initCodeEditor(); + + this.grid.stopEditing(); + } }); + Ext.form.ComplexCalledElementField = Ext.extend(Ext.form.TriggerField, { onTriggerClick : function(){ if(this.disabled){