提交 e643b5a7 编写于 作者: R Robert Hafner

Add additional localization support for the following types:

* ProcessInstance
* Execution (Process/SubProcess)
* HistoricProcessInstance

In addition, this change includes an improvement to add fallback support for resolving a localization.
上级 626761e0
......@@ -10,3 +10,4 @@ target
*.bpmn/
/userguide/src/en/index.html
migration.html
/modules/**/bin
......@@ -83,6 +83,11 @@ public interface HistoricProcessInstance {
*/
String getName();
/**
* The description for the process instance.
*/
String getDescription();
/** Returns the process variables if requested in the process instance query */
Map<String, Object> getProcessVariables();
}
......@@ -289,4 +289,14 @@ public interface HistoricProcessInstanceQuery extends Query<HistoricProcessInsta
* Only select process instances with a name like the given value, ignoring upper/lower case.
*/
HistoricProcessInstanceQuery processInstanceNameLikeIgnoreCase(String nameLikeIgnoreCase);
/**
* Localize historic process name and description to specified locale.
*/
public HistoricProcessInstanceQuery locale(String locale);
/**
* Instruct localization to fallback to more general locales including the default locale of the JVM if the specified locale is not found.
*/
public HistoricProcessInstanceQuery withLocalizationFallback();
}
......@@ -12,13 +12,24 @@
*/
package org.activiti.engine.impl;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SubProcess;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.DynamicBpmnConstants;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.SuspensionState;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ExecutionQuery;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
......@@ -45,6 +56,8 @@ public class ExecutionQueryImpl extends AbstractVariableQueryImpl<ExecutionQuery
protected String tenantId;
protected String tenantIdLike;
protected boolean withoutTenantId;
protected String locale;
protected boolean withLocalizationFallback;
// Not used by end-users, but needed for dynamic ibatis query
protected String superProcessInstanceId;
......@@ -248,6 +261,17 @@ public class ExecutionQueryImpl extends AbstractVariableQueryImpl<ExecutionQuery
return variableValueNotEqualsIgnoreCase(name, value, false);
}
@Override
public ExecutionQuery locale(String locale) {
this.locale = locale;
return this;
}
public ExecutionQuery withLocalizationFallback() {
withLocalizationFallback = true;
return this;
}
// ordering ////////////////////////////////////////////////////
public ExecutionQueryImpl orderByProcessInstanceId() {
......@@ -282,7 +306,57 @@ public class ExecutionQueryImpl extends AbstractVariableQueryImpl<ExecutionQuery
public List<Execution> executeList(CommandContext commandContext, Page page) {
checkQueryOk();
ensureVariablesInitialized();
return (List) commandContext.getExecutionEntityManager().findExecutionsByQueryCriteria(this, page);
List<?> executions = commandContext.getExecutionEntityManager().findExecutionsByQueryCriteria(this, page);
for(ExecutionEntity execution : (List<ExecutionEntity>)executions) {
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId());
String activityId;
if(execution.isScope()) {
if(execution.getId() == execution.getProcessInstanceId()) {
Process process = bpmnModel.getMainProcess();
execution.setName(process.getName());
execution.setDescription(process.getDocumentation());
activityId = process.getId();
}
else {
activityId = execution.getActivityId();
FlowElement element = bpmnModel.getFlowElement(activityId);
if(element instanceof SubProcess) {
SubProcess subprocess = (SubProcess) element;
execution.setName(subprocess.getName());
execution.setDescription(subprocess.getDocumentation());
}
}
if(locale != null && activityId != null) {
localize(execution, activityId);
}
}
}
return (List<Execution>) executions;
}
protected void localize(Execution execution, String activityId) {
ExecutionEntity executionEntity = (ExecutionEntity) execution;
executionEntity.setLocalizedName(null);
executionEntity.setLocalizedDescription(null);
String processDefinitionId = executionEntity.getProcessDefinitionId();
if (processDefinitionId != null) {
ObjectNode languageNode = Context.getLocalizationElementProperties(locale, activityId, processDefinitionId, withLocalizationFallback);
if (languageNode != null) {
JsonNode languageNameNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_NAME);
if (languageNameNode != null && languageNameNode.isNull() == false) {
executionEntity.setLocalizedName(languageNameNode.asText());
}
JsonNode languageDescriptionNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_DESCRIPTION);
if (languageDescriptionNode != null && languageDescriptionNode.isNull() == false) {
executionEntity.setLocalizedDescription(languageDescriptionNode.asText());
}
}
}
}
// getters ////////////////////////////////////////////////////
......
......@@ -18,12 +18,21 @@ import java.util.Date;
import java.util.List;
import java.util.Set;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.DynamicBpmnConstants;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tom Baeyens
......@@ -66,6 +75,8 @@ public class HistoricProcessInstanceQueryImpl extends AbstractVariableQueryImpl<
protected List<HistoricProcessInstanceQueryImpl> orQueryObjects = new ArrayList<HistoricProcessInstanceQueryImpl>();
protected HistoricProcessInstanceQueryImpl currentOrQueryObject = null;
protected boolean inOrStatement = false;
protected String locale;
protected boolean withLocalizationFallback;
public HistoricProcessInstanceQueryImpl() {
}
......@@ -495,6 +506,16 @@ public class HistoricProcessInstanceQueryImpl extends AbstractVariableQueryImpl<
return orderBy(HistoricProcessInstanceQueryProperty.TENANT_ID);
}
public HistoricProcessInstanceQuery locale(String locale) {
this.locale = locale;
return this;
}
public HistoricProcessInstanceQuery withLocalizationFallback() {
withLocalizationFallback = true;
return this;
}
public String getMssqlOrDB2OrderBy() {
String specialOrderBy = super.getOrderBy();
if (specialOrderBy != null && specialOrderBy.length() > 0) {
......@@ -513,13 +534,53 @@ public class HistoricProcessInstanceQueryImpl extends AbstractVariableQueryImpl<
public List<HistoricProcessInstance> executeList(CommandContext commandContext, Page page) {
checkQueryOk();
ensureVariablesInitialized();
List<HistoricProcessInstance> results;
if (includeProcessVariables) {
return commandContext.getHistoricProcessInstanceEntityManager().findHistoricProcessInstancesAndVariablesByQueryCriteria(this);
results = commandContext.getHistoricProcessInstanceEntityManager().findHistoricProcessInstancesAndVariablesByQueryCriteria(this);
} else {
return commandContext.getHistoricProcessInstanceEntityManager().findHistoricProcessInstancesByQueryCriteria(this);
results = commandContext.getHistoricProcessInstanceEntityManager().findHistoricProcessInstancesByQueryCriteria(this);
}
}
for(HistoricProcessInstance processInstance : results) {
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processInstance.getProcessDefinitionId());
Process process = bpmnModel.getMainProcess();
HistoricProcessInstanceEntity processInstanceEntity = (HistoricProcessInstanceEntity) processInstance;
if (null == processInstance.getName()) {
processInstanceEntity.setName(process.getName());
}
processInstanceEntity.setDescription(process.getDocumentation());
if (locale != null) {
localize(processInstanceEntity, bpmnModel);
}
}
return results;
}
protected void localize(HistoricProcessInstanceEntity processInstance, BpmnModel bpmnModel) {
processInstance.setLocalizedName(null);
processInstance.setLocalizedDescription(null);
String processDefinitionId = processInstance.getProcessDefinitionId();
String processDefinitionKey = bpmnModel.getMainProcess().getId();
if (processDefinitionId != null) {
ObjectNode languageNode = Context.getLocalizationElementProperties(locale, processDefinitionKey, processDefinitionId, withLocalizationFallback);
if (languageNode != null) {
JsonNode languageNameNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_NAME);
if (languageNameNode != null && languageNameNode.isNull() == false) {
processInstance.setLocalizedName(languageNameNode.asText());
}
JsonNode languageDescriptionNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_DESCRIPTION);
if (languageDescriptionNode != null && languageDescriptionNode.isNull() == false) {
processInstance.setLocalizedDescription(languageDescriptionNode.asText());
}
}
}
}
@Override
protected void ensureVariablesInitialized() {
super.ensureVariablesInitialized();
......@@ -537,7 +598,7 @@ public class HistoricProcessInstanceQueryImpl extends AbstractVariableQueryImpl<
this.orderBy(HistoricProcessInstanceQueryProperty.INCLUDED_VARIABLE_TIME).asc();
}
}
public String getBusinessKey() {
return businessKey;
}
......
......@@ -101,6 +101,7 @@ public class HistoricTaskInstanceQueryImpl extends AbstractVariableQueryImpl<His
protected String tenantIdLike;
protected boolean withoutTenantId;
protected String locale;
protected boolean withLocalizationFallback;
protected boolean includeTaskLocalVariables = false;
protected boolean includeProcessVariables = false;
protected List<HistoricTaskInstanceQueryImpl> orQueryObjects = new ArrayList<HistoricTaskInstanceQueryImpl>();
......@@ -1016,6 +1017,11 @@ public class HistoricTaskInstanceQueryImpl extends AbstractVariableQueryImpl<His
return this;
}
public HistoricTaskInstanceQuery withLocalizationFallback() {
withLocalizationFallback = true;
return this;
}
public HistoricTaskInstanceQuery includeTaskLocalVariables() {
this.includeTaskLocalVariables = true;
return this;
......@@ -1055,7 +1061,7 @@ public class HistoricTaskInstanceQueryImpl extends AbstractVariableQueryImpl<His
if (locale != null) {
String processDefinitionId = task.getProcessDefinitionId();
if (processDefinitionId != null) {
ObjectNode languageNode = Context.getLocalizationElementProperties(locale, task.getTaskDefinitionKey(), processDefinitionId);
ObjectNode languageNode = Context.getLocalizationElementProperties(locale, task.getTaskDefinitionKey(), processDefinitionId, withLocalizationFallback);
if (languageNode != null) {
JsonNode languageNameNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_NAME);
if (languageNameNode != null && languageNameNode.isNull() == false) {
......
......@@ -18,14 +18,23 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.DynamicBpmnConstants;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.SuspensionState;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tom Baeyens
......@@ -58,6 +67,8 @@ public class ProcessInstanceQueryImpl extends AbstractVariableQueryImpl<ProcessI
protected String name;
protected String nameLike;
protected String nameLikeIgnoreCase;
protected String locale;
protected boolean withLocalizationFallback;
protected String tenantId;
protected String tenantIdLike;
......@@ -495,6 +506,16 @@ public class ProcessInstanceQueryImpl extends AbstractVariableQueryImpl<ProcessI
return this;
}
public ProcessInstanceQuery locale(String locale) {
this.locale = locale;
return this;
}
public ProcessInstanceQuery withLocalizationFallback() {
withLocalizationFallback = true;
return this;
}
public String getMssqlOrDB2OrderBy() {
String specialOrderBy = super.getOrderBy();
if (specialOrderBy != null && specialOrderBy.length() > 0) {
......@@ -504,7 +525,7 @@ public class ProcessInstanceQueryImpl extends AbstractVariableQueryImpl<ProcessI
}
return specialOrderBy;
}
// results /////////////////////////////////////////////////////////////////
public long executeCount(CommandContext commandContext) {
......@@ -516,11 +537,29 @@ public class ProcessInstanceQueryImpl extends AbstractVariableQueryImpl<ProcessI
public List<ProcessInstance> executeList(CommandContext commandContext, Page page) {
checkQueryOk();
ensureVariablesInitialized();
List<ProcessInstance> processInstances;
if (includeProcessVariables) {
return commandContext.getExecutionEntityManager().findProcessInstanceAndVariablesByQueryCriteria(this);
processInstances = commandContext.getExecutionEntityManager().findProcessInstanceAndVariablesByQueryCriteria(this);
} else {
return commandContext.getExecutionEntityManager().findProcessInstanceByQueryCriteria(this);
processInstances= commandContext.getExecutionEntityManager().findProcessInstanceByQueryCriteria(this);
}
for (ProcessInstance processInstance : processInstances) {
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processInstance.getProcessDefinitionId());
Process process = bpmnModel.getMainProcess();
ExecutionEntity processInstanceExecution = (ExecutionEntity) processInstance;
if (null == processInstance.getName()) {
processInstanceExecution.setName(process.getName());
}
processInstanceExecution.setDescription(process.getDocumentation());
if (locale != null) {
localize(processInstanceExecution);
}
}
return processInstances;
}
@Override
......@@ -532,6 +571,29 @@ public class ProcessInstanceQueryImpl extends AbstractVariableQueryImpl<ProcessI
}
}
protected void localize(ExecutionEntity processInstanceExecution) {
processInstanceExecution.setLocalizedName(null);
processInstanceExecution.setLocalizedDescription(null);
if (locale != null) {
String processDefinitionId = processInstanceExecution.getProcessDefinitionId();
if (processDefinitionId != null) {
ObjectNode languageNode = Context.getLocalizationElementProperties(locale, processInstanceExecution.getProcessDefinitionKey(), processDefinitionId, withLocalizationFallback);
if (languageNode != null) {
JsonNode languageNameNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_NAME);
if (languageNameNode != null && languageNameNode.isNull() == false) {
processInstanceExecution.setLocalizedName(languageNameNode.asText());
}
JsonNode languageDescriptionNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_DESCRIPTION);
if (languageDescriptionNode != null && languageDescriptionNode.isNull() == false) {
processInstanceExecution.setLocalizedDescription(languageDescriptionNode.asText());
}
}
}
}
}
// getters /////////////////////////////////////////////////////////////////
public boolean getOnlyProcessInstances() {
......
......@@ -105,6 +105,7 @@ public class TaskQueryImpl extends AbstractVariableQueryImpl<TaskQuery, Task> im
protected boolean bothCandidateAndAssigned;
protected boolean orActive;
protected String locale;
protected boolean withLocalizationFallback;
protected List<TaskQueryImpl> orQueryObjects = new ArrayList<TaskQueryImpl>();
protected TaskQueryImpl currentOrQueryObject = null;
......@@ -1053,6 +1054,11 @@ public class TaskQueryImpl extends AbstractVariableQueryImpl<TaskQuery, Task> im
return this;
}
public TaskQuery withLocalizationFallback() {
withLocalizationFallback = true;
return this;
}
public TaskQuery includeTaskLocalVariables() {
this.includeTaskLocalVariables = true;
return this;
......@@ -1241,7 +1247,7 @@ public class TaskQueryImpl extends AbstractVariableQueryImpl<TaskQuery, Task> im
if (locale != null) {
String processDefinitionId = task.getProcessDefinitionId();
if (processDefinitionId != null) {
ObjectNode languageNode = Context.getLocalizationElementProperties(locale, task.getTaskDefinitionKey(), processDefinitionId);
ObjectNode languageNode = Context.getLocalizationElementProperties(locale, task.getTaskDefinitionKey(), processDefinitionId, withLocalizationFallback);
if (languageNode != null) {
JsonNode languageNameNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_NAME);
if (languageNameNode != null && languageNameNode.isNull() == false) {
......
......@@ -14,7 +14,12 @@
package org.activiti.engine.impl.context;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Stack;
import org.activiti.engine.compatibility.Activiti5CompatibilityHandler;
......@@ -41,6 +46,7 @@ public class Context {
protected static ThreadLocal<Map<String, ObjectNode>> bpmnOverrideContextThreadLocal = new ThreadLocal<Map<String, ObjectNode>>();
protected static ThreadLocal<Activiti5CompatibilityHandler> activiti5CompatibilityHandlerThreadLocal = new ThreadLocal<Activiti5CompatibilityHandler>();
protected static ThreadLocal<Activiti5CompatibilityHandler> fallbackActiviti5CompatibilityHandlerThreadLocal = new ThreadLocal<Activiti5CompatibilityHandler>();
protected static ResourceBundle.Control resourceBundleControl = new ResourceBundleControl();
public static CommandContext getCommandContext() {
Stack<CommandContext> stack = getStack(commandContextThreadLocal);
......@@ -125,12 +131,26 @@ public class Context {
return elementProperties;
}
public static ObjectNode getLocalizationElementProperties(String language, String id, String processDefinitionId) {
public static ObjectNode getLocalizationElementProperties(String language, String id, String processDefinitionId, boolean useFallback) {
ObjectNode definitionInfoNode = getProcessDefinitionInfoNode(processDefinitionId);
ObjectNode localizationProperties = null;
if (definitionInfoNode != null) {
localizationProperties = getProcessEngineConfiguration().getDynamicBpmnService().getLocalizationElementProperties(
language, id, definitionInfoNode);
if(!useFallback) {
localizationProperties = getProcessEngineConfiguration().getDynamicBpmnService().getLocalizationElementProperties(language, id,
definitionInfoNode);
}
else {
HashSet<Locale> candidateLocales = new LinkedHashSet<Locale>();
candidateLocales.addAll(resourceBundleControl.getCandidateLocales(id, Locale.forLanguageTag(language)));
candidateLocales.addAll(resourceBundleControl.getCandidateLocales(id, Locale.getDefault()));
for (Locale locale : candidateLocales) {
localizationProperties = getProcessEngineConfiguration().getDynamicBpmnService().getLocalizationElementProperties(locale.toLanguageTag(), id,
definitionInfoNode);
if (localizationProperties != null) {
break;
}
}
}
}
return localizationProperties;
}
......@@ -192,4 +212,11 @@ public class Context {
public static void removeFallbackActiviti5CompatibilityHandler() {
fallbackActiviti5CompatibilityHandlerThreadLocal.remove();
}
static class ResourceBundleControl extends ResourceBundle.Control {
@Override
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
return super.getCandidateLocales(baseName, locale);
}
}
}
......@@ -99,7 +99,13 @@ public interface ExecutionEntity extends DelegateExecution, Execution, ProcessIn
void setMultiInstanceRoot(boolean isMultiInstanceRoot);
void setName(String name);
void setDescription(String description);
void setLocalizedName(String localizedName);
void setLocalizedDescription(String localizedDescription);
void setTenantId(String tenantId);
Date getLockTime();
......
......@@ -64,6 +64,9 @@ public class ExecutionEntityImpl extends VariableScopeImpl implements ExecutionE
/** The tenant identifier (if any) */
protected String tenantId = ProcessEngineConfiguration.NO_TENANT_ID;
protected String name;
protected String description;
protected String localizedName;
protected String localizedDescription;
protected Date lockTime;
......@@ -676,13 +679,45 @@ public class ExecutionEntityImpl extends VariableScopeImpl implements ExecutionE
@Override
public String getName() {
return this.name;
if (localizedName != null && localizedName.length() > 0) {
return localizedName;
} else {
return name;
}
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
if (localizedDescription != null && localizedDescription.length() > 0) {
return localizedDescription;
} else {
return description;
}
}
public void setDescription(String description) {
this.description = description;
}
public String getLocalizedName() {
return localizedName;
}
public void setLocalizedName(String localizedName) {
this.localizedName = localizedName;
}
public String getLocalizedDescription() {
return localizedDescription;
}
public void setLocalizedDescription(String localizedDescription) {
this.localizedDescription = localizedDescription;
}
public String getTenantId() {
return tenantId;
}
......
......@@ -36,6 +36,12 @@ public interface HistoricProcessInstanceEntity extends HistoricScopeInstanceEnti
void setTenantId(String tenantId);
void setName(String name);
void setLocalizedName(String localizedName);
void setDescription(String description);
void setLocalizedDescription(String localizedDescription);
List<HistoricVariableInstanceEntity> getQueryVariables();
......
......@@ -39,6 +39,9 @@ public class HistoricProcessInstanceEntityImpl extends HistoricScopeInstanceEnti
protected String superProcessInstanceId;
protected String tenantId = ProcessEngineConfiguration.NO_TENANT_ID;
protected String name;
protected String localizedName;
protected String description;
protected String localizedDescription;
protected List<HistoricVariableInstanceEntity> queryVariables;
public HistoricProcessInstanceEntityImpl() {
......@@ -124,13 +127,45 @@ public class HistoricProcessInstanceEntityImpl extends HistoricScopeInstanceEnti
}
public String getName() {
return name;
if (localizedName != null && localizedName.length() > 0) {
return localizedName;
} else {
return name;
}
}
public void setName(String name) {
this.name = name;
}
public String getLocalizedName() {
return localizedName;
}
public void setLocalizedName(String localizedName) {
this.localizedName = localizedName;
}
public String getDescription() {
if (localizedDescription != null && localizedDescription.length() > 0) {
return localizedDescription;
} else {
return description;
}
}
public void setDescription(String description) {
this.description = description;
}
public String getLocalizedDescription() {
return localizedDescription;
}
public void setLocalizedDescription(String localizedDescription) {
this.localizedDescription = localizedDescription;
}
public Map<String, Object> getProcessVariables() {
Map<String, Object> variables = new HashMap<String, Object>();
if (queryVariables != null) {
......
......@@ -56,4 +56,13 @@ public interface Execution {
*/
String getTenantId();
/**
* Returns the name of this execution.
*/
String getName();
/**
* Returns the description of this execution.
*/
String getDescription();
}
......@@ -264,6 +264,16 @@ public interface ExecutionQuery extends Query<ExecutionQuery, Execution> {
*/
ExecutionQuery messageEventSubscriptionName(String messageName);
/**
* Localize execution name and description to specified locale.
*/
ExecutionQuery locale(String locale);
/**
* Instruct localization to fallback to more general locales including the default locale of the JVM if the specified locale is not found.
*/
public ExecutionQuery withLocalizationFallback();
// ordering //////////////////////////////////////////////////////////////
/** Order by id (needs to be followed by {@link #asc()} or {@link #desc()}). */
......
......@@ -76,4 +76,18 @@ public interface ProcessInstance extends Execution {
*/
String getName();
/**
* Returns the description of this process instance.
*/
String getDescription();
/**
* Returns the localized name of this process instance.
*/
String getLocalizedName();
/**
* Returns the localized description of this process instance.
*/
String getLocalizedDescription();
}
......@@ -281,4 +281,13 @@ public interface ProcessInstanceQuery extends Query<ProcessInstanceQuery, Proces
*/
ProcessInstanceQuery orderByTenantId();
/**
* Localize process name and description to specified locale.
*/
public ProcessInstanceQuery locale(String locale);
/**
* Instruct localization to fallback to more general locales including the default locale of the JVM if the specified locale is not found.
*/
public ProcessInstanceQuery withLocalizationFallback();
}
......@@ -494,6 +494,11 @@ public interface TaskInfoQuery<T extends TaskInfoQuery<?, ?>, V extends TaskInfo
*/
T locale(String locale);
/**
* Instruct localization to fallback to more general locales including the default locale of the JVM if the specified locale is not found.
*/
public T withLocalizationFallback();
/**
* All query clauses called will be added to a single or-statement. This or-statement will be included with the other already existing clauses in the query, joined by an 'and'.
*
......
/* 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.activiti.engine.test.api.history;
import java.util.List;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class HistoricProcessInstanceQueryTest extends PluggableActivitiTestCase {
@Deployment
public void testLocalization() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("historicProcessLocalization");
String processInstanceId = processInstance.getId();
Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
taskService.complete(task.getId());
if (processEngineConfiguration.getHistoryLevel().isAtLeast(HistoryLevel.ACTIVITY)) {
List<HistoricProcessInstance> processes = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).list();
assertEquals(1, processes.size());
assertEquals("Historic Process Name", processes.get(0).getName());
assertEquals("Historic Process Description", processes.get(0).getDescription());
ObjectNode infoNode = dynamicBpmnService.changeLocalizationName("en-GB", "historicProcessLocalization", "Historic Process Name 'en-GB'");
dynamicBpmnService.changeLocalizationDescription("en-GB", "historicProcessLocalization", "Historic Process Description 'en-GB'", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
dynamicBpmnService.changeLocalizationName("en", "historicProcessLocalization", "Historic Process Name 'en'", infoNode);
dynamicBpmnService.changeLocalizationDescription("en", "historicProcessLocalization", "Historic Process Description 'en'", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
processes = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).list();
assertEquals(1, processes.size());
assertEquals("Historic Process Name", processes.get(0).getName());
assertEquals("Historic Process Description", processes.get(0).getDescription());
processes = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).locale("en-GB").list();
assertEquals(1, processes.size());
assertEquals("Historic Process Name 'en-GB'", processes.get(0).getName());
assertEquals("Historic Process Description 'en-GB'", processes.get(0).getDescription());
processes = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).listPage(0,10);
assertEquals(1, processes.size());
assertEquals("Historic Process Name", processes.get(0).getName());
assertEquals("Historic Process Description", processes.get(0).getDescription());
processes = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).locale("en-GB").listPage(0,10);
assertEquals(1, processes.size());
assertEquals("Historic Process Name 'en-GB'", processes.get(0).getName());
assertEquals("Historic Process Description 'en-GB'", processes.get(0).getDescription());
HistoricProcessInstance process = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
assertEquals("Historic Process Name", process.getName());
assertEquals("Historic Process Description", process.getDescription());
process = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).locale("en-GB").singleResult();
assertEquals("Historic Process Name 'en-GB'", process.getName());
assertEquals("Historic Process Description 'en-GB'", process.getDescription());
process = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).locale("en").singleResult();
assertEquals("Historic Process Name 'en'", process.getName());
assertEquals("Historic Process Description 'en'", process.getDescription());
process = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).locale("en-AU").withLocalizationFallback().singleResult();
assertEquals("Historic Process Name 'en'", process.getName());
assertEquals("Historic Process Description 'en'", process.getDescription());
}
}
}
......@@ -46,6 +46,8 @@ import org.activiti.engine.runtime.ExecutionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.test.Deployment;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Joram Barrez
* @author Frederik Heremans
......@@ -1299,4 +1301,136 @@ public class ExecutionQueryTest extends PluggableActivitiTestCase {
assertEquals(3, runtimeService.createExecutionQuery().processInstanceId(pi.getId()).processVariableValueNotEqualsIgnoreCase("xIgnoreCase", "chilD").count());
}
@Deployment(resources={"org/activiti/engine/test/api/runtime/executionLocalization.bpmn20.xml"})
public void testLocalizeExecution() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("executionLocalization");
List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).list();
assertEquals(3, executions.size());
for(Execution execution : executions) {
if(execution.getParentId() == null) {
assertEquals("Process Name", execution.getName());
assertEquals("Process Description", execution.getDescription());
}
else if(execution.getParentId() == execution.getProcessInstanceId()){
assertEquals("SubProcess Name", execution.getName());
assertEquals("SubProcess Description", execution.getDescription());
}
}
ObjectNode infoNode = dynamicBpmnService.changeLocalizationName("en-GB", "executionLocalization", "Process Name 'en-GB'");
dynamicBpmnService.changeLocalizationDescription("en-GB", "executionLocalization", "Process Description 'en-GB'", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
dynamicBpmnService.changeLocalizationName("en", "executionLocalization", "Process Name 'en'", infoNode);
dynamicBpmnService.changeLocalizationDescription("en", "executionLocalization", "Process Description 'en'", infoNode);
dynamicBpmnService.changeLocalizationName("en-GB", "subProcess", "SubProcess Name 'en-GB'", infoNode);
dynamicBpmnService.changeLocalizationDescription("en-GB", "subProcess", "SubProcess Description 'en-GB'", infoNode);
dynamicBpmnService.changeLocalizationName("en", "subProcess", "SubProcess Name 'en'", infoNode);
dynamicBpmnService.changeLocalizationDescription("en", "subProcess", "SubProcess Description 'en'", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).list();
String subProcessId = null;
assertEquals(3, executions.size());
for(Execution execution : executions) {
if(execution.getParentId() == null) {
assertEquals("Process Name", execution.getName());
assertEquals("Process Description", execution.getDescription());
}
else if(execution.getParentId() == execution.getProcessInstanceId()){
assertEquals("SubProcess Name", execution.getName());
assertEquals("SubProcess Description", execution.getDescription());
subProcessId = execution.getId();
}
}
executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).locale("en-GB").list();
assertEquals(3, executions.size());
for(Execution execution : executions) {
if(execution.getParentId() == null) {
assertEquals("Process Name 'en-GB'", execution.getName());
assertEquals("Process Description 'en-GB'", execution.getDescription());
}
else if(execution.getParentId() == execution.getProcessInstanceId()){
assertEquals("SubProcess Name 'en-GB'", execution.getName());
assertEquals("SubProcess Description 'en-GB'", execution.getDescription());
}
}
executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).listPage(0,10);
assertEquals(3, executions.size());
for(Execution execution : executions) {
if(execution.getParentId() == null) {
assertEquals("Process Name", execution.getName());
assertEquals("Process Description", execution.getDescription());
}
else if(execution.getParentId() == execution.getProcessInstanceId()){
assertEquals("SubProcess Name", execution.getName());
assertEquals("SubProcess Description", execution.getDescription());
}
}
executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).locale("en-GB").listPage(0,10);
assertEquals(3, executions.size());
for(Execution execution : executions) {
if(execution.getParentId() == null) {
assertEquals("Process Name 'en-GB'", execution.getName());
assertEquals("Process Description 'en-GB'", execution.getDescription());
}
else if(execution.getParentId() == execution.getProcessInstanceId()){
assertEquals("SubProcess Name 'en-GB'", execution.getName());
assertEquals("SubProcess Description 'en-GB'", execution.getDescription());
}
}
Execution execution = runtimeService.createExecutionQuery().executionId(processInstance.getId()).singleResult();
assertEquals("Process Name", execution.getName());
assertEquals("Process Description", execution.getDescription());
execution = runtimeService.createExecutionQuery().executionId(subProcessId).singleResult();
assertEquals("SubProcess Name", execution.getName());
assertEquals("SubProcess Description", execution.getDescription());
execution = runtimeService.createExecutionQuery().executionId(processInstance.getId()).locale("en-GB").singleResult();
assertEquals("Process Name 'en-GB'", execution.getName());
assertEquals("Process Description 'en-GB'", execution.getDescription());
execution = runtimeService.createExecutionQuery().executionId(subProcessId).locale("en-GB").singleResult();
assertEquals("SubProcess Name 'en-GB'", execution.getName());
assertEquals("SubProcess Description 'en-GB'", execution.getDescription());
execution = runtimeService.createExecutionQuery().executionId(processInstance.getId()).locale("en-AU").withLocalizationFallback().singleResult();
assertEquals("Process Name 'en'", execution.getName());
assertEquals("Process Description 'en'", execution.getDescription());
execution = runtimeService.createExecutionQuery().executionId(subProcessId).locale("en-AU").withLocalizationFallback().singleResult();
assertEquals("SubProcess Name 'en'", execution.getName());
assertEquals("SubProcess Description 'en'", execution.getDescription());
infoNode = dynamicBpmnService.changeLocalizationName("en-US", "executionLocalization", "Process Name 'en-US'");
dynamicBpmnService.changeLocalizationDescription("en-US", "executionLocalization", "Process Description 'en-US'", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
dynamicBpmnService.changeLocalizationName("en-US", "subProcess", "SubProcess Name 'en-US'", infoNode);
dynamicBpmnService.changeLocalizationDescription("en-US", "subProcess", "SubProcess Description 'en-US'", infoNode);
dynamicBpmnService.changeLocalizationName("en-US", "subProcess", "SubProcess Name 'en-US'", infoNode);
dynamicBpmnService.changeLocalizationDescription("en-US", "subProcess", "SubProcess Description 'en-US'", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
execution = runtimeService.createExecutionQuery().executionId(processInstance.getId()).locale("en-GB").withLocalizationFallback().singleResult();
assertEquals("Process Name 'en-US'", execution.getName());
assertEquals("Process Description 'en-US'", execution.getDescription());
execution = runtimeService.createExecutionQuery().executionId(subProcessId).locale("en-US").singleResult();
assertEquals("SubProcess Name 'en-US'", execution.getName());
assertEquals("SubProcess Description 'en-US'", execution.getDescription());
}
}
......@@ -35,6 +35,8 @@ import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.test.Deployment;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Joram Barrez
* @author Tijs Rademakers
......@@ -1748,4 +1750,62 @@ public class ProcessInstanceQueryTest extends PluggableActivitiTestCase {
public void testNativeQueryPaging() {
assertEquals(5, runtimeService.createNativeProcessInstanceQuery().sql("SELECT * FROM " + managementService.getTableName(ProcessInstance.class)).listPage(0, 5).size());
}
public void testLocalizeProcess() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");
List<ProcessInstance> processes = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).list();
assertEquals(1, processes.size());
assertEquals("oneTaskProcessName", processes.get(0).getName());
assertEquals("oneTaskProcessDescription", processes.get(0).getDescription());
ObjectNode infoNode = dynamicBpmnService.changeLocalizationName("en-GB", "oneTaskProcess", "The One Task Process 'en-GB' localized name");
dynamicBpmnService.changeLocalizationDescription("en-GB", "oneTaskProcess", "The One Task Process 'en-GB' localized description", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
dynamicBpmnService.changeLocalizationName("en", "oneTaskProcess", "The One Task Process 'en' localized name", infoNode);
dynamicBpmnService.changeLocalizationDescription("en", "oneTaskProcess", "The One Task Process 'en' localized description", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
processes = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).list();
assertEquals(1, processes.size());
assertEquals("oneTaskProcessName", processes.get(0).getName());
assertEquals("oneTaskProcessDescription", processes.get(0).getDescription());
processes = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).locale("en-GB").list();
assertEquals(1, processes.size());
assertEquals("The One Task Process 'en-GB' localized name", processes.get(0).getName());
assertEquals("The One Task Process 'en-GB' localized description", processes.get(0).getDescription());
processes = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).listPage(0, 10);
assertEquals(1, processes.size());
assertEquals("oneTaskProcessName", processes.get(0).getName());
assertEquals("oneTaskProcessDescription", processes.get(0).getDescription());
processes = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).locale("en-GB").listPage(0, 10);
assertEquals(1, processes.size());
assertEquals("The One Task Process 'en-GB' localized name", processes.get(0).getName());
assertEquals("The One Task Process 'en-GB' localized description", processes.get(0).getDescription());
processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("oneTaskProcessName", processInstance.getName());
assertEquals("oneTaskProcessDescription", processInstance.getDescription());
processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).locale("en-GB").singleResult();
assertEquals("The One Task Process 'en-GB' localized name", processInstance.getName());
assertEquals("The One Task Process 'en-GB' localized description", processInstance.getDescription());
processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("oneTaskProcessName", processInstance.getName());
assertEquals("oneTaskProcessDescription", processInstance.getDescription());
processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).locale("en").singleResult();
assertEquals("The One Task Process 'en' localized name", processInstance.getName());
assertEquals("The One Task Process 'en' localized description", processInstance.getDescription());
processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).locale("en-AU").withLocalizationFallback().singleResult();
assertEquals("The One Task Process 'en' localized name", processInstance.getName());
assertEquals("The One Task Process 'en' localized description", processInstance.getDescription());
}
}
......@@ -864,7 +864,7 @@ public class RuntimeServiceTest extends PluggableActivitiTestCase {
runtimeService.setProcessInstanceName(processInstance.getId(), null);
processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
assertNotNull(processInstance);
assertNull(processInstance.getName());
assertEquals("The One Task Process", processInstance.getName());
// Set name for unexisting process instance, should fail
try {
......@@ -876,7 +876,7 @@ public class RuntimeServiceTest extends PluggableActivitiTestCase {
processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
assertNotNull(processInstance);
assertNull(processInstance.getName());
assertEquals("The One Task Process", processInstance.getName());
// Set name for suspended process instance, should fail
runtimeService.suspendProcessInstanceById(processInstance.getId());
......@@ -889,7 +889,7 @@ public class RuntimeServiceTest extends PluggableActivitiTestCase {
processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
assertNotNull(processInstance);
assertNull(processInstance.getName());
assertEquals("The One Task Process", processInstance.getName());
}
private void startSignalCatchProcesses() {
......
......@@ -2515,8 +2515,12 @@ public class TaskQueryTest extends PluggableActivitiTestCase {
assertEquals("my task", tasks.get(0).getName());
assertNull(tasks.get(0).getDescription());
ObjectNode infoNode = dynamicBpmnService.changeLocalizationName("en-GB", "theTask", "My localized name");
dynamicBpmnService.changeLocalizationDescription("en-GB".toString(), "theTask", "My localized description", infoNode);
ObjectNode infoNode = dynamicBpmnService.changeLocalizationName("en-GB", "theTask", "My 'en-GB' localized name");
dynamicBpmnService.changeLocalizationDescription("en-GB", "theTask", "My 'en-GB' localized description", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
dynamicBpmnService.changeLocalizationName("en", "theTask", "My 'en' localized name", infoNode);
dynamicBpmnService.changeLocalizationDescription("en", "theTask", "My 'en' localized description", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode);
tasks = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).list();
......@@ -2526,8 +2530,8 @@ public class TaskQueryTest extends PluggableActivitiTestCase {
tasks = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-GB").list();
assertEquals(1, tasks.size());
assertEquals("My localized name", tasks.get(0).getName());
assertEquals("My localized description", tasks.get(0).getDescription());
assertEquals("My 'en-GB' localized name", tasks.get(0).getName());
assertEquals("My 'en-GB' localized description", tasks.get(0).getDescription());
tasks = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).listPage(0, 10);
assertEquals(1, tasks.size());
......@@ -2536,20 +2540,28 @@ public class TaskQueryTest extends PluggableActivitiTestCase {
tasks = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-GB").listPage(0, 10);
assertEquals(1, tasks.size());
assertEquals("My localized name", tasks.get(0).getName());
assertEquals("My localized description", tasks.get(0).getDescription());
assertEquals("My 'en-GB' localized name", tasks.get(0).getName());
assertEquals("My 'en-GB' localized description", tasks.get(0).getDescription());
Task task = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
assertEquals("my task", task.getName());
assertNull(task.getDescription());
task = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-GB").singleResult();
assertEquals("My localized name", task.getName());
assertEquals("My localized description", task.getDescription());
assertEquals("My 'en-GB' localized name", task.getName());
assertEquals("My 'en-GB' localized description", task.getDescription());
task = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
assertEquals("my task", task.getName());
assertNull(task.getDescription());
task = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en").singleResult();
assertEquals("My 'en' localized name", task.getName());
assertEquals("My 'en' localized description", task.getDescription());
task = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-AU").withLocalizationFallback().singleResult();
assertEquals("My 'en' localized name", task.getName());
assertEquals("My 'en' localized description", task.getDescription());
}
/**
......
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="historicProcessLocalization" name="Historic Process Name">
<documentation>Historic Process Description</documentation>
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="theProcessTask" />
<userTask id="theProcessTask" name="my process task" />
<sequenceFlow id="flow2" sourceRef="theProcessTask" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="org.activiti.enginge.test.api.runtime">
<process id="executionLocalization" name="Process Name">
<documentation>Process Description</documentation>
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="subProcess" />
<subProcess id="subProcess" name="SubProcess Name">
<documentation>SubProcess Description</documentation>
<startEvent id="subStart" />
<sequenceFlow id="flow3" sourceRef="subStart" targetRef="subTask" />
<userTask id="subTask" name="sub task" />
<sequenceFlow id="flow4" sourceRef="subTask" targetRef="subEnd" />
<endEvent id="subEnd" />
</subProcess>
<sequenceFlow id="flow5" sourceRef="subProcess" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
\ No newline at end of file
......@@ -5,6 +5,7 @@
targetNamespace="org.activiti.enginge.test.api.runtime">
<process id="oneTaskProcess" name="oneTaskProcessName">
<documentation>oneTaskProcessDescription</documentation>
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册