http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequest.java ---------------------------------------------------------------------- diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequest.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequest.java new file mode 100644 index 0000000..251eb89 --- /dev/null +++ b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequest.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.common.lib.to; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import org.apache.syncope.common.lib.AbstractBaseBean; + +@XmlRootElement(name = "userRequest") +@XmlType +public class UserRequest extends AbstractBaseBean { + + private static final long serialVersionUID = -8430826310789942133L; + + private String bpmnProcess; + + private String user; + + private String executionId; + + private String activityId; + + public String getBpmnProcess() { + return bpmnProcess; + } + + public void setBpmnProcess(final String bpmnProcess) { + this.bpmnProcess = bpmnProcess; + } + + public String getUser() { + return user; + } + + public void setUser(final String user) { + this.user = user; + } + + public String getExecutionId() { + return executionId; + } + + public void setExecutionId(final String executionId) { + this.executionId = executionId; + } + + public String getActivityId() { + return activityId; + } + + public void setActivityId(final String activityId) { + this.activityId = activityId; + } +}
http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestForm.java ---------------------------------------------------------------------- diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestForm.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestForm.java index 897cfc0..22118b5 100644 --- a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestForm.java +++ b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestForm.java @@ -37,8 +37,12 @@ public class UserRequestForm extends AbstractBaseBean { private static final long serialVersionUID = -7044543391316529128L; + private String bpmnProcess; + private String username; + private String executionId; + private String taskId; private String formKey; @@ -55,6 +59,14 @@ public class UserRequestForm extends AbstractBaseBean { private final List<UserRequestFormProperty> properties = new ArrayList<>(); + public String getBpmnProcess() { + return bpmnProcess; + } + + public void setBpmnProcess(final String bpmnProcess) { + this.bpmnProcess = bpmnProcess; + } + public String getUsername() { return username; } @@ -63,6 +75,14 @@ public class UserRequestForm extends AbstractBaseBean { this.username = username; } + public String getExecutionId() { + return executionId; + } + + public void setExecutionId(final String executionId) { + this.executionId = executionId; + } + public String getTaskId() { return taskId; } @@ -138,9 +158,9 @@ public class UserRequestForm extends AbstractBaseBean { return properties.stream().filter(property -> id.equals(property.getId())).findFirst(); } - @XmlElementWrapper(name = "workflowFormProperties") - @XmlElement(name = "workflowFormProperty") - @JsonProperty("workflowFormProperties") + @XmlElementWrapper(name = "properties") + @XmlElement(name = "property") + @JsonProperty("properties") public List<UserRequestFormProperty> getProperties() { return properties; } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestFormProperty.java ---------------------------------------------------------------------- diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestFormProperty.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestFormProperty.java index 0a431c6..95f2fec 100644 --- a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestFormProperty.java +++ b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestFormProperty.java @@ -51,6 +51,9 @@ public class UserRequestFormProperty extends AbstractBaseBean { @XmlJavaTypeAdapter(XmlGenericMapAdapter.class) private final Map<String, String> enumValues = new HashMap<>(); + @XmlJavaTypeAdapter(XmlGenericMapAdapter.class) + private final Map<String, String> dropdownValues = new HashMap<>(); + private String value; public String getId() { @@ -114,6 +117,11 @@ public class UserRequestFormProperty extends AbstractBaseBean { return enumValues; } + @JsonProperty + public Map<String, String> getDropdownValues() { + return dropdownValues; + } + public String getValue() { return value; } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestTO.java ---------------------------------------------------------------------- diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestTO.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestTO.java deleted file mode 100644 index d5fad6c..0000000 --- a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestTO.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.syncope.common.lib.to; - -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; -import org.apache.syncope.common.lib.AbstractBaseBean; - -@XmlRootElement(name = "userRequest") -@XmlType -public class UserRequestTO extends AbstractBaseBean { - - private static final long serialVersionUID = -8430826310789942133L; - - private String processInstanceId; - - private String executionId; - - private String bpmnProcess; - - private String user; - - public String getProcessInstanceId() { - return processInstanceId; - } - - public void setProcessInstanceId(final String processInstanceId) { - this.processInstanceId = processInstanceId; - } - - public String getExecutionId() { - return executionId; - } - - public void setExecutionId(final String executionId) { - this.executionId = executionId; - } - - public String getBpmnProcess() { - return bpmnProcess; - } - - public void setBpmnProcess(final String bpmnProcess) { - this.bpmnProcess = bpmnProcess; - } - - public String getUser() { - return user; - } - - public void setUser(final String user) { - this.user = user; - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/FlowableEntitlement.java ---------------------------------------------------------------------- diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/FlowableEntitlement.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/FlowableEntitlement.java index 43825a4..fbf5b02 100644 --- a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/FlowableEntitlement.java +++ b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/FlowableEntitlement.java @@ -36,19 +36,13 @@ public final class FlowableEntitlement { public static final String WORKFLOW_TASK_LIST = "WORKFLOW_TASK_LIST"; - public static final String WORKFLOW_FORM_LIST = "WORKFLOW_FORM_LIST"; + public static final String USER_REQUEST_LIST = "USER_REQUEST_LIST"; - public static final String WORKFLOW_FORM_READ = "WORKFLOW_FORM_READ"; + public static final String USER_REQUEST_FORM_LIST = "USER_REQUEST_FORM_LIST"; - public static final String WORKFLOW_FORM_CLAIM = "WORKFLOW_FORM_CLAIM"; + public static final String USER_REQUEST_FORM_CLAIM = "USER_REQUEST_FORM_CLAIM"; - public static final String WORKFLOW_FORM_SUBMIT = "WORKFLOW_FORM_SUBMIT"; - - public static final String USER_REQUEST_DEF_CREATE = "USER_REQUEST_DEF_CREATE"; - - public static final String USER_REQUEST_DEF_UPDATE = "USER_REQUEST_DEF_UPDATE"; - - public static final String USER_REQUEST_DEF_DELETE = "USER_REQUEST_DEF_DELETE"; + public static final String USER_REQUEST_FORM_SUBMIT = "USER_REQUEST_FORM_SUBMIT"; public static final String USER_REQUEST_START = "USER_REQUEST_START"; http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/UserRequestFormPropertyType.java ---------------------------------------------------------------------- diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/UserRequestFormPropertyType.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/UserRequestFormPropertyType.java index 9565f99..227296b 100644 --- a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/UserRequestFormPropertyType.java +++ b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/UserRequestFormPropertyType.java @@ -27,6 +27,7 @@ public enum UserRequestFormPropertyType { Long, Enum, Date, - Boolean + Boolean, + Dropdown } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/BpmnProcessManager.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/BpmnProcessManager.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/BpmnProcessManager.java index 9247fd4..f7d1747 100644 --- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/BpmnProcessManager.java +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/BpmnProcessManager.java @@ -20,7 +20,7 @@ package org.apache.syncope.core.flowable.api; import java.io.OutputStream; import java.util.List; -import org.apache.syncope.common.lib.to.BpmnProcessTO; +import org.apache.syncope.common.lib.to.BpmnProcess; import org.apache.syncope.common.lib.types.BpmnProcessFormat; public interface BpmnProcessManager { @@ -28,7 +28,7 @@ public interface BpmnProcessManager { /** * @return all available workflow processes. */ - List<BpmnProcessTO> getProcesses(); + List<BpmnProcess> getProcesses(); /** * Export the process for the given key, in the requested format. http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/DropdownValueProvider.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/DropdownValueProvider.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/DropdownValueProvider.java new file mode 100644 index 0000000..b6c79cf --- /dev/null +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/DropdownValueProvider.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.flowable.api; + +import java.util.Map; + +/** + * Implementations of this interface are used with {@link org.apache.syncope.core.flowable.support.DropdownFormType}. + */ +public interface DropdownValueProvider { + + String NAME = "dropdownValueProvider"; + + Map<String, String> getValues(); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java index b11b97c..c3c6f0d 100644 --- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java @@ -21,7 +21,7 @@ package org.apache.syncope.core.flowable.api; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.common.lib.patch.UserPatch; -import org.apache.syncope.common.lib.to.UserRequestTO; +import org.apache.syncope.common.lib.to.UserRequest; import org.apache.syncope.common.lib.to.UserRequestForm; import org.apache.syncope.core.persistence.api.dao.search.OrderByClause; import org.apache.syncope.core.persistence.api.entity.user.User; @@ -33,13 +33,25 @@ import org.springframework.transaction.event.TransactionalEventListener; public interface UserRequestHandler { /** + * Get the running user requests matching the provided parameters. + * + * @param userKey user key (optional) + * @param page result page + * @param size items per page + * @param orderByClauses sort conditions + * @return total number of user requests, list of user requests matching the provided parameters + */ + Pair<Integer, List<UserRequest>> getUserRequests( + String userKey, int page, int size, List<OrderByClause> orderByClauses); + + /** * Starts a new user request, for the given BPMN process and user. * * @param bpmnProcess BPMN process * @param user user * @return data about the started request service, including execution id */ - UserRequestTO start(String bpmnProcess, User user); + UserRequest start(String bpmnProcess, User user); /** * Parses the given execution id to find matching user request and owner. @@ -73,22 +85,16 @@ public interface UserRequestHandler { void cancelByUser(AnyDeletedEvent event); /** - * Get the forms for current workflow process instances matching the provided parameters. + * Get the forms matching the provided parameters. * + * @param userKey user key (optional) * @param page result page * @param size items per page * @param orderByClauses sort conditions * @return total number of forms, list of forms matching the provided parameters */ - Pair<Integer, List<UserRequestForm>> getForms(int page, int size, List<OrderByClause> orderByClauses); - - /** - * Get forms for given user (if present). - * - * @param userKey user key - * @return form (if present), otherwise null - */ - List<UserRequestForm> getForms(String userKey); + Pair<Integer, List<UserRequestForm>> getForms( + String userKey, int page, int size, List<OrderByClause> orderByClauses); /** * Claim a form for a given object. http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableBpmnProcessManager.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableBpmnProcessManager.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableBpmnProcessManager.java index bca8b25..50b078b 100644 --- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableBpmnProcessManager.java +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableBpmnProcessManager.java @@ -28,9 +28,10 @@ import java.io.OutputStream; import java.util.List; import java.util.stream.Collectors; import org.apache.commons.io.IOUtils; -import org.apache.syncope.common.lib.to.BpmnProcessTO; +import org.apache.syncope.common.lib.to.BpmnProcess; import org.apache.syncope.common.lib.types.BpmnProcessFormat; import org.apache.syncope.core.flowable.support.DomainProcessEngine; +import org.apache.syncope.core.flowable.support.DropdownAwareJsonConverter; import org.apache.syncope.core.persistence.api.dao.NotFoundException; import org.apache.syncope.core.workflow.api.WorkflowException; import org.flowable.bpmn.converter.BpmnXMLConverter; @@ -73,11 +74,11 @@ public class FlowableBpmnProcessManager implements BpmnProcessManager { } @Override - public List<BpmnProcessTO> getProcesses() { + public List<BpmnProcess> getProcesses() { try { return engine.getRepositoryService().createProcessDefinitionQuery().latestVersion().list().stream(). map(procDef -> { - BpmnProcessTO defTO = new BpmnProcessTO(); + BpmnProcess defTO = new BpmnProcess(); defTO.setKey(procDef.getKey()); defTO.setName(procDef.getName()); @@ -163,7 +164,7 @@ public class FlowableBpmnProcessManager implements BpmnProcessManager { "Could not find JSON node " + BpmnJsonConverter.EDITOR_CHILD_SHAPES); } - BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(definitionNode); + BpmnModel bpmnModel = new DropdownAwareJsonConverter().convertToBpmnModel(definitionNode); deployment = FlowableDeployUtils.deployDefinition( engine, resourceName, http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableRuntimeUtils.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableRuntimeUtils.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableRuntimeUtils.java index 12d8faa..cdf035d 100644 --- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableRuntimeUtils.java +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableRuntimeUtils.java @@ -22,6 +22,7 @@ import java.util.Base64; import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.common.lib.SyncopeClientException; import org.apache.syncope.common.lib.to.UserTO; import org.apache.syncope.core.flowable.support.DomainProcessEngine; @@ -33,7 +34,6 @@ import org.apache.syncope.core.workflow.api.WorkflowException; import org.flowable.common.engine.api.FlowableException; import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.impl.RuntimeServiceImpl; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; @@ -97,8 +97,17 @@ public final class FlowableRuntimeUtils { return procInst == null ? null : procInst.getId(); } - public static String getProcBusinessKey(final String processDefinitionId, final String userKey) { - return processDefinitionId + ":" + userKey; + public static String getProcBusinessKey(final String procDefId, final String userKey) { + return procDefId + ":" + userKey; + } + + public static Pair<String, String> splitProcBusinessKey(final String procBusinessKey) { + String[] split = procBusinessKey.split(":"); + if (split == null || split.length != 2) { + throw new WorkflowException(new IllegalArgumentException("Unexpected business key: " + procBusinessKey)); + } + + return Pair.of(split[0], split[1]); } public static ProcessDefinition getLatestProcDefByKey(final DomainProcessEngine engine, final String key) { @@ -111,17 +120,17 @@ public final class FlowableRuntimeUtils { } public static Set<String> getPerformedTasks( - final DomainProcessEngine engine, final String procInstID, final User user) { + final DomainProcessEngine engine, final String procInstId, final User user) { return engine.getHistoryService().createHistoricActivityInstanceQuery(). - executionId(procInstID). + executionId(procInstId). list().stream(). map(HistoricActivityInstance::getActivityId). collect(Collectors.toSet()); } - public static void updateStatus(final DomainProcessEngine engine, final String procInstID, final User user) { - List<Task> tasks = createTaskQuery(engine, false).processInstanceId(procInstID).list(); + public static void updateStatus(final DomainProcessEngine engine, final String procInstId, final User user) { + List<Task> tasks = createTaskQuery(engine, false).processInstanceId(procInstId).list(); if (tasks.isEmpty() || tasks.size() > 1) { LOG.warn("While setting user status: unexpected task number ({})", tasks.size()); } else { @@ -129,13 +138,6 @@ public final class FlowableRuntimeUtils { } } - public static List<ProcessInstance> getProcessInstances(final DomainProcessEngine engine, final String userKey) { - return engine.getRuntimeService().createNativeProcessInstanceQuery(). - sql("SELECT ID_,PROC_INST_ID_ FROM " + engine.getManagementService().getTableName(ExecutionEntity.class) - + " WHERE BUSINESS_KEY_ LIKE '" + getProcBusinessKey("%", userKey) + "'" - + " AND PARENT_ID_ IS NULL").list(); - } - public static TaskQuery createTaskQuery(final DomainProcessEngine engine, final boolean onlyFormTasks) { SyncopeTaskQueryImpl taskQuery = new SyncopeTaskQueryImpl( ((RuntimeServiceImpl) engine.getRuntimeService()).getCommandExecutor()); @@ -145,10 +147,10 @@ public final class FlowableRuntimeUtils { return taskQuery; } - public static String getFormTask(final DomainProcessEngine engine, final String procInstID) { + public static String getFormTask(final DomainProcessEngine engine, final String procInstId) { String result = null; - List<Task> tasks = createTaskQuery(engine, true).processInstanceId(procInstID).list(); + List<Task> tasks = createTaskQuery(engine, true).processInstanceId(procInstId).list(); if (tasks.isEmpty() || tasks.size() > 1) { LOG.debug("While checking if form task: unexpected task number ({})", tasks.size()); } else { @@ -162,7 +164,7 @@ public final class FlowableRuntimeUtils { * Saves resources to be propagated and password for later - after form submission - propagation. * * @param engine Flowable engine - * @param procInstID process instance id + * @param procInstId process instance id * @param user user JPA entity * @param userTO user transfer object * @param password password @@ -171,35 +173,35 @@ public final class FlowableRuntimeUtils { */ public static void saveForFormSubmit( final DomainProcessEngine engine, - final String procInstID, + final String procInstId, final User user, final UserTO userTO, final String password, final Boolean enabled, final PropagationByResource propByRes) { - String formTaskId = getFormTask(engine, procInstID); + String formTaskId = getFormTask(engine, procInstId); if (formTaskId == null) { return; } - engine.getRuntimeService().setVariable(procInstID, FlowableRuntimeUtils.USER_TO, userTO); + engine.getRuntimeService().setVariable(procInstId, FlowableRuntimeUtils.USER_TO, userTO); if (password == null) { String encryptedPwd = engine.getRuntimeService(). - getVariable(procInstID, FlowableRuntimeUtils.ENCRYPTED_PWD, String.class); + getVariable(procInstId, FlowableRuntimeUtils.ENCRYPTED_PWD, String.class); if (encryptedPwd != null) { userTO.setPassword(decrypt(encryptedPwd)); } } else { userTO.setPassword(password); engine.getRuntimeService(). - setVariable(procInstID, FlowableRuntimeUtils.ENCRYPTED_PWD, encrypt(password)); + setVariable(procInstId, FlowableRuntimeUtils.ENCRYPTED_PWD, encrypt(password)); } - engine.getRuntimeService().setVariable(procInstID, FlowableRuntimeUtils.ENABLED, enabled); + engine.getRuntimeService().setVariable(procInstId, FlowableRuntimeUtils.ENABLED, enabled); - engine.getRuntimeService().setVariable(procInstID, FlowableRuntimeUtils.PROP_BY_RESOURCE, propByRes); + engine.getRuntimeService().setVariable(procInstId, FlowableRuntimeUtils.PROP_BY_RESOURCE, propByRes); if (propByRes != null) { propByRes.clear(); } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java index 1c198a8..45a834b 100644 --- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java @@ -31,13 +31,14 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.common.lib.patch.PasswordPatch; import org.apache.syncope.common.lib.patch.UserPatch; -import org.apache.syncope.common.lib.to.UserRequestTO; +import org.apache.syncope.common.lib.to.UserRequest; import org.apache.syncope.common.lib.to.UserTO; import org.apache.syncope.common.lib.to.UserRequestFormProperty; import org.apache.syncope.common.lib.to.UserRequestForm; import org.apache.syncope.common.lib.types.AnyTypeKind; import org.apache.syncope.common.lib.types.ResourceOperation; import org.apache.syncope.common.lib.types.UserRequestFormPropertyType; +import org.apache.syncope.core.flowable.api.DropdownValueProvider; import org.apache.syncope.core.flowable.api.WorkflowTaskManager; import org.apache.syncope.core.flowable.support.DomainProcessEngine; import org.apache.syncope.core.persistence.api.dao.NotFoundException; @@ -49,16 +50,21 @@ import org.apache.syncope.core.provisioning.api.PropagationByResource; import org.apache.syncope.core.provisioning.api.WorkflowResult; import org.apache.syncope.core.provisioning.api.data.UserDataBinder; import org.apache.syncope.core.provisioning.api.event.AnyDeletedEvent; +import org.apache.syncope.core.spring.ApplicationContextProvider; import org.apache.syncope.core.spring.BeanUtils; import org.apache.syncope.core.spring.security.AuthContextUtils; import org.apache.syncope.core.workflow.api.WorkflowException; import org.flowable.common.engine.api.FlowableException; +import org.flowable.common.engine.api.FlowableIllegalArgumentException; import org.flowable.engine.form.FormProperty; import org.flowable.engine.form.FormType; import org.flowable.engine.form.TaskFormData; import org.flowable.engine.history.HistoricActivityInstance; +import org.flowable.engine.impl.persistence.entity.ExecutionEntity; import org.flowable.engine.impl.persistence.entity.HistoricFormPropertyEntity; +import org.flowable.engine.runtime.NativeProcessInstanceQuery; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.engine.runtime.ProcessInstanceQuery; import org.flowable.task.api.Task; import org.flowable.task.api.TaskQuery; import org.flowable.task.api.history.HistoricTaskInstance; @@ -93,6 +99,93 @@ public class FlowableUserRequestHandler implements UserRequestHandler { @Autowired protected EntityFactory entityFactory; + protected NativeProcessInstanceQuery createProcessInstanceQuery(final String userKey) { + return engine.getRuntimeService().createNativeProcessInstanceQuery(). + sql("SELECT DISTINCT ID_,BUSINESS_KEY_,ACT_ID_ FROM " + + engine.getManagementService().getTableName(ExecutionEntity.class) + + " WHERE BUSINESS_KEY_ LIKE '" + + FlowableRuntimeUtils.getProcBusinessKey("%", userKey) + "'" + + " AND BUSINESS_KEY_ NOT LIKE '" + + FlowableRuntimeUtils.getProcBusinessKey(FlowableRuntimeUtils.WF_PROCESS_ID, "%") + "'" + + " AND PARENT_ID_ IS NULL"); + } + + protected int countProcessInstances(final String userKey) { + return (int) engine.getRuntimeService().createNativeProcessInstanceQuery(). + sql("SELECT COUNT(ID_) FROM " + + engine.getManagementService().getTableName(ExecutionEntity.class) + + " WHERE BUSINESS_KEY_ LIKE '" + + FlowableRuntimeUtils.getProcBusinessKey("%", userKey) + "'" + + " AND BUSINESS_KEY_ NOT LIKE '" + + FlowableRuntimeUtils.getProcBusinessKey(FlowableRuntimeUtils.WF_PROCESS_ID, "%") + "'" + + " AND PARENT_ID_ IS NULL").count(); + } + + protected UserRequest getUserRequest(final ProcessInstance procInst) { + Pair<String, String> split = FlowableRuntimeUtils.splitProcBusinessKey(procInst.getBusinessKey()); + + UserRequest userRequest = new UserRequest(); + userRequest.setBpmnProcess(split.getLeft()); + userRequest.setUser(split.getRight()); + userRequest.setExecutionId(procInst.getId()); + userRequest.setActivityId(procInst.getActivityId()); + return userRequest; + } + + @Transactional(readOnly = true) + @Override + public Pair<Integer, List<UserRequest>> getUserRequests( + final String userKey, + final int page, + final int size, + final List<OrderByClause> orderByClauses) { + + Integer count = null; + List<UserRequest> result = null; + if (userKey == null) { + ProcessInstanceQuery query = engine.getRuntimeService().createProcessInstanceQuery().active(); + for (OrderByClause clause : orderByClauses) { + boolean sorted = true; + switch (clause.getField().trim()) { + case "processDefinitionId": + query.orderByProcessDefinitionId(); + break; + + case "processDefinitionKey": + query.orderByProcessDefinitionKey(); + break; + + case "processInstanceId": + query.orderByProcessInstanceId(); + break; + + default: + LOG.warn("User request sort request by {}: unsupported, ignoring", clause.getField().trim()); + sorted = false; + } + if (sorted) { + if (clause.getDirection() == OrderByClause.Direction.ASC) { + query.asc(); + } else { + query.desc(); + } + } + + count = (int) query.count(); + result = query.listPage(size * (page <= 0 ? 0 : page - 1), size).stream(). + map(procInst -> getUserRequest(procInst)). + collect(Collectors.toList()); + } + } else { + count = countProcessInstances(userKey); + result = createProcessInstanceQuery(userKey).listPage(size * (page <= 0 ? 0 : page - 1), size).stream(). + map(procInst -> getUserRequest(procInst)). + collect(Collectors.toList()); + } + + return Pair.of(count, result); + } + protected User lazyLoad(final User user) { // using BeanUtils to access all user's properties and trigger lazy loading - we are about to // serialize a User instance for availability within workflow tasks, and this breaks transactions @@ -101,8 +194,8 @@ public class FlowableUserRequestHandler implements UserRequestHandler { } @Override - public UserRequestTO start(final String bpmnProcess, final User user) { - Map<String, Object> variables = new HashMap<>(2); + public UserRequest start(final String bpmnProcess, final User user) { + Map<String, Object> variables = new HashMap<>(); variables.put(FlowableRuntimeUtils.WF_EXECUTOR, AuthContextUtils.getUsername()); variables.put(FlowableRuntimeUtils.USER, lazyLoad(user)); variables.put(FlowableRuntimeUtils.USER_TO, dataBinder.getUserTO(user, true)); @@ -118,12 +211,8 @@ public class FlowableUserRequestHandler implements UserRequestHandler { procInst.getProcessInstanceId(), FlowableRuntimeUtils.getProcBusinessKey(bpmnProcess, user.getKey())); - UserRequestTO userRequestTO = new UserRequestTO(); - userRequestTO.setProcessInstanceId(procInst.getProcessInstanceId()); - userRequestTO.setExecutionId(procInst.getId()); - userRequestTO.setBpmnProcess(bpmnProcess); - userRequestTO.setUser(user.getKey()); - return userRequestTO; + return getUserRequest(engine.getRuntimeService().createProcessInstanceQuery(). + processInstanceId(procInst.getProcessInstanceId()).singleResult()); } @Override @@ -132,7 +221,11 @@ public class FlowableUserRequestHandler implements UserRequestHandler { try { procInst = engine.getRuntimeService(). createProcessInstanceQuery().processInstanceId(executionId).singleResult(); + if (procInst == null) { + throw new FlowableIllegalArgumentException("ProcessInstance with id " + executionId); + } } catch (FlowableException e) { + LOG.error("Could find execution ProcessInstance with id {}", executionId, e); throw new NotFoundException("User request execution with id " + executionId); } @@ -163,7 +256,7 @@ public class FlowableUserRequestHandler implements UserRequestHandler { public void cancelByUser(final AnyDeletedEvent event) { if (AuthContextUtils.getDomain().equals(event.getDomain()) && event.getAnyTypeKind() == AnyTypeKind.USER) { String username = event.getAnyName(); - FlowableRuntimeUtils.getProcessInstances(engine, event.getAnyKey()). + createProcessInstanceQuery(event.getAnyKey()).list(). forEach(procInst -> { engine.getRuntimeService().deleteProcessInstance( procInst.getId(), "Cascade Delete user " + username); @@ -192,6 +285,10 @@ public class FlowableUserRequestHandler implements UserRequestHandler { result = UserRequestFormPropertyType.Boolean; break; + case "dropdown": + result = UserRequestFormPropertyType.Dropdown; + break; + case "string": default: break; @@ -201,19 +298,19 @@ public class FlowableUserRequestHandler implements UserRequestHandler { return result; } - protected UserRequestForm getFormTO(final Task task) { - return getFormTO(task, engine.getFormService().getTaskFormData(task.getId())); + protected UserRequestForm getForm(final Task task) { + return FlowableUserRequestHandler.this.getForm(task, engine.getFormService().getTaskFormData(task.getId())); } - protected UserRequestForm getFormTO(final Task task, final TaskFormData fd) { + protected UserRequestForm getForm(final Task task, final TaskFormData fd) { UserRequestForm formTO = - getFormTO(task.getProcessInstanceId(), task.getId(), fd.getFormKey(), fd.getFormProperties()); + getForm(task.getProcessInstanceId(), task.getId(), fd.getFormKey(), fd.getFormProperties()); BeanUtils.copyProperties(task, formTO); return formTO; } - protected UserRequestForm getFormTO(final HistoricTaskInstance task) { + protected UserRequestForm getForm(final HistoricTaskInstance task) { List<HistoricFormPropertyEntity> props = engine.getHistoryService(). createHistoricDetailQuery().taskId(task.getId()).list().stream(). filter(HistoricFormPropertyEntity.class::isInstance). @@ -244,16 +341,19 @@ public class FlowableUserRequestHandler implements UserRequestHandler { } protected UserRequestForm getHistoricFormTO( - final String procInstID, + final String procInstId, final String taskId, final String formKey, final List<HistoricFormPropertyEntity> props) { UserRequestForm formTO = new UserRequestForm(); - User user = userDAO.find(getUserKey(procInstID)); + formTO.setBpmnProcess(engine.getRuntimeService().createProcessInstanceQuery(). + processInstanceId(procInstId).singleResult().getProcessDefinitionKey()); + + User user = userDAO.find(getUserKey(procInstId)); if (user == null) { - throw new NotFoundException("User for process instance id " + procInstID); + throw new NotFoundException("User for process instance id " + procInstId); } formTO.setUsername(user.getUsername()); @@ -261,9 +361,9 @@ public class FlowableUserRequestHandler implements UserRequestHandler { formTO.setFormKey(formKey); formTO.setUserTO(engine.getRuntimeService(). - getVariable(procInstID, FlowableRuntimeUtils.USER_TO, UserTO.class)); + getVariable(procInstId, FlowableRuntimeUtils.USER_TO, UserTO.class)); formTO.setUserPatch(engine.getRuntimeService(). - getVariable(procInstID, FlowableRuntimeUtils.USER_PATCH, UserPatch.class)); + getVariable(procInstId, FlowableRuntimeUtils.USER_PATCH, UserPatch.class)); formTO.getProperties().addAll(props.stream().map(prop -> { UserRequestFormProperty propertyTO = new UserRequestFormProperty(); @@ -277,37 +377,58 @@ public class FlowableUserRequestHandler implements UserRequestHandler { } @SuppressWarnings("unchecked") - protected UserRequestForm getFormTO( - final String procInstID, + protected UserRequestForm getForm( + final String procInstId, final String taskId, final String formKey, final List<FormProperty> props) { UserRequestForm formTO = new UserRequestForm(); - User user = userDAO.find(getUserKey(procInstID)); + formTO.setBpmnProcess(engine.getRuntimeService().createProcessInstanceQuery(). + processInstanceId(procInstId).singleResult().getProcessDefinitionKey()); + + User user = userDAO.find(getUserKey(procInstId)); if (user == null) { - throw new NotFoundException("User for process instance id " + procInstID); + throw new NotFoundException("User for process instance id " + procInstId); } formTO.setUsername(user.getUsername()); + formTO.setExecutionId(procInstId); formTO.setTaskId(taskId); formTO.setFormKey(formKey); formTO.setUserTO(engine.getRuntimeService(). - getVariable(procInstID, FlowableRuntimeUtils.USER_TO, UserTO.class)); + getVariable(procInstId, FlowableRuntimeUtils.USER_TO, UserTO.class)); formTO.setUserPatch(engine.getRuntimeService(). - getVariable(procInstID, FlowableRuntimeUtils.USER_PATCH, UserPatch.class)); + getVariable(procInstId, FlowableRuntimeUtils.USER_PATCH, UserPatch.class)); formTO.getProperties().addAll(props.stream().map(fProp -> { UserRequestFormProperty propertyTO = new UserRequestFormProperty(); BeanUtils.copyProperties(fProp, propertyTO, PROPERTY_IGNORE_PROPS); propertyTO.setType(fromFlowableFormType(fProp.getType())); - if (propertyTO.getType() == UserRequestFormPropertyType.Date) { - propertyTO.setDatePattern((String) fProp.getType().getInformation("datePattern")); - } - if (propertyTO.getType() == UserRequestFormPropertyType.Enum) { - propertyTO.getEnumValues().putAll((Map<String, String>) fProp.getType().getInformation("values")); + switch (propertyTO.getType()) { + case Date: + propertyTO.setDatePattern((String) fProp.getType().getInformation("datePattern")); + break; + + case Enum: + propertyTO.getEnumValues().putAll((Map<String, String>) fProp.getType().getInformation("values")); + break; + + case Dropdown: + String valueProviderBean = (String) fProp.getType().getInformation(DropdownValueProvider.NAME); + try { + DropdownValueProvider valueProvider = ApplicationContextProvider.getApplicationContext(). + getBean(valueProviderBean, DropdownValueProvider.class); + propertyTO.getDropdownValues().putAll(valueProvider.getValues()); + } catch (Exception e) { + LOG.error("Could not find bean {} of type {} for form property {}", + valueProviderBean, DropdownValueProvider.class.getName(), propertyTO.getId(), e); + } + break; + + default: } return propertyTO; }).collect(Collectors.toList())); @@ -318,26 +439,28 @@ public class FlowableUserRequestHandler implements UserRequestHandler { @Transactional(readOnly = true) @Override public Pair<Integer, List<UserRequestForm>> getForms( - final int page, final int size, final List<OrderByClause> orderByClauses) { + final String userKey, + final int page, + final int size, + final List<OrderByClause> orderByClauses) { - Pair<Integer, List<UserRequestForm>> forms = null; + Pair<Integer, List<UserRequestForm>> forms; - TaskQuery formTaskQuery = FlowableRuntimeUtils.createTaskQuery(engine, true); + TaskQuery query = FlowableRuntimeUtils.createTaskQuery(engine, true); + if (userKey != null) { + query.processInstanceBusinessKeyLike(FlowableRuntimeUtils.getProcBusinessKey("%", userKey)); + } String authUser = AuthContextUtils.getUsername(); if (adminUser.equals(authUser)) { - forms = getForms(formTaskQuery, page, size, orderByClauses); + forms = getForms(query, page, size, orderByClauses); } else { User user = userDAO.findByUsername(authUser); - if (user == null) { - throw new NotFoundException("Syncope User " + authUser); - } - - forms = getForms(formTaskQuery.taskCandidateOrAssigned(user.getUsername()), page, size, orderByClauses); + forms = getForms(query.taskCandidateOrAssigned(user.getUsername()), page, size, orderByClauses); List<String> candidateGroups = new ArrayList<>(userDAO.findAllGroupNames(user)); if (!candidateGroups.isEmpty()) { - forms = getForms(formTaskQuery.taskCandidateGroupIn(candidateGroups), page, size, orderByClauses); + forms = getForms(query.taskCandidateGroupIn(candidateGroups), page, size, orderByClauses); } } @@ -349,75 +472,56 @@ public class FlowableUserRequestHandler implements UserRequestHandler { protected Pair<Integer, List<UserRequestForm>> getForms( final TaskQuery query, final int page, final int size, final List<OrderByClause> orderByClauses) { - TaskQuery sortedQuery = query; for (OrderByClause clause : orderByClauses) { - boolean ack = true; + boolean sorted = true; switch (clause.getField().trim()) { + case "bpmnProcess": + query.orderByProcessDefinitionId(); + break; + + case "executionId": + query.orderByExecutionId(); + break; + case "taskId": - sortedQuery = sortedQuery.orderByTaskId(); + query.orderByTaskId(); break; case "createTime": - sortedQuery = sortedQuery.orderByTaskCreateTime(); + query.orderByTaskCreateTime(); break; case "dueDate": - sortedQuery = sortedQuery.orderByTaskDueDate(); + query.orderByTaskDueDate(); break; case "owner": - sortedQuery = sortedQuery.orderByTaskOwner(); + query.orderByTaskOwner(); break; default: LOG.warn("Form sort request by {}: unsupported, ignoring", clause.getField().trim()); - ack = false; + sorted = false; } - if (ack) { - sortedQuery = clause.getDirection() == OrderByClause.Direction.ASC - ? sortedQuery.asc() - : sortedQuery.desc(); + if (sorted) { + if (clause.getDirection() == OrderByClause.Direction.ASC) { + query.asc(); + } else { + query.desc(); + } } } - List<UserRequestForm> result = sortedQuery.listPage(size * (page <= 0 ? 0 : page - 1), size).stream(). + List<UserRequestForm> result = query.listPage(size * (page <= 0 ? 0 : page - 1), size).stream(). map(task -> task instanceof HistoricTaskInstance - ? getFormTO((HistoricTaskInstance) task) : getFormTO(task)). + ? FlowableUserRequestHandler.this.getForm((HistoricTaskInstance) task) + : FlowableUserRequestHandler.this.getForm(task)). collect(Collectors.toList()); return Pair.of((int) query.count(), result); } - @Override - public List<UserRequestForm> getForms(final String userKey) { - List<UserRequestForm> result = new ArrayList<>(); - FlowableRuntimeUtils.getProcessInstances(engine, userKey).forEach(procInst -> { - Task task; - try { - task = FlowableRuntimeUtils.createTaskQuery(engine, true). - processInstanceId(procInst.getProcessInstanceId()).singleResult(); - } catch (FlowableException e) { - throw new WorkflowException("While reading form for process instance " - + procInst.getProcessInstanceId(), e); - } - - if (task != null) { - TaskFormData formData; - try { - formData = engine.getFormService().getTaskFormData(task.getId()); - } catch (FlowableException e) { - throw new WorkflowException("Error while getting form data for task " + task.getId(), e); - } - if (formData != null && !formData.getFormProperties().isEmpty()) { - result.add(getFormTO(task, formData)); - } - } - }); - - return result; - } - - protected Pair<Task, TaskFormData> checkTask(final String taskId, final String authUser) { + protected Pair<Task, TaskFormData> parseTask(final String taskId) { Task task; try { task = FlowableRuntimeUtils.createTaskQuery(engine, true).taskId(taskId).singleResult(); @@ -435,27 +539,20 @@ public class FlowableUserRequestHandler implements UserRequestHandler { throw new NotFoundException("Form for Flowable Task " + taskId, e); } - if (!adminUser.equals(authUser)) { - User user = userDAO.findByUsername(authUser); - if (user == null) { - throw new NotFoundException("Syncope User " + authUser); - } - } - return Pair.of(task, formData); } @Override public UserRequestForm claimForm(final String taskId) { - String authUser = AuthContextUtils.getUsername(); - Pair<Task, TaskFormData> checked = checkTask(taskId, authUser); + Pair<Task, TaskFormData> parsed = parseTask(taskId); + String authUser = AuthContextUtils.getUsername(); if (!adminUser.equals(authUser)) { List<Task> tasksForUser = FlowableRuntimeUtils.createTaskQuery(engine, true). - taskId(taskId).taskCandidateUser(authUser).list(); + taskId(taskId).taskCandidateOrAssigned(authUser).list(); if (tasksForUser.isEmpty()) { throw new WorkflowException( - new IllegalArgumentException(authUser + " is not candidate for task " + taskId)); + new IllegalArgumentException(authUser + " is not candidate nor assignee of task " + taskId)); } } @@ -467,7 +564,7 @@ public class FlowableUserRequestHandler implements UserRequestHandler { throw new WorkflowException("While reading task " + taskId, e); } - return getFormTO(task, checked.getRight()); + return FlowableUserRequestHandler.this.getForm(task, parsed.getRight()); } private Map<String, String> getPropertiesForSubmit(final UserRequestForm form) { @@ -482,36 +579,36 @@ public class FlowableUserRequestHandler implements UserRequestHandler { @Override public WorkflowResult<UserPatch> submitForm(final UserRequestForm form) { - String authUser = AuthContextUtils.getUsername(); - Pair<Task, TaskFormData> checked = checkTask(form.getTaskId(), authUser); + Pair<Task, TaskFormData> parsed = parseTask(form.getTaskId()); - if (!checked.getLeft().getOwner().equals(authUser)) { + String authUser = AuthContextUtils.getUsername(); + if (!parsed.getLeft().getOwner().equals(authUser)) { throw new WorkflowException(new IllegalArgumentException("Task " + form.getTaskId() + " assigned to " - + checked.getLeft().getOwner() + " but submitted by " + authUser)); + + parsed.getLeft().getOwner() + " but submitted by " + authUser)); } - String procInstID = checked.getLeft().getProcessInstanceId(); + String procInstId = parsed.getLeft().getProcessInstanceId(); - User user = userDAO.find(getUserKey(procInstID)); + User user = userDAO.find(getUserKey(procInstId)); if (user == null) { - throw new NotFoundException("User with key " + getUserKey(procInstID)); + throw new NotFoundException("User with key " + getUserKey(procInstId)); } - Set<String> preTasks = FlowableRuntimeUtils.getPerformedTasks(engine, procInstID, user); + Set<String> preTasks = FlowableRuntimeUtils.getPerformedTasks(engine, procInstId, user); - engine.getRuntimeService().setVariable(procInstID, FlowableRuntimeUtils.TASK, "submit"); - engine.getRuntimeService().setVariable(procInstID, FlowableRuntimeUtils.FORM_SUBMITTER, authUser); - engine.getRuntimeService().setVariable(procInstID, FlowableRuntimeUtils.USER, lazyLoad(user)); + engine.getRuntimeService().setVariable(procInstId, FlowableRuntimeUtils.TASK, "submit"); + engine.getRuntimeService().setVariable(procInstId, FlowableRuntimeUtils.FORM_SUBMITTER, authUser); + engine.getRuntimeService().setVariable(procInstId, FlowableRuntimeUtils.USER, lazyLoad(user)); try { engine.getFormService().submitTaskFormData(form.getTaskId(), getPropertiesForSubmit(form)); } catch (FlowableException e) { FlowableRuntimeUtils.throwException(e, "While submitting form for task " + form.getTaskId()); } - Set<String> postTasks = FlowableRuntimeUtils.getPerformedTasks(engine, procInstID, user); + Set<String> postTasks = FlowableRuntimeUtils.getPerformedTasks(engine, procInstId, user); postTasks.removeAll(preTasks); postTasks.add(form.getTaskId()); - if (procInstID.equals(FlowableRuntimeUtils.getWFProcInstID(engine, user.getKey()))) { - FlowableRuntimeUtils.updateStatus(engine, procInstID, user); + if (procInstId.equals(FlowableRuntimeUtils.getWFProcInstID(engine, user.getKey()))) { + FlowableRuntimeUtils.updateStatus(engine, procInstId, user); } user = userDAO.save(user); @@ -521,34 +618,34 @@ public class FlowableUserRequestHandler implements UserRequestHandler { PropagationByResource propByRes = null; ProcessInstance afterSubmitPI = engine.getRuntimeService(). - createProcessInstanceQuery().processInstanceId(procInstID).singleResult(); + createProcessInstanceQuery().processInstanceId(procInstId).singleResult(); if (afterSubmitPI != null) { - engine.getRuntimeService().removeVariable(procInstID, FlowableRuntimeUtils.TASK); - engine.getRuntimeService().removeVariable(procInstID, FlowableRuntimeUtils.FORM_SUBMITTER); - engine.getRuntimeService().removeVariable(procInstID, FlowableRuntimeUtils.USER); - engine.getRuntimeService().removeVariable(procInstID, FlowableRuntimeUtils.USER_TO); + engine.getRuntimeService().removeVariable(procInstId, FlowableRuntimeUtils.TASK); + engine.getRuntimeService().removeVariable(procInstId, FlowableRuntimeUtils.FORM_SUBMITTER); + engine.getRuntimeService().removeVariable(procInstId, FlowableRuntimeUtils.USER); + engine.getRuntimeService().removeVariable(procInstId, FlowableRuntimeUtils.USER_TO); // see if there is any propagation to be done propByRes = engine.getRuntimeService(). - getVariable(procInstID, FlowableRuntimeUtils.PROP_BY_RESOURCE, PropagationByResource.class); - engine.getRuntimeService().removeVariable(procInstID, FlowableRuntimeUtils.PROP_BY_RESOURCE); + getVariable(procInstId, FlowableRuntimeUtils.PROP_BY_RESOURCE, PropagationByResource.class); + engine.getRuntimeService().removeVariable(procInstId, FlowableRuntimeUtils.PROP_BY_RESOURCE); // fetch - if available - the encrypted password String encryptedPwd = engine.getRuntimeService(). - getVariable(procInstID, FlowableRuntimeUtils.ENCRYPTED_PWD, String.class); - engine.getRuntimeService().removeVariable(procInstID, FlowableRuntimeUtils.ENCRYPTED_PWD); + getVariable(procInstId, FlowableRuntimeUtils.ENCRYPTED_PWD, String.class); + engine.getRuntimeService().removeVariable(procInstId, FlowableRuntimeUtils.ENCRYPTED_PWD); if (StringUtils.isNotBlank(encryptedPwd)) { clearPassword = FlowableRuntimeUtils.decrypt(encryptedPwd); } Boolean enabled = engine.getRuntimeService(). - getVariable(procInstID, FlowableRuntimeUtils.ENABLED, Boolean.class); - engine.getRuntimeService().removeVariable(procInstID, FlowableRuntimeUtils.ENABLED); + getVariable(procInstId, FlowableRuntimeUtils.ENABLED, Boolean.class); + engine.getRuntimeService().removeVariable(procInstId, FlowableRuntimeUtils.ENABLED); // supports approval chains FlowableRuntimeUtils.saveForFormSubmit( engine, - procInstID, + procInstId, user, dataBinder.getUserTO(user, true), clearPassword, @@ -556,8 +653,8 @@ public class FlowableUserRequestHandler implements UserRequestHandler { propByRes); userPatch = engine.getRuntimeService(). - getVariable(procInstID, FlowableRuntimeUtils.USER_PATCH, UserPatch.class); - engine.getRuntimeService().removeVariable(procInstID, FlowableRuntimeUtils.USER_PATCH); + getVariable(procInstId, FlowableRuntimeUtils.USER_PATCH, UserPatch.class); + engine.getRuntimeService().removeVariable(procInstId, FlowableRuntimeUtils.USER_PATCH); } if (userPatch == null) { userPatch = new UserPatch(); http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngineFactoryBean.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngineFactoryBean.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngineFactoryBean.java index 162b113..de2bbfe 100644 --- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngineFactoryBean.java +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngineFactoryBean.java @@ -18,13 +18,16 @@ */ package org.apache.syncope.core.flowable.support; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.sql.DataSource; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.ProcessEngine; import org.flowable.common.engine.impl.cfg.SpringBeanFactoryProxyMap; import org.flowable.common.engine.impl.interceptor.EngineConfigurationConstants; +import org.flowable.engine.form.AbstractFormType; import org.flowable.engine.impl.util.EngineServiceUtil; import org.flowable.idm.spring.SpringIdmEngineConfiguration; import org.flowable.spring.SpringExpressionManager; @@ -81,6 +84,9 @@ public class DomainProcessEngineFactoryBean EngineConfigurationConstants.KEY_IDM_ENGINE_CONFIG, ctx.getBean(SpringIdmEngineConfiguration.class)); } + List<AbstractFormType> customFormTypes = new ArrayList<>(); + customFormTypes.add(new DropdownFormType(null)); + conf.setCustomFormTypes(customFormTypes); engines.put(domain, conf.buildProcessEngine()); } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownAwareJsonConverter.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownAwareJsonConverter.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownAwareJsonConverter.java new file mode 100644 index 0000000..ad29e17 --- /dev/null +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownAwareJsonConverter.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.flowable.support; + +import org.flowable.bpmn.model.UserTask; +import org.flowable.editor.constants.StencilConstants; +import org.flowable.editor.language.json.converter.BpmnJsonConverter; + +public class DropdownAwareJsonConverter extends BpmnJsonConverter { + + public DropdownAwareJsonConverter() { + convertersToBpmnMap.put(StencilConstants.STENCIL_TASK_USER, DropdownAwareUserTaskJsonConverter.class); + convertersToJsonMap.put(UserTask.class, DropdownAwareUserTaskJsonConverter.class); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownAwareUserTaskJsonConverter.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownAwareUserTaskJsonConverter.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownAwareUserTaskJsonConverter.java new file mode 100644 index 0000000..838201c --- /dev/null +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownAwareUserTaskJsonConverter.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.flowable.support; + +import com.fasterxml.jackson.databind.JsonNode; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.flowable.bpmn.model.BaseElement; +import org.flowable.bpmn.model.FormProperty; +import org.flowable.bpmn.model.FormValue; +import org.flowable.bpmn.model.StartEvent; +import org.flowable.bpmn.model.UserTask; +import org.flowable.editor.language.json.converter.BpmnJsonConverterUtil; +import org.flowable.editor.language.json.converter.UserTaskJsonConverter; + +public class DropdownAwareUserTaskJsonConverter extends UserTaskJsonConverter { + + @Override + protected void convertJsonToFormProperties(final JsonNode objectNode, final BaseElement element) { + JsonNode formPropertiesNode = getProperty(PROPERTY_FORM_PROPERTIES, objectNode); + if (formPropertiesNode != null) { + formPropertiesNode = BpmnJsonConverterUtil.validateIfNodeIsTextual(formPropertiesNode); + JsonNode propertiesArray = formPropertiesNode.get("formProperties"); + if (propertiesArray != null) { + for (JsonNode formNode : propertiesArray) { + JsonNode formIdNode = formNode.get(PROPERTY_FORM_ID); + if (formIdNode != null && StringUtils.isNotEmpty(formIdNode.asText())) { + + FormProperty formProperty = new FormProperty(); + formProperty.setId(formIdNode.asText()); + formProperty.setName(getValueAsString(PROPERTY_FORM_NAME, formNode)); + formProperty.setType(getValueAsString(PROPERTY_FORM_TYPE, formNode)); + formProperty.setExpression(getValueAsString(PROPERTY_FORM_EXPRESSION, formNode)); + formProperty.setVariable(getValueAsString(PROPERTY_FORM_VARIABLE, formNode)); + + if ("date".equalsIgnoreCase(formProperty.getType())) { + formProperty.setDatePattern(getValueAsString(PROPERTY_FORM_DATE_PATTERN, formNode)); + + } else if ("enum".equalsIgnoreCase(formProperty.getType()) + || "dropdown".equalsIgnoreCase(formProperty.getType())) { + + JsonNode enumValuesNode = formNode.get(PROPERTY_FORM_ENUM_VALUES); + if (enumValuesNode != null) { + List<FormValue> formValueList = new ArrayList<>(); + for (JsonNode enumNode : enumValuesNode) { + if (enumNode.get(PROPERTY_FORM_ENUM_VALUES_ID) != null && !enumNode.get( + PROPERTY_FORM_ENUM_VALUES_ID).isNull() && enumNode.get( + PROPERTY_FORM_ENUM_VALUES_NAME) != null + && !enumNode.get(PROPERTY_FORM_ENUM_VALUES_NAME).isNull()) { + + FormValue formValue = new FormValue(); + formValue.setId(enumNode.get(PROPERTY_FORM_ENUM_VALUES_ID).asText()); + formValue.setName(enumNode.get(PROPERTY_FORM_ENUM_VALUES_NAME).asText()); + formValueList.add(formValue); + + } else if (enumNode.get("value") != null && !enumNode.get("value").isNull()) { + FormValue formValue = new FormValue(); + formValue.setId(enumNode.get("value").asText()); + formValue.setName(enumNode.get("value").asText()); + formValueList.add(formValue); + } + } + formProperty.setFormValues(formValueList); + } + } + + formProperty.setRequired(getValueAsBoolean(PROPERTY_FORM_REQUIRED, formNode)); + formProperty.setReadable(getValueAsBoolean(PROPERTY_FORM_READABLE, formNode)); + formProperty.setWriteable(getValueAsBoolean(PROPERTY_FORM_WRITABLE, formNode)); + + if (element instanceof StartEvent) { + ((StartEvent) element).getFormProperties().add(formProperty); + } else if (element instanceof UserTask) { + ((UserTask) element).getFormProperties().add(formProperty); + } + } + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownFormType.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownFormType.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownFormType.java new file mode 100644 index 0000000..6c612f6 --- /dev/null +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DropdownFormType.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.flowable.support; + +import org.flowable.engine.form.AbstractFormType; + +/** + * Extension to predefined Flowable form types relying on the provided + * {@link org.apache.syncope.core.flowable.api.DropdownValueProvider} bean to populate values. + */ +public class DropdownFormType extends AbstractFormType { + + private static final long serialVersionUID = -3549337216346168946L; + + protected final String dropdownValueProvider; + + public DropdownFormType(final String dropdownValueProvider) { + this.dropdownValueProvider = dropdownValueProvider; + } + + @Override + public String getName() { + return "dropdown"; + } + + @Override + public Object getInformation(final String key) { + if (key.equals("dropdownValueProvider")) { + return dropdownValueProvider; + } + return null; + } + + @Override + public Object convertFormValueToModelValue(final String propertyValue) { + return propertyValue; + } + + @Override + public String convertModelValueToFormValue(final Object modelValue) { + return modelValue == null ? null : modelValue.toString(); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/SyncopeFormHandlerHelper.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/SyncopeFormHandlerHelper.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/SyncopeFormHandlerHelper.java new file mode 100644 index 0000000..9f6e751 --- /dev/null +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/SyncopeFormHandlerHelper.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.flowable.support; + +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.UserTask; +import org.flowable.bpmn.model.Process; +import org.flowable.engine.impl.form.FormHandlerHelper; +import org.flowable.engine.impl.form.TaskFormHandler; +import org.flowable.engine.impl.persistence.entity.DeploymentEntity; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.engine.impl.util.ProcessDefinitionUtil; +import org.flowable.engine.repository.ProcessDefinition; + +/** + * Used to inject {@link SyncopeTaskFormHandler} rather than + * {@link org.flowable.engine.impl.form.DefaultTaskFormHandler}. + */ +public class SyncopeFormHandlerHelper extends FormHandlerHelper { + + @Override + public TaskFormHandler getTaskFormHandlder(final String procDefId, final String taskId) { + Process process = ProcessDefinitionUtil.getProcess(procDefId); + FlowElement flowElement = process.getFlowElement(taskId, true); + if (flowElement instanceof UserTask) { + UserTask userTask = (UserTask) flowElement; + + ProcessDefinition processDefinitionEntity = ProcessDefinitionUtil.getProcessDefinition(procDefId); + DeploymentEntity deploymentEntity = CommandContextUtil.getProcessEngineConfiguration(). + getDeploymentEntityManager().findById(processDefinitionEntity.getDeploymentId()); + + TaskFormHandler taskFormHandler = new SyncopeTaskFormHandler(); + taskFormHandler.parseConfiguration( + userTask.getFormProperties(), userTask.getFormKey(), deploymentEntity, processDefinitionEntity); + return taskFormHandler; + } + + return null; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/SyncopeTaskFormHandler.java ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/SyncopeTaskFormHandler.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/SyncopeTaskFormHandler.java new file mode 100644 index 0000000..69c5e50 --- /dev/null +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/SyncopeTaskFormHandler.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.syncope.core.flowable.support; + +import java.util.List; +import java.util.Optional; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.core.flowable.api.DropdownValueProvider; +import org.flowable.bpmn.model.FormProperty; +import org.flowable.common.engine.api.delegate.Expression; +import org.flowable.common.engine.impl.el.ExpressionManager; +import org.flowable.engine.form.AbstractFormType; +import org.flowable.engine.impl.form.DefaultTaskFormHandler; +import org.flowable.engine.impl.form.FormPropertyHandler; +import org.flowable.engine.impl.form.FormTypes; +import org.flowable.engine.impl.persistence.entity.DeploymentEntity; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.engine.repository.ProcessDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Extends {@link DefaultTaskFormHandler} with purpose of supporting more form types than Flowable's default. + */ +public class SyncopeTaskFormHandler extends DefaultTaskFormHandler { + + private static final long serialVersionUID = -5271243544388455797L; + + protected static final Logger LOG = LoggerFactory.getLogger(SyncopeTaskFormHandler.class); + + protected Optional<AbstractFormType> parseFormPropertyType( + final FormProperty formProperty, final ExpressionManager expressionManager) { + + AbstractFormType formType = null; + + switch (formProperty.getType()) { + case "dropdown": + if (formProperty.getFormValues().isEmpty() + || !DropdownValueProvider.NAME.equals(formProperty.getFormValues().get(0).getId())) { + + LOG.warn("A single value with id '" + DropdownValueProvider.NAME + "' was expected, ignoring"); + } else { + formType = new DropdownFormType(formProperty.getFormValues().get(0).getName()); + } + break; + + default: + } + + return Optional.ofNullable(formType); + } + + @Override + public void parseConfiguration( + final List<FormProperty> formProperties, + final String formKey, + final DeploymentEntity deployment, + final ProcessDefinition processDefinition) { + + this.deploymentId = deployment.getId(); + + ExpressionManager expressionManager = CommandContextUtil.getProcessEngineConfiguration().getExpressionManager(); + + if (StringUtils.isNotEmpty(formKey)) { + this.formKey = expressionManager.createExpression(formKey); + } + + FormTypes formTypes = CommandContextUtil.getProcessEngineConfiguration().getFormTypes(); + + formProperties.forEach(formProperty -> { + FormPropertyHandler formPropertyHandler = new FormPropertyHandler(); + formPropertyHandler.setId(formProperty.getId()); + formPropertyHandler.setName(formProperty.getName()); + + AbstractFormType type = parseFormPropertyType(formProperty, expressionManager). + orElse(formTypes.parseFormPropertyType(formProperty)); + formPropertyHandler.setType(type); + formPropertyHandler.setRequired(formProperty.isRequired()); + formPropertyHandler.setReadable(formProperty.isReadable()); + formPropertyHandler.setWritable(formProperty.isWriteable()); + formPropertyHandler.setVariableName(formProperty.getVariable()); + + if (StringUtils.isNotEmpty(formProperty.getExpression())) { + Expression expression = expressionManager.createExpression(formProperty.getExpression()); + formPropertyHandler.setVariableExpression(expression); + } + + if (StringUtils.isNotEmpty(formProperty.getDefaultExpression())) { + Expression defaultExpression = expressionManager.createExpression(formProperty.getDefaultExpression()); + formPropertyHandler.setDefaultExpression(defaultExpression); + } + + formPropertyHandlers.add(formPropertyHandler); + }); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/flowable-bpmn/src/main/resources/workflowFlowableContext.xml ---------------------------------------------------------------------- diff --git a/ext/flowable/flowable-bpmn/src/main/resources/workflowFlowableContext.xml b/ext/flowable/flowable-bpmn/src/main/resources/workflowFlowableContext.xml index 9e27f47..4f34237 100644 --- a/ext/flowable/flowable-bpmn/src/main/resources/workflowFlowableContext.xml +++ b/ext/flowable/flowable-bpmn/src/main/resources/workflowFlowableContext.xml @@ -38,6 +38,8 @@ under the License. <property name="idmEngineConfiguration" ref="syncopeIdmEngineConfiguration"/> </bean> + <bean id="syncopeFormHandlerHelper" class="org.apache.syncope.core.flowable.support.SyncopeFormHandlerHelper"/> + <bean class="org.apache.syncope.core.flowable.support.DomainProcessEngineConfiguration" scope="prototype"> <property name="databaseSchemaUpdate" value="true"/> @@ -52,6 +54,8 @@ under the License. <bean class="org.apache.syncope.core.flowable.support.SyncopeEntitiesVariableType"/> </list> </property> + + <property name="formHandlerHelper" ref="syncopeFormHandlerHelper"/> </bean> <bean id="bpmnProcessManager" class="org.apache.syncope.core.flowable.impl.FlowableBpmnProcessManager"/> http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/BpmnProcessLogic.java ---------------------------------------------------------------------- diff --git a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/BpmnProcessLogic.java b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/BpmnProcessLogic.java index 8d280ac..ad76605 100644 --- a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/BpmnProcessLogic.java +++ b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/BpmnProcessLogic.java @@ -21,7 +21,7 @@ package org.apache.syncope.core.logic; import java.io.OutputStream; import java.lang.reflect.Method; import java.util.List; -import org.apache.syncope.common.lib.to.BpmnProcessTO; +import org.apache.syncope.common.lib.to.BpmnProcess; import org.apache.syncope.common.lib.types.FlowableEntitlement; import org.apache.syncope.common.lib.types.BpmnProcessFormat; import org.springframework.beans.factory.annotation.Autowired; @@ -31,14 +31,14 @@ import org.springframework.transaction.annotation.Transactional; import org.apache.syncope.core.flowable.api.BpmnProcessManager; @Component -public class BpmnProcessLogic extends AbstractTransactionalLogic<BpmnProcessTO> { +public class BpmnProcessLogic extends AbstractTransactionalLogic<BpmnProcess> { @Autowired private BpmnProcessManager bpmnProcessManager; @PreAuthorize("hasRole('" + FlowableEntitlement.BPMN_PROCESS_LIST + "')") @Transactional(readOnly = true) - public List<BpmnProcessTO> list() { + public List<BpmnProcess> list() { return bpmnProcessManager.getProcesses(); } @@ -65,7 +65,7 @@ public class BpmnProcessLogic extends AbstractTransactionalLogic<BpmnProcessTO> } @Override - protected BpmnProcessTO resolveReference(final Method method, final Object... args) + protected BpmnProcess resolveReference(final Method method, final Object... args) throws UnresolvedReferenceException { throw new UnresolvedReferenceException();