diff --git a/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/DataServer.java b/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/DataServer.java index 7f38f9070759e2b564b37a2aec6a90e649ceb091..e9fa5bcbe2cdf236afc8ab7506fdbbae46a6841e 100644 --- a/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/DataServer.java +++ b/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/DataServer.java @@ -63,7 +63,7 @@ public class DataServer extends ConfigObject { private Integer maxTotal; @FieldDescribe("最大空闲连接数") private Integer maxIdle; - @FieldDescribe("启用统计,默认启用") + @FieldDescribe("启用统计,默认开启") private Boolean statEnable; @FieldDescribe("统计方式配置,默认mergeStat") private String statFilter; diff --git a/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ProcessPlatform.java b/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ProcessPlatform.java index 02fe0e260303af863633fe57c1440bf6fa3986a2..dacb61d4d764d9db1b90dee047476053aebafcc0 100644 --- a/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ProcessPlatform.java +++ b/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ProcessPlatform.java @@ -75,6 +75,7 @@ public class ProcessPlatform extends ConfigObject { this.urge = new Urge(); this.expire = new Expire(); this.touchDelay = new TouchDelay(); + this.touchEmbedWaitUntilCompleted = new TouchEmbedWaitUntilCompleted(); this.merge = new Merge(); this.touchDetained = new TouchDetained(); this.deleteDraft = new DeleteDraft(); @@ -162,6 +163,9 @@ public class ProcessPlatform extends ConfigObject { @FieldDescribe("延时任务设置,定时触发延时任务,当超过延时时间后继续流转.") private TouchDelay touchDelay; + @FieldDescribe("触发等待子流程结束设置,当子流程结束回写标识后继续流转.") + private TouchEmbedWaitUntilCompleted touchEmbedWaitUntilCompleted; + @FieldDescribe("合并任务设置,定时触发合并任务,将已完成工作的Data从Item表中提取合并到WorkCompleted的Data字段中,默认工作完成后2年开始进行合并.") private Merge merge; @@ -237,6 +241,11 @@ public class ProcessPlatform extends ConfigObject { return this.touchDelay == null ? new TouchDelay() : this.touchDelay; } + public TouchEmbedWaitUntilCompleted getTouchEmbedWaitUntilCompleted() { + return this.touchEmbedWaitUntilCompleted == null ? new TouchEmbedWaitUntilCompleted() + : this.touchEmbedWaitUntilCompleted; + } + public TouchDetained getTouchDetained() { return this.touchDetained == null ? new TouchDetained() : this.touchDetained; } @@ -269,8 +278,7 @@ public class ProcessPlatform extends ConfigObject { public static class Urge extends ConfigObject { public static Urge defaultInstance() { - Urge o = new Urge(); - return o; + return new Urge(); } public static final Boolean DEFAULT_ENABLE = false; @@ -307,8 +315,7 @@ public class ProcessPlatform extends ConfigObject { public static class Expire extends ConfigObject { public static Expire defaultInstance() { - Expire o = new Expire(); - return o; + return new Expire(); } public static final Boolean DEFAULT_ENABLE = true; @@ -338,8 +345,7 @@ public class ProcessPlatform extends ConfigObject { public static class TouchDelay extends ConfigObject { public static TouchDelay defaultInstance() { - TouchDelay o = new TouchDelay(); - return o; + return new TouchDelay(); } public static final Boolean DEFAULT_ENABLE = true; @@ -366,13 +372,42 @@ public class ProcessPlatform extends ConfigObject { } + public static class TouchEmbedWaitUntilCompleted extends ConfigObject { + + public static TouchEmbedWaitUntilCompleted defaultInstance() { + return new TouchEmbedWaitUntilCompleted(); + } + + public static final Boolean DEFAULT_ENABLE = true; + + public static final String DEFAULT_CRON = "15 0/5 * * * ?"; + + @FieldDescribe("是否启用") + private Boolean enable = DEFAULT_ENABLE; + + @FieldDescribe("定时cron表达式") + private String cron = DEFAULT_CRON; + + public String getCron() { + if (StringUtils.isNotEmpty(this.cron) && CronExpression.isValidExpression(this.cron)) { + return this.cron; + } else { + return DEFAULT_CRON; + } + } + + public Boolean getEnable() { + return BooleanUtils.isTrue(this.enable); + } + + } + public static class Merge extends ConfigObject { private static final long serialVersionUID = -5858277850858377338L; public static Merge defaultInstance() { - Merge o = new Merge(); - return o; + return new Merge(); } public Merge() { @@ -427,8 +462,7 @@ public class ProcessPlatform extends ConfigObject { public static class TouchDetained extends ConfigObject { public static TouchDetained defaultInstance() { - TouchDetained o = new TouchDetained(); - return o; + return new TouchDetained(); } public static final String DEFAULT_CRON = "30 30 12 * * ?"; @@ -467,8 +501,7 @@ public class ProcessPlatform extends ConfigObject { public static class DeleteDraft extends ConfigObject { public static DeleteDraft defaultInstance() { - DeleteDraft o = new DeleteDraft(); - return o; + return new DeleteDraft(); } public static final String DEFAULT_CRON = "0 0 20 * * ?"; @@ -507,8 +540,7 @@ public class ProcessPlatform extends ConfigObject { public static class PassExpired extends ConfigObject { public static PassExpired defaultInstance() { - PassExpired o = new PassExpired(); - return o; + return new PassExpired(); } public static final String DEFAULT_CRON = "5 5 8-18 * * ?"; @@ -537,8 +569,7 @@ public class ProcessPlatform extends ConfigObject { public static class LogLongDetained extends ConfigObject { public static LogLongDetained defaultInstance() { - LogLongDetained o = new LogLongDetained(); - return o; + return new LogLongDetained(); } public static final String DEFAULT_CRON = "0 0 4 * * ?"; @@ -598,8 +629,7 @@ public class ProcessPlatform extends ConfigObject { public static class Press extends ConfigObject { public static Press defaultInstance() { - Press o = new Press(); - return o; + return new Press(); } public static final Integer DEFAULT_INTERVALMINUTES = 10; @@ -633,8 +663,7 @@ public class ProcessPlatform extends ConfigObject { public static class AttachmentConfig extends ConfigObject { public static AttachmentConfig defaultInstance() { - AttachmentConfig o = new AttachmentConfig(); - return o; + return new AttachmentConfig(); } public static final Integer DEFAULT_FILE_SIZE = 0; diff --git a/o2server/x_base_core_project/src/main/java/com/x/base/core/project/scripting/ScriptingFactory.java b/o2server/x_base_core_project/src/main/java/com/x/base/core/project/scripting/ScriptingFactory.java index cc73dd912546c6e7da13f9b908e6fb1ceff183ff..e3f65fd58c9e7f1f01516b43667d6f08e7c03a7f 100644 --- a/o2server/x_base_core_project/src/main/java/com/x/base/core/project/scripting/ScriptingFactory.java +++ b/o2server/x_base_core_project/src/main/java/com/x/base/core/project/scripting/ScriptingFactory.java @@ -45,6 +45,8 @@ public class ScriptingFactory { public static final String BINDING_NAME_EFFECTIVEPERSON = "java_effectivePerson"; public static final String BINDING_NAME_DATA = "data"; + // embedData + public static final String BINDING_NAME_EMBEDDATA = "embedData"; public static final String BINDING_NAME_SERIAL = "serial"; public static final String BINDING_NAME_PROCESS = "process"; diff --git a/o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/application/ApplicationAction.java b/o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/application/ApplicationAction.java index fc3b2b9d2084fabff327a477e3e78ba98034fe73..04bbc9ba26a418dca803d62543407e5a77a996c2 100644 --- a/o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/application/ApplicationAction.java +++ b/o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/application/ApplicationAction.java @@ -12,7 +12,6 @@ import javax.ws.rs.container.AsyncResponse; import javax.ws.rs.container.Suspended; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; import com.x.base.core.project.annotation.JaxrsDescribe; import com.x.base.core.project.annotation.JaxrsMethodDescribe; @@ -49,7 +48,7 @@ public class ApplicationAction extends StandardJaxrsAction { asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result)); } - @JaxrsMethodDescribe(value = "获取可见的应用,同时判断应用下有可见的流程.", action = ActionListWithPerson.class) + @JaxrsMethodDescribe(value = "获取可见的应用,同时判断应用下有启动的流程.", action = ActionListWithPerson.class) @GET @Path("list") @Produces(HttpMediaType.APPLICATION_JSON_UTF_8) @@ -66,13 +65,13 @@ public class ApplicationAction extends StandardJaxrsAction { asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result)); } - @JaxrsMethodDescribe(value = "获取可见的应用,同时判断应用下有可见的流程,并进行流程的名称匹配.", action = ActionListWithPersonLike.class) + @JaxrsMethodDescribe(value = "获取可见的应用,同时判断应用下有启动的流程,并进行流程的名称匹配.", action = ActionListWithPersonLike.class) @GET @Path("list/key/{key}") @Produces(HttpMediaType.APPLICATION_JSON_UTF_8) @Consumes(MediaType.APPLICATION_JSON) - public void listWithPersonLike(@Suspended final AsyncResponse asyncResponse, - @Context HttpServletRequest request, @JaxrsParameterDescribe("关键字") @PathParam("key") String key) { + public void listWithPersonLike(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request, + @JaxrsParameterDescribe("关键字") @PathParam("key") String key) { ActionResult> result = new ActionResult<>(); EffectivePerson effectivePerson = this.effectivePerson(request); try { @@ -84,7 +83,7 @@ public class ApplicationAction extends StandardJaxrsAction { asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result)); } - @JaxrsMethodDescribe(value = "根据当前用户所有可见的Application,并绑定其可见的Porcess", action = ActionListWithPersonComplex.class) + @JaxrsMethodDescribe(value = "根据当前用户所有可见的Application,并绑定其启动的Porcess", action = ActionListWithPersonComplex.class) @GET @Path("list/complex") @Produces(HttpMediaType.APPLICATION_JSON_UTF_8) @@ -102,17 +101,17 @@ public class ApplicationAction extends StandardJaxrsAction { asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result)); } - @JaxrsMethodDescribe(value = "根据传入用户,获取可见的Application,并绑定其可见的Porcess", action = ActionManageListWithPersonComplex.class) + @JaxrsMethodDescribe(value = "根据传入用户,获取可见的Application,并绑定其启动的Porcess", action = ActionManageListWithPersonComplex.class) @GET @Path("list/complex/manage/{person}") @Produces(HttpMediaType.APPLICATION_JSON_UTF_8) @Consumes(MediaType.APPLICATION_JSON) public void manageListWithPersonComplex(@Suspended final AsyncResponse asyncResponse, - @Context HttpServletRequest request, @JaxrsParameterDescribe("用户") @PathParam("person") String person) { + @Context HttpServletRequest request, @JaxrsParameterDescribe("用户") @PathParam("person") String person) { ActionResult> result = new ActionResult<>(); EffectivePerson effectivePerson = this.effectivePerson(request); try { - result = new ActionManageListWithPersonComplex().execute(effectivePerson,person); + result = new ActionManageListWithPersonComplex().execute(effectivePerson, person); } catch (Exception e) { logger.error(e, effectivePerson, request, null); result.error(e); diff --git a/o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionCreate.java b/o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionCreate.java index 891b15ad79d446a4d269c551c37ed823858d1bd3..19b5dfc4f0755a3bd686494e7263e8326c858873 100644 --- a/o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionCreate.java +++ b/o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionCreate.java @@ -83,8 +83,9 @@ class ActionCreate extends BaseAction { } } if (StringUtils.isEmpty(workId)) { - WoId woId = ThisApplication.context().applications().postQuery(x_processplatform_service_processing.class, - Applications.joinQueryUri("work", "process", process.getId()), wi.getData(), null) + WoId woId = ThisApplication.context().applications() + .postQuery(x_processplatform_service_processing.class, + Applications.joinQueryUri("work", "process", process.getId()), wi.getData(), null) .getData(WoId.class); workId = woId.getId(); } @@ -100,6 +101,10 @@ class ActionCreate extends BaseAction { throw new ExceptionWorkNotExist(workId); } work.setTitle(wi.getTitle()); + // 写入父work标识 + if (StringUtils.isNotBlank(wi.getParentWork())) { + work.getProperties().setParentWork(wi.getParentWork()); + } work.setCreatorIdentity(identity); work.setCreatorPerson(organization.person().getWithIdentity(identity)); work.setCreatorUnit(organization.unit().getWithIdentity(identity)); @@ -157,6 +162,17 @@ class ActionCreate extends BaseAction { @FieldDescribe("工作数据.") private JsonElement data; + @FieldDescribe("父工作标识.") + private String parentWork; + + public String getParentWork() { + return parentWork; + } + + public void setParentWork(String parentWork) { + this.parentWork = parentWork; + } + public String getTitle() { return title; } @@ -248,12 +264,6 @@ class ActionCreate extends BaseAction { private static final long serialVersionUID = 2279846765261247910L; - // public static List Includes = ListTools.toList("createTime", - // "updateTime", "startTime", - // "startTimeMonth", "person", "identity", "unit", "topUnit", - // "routeList", "routeNameList", "work", - // "allowRapid"); - static WrapCopier copier = WrapCopierFactory.wo(Task.class, WoTask.class, null, JpaObject.FieldsInvisible); @@ -370,21 +380,6 @@ class ActionCreate extends BaseAction { } }); wo.setTaskCompletedList(list); -// /* 补充召回 */ -// List results = new ArrayList<>(); -// for (WoTaskCompleted o : list) { -// results.add(o); -// if (o.getProcessingType().equals(ProcessingType.retract)) { -// WoTaskCompleted retract = new WoTaskCompleted(); -// o.copyTo(retract); -// retract.setRouteName("撤回"); -// retract.setOpinion("撤回"); -// retract.setStartTime(retract.getRetractTime()); -// retract.setCompletedTime(retract.getRetractTime()); -// results.add(retract); -// } -// } -// wo.setTaskCompletedList(results); } } \ No newline at end of file diff --git a/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Work.java b/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Work.java index a9e1f19b88abbd84ec32e03b45c85208e1fdfe46..0aabb1ab1a6ae53b1eb951017472a88a6fbb1b4f 100644 --- a/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Work.java +++ b/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Work.java @@ -91,8 +91,6 @@ public class Work extends SliceJpaObject implements ProjectionInterface { text = StringTools.utf8SubString(text, length_255B); this.setManualTaskIdentityText(text); } - // 强制进行properties对象写入 - //this.setProperties(this.getProperties()); } @PostLoad @@ -154,11 +152,6 @@ public class Work extends SliceJpaObject implements ProjectionInterface { } public List getSplitValueList() { - // 这里调用必须重新指向一次,如果使用 - // Work copy = XGsonBuilder.convert(work, Work.class); - // copy.copyTo(this, JpaObject.id_FIELDNAME); - // 这样的方法调用,那么在运行完成以后copy.splitValueList不再指向this.getProperties().getSplitValueList() - this.splitValueList = this.getProperties().getSplitValueList(); return this.splitValueList; } @@ -399,8 +392,9 @@ public class Work extends SliceJpaObject implements ProjectionInterface { @FieldDescribe("拆分工作产生的Token") @PersistentCollection(fetch = FetchType.EAGER) @OrderColumn(name = ORDERCOLUMNCOLUMN) - @ContainerTable(name = TABLE + ContainerTableNameMiddle + splitTokenList_FIELDNAME, joinIndex = @Index(name = TABLE - + IndexNameMiddle + splitTokenList_FIELDNAME + JoinIndexNameSuffix)) + @ContainerTable(name = TABLE + ContainerTableNameMiddle + + splitTokenList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle + splitTokenList_FIELDNAME + + JoinIndexNameSuffix)) @ElementColumn(length = JpaObject.length_id, name = ColumnNamePrefix + splitTokenList_FIELDNAME) @ElementIndex(name = TABLE + IndexNameMiddle + splitTokenList_FIELDNAME + ElementIndexNameSuffix) @CheckPersist(allowEmpty = true) diff --git a/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/WorkProperties.java b/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/WorkProperties.java index 0ac6f62b6f420bd16317d07da616b70ffe57cc1e..e9eb9a06fa919a1f249c202ae07950980cc7177a 100644 --- a/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/WorkProperties.java +++ b/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/WorkProperties.java @@ -13,23 +13,29 @@ public class WorkProperties extends JsonProperties { private static final long serialVersionUID = -62236689373222398L; @FieldDescribe("强制待办处理人") - private List manualForceTaskIdentityList = new ArrayList(); + private List manualForceTaskIdentityList = new ArrayList<>(); @FieldDescribe("授权对象") - private Map manualEmpowerMap = new LinkedHashMap(); + private Map manualEmpowerMap = new LinkedHashMap<>(); @FieldDescribe("服务回调值") - private Map serviceValue = new LinkedHashMap(); + private Map serviceValue = new LinkedHashMap<>(); @FieldDescribe("标题") private String title; + @FieldDescribe("调用子流程后子流程结束将回写,用于标识子流程已经结束.") + private String embedCompleted; + + @FieldDescribe("父工作,在当前工作是通过子流程调用时产生.") + private String parentWork; + @FieldDescribe("拆分值列表") - private List splitValueList = new ArrayList(); + private List splitValueList = new ArrayList<>(); public List getManualForceTaskIdentityList() { if (this.manualForceTaskIdentityList == null) { - this.manualForceTaskIdentityList = new ArrayList(); + this.manualForceTaskIdentityList = new ArrayList<>(); } return this.manualForceTaskIdentityList; } @@ -40,7 +46,7 @@ public class WorkProperties extends JsonProperties { public Map getManualEmpowerMap() { if (this.manualEmpowerMap == null) { - this.manualEmpowerMap = new LinkedHashMap(); + this.manualEmpowerMap = new LinkedHashMap<>(); } return this.manualEmpowerMap; } @@ -79,4 +85,20 @@ public class WorkProperties extends JsonProperties { this.splitValueList = splitValueList; } + public String getEmbedCompleted() { + return embedCompleted; + } + + public void setEmbedCompleted(String embedCompleted) { + this.embedCompleted = embedCompleted; + } + + public String getParentWork() { + return parentWork; + } + + public void setParentWork(String parentWork) { + this.parentWork = parentWork; + } + } diff --git a/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/Embed.java b/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/Embed.java index 833d93e8e3bdb364f0de836303de8d244f928422..672d12c813b94142ac9c9da6dad4c95d4a24affe 100644 --- a/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/Embed.java +++ b/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/Embed.java @@ -75,6 +75,10 @@ public class Embed extends Activity { public void postLoad() { if (null != this.properties) { this.customData = this.getProperties().getCustomData(); + this.completedEndScript = this.getProperties().getCompletedEndScript(); + this.completedEndScriptText = this.getProperties().getCompletedEndScriptText(); + this.completedCancelScript = this.getProperties().getCompletedCancelScript(); + this.completedCancelScriptText = this.getProperties().getCompletedCancelScriptText(); } } @@ -104,17 +108,50 @@ public class Embed extends Activity { this.properties = new EmbedProperties(); } + public static final String COMPLETEDENDSCRIPT_FIELDNAME = "completedEndScript"; + @FieldDescribe("嵌入子流程在End节点结束事件脚本.") + @Transient + private String completedEndScript; + + public static final String COMPLETEDENDSCRIPTTEXT_FIELDNAME = "completedEndScriptText"; + @FieldDescribe("嵌入子流程在End节点结束事件脚本文本.") + @Transient + private String completedEndScriptText; + + public static final String COMPLETEDCANCELSCRIPT_FIELDNAME = "completedCancelScript"; + @FieldDescribe("嵌入子流程在Cancel节点结束事件脚本.") + @Transient + private String completedCancelScript; + + public static final String COMPLETEDCANCELSCRIPTTEXT_FIELDNAME = "completedCancelScriptText"; + @FieldDescribe("嵌入子流程在Cancel节点结束事件脚本文本.") + @Transient + private String completedCancelScriptText; + public static final String CUSTOMDATA_FIELDNAME = "customData"; + @FieldDescribe("节点自定义数据.") @Transient private JsonElement customData; @Override public JsonElement getCustomData() { - if (null != customData) { - return this.customData; - } else { - return this.getProperties().getCustomData(); - } + return this.customData; + } + + public String getCompletedEndScript() { + return completedEndScript; + } + + public String getCompletedCancelScriptText() { + return completedCancelScriptText; + } + + public String getCompletedCancelScript() { + return completedCancelScript; + } + + public String getCompletedEndScriptText() { + return completedEndScriptText; } @Override @@ -123,6 +160,26 @@ public class Embed extends Activity { this.properties.setCustomData(customData); } + public void setCompletedEndScript(String completedEndScript) { + this.getProperties().setCompletedEndScript(completedEndScript); + this.completedEndScript = completedEndScript; + } + + public void setCompletedEndScriptText(String completedEndScriptText) { + this.getProperties().setCompletedEndScriptText(completedEndScriptText); + this.completedEndScriptText = completedEndScriptText; + } + + public void setCompletedCancelScript(String completedCancelScript) { + this.getProperties().setCompletedCancelScript(completedCancelScript); + this.completedCancelScript = completedCancelScript; + } + + public void setCompletedCancelScriptText(String completedCancelScriptText) { + this.getProperties().setCompletedCancelScriptText(completedCancelScriptText); + this.completedCancelScriptText = completedCancelScriptText; + } + @FieldDescribe("分组") @CheckPersist(allowEmpty = true) @Column(length = JpaObject.length_255B, name = ColumnNamePrefix + group_FIELDNAME) @@ -560,12 +617,19 @@ public class Embed extends Activity { @CheckPersist(allowEmpty = true) private EmbedProperties properties; - public static final String WAITUNTILEND_FIELDNAME = "waitUntilEnd"; + public static final String WAITUNTILCOMPLETED_FIELDNAME = "waitUntilCompleted"; @FieldDescribe("等待至子流程结束.") @CheckPersist(allowEmpty = true) - @Column(name = ColumnNamePrefix + WAITUNTILEND_FIELDNAME) - @Index(name = TABLE + IndexNameMiddle + WAITUNTILEND_FIELDNAME) - private Boolean waitUntilEnd; + @Column(name = ColumnNamePrefix + WAITUNTILCOMPLETED_FIELDNAME) + private Boolean waitUntilCompleted; + + public Boolean getWaitUntilCompleted() { + return waitUntilCompleted; + } + + public void setWaitUntilCompleted(Boolean waitUntilCompleted) { + this.waitUntilCompleted = waitUntilCompleted; + } public String getDisplayLogScript() { return displayLogScript; diff --git a/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/EmbedProperties.java b/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/EmbedProperties.java index ecac997d5c81289a0e1174fd59e9294a98faab95..bbb78ad2bb8f435c25d4ef1a4504e75dae90d0b4 100644 --- a/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/EmbedProperties.java +++ b/o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/EmbedProperties.java @@ -19,4 +19,48 @@ public class EmbedProperties extends JsonProperties { this.customData = customData; } + @FieldDescribe("嵌入子流程在End节点结束事件脚本.") + private String completedEndScript; + + @FieldDescribe("嵌入子流程在End节点结束事件脚本文本.") + private String completedEndScriptText; + + @FieldDescribe("嵌入子流程在Cancel节点结束事件脚本.") + private String completedCancelScript; + + @FieldDescribe("嵌入子流程在Cancel节点结束事件脚本文本.") + private String completedCancelScriptText; + + public String getCompletedEndScript() { + return completedEndScript; + } + + public void setCompletedEndScript(String completedEndScript) { + this.completedEndScript = completedEndScript; + } + + public String getCompletedEndScriptText() { + return completedEndScriptText; + } + + public void setCompletedEndScriptText(String completedEndScriptText) { + this.completedEndScriptText = completedEndScriptText; + } + + public String getCompletedCancelScript() { + return completedCancelScript; + } + + public void setCompletedCancelScript(String completedCancelScript) { + this.completedCancelScript = completedCancelScript; + } + + public String getCompletedCancelScriptText() { + return completedCancelScriptText; + } + + public void setCompletedCancelScriptText(String completedCancelScriptText) { + this.completedCancelScriptText = completedCancelScriptText; + } + } diff --git a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/Business.java b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/Business.java index 63739965cc2dc8d5f82cbac4459e78c27003dbf1..1dcc117cba4cd0b63b79886a895bc75ece60e27b 100644 --- a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/Business.java +++ b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/Business.java @@ -45,6 +45,8 @@ public class Business { public static final String EVENT_EMBEDTARGETASSIGNDATA = "embedTargetAssignData"; public static final String EVENT_EMBEDTARGETIDENTITY = "embedTargetIdentity"; public static final String EVENT_EMBEDTARGETTITLE = "embedTargetTitle"; + public static final String EVENT_EMBEDCOMPLETEDEND = "embedCompletedEnd"; + public static final String EVENT_EMBEDCOMPLETEDCANCEL = "embedCompletedCancel"; public static final String EVENT_PROCESSAFTERBEGIN = "processAfterBegin"; public static final String EVENT_PROCESSAFTEREND = "processAfterEnd"; public static final String EVENT_PROCESSEXPIRE = "processExpire"; diff --git a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/ThisApplication.java b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/ThisApplication.java index ab6649e1f6f90395156bd3bb2e370f1bffceb8d2..c105eede218bd47b8c75a8636f01c00258a1526c 100644 --- a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/ThisApplication.java +++ b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/ThisApplication.java @@ -16,6 +16,7 @@ import com.x.processplatform.service.processing.schedule.Merge; import com.x.processplatform.service.processing.schedule.PassExpired; import com.x.processplatform.service.processing.schedule.TouchDelay; import com.x.processplatform.service.processing.schedule.TouchDetained; +import com.x.processplatform.service.processing.schedule.TouchEmbedWaitUntilCompleted; import com.x.processplatform.service.processing.schedule.Urge; public class ThisApplication { @@ -73,6 +74,10 @@ public class ThisApplication { if (BooleanUtils.isTrue(Config.processPlatform().getUrge().getEnable())) { context.schedule(Urge.class, Config.processPlatform().getUrge().getCron()); } + if (BooleanUtils.isTrue(Config.processPlatform().getTouchEmbedWaitUntilCompleted().getEnable())) { + context.schedule(TouchEmbedWaitUntilCompleted.class, + Config.processPlatform().getTouchEmbedWaitUntilCompleted().getCron()); + } } catch (Exception e) { e.printStackTrace(); diff --git a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/WorkDataHelper.java b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/WorkDataHelper.java index afd3ffbfa112bcebd5728f253827beabab1f015b..8ab1553a3491cf10633342578c46cfd8e0cf4c2c 100644 --- a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/WorkDataHelper.java +++ b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/WorkDataHelper.java @@ -65,7 +65,7 @@ public class WorkDataHelper { this.items = this.load(); } - private List load() throws Exception { + private List load() throws Exception { EntityManager em = emc.get(Item.class); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(Item.class); diff --git a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/AbstractBaseProcessor.java b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/AbstractBaseProcessor.java index d334ce79108c4446d5a333c1e99f3061c8af7cc5..2254303619215aa6b2a18d4aa2c61b1fde8b0893 100644 --- a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/AbstractBaseProcessor.java +++ b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/AbstractBaseProcessor.java @@ -20,6 +20,7 @@ import com.x.processplatform.core.entity.content.Work; import com.x.processplatform.core.entity.content.WorkLog; import com.x.processplatform.core.entity.content.WorkStatus; import com.x.processplatform.core.entity.element.Activity; +import com.x.processplatform.core.entity.element.Embed; import com.x.processplatform.core.entity.element.Form; import com.x.processplatform.core.entity.element.Process; import com.x.processplatform.service.processing.Business; @@ -255,6 +256,16 @@ public abstract class AbstractBaseProcessor { || StringUtils.isNotEmpty(activity.get(AIST, String.class)); } + protected boolean hasEmbedCompletedEndScript(Embed embed) { + return StringUtils.isNotEmpty(embed.getProperties().getCompletedEndScript()) + || StringUtils.isNotEmpty(embed.getProperties().getCompletedEndScriptText()); + } + + protected boolean hasEmbedCompletedCancelScript(Embed embed) { + return StringUtils.isNotEmpty(embed.getProperties().getCompletedCancelScript()) + || StringUtils.isNotEmpty(embed.getProperties().getCompletedCancelScriptText()); + } + protected void createFromWorkLog(AeiObjects aeiObjects, String token, Date date) throws Exception { WorkLog workLog = WorkLog.createFromWork(aeiObjects.getWork(), aeiObjects.getActivity(), token, date); aeiObjects.getCreateWorkLogs().add(workLog); diff --git a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/embed/EmbedProcessor.java b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/embed/EmbedProcessor.java index 864ca2b29be5d13c831f8fda7fbc4a4a438a4f20..86f70a46ad94e985314fa9968b2055ea22dff72b 100644 --- a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/embed/EmbedProcessor.java +++ b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/embed/EmbedProcessor.java @@ -102,9 +102,12 @@ public class EmbedProcessor extends AbstractEmbedProcessor { String embedWorkId = executor.execute(assignData); aeiObjects.getWork().setEmbedTargetWork(embedWorkId); } - List results = new ArrayList<>(); - results.add(aeiObjects.getWork()); + // 如果设置了停留至子流程结束,需要等待回写的标记. + if (BooleanUtils.isNotTrue(embed.getWaitUntilCompleted()) + || StringUtils.isNotBlank(aeiObjects.getWork().getProperties().getEmbedCompleted())) { + results.add(aeiObjects.getWork()); + } return results; } diff --git a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/end/EndProcessor.java b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/end/EndProcessor.java index cc86e81b84b78d3be26732a38c7bbb7d92435ae7..620e8dfdc7db5e8fbb187ce2f9af0fc24a352b3f 100644 --- a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/end/EndProcessor.java +++ b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/end/EndProcessor.java @@ -4,8 +4,11 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.List; +import java.util.Objects; +import javax.script.Bindings; import javax.script.CompiledScript; +import javax.script.ScriptContext; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; @@ -15,8 +18,11 @@ import com.x.base.core.project.config.Config; import com.x.base.core.project.logger.Logger; import com.x.base.core.project.logger.LoggerFactory; import com.x.base.core.project.scripting.JsonScriptingExecutor; +import com.x.base.core.project.scripting.ScriptingFactory; import com.x.processplatform.core.entity.content.Work; import com.x.processplatform.core.entity.content.WorkCompleted; +import com.x.processplatform.core.entity.element.ActivityType; +import com.x.processplatform.core.entity.element.Embed; import com.x.processplatform.core.entity.element.End; import com.x.processplatform.core.entity.element.Route; import com.x.processplatform.core.entity.log.Signal; @@ -151,7 +157,45 @@ public class EndProcessor extends AbstractEndProcessor { CompiledScript cs = aeiObjects.business().element().getCompiledScript(aeiObjects.getWork().getApplication(), aeiObjects.getProcess(), Business.EVENT_PROCESSAFTEREND); JsonScriptingExecutor.eval(cs, aeiObjects.scriptContext()); + // 回写到父Work + tryUpdateParentWork(aeiObjects); + + } + } + + private void tryUpdateParentWork(AeiObjects aeiObjects) { + if (StringUtils.isBlank(aeiObjects.getWork().getProperties().getParentWork())) { + try { + Work work = aeiObjects.entityManagerContainer() + .find(aeiObjects.getWork().getProperties().getParentWork(), Work.class); + if ((null != work) && Objects.equals(work.getActivityType(), ActivityType.embed)) { + Embed embed = (Embed) aeiObjects.business().element().get(work.getActivity(), + work.getActivityType()); + if ((null != embed) && BooleanUtils.isTrue(embed.getWaitUntilCompleted())) { + updateParentWork(aeiObjects, work, embed); + } + } + } catch (Exception e) { + LOGGER.error(new ExceptionUpdateParentWork(aeiObjects.getWork().getId(), + aeiObjects.getWork().getProperties().getParentWork())); + } + } + } + + private void updateParentWork(AeiObjects aeiObjects, Work work, Embed embed) throws Exception { + AeiObjects embedAeiObjects = new AeiObjects(aeiObjects.business(), work, embed, + aeiObjects.getProcessingConfigurator(), aeiObjects.getProcessingAttributes()); + embedAeiObjects.entityManagerContainer().beginTransaction(Work.class); + work.getProperties().setEmbedCompleted(ActivityType.end.toString()); + if (this.hasEmbedCompletedEndScript(embed)) { + CompiledScript cs = aeiObjects.business().element().getCompiledScript(aeiObjects.getWork().getApplication(), + embed, Business.EVENT_EMBEDCOMPLETEDEND); + ScriptContext scriptContext = embedAeiObjects.scriptContext(); + Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE); + bindings.put(ScriptingFactory.BINDING_NAME_EMBEDDATA, aeiObjects.getData()); + JsonScriptingExecutor.eval(cs, scriptContext); } + embedAeiObjects.commit(); } @Override diff --git a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/end/ExceptionUpdateParentWork.java b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/end/ExceptionUpdateParentWork.java new file mode 100644 index 0000000000000000000000000000000000000000..883ec5ef816b85fae349e903671a81f379bd990d --- /dev/null +++ b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/end/ExceptionUpdateParentWork.java @@ -0,0 +1,13 @@ +package com.x.processplatform.service.processing.processor.end; + +import com.x.base.core.project.exception.RunningException; + +class ExceptionUpdateParentWork extends RunningException { + + private static final long serialVersionUID = 9085364457175859374L; + + ExceptionUpdateParentWork(String work, String parentWork) { + super("updateParentWork error, work: {}, parent work:{}.", work, parentWork); + } + +} diff --git a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/schedule/ExceptionTouchEmbedWaitUntilCompleted.java b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/schedule/ExceptionTouchEmbedWaitUntilCompleted.java new file mode 100644 index 0000000000000000000000000000000000000000..5b4039e39af255c3eca9e9ee34845c6bf9e81a24 --- /dev/null +++ b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/schedule/ExceptionTouchEmbedWaitUntilCompleted.java @@ -0,0 +1,13 @@ +package com.x.processplatform.service.processing.schedule; + +import com.x.base.core.project.exception.PromptException; + +class ExceptionTouchEmbedWaitUntilCompleted extends PromptException { + + private static final long serialVersionUID = -7038279889683420366L; + + ExceptionTouchEmbedWaitUntilCompleted(Exception e, String id, String job) { + super(e, "子流程结束工作触发失败, id:{}, job:{}.", id, job); + } + +} diff --git a/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/schedule/TouchEmbedWaitUntilCompleted.java b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/schedule/TouchEmbedWaitUntilCompleted.java new file mode 100644 index 0000000000000000000000000000000000000000..2589f907871d857e9c0511ce1531955780f14fd2 --- /dev/null +++ b/o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/schedule/TouchEmbedWaitUntilCompleted.java @@ -0,0 +1,77 @@ +package com.x.processplatform.service.processing.schedule; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.commons.lang3.StringUtils; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import com.x.base.core.container.EntityManagerContainer; +import com.x.base.core.container.factory.EntityManagerContainerFactory; +import com.x.base.core.project.Applications; +import com.x.base.core.project.x_processplatform_service_processing; +import com.x.base.core.project.jaxrs.WoId; +import com.x.base.core.project.logger.Logger; +import com.x.base.core.project.logger.LoggerFactory; +import com.x.base.core.project.schedule.AbstractJob; +import com.x.base.core.project.utils.time.TimeStamp; +import com.x.processplatform.core.entity.content.Work; +import com.x.processplatform.core.entity.element.ActivityType; +import com.x.processplatform.core.entity.element.Embed; +import com.x.processplatform.core.express.ProcessingAttributes; +import com.x.processplatform.service.processing.ThisApplication; + +public class TouchEmbedWaitUntilCompleted extends AbstractJob { + + private static final Logger LOGGER = LoggerFactory.getLogger(TouchEmbedWaitUntilCompleted.class); + + @Override + public void schedule(JobExecutionContext jobExecutionContext) throws Exception { + try { + TimeStamp stamp = new TimeStamp(); + AtomicInteger count = new AtomicInteger(); + Map idJobs = this.list(); + if (!idJobs.isEmpty()) { + for (Map.Entry en : idJobs.entrySet()) { + touch(en.getKey(), en.getValue(), count); + } + } + if (count.get() > 0) { + LOGGER.info("完成触发{}个等待子流程结束工作, 耗时:{}.", count::intValue, stamp::consumingMilliseconds); + } + } catch (Exception e) { + throw new JobExecutionException(e); + } + } + + private void touch(String id, String job, AtomicInteger count) { + try { + ThisApplication.context().applications() + .putQuery(x_processplatform_service_processing.class, + Applications.joinQueryUri("work", id, "processing"), new ProcessingAttributes(), job) + .getData(WoId.class); + count.incrementAndGet(); + } catch (Exception e) { + LOGGER.error(new ExceptionTouchEmbedWaitUntilCompleted(e, id, job)); + } + } + + private Map list() throws Exception { + Map idJobs = new HashMap<>(); + try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) { + List embeds = emc.idsEqual(Embed.class, Embed.WAITUNTILCOMPLETED_FIELDNAME, true); + List ids = emc.idsEqualAndIn(Work.class, Work.activityType_FIELDNAME, ActivityType.embed, + Work.activity_FIELDNAME, embeds); + for (String id : ids) { + Work work = emc.find(id, Work.class); + if (StringUtils.isNotBlank(work.getProperties().getEmbedCompleted())) { + idJobs.put(work.getId(), work.getJob()); + } + } + } + return idJobs; + } +} \ No newline at end of file