diff --git a/docs/user-guide/workflow.md b/docs/user-guide/workflow.md index 8b1378917..196b68afa 100644 --- a/docs/user-guide/workflow.md +++ b/docs/user-guide/workflow.md @@ -1 +1,23 @@ +# 工作流 + +## 流程引擎后台变量 + +* wfRt: IWorkflowRuntime类型 +* wf: IWorkflow类型 +* wfVars: IWorkflowVarSet类型,对应于`wf.getGlobalVars()` + +## 参数 +arg定义具有persist属性,如果设置为true,则会保存到wfVars集合中,存储到`nop_wf_var`表中。 + +## 条件判断 + +```xml + + + + +``` + +条件判断中值如果不是字符串类型,则可以用表达式语法或者前缀引导语法来标识数值类型。 + diff --git a/nop-wf/model/nop-wf.orm.xlsx b/nop-wf/model/nop-wf.orm.xlsx index df0f44c0a..c66c9490f 100644 Binary files a/nop-wf/model/nop-wf.orm.xlsx and b/nop-wf/model/nop-wf.orm.xlsx differ diff --git a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/IWorkflowVarSet.java b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/IWorkflowVarSet.java index f1037cd02..905d6b451 100644 --- a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/IWorkflowVarSet.java +++ b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/IWorkflowVarSet.java @@ -7,15 +7,29 @@ */ package io.nop.wf.core; +import io.nop.core.reflect.hook.IPropGetMissingHook; + import java.util.Map; import java.util.Set; /** * 每个工作流实例都对应一个全局变量集合 */ -public interface IWorkflowVarSet { +public interface IWorkflowVarSet extends IPropGetMissingHook { + @Override + default Object prop_get(String propName) { + return getVar(propName); + } + + @Override + default boolean prop_has(String propName) { + return containsVar(propName); + } + Set getVarNames(); + boolean containsVar(String varName); + Object getVar(String varName); void removeVar(String varName); diff --git a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/NopWfCoreConstants.java b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/NopWfCoreConstants.java index 7cba43651..e7a65b969 100644 --- a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/NopWfCoreConstants.java +++ b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/NopWfCoreConstants.java @@ -32,6 +32,7 @@ public interface NopWfCoreConstants extends _NopWfCoreConstants { String VAR_WF = "wf"; String VAR_WF_RT = "wfRt"; + String VAR_WF_VARS = "wfVars"; String VAR_WF_STEP = "wfStep"; String VAR_ACTOR_MODEL = "actorModel"; String VAR_SELECTED_ACTORS = "selectedActors"; diff --git a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/engine/WfRuntime.java b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/engine/WfRuntime.java index dde62d895..ae00aae10 100644 --- a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/engine/WfRuntime.java +++ b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/engine/WfRuntime.java @@ -87,6 +87,7 @@ private IEvalScope newEvalScope() { IEvalScope scope = serviceContext.getEvalScope().newChildScope(); scope.setLocalValue(null, NopWfCoreConstants.VAR_WF, wf); scope.setLocalValue(null, NopWfCoreConstants.VAR_WF_RT, this); + scope.setLocalValue(null, NopWfCoreConstants.VAR_WF_VARS, wf.getGlobalVars()); return scope; } diff --git a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/engine/WorkflowEngineImpl.java b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/engine/WorkflowEngineImpl.java index 0620e8536..711e55bd5 100644 --- a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/engine/WorkflowEngineImpl.java +++ b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/engine/WorkflowEngineImpl.java @@ -544,6 +544,9 @@ private void initArgs(IWorkflowArgumentsModel argsModel, Map arg throw wfRt.newError(ERR_WF_EMPTY_ACTION_ARG) .param(ARG_ACTION_NAME, actionName).param(ARG_ARG_NAME, name); } + if (argModel.isPersist()) { + wf.getGlobalVars().setVar(name, args.get(name)); + } } } diff --git a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/model/_gen/_WfArgVarModel.java b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/model/_gen/_WfArgVarModel.java index 9ed293d33..8e93ce862 100644 --- a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/model/_gen/_WfArgVarModel.java +++ b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/model/_gen/_WfArgVarModel.java @@ -44,6 +44,13 @@ public abstract class _WfArgVarModel extends io.nop.core.resource.component.Abst */ private java.lang.String _name ; + /** + * + * xml name: persist + * + */ + private boolean _persist = false; + /** * * xml name: schema @@ -52,6 +59,13 @@ public abstract class _WfArgVarModel extends io.nop.core.resource.component.Abst */ private io.nop.xlang.xmeta.ISchema _schema ; + /** + * + * xml name: type + * + */ + private io.nop.core.type.IGenericType _type ; + /** * * xml name: description @@ -128,6 +142,25 @@ public void setName(java.lang.String value){ } + /** + * + * xml name: persist + * + */ + + public boolean isPersist(){ + return _persist; + } + + + public void setPersist(boolean value){ + checkAllowChange(); + + this._persist = value; + + } + + /** * * xml name: schema @@ -148,6 +181,25 @@ public void setSchema(io.nop.xlang.xmeta.ISchema value){ } + /** + * + * xml name: type + * + */ + + public io.nop.core.type.IGenericType getType(){ + return _type; + } + + + public void setType(io.nop.core.type.IGenericType value){ + checkAllowChange(); + + this._type = value; + + } + + @Override public void freeze(boolean cascade){ @@ -169,7 +221,9 @@ protected void outputJson(IJsonHandler out){ out.putNotNull("displayName",this.getDisplayName()); out.putNotNull("mandatory",this.isMandatory()); out.putNotNull("name",this.getName()); + out.putNotNull("persist",this.isPersist()); out.putNotNull("schema",this.getSchema()); + out.putNotNull("type",this.getType()); } public WfArgVarModel cloneInstance(){ @@ -185,7 +239,9 @@ protected void copyTo(WfArgVarModel instance){ instance.setDisplayName(this.getDisplayName()); instance.setMandatory(this.isMandatory()); instance.setName(this.getName()); + instance.setPersist(this.isPersist()); instance.setSchema(this.getSchema()); + instance.setType(this.getType()); } protected WfArgVarModel newInstance(){ diff --git a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/model/_gen/_WfAssignmentActorModel.java b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/model/_gen/_WfAssignmentActorModel.java index c7a5bcfba..6e3587e73 100644 --- a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/model/_gen/_WfAssignmentActorModel.java +++ b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/model/_gen/_WfAssignmentActorModel.java @@ -16,13 +16,6 @@ "PMD.UnnecessaryFullyQualifiedName","PMD.EmptyControlStatement","java:S116","java:S101","java:S1128","java:S1161"}) public abstract class _WfAssignmentActorModel extends io.nop.core.resource.component.AbstractComponentModel { - /** - * - * xml name: actionName - * - */ - private java.lang.String _actionName ; - /** * * xml name: actorId @@ -37,6 +30,13 @@ public abstract class _WfAssignmentActorModel extends io.nop.core.resource.compo */ private java.lang.String _actorModelId ; + /** + * + * xml name: actorName + * + */ + private java.lang.String _actorName ; + /** * * xml name: actorType @@ -74,57 +74,57 @@ public abstract class _WfAssignmentActorModel extends io.nop.core.resource.compo /** * - * xml name: actionName + * xml name: actorId * */ - public java.lang.String getActionName(){ - return _actionName; + public java.lang.String getActorId(){ + return _actorId; } - public void setActionName(java.lang.String value){ + public void setActorId(java.lang.String value){ checkAllowChange(); - this._actionName = value; + this._actorId = value; } /** * - * xml name: actorId - * + * xml name: actorModelId + * actor节点的唯一标识 */ - public java.lang.String getActorId(){ - return _actorId; + public java.lang.String getActorModelId(){ + return _actorModelId; } - public void setActorId(java.lang.String value){ + public void setActorModelId(java.lang.String value){ checkAllowChange(); - this._actorId = value; + this._actorModelId = value; } /** * - * xml name: actorModelId - * actor节点的唯一标识 + * xml name: actorName + * */ - public java.lang.String getActorModelId(){ - return _actorModelId; + public java.lang.String getActorName(){ + return _actorName; } - public void setActorModelId(java.lang.String value){ + public void setActorName(java.lang.String value){ checkAllowChange(); - this._actorModelId = value; + this._actorName = value; } @@ -239,9 +239,9 @@ public void freeze(boolean cascade){ protected void outputJson(IJsonHandler out){ super.outputJson(out); - out.putNotNull("actionName",this.getActionName()); out.putNotNull("actorId",this.getActorId()); out.putNotNull("actorModelId",this.getActorModelId()); + out.putNotNull("actorName",this.getActorName()); out.putNotNull("actorType",this.getActorType()); out.putNotNull("assignForUser",this.isAssignForUser()); out.putNotNull("deptId",this.getDeptId()); @@ -258,9 +258,9 @@ public WfAssignmentActorModel cloneInstance(){ protected void copyTo(WfAssignmentActorModel instance){ super.copyTo(instance); - instance.setActionName(this.getActionName()); instance.setActorId(this.getActorId()); instance.setActorModelId(this.getActorModelId()); + instance.setActorName(this.getActorName()); instance.setActorType(this.getActorType()); instance.setAssignForUser(this.isAssignForUser()); instance.setDeptId(this.getDeptId()); diff --git a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/store/beans/MapVarSet.java b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/store/beans/MapVarSet.java index 70b217567..6b32a3996 100644 --- a/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/store/beans/MapVarSet.java +++ b/nop-wf/nop-wf-core/src/main/java/io/nop/wf/core/store/beans/MapVarSet.java @@ -45,4 +45,9 @@ public void setVars(Map vars) { if (vars != null) this.vars.putAll(vars); } + + @Override + public boolean containsVar(String varName) { + return vars.containsKey(varName); + } } diff --git a/nop-wf/nop-wf-dao/src/main/java/io/nop/wf/dao/entity/_gen/_NopWfInstance.java b/nop-wf/nop-wf-dao/src/main/java/io/nop/wf/dao/entity/_gen/_NopWfInstance.java index 4abd2d7d0..ff68aa683 100644 --- a/nop-wf/nop-wf-dao/src/main/java/io/nop/wf/dao/entity/_gen/_NopWfInstance.java +++ b/nop-wf/nop-wf-dao/src/main/java/io/nop/wf/dao/entity/_gen/_NopWfInstance.java @@ -2118,7 +2118,7 @@ public IOrmEntitySet getOutputs(){ } private final OrmEntitySet _globalVars = new OrmEntitySet<>(this, PROP_NAME_globalVars, - io.nop.wf.dao.entity.NopWfVar.PROP_NAME_wfInstance, null,io.nop.wf.dao.entity.NopWfVar.class); + io.nop.wf.dao.entity.NopWfVar.PROP_NAME_wfInstance, io.nop.wf.dao.entity.NopWfVar.PROP_NAME_fieldName,io.nop.wf.dao.entity.NopWfVar.class); /** * 。 refPropName: wfInstance, keyProp: {rel.keyProp} diff --git a/nop-wf/nop-wf-dao/src/main/java/io/nop/wf/dao/store/KvTableVarSet.java b/nop-wf/nop-wf-dao/src/main/java/io/nop/wf/dao/store/KvTableVarSet.java index c87498ae8..f6d39211a 100644 --- a/nop-wf/nop-wf-dao/src/main/java/io/nop/wf/dao/store/KvTableVarSet.java +++ b/nop-wf/nop-wf-dao/src/main/java/io/nop/wf/dao/store/KvTableVarSet.java @@ -41,6 +41,11 @@ public void removeVar(String varName) { } } + @Override + public boolean containsVar(String varName) { + return set.prop_has(varName); + } + @Override public void setVar(String varName, Object value) { IOrmKeyValueTable item = (IOrmKeyValueTable) set.prop_make(varName); diff --git a/nop-wf/nop-wf-dao/src/main/resources/_vfs/nop/wf/orm/_app.orm.xml b/nop-wf/nop-wf-dao/src/main/resources/_vfs/nop/wf/orm/_app.orm.xml index bd5fecf15..11d09d788 100644 --- a/nop-wf/nop-wf-dao/src/main/resources/_vfs/nop/wf/orm/_app.orm.xml +++ b/nop-wf/nop-wf-dao/src/main/resources/_vfs/nop/wf/orm/_app.orm.xml @@ -298,8 +298,9 @@ - + @@ -706,7 +707,7 @@ - + diff --git a/nop-wf/nop-wf-service/src/test/resources/_vfs/nop/wf/flowlong/counter-sign/v1.xwf b/nop-wf/nop-wf-service/src/test/resources/_vfs/nop/wf/flowlong/counter-sign/v1.xwf index 5570cc11b..d41bb65da 100644 --- a/nop-wf/nop-wf-service/src/test/resources/_vfs/nop/wf/flowlong/counter-sign/v1.xwf +++ b/nop-wf/nop-wf-service/src/test/resources/_vfs/nop/wf/flowlong/counter-sign/v1.xwf @@ -1,8 +1,8 @@ - - + + @@ -10,7 +10,7 @@ - + diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfAction/_gen/_NopWfAction.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfAction/_gen/_NopWfAction.view.xml index ccdd60191..6512247c9 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfAction/_gen/_NopWfAction.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfAction/_gen/_NopWfAction.view.xml @@ -86,18 +86,17 @@ errCode[错误码] errMsg[错误消息] -
- - -
- - -
- - +
+ + + + + +
+
@@ -134,7 +133,7 @@ -
+
diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfDefinition/_gen/_NopWfDefinition.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfDefinition/_gen/_NopWfDefinition.view.xml index 1e6d27972..38cd8c351 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfDefinition/_gen/_NopWfDefinition.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfDefinition/_gen/_NopWfDefinition.view.xml @@ -96,19 +96,18 @@ remark[备注] -
- - -
- - +
+ - - + i18n-en:title="Update Worflow Definition"/> + + + +
+
@@ -145,7 +144,7 @@ -
+
diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfDefinitionAuth/_gen/_NopWfDefinitionAuth.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfDefinitionAuth/_gen/_NopWfDefinitionAuth.view.xml index 3ed1ec13a..96cf02f33 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfDefinitionAuth/_gen/_NopWfDefinitionAuth.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfDefinitionAuth/_gen/_NopWfDefinitionAuth.view.xml @@ -97,19 +97,18 @@ remark[备注]
-
- - -
- - +
+ - - + i18n-en:title="Update Workflow Definition Auth"/> + + + +
+
@@ -146,7 +145,7 @@ -
+
diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfInstance/_gen/_NopWfInstance.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfInstance/_gen/_NopWfInstance.view.xml index c8901f16b..9e874eca2 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfInstance/_gen/_NopWfInstance.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfInstance/_gen/_NopWfInstance.view.xml @@ -171,19 +171,18 @@ remark[备注]
-
- - -
- - +
+ - - + i18n-en:title="Update Worflow Instance"/> + + + +
+
@@ -220,7 +219,7 @@ -
+
diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfLog/_gen/_NopWfLog.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfLog/_gen/_NopWfLog.view.xml index 225899104..68a41dc44 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfLog/_gen/_NopWfLog.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfLog/_gen/_NopWfLog.view.xml @@ -59,15 +59,16 @@ createTime[创建时间]
-
- - -
- - +
+ + + + +
+
@@ -101,7 +102,7 @@ -
+
diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfOutput/_gen/_NopWfOutput.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfOutput/_gen/_NopWfOutput.view.xml index b74bceb63..9de06c951 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfOutput/_gen/_NopWfOutput.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfOutput/_gen/_NopWfOutput.view.xml @@ -82,19 +82,18 @@ timestampValue[时间点值] -
- - -
- - +
+ - - + i18n-en:title="Update Workflow Outputs"/> + + + +
+
@@ -131,7 +130,7 @@ -
+
diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfStatusHistory/_gen/_NopWfStatusHistory.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfStatusHistory/_gen/_NopWfStatusHistory.view.xml index 9cca745ca..5054a5594 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfStatusHistory/_gen/_NopWfStatusHistory.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfStatusHistory/_gen/_NopWfStatusHistory.view.xml @@ -76,19 +76,18 @@ operatorDeptId[操作者部门ID]
-
- - -
- - +
+ - - + i18n-en:title="Update Workflow Status History"/> + + + +
+
@@ -125,7 +124,7 @@ -
+
diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfStepInstance/_gen/_NopWfStepInstance.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfStepInstance/_gen/_NopWfStepInstance.view.xml index 9629f2ecd..88e663645 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfStepInstance/_gen/_NopWfStepInstance.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfStepInstance/_gen/_NopWfStepInstance.view.xml @@ -160,19 +160,18 @@ remark[备注]
-
- - -
- - +
+ - - + i18n-en:title="Update Workflow Step Instance"/> + + + +
+
@@ -209,7 +208,7 @@ -
+
diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfVar/_gen/_NopWfVar.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfVar/_gen/_NopWfVar.view.xml index 33e023d34..557eb24a4 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfVar/_gen/_NopWfVar.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfVar/_gen/_NopWfVar.view.xml @@ -82,19 +82,18 @@ timestampValue[时间点值]
-
- - -
- - +
+ - - + i18n-en:title="Update Workflow Variables"/> + + + +
+
@@ -131,7 +130,7 @@ -
+
diff --git a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfWork/_gen/_NopWfWork.view.xml b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfWork/_gen/_NopWfWork.view.xml index df2b3655b..ad74d946f 100644 --- a/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfWork/_gen/_NopWfWork.view.xml +++ b/nop-wf/nop-wf-web/src/main/resources/_vfs/nop/wf/pages/NopWfWork/_gen/_NopWfWork.view.xml @@ -99,18 +99,17 @@ remark[备注]
-
- - -
- - -
- - +
+ + + + + +
+
@@ -147,7 +146,7 @@ -
+
diff --git a/nop-xdefs/src/main/resources/_vfs/nop/schema/wf/wf.xdef b/nop-xdefs/src/main/resources/_vfs/nop/schema/wf/wf.xdef index 9432ddf5f..2f6ff311a 100644 --- a/nop-xdefs/src/main/resources/_vfs/nop/schema/wf/wf.xdef +++ b/nop-xdefs/src/main/resources/_vfs/nop/schema/wf/wf.xdef @@ -22,7 +22,7 @@ + displayName="string" xdef:unique-attr="name" persist="!boolean=false"> diff --git a/nop-xlang/src/main/java/io/nop/xlang/xpl/tags/FilterBeanExpressionCompiler.java b/nop-xlang/src/main/java/io/nop/xlang/xpl/tags/FilterBeanExpressionCompiler.java index af0f68e84..7c2d1e3b5 100644 --- a/nop-xlang/src/main/java/io/nop/xlang/xpl/tags/FilterBeanExpressionCompiler.java +++ b/nop-xlang/src/main/java/io/nop/xlang/xpl/tags/FilterBeanExpressionCompiler.java @@ -136,7 +136,7 @@ protected Expression compileValueExpr(SourceLocation loc, Object value) { Object jsonValue = JsonTool.parseNonStrict(loc, str.substring(2).trim()); return Literal.valueOf(loc, jsonValue); } - if (str.indexOf("${") > 0) + if (str.contains("${")) return compiler.parseTemplateExpr(loc, str, false, ExprPhase.eval, compileScope); return Literal.valueOf(loc, value); } else {