You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2018/10/02 12:32:18 UTC
[2/6] syncope git commit: [SYNCOPE-1369] User requests forms now
support dropdowns - via Flowable customization
http://git-wip-us.apache.org/repos/asf/syncope/blob/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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/6f6d9156/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();