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:22 UTC

[6/6] syncope git commit: [SYNCOPE-1369] User requests forms now support dropdowns - via Flowable customization

[SYNCOPE-1369] User requests forms now support dropdowns - via Flowable customization


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/fee1317d
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/fee1317d
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/fee1317d

Branch: refs/heads/master
Commit: fee1317dc3e32d89fcbab5f5e748f49ce5e04f83
Parents: fba9bce
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Oct 2 14:31:40 2018 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Oct 2 14:32:07 2018 +0200

----------------------------------------------------------------------
 .../console/commons/MapChoiceRenderer.java      |  21 +-
 .../html/form/AjaxDropDownChoicePanel.java      |   3 +-
 .../console/wizards/any/Relationships.java      |   5 +-
 .../wizards/any/Relationships.properties        |   3 +
 .../wizards/any/Relationships_it.properties     |   3 +
 .../wizards/any/Relationships_ja.properties     |   3 +
 .../wizards/any/Relationships_pt_BR.properties  |   3 +
 .../wizards/any/Relationships_ru.properties     |   3 +
 .../syncope/common/lib/to/RelationshipTO.java   |  16 +
 .../core/persistence/api/dao/AnyObjectDAO.java  |   2 +-
 .../persistence/jpa/dao/JPAAnyObjectDAO.java    |  12 +-
 .../test/resources/domains/MasterContent.xml    |   6 +-
 .../provisioning/java/MappingManagerImpl.java   |  47 +--
 .../java/data/AbstractAnyDataBinder.java        |   5 +-
 .../java/data/AnyObjectDataBinderImpl.java      |  11 +-
 .../java/data/UserDataBinderImpl.java           |   7 +-
 ext/flowable/client-console/pom.xml             |  32 +-
 .../client/console/approvals/Approval.java      |  29 +-
 .../approvals/ApprovalDirectoryPanel.java       |  19 +-
 .../syncope/client/console/pages/Flowable.java  |   4 +-
 .../panels/BpmnProcessDirectoryPanel.java       |  48 +--
 .../resources/AbstractBpmnProcessResource.java  |   6 +-
 .../resources/BpmnProcessGETResource.java       |   4 +-
 .../resources/BpmnProcessPUTResource.java       |   4 +-
 .../console/rest/BpmnProcessRestClient.java     |   4 +-
 .../console/rest/UserRequestRestClient.java     |  11 +-
 .../client/console/widgets/ApprovalsWidget.java |  10 +-
 .../src/main/resources/dropdown.diff            | 139 ++++++++
 .../client/console/pages/Approvals.properties   |   2 +-
 .../console/pages/Approvals_it.properties       |   2 +-
 .../console/pages/Approvals_ja.properties       |   2 +-
 .../console/pages/Approvals_pt_BR.properties    |   2 +-
 .../console/pages/Approvals_ru.properties       |   2 +-
 .../syncope/common/lib/to/BpmnProcess.java      |  72 ++++
 .../syncope/common/lib/to/BpmnProcessTO.java    |  72 ----
 .../syncope/common/lib/to/UserRequest.java      |  70 ++++
 .../syncope/common/lib/to/UserRequestForm.java  |  26 +-
 .../common/lib/to/UserRequestFormProperty.java  |   8 +
 .../syncope/common/lib/to/UserRequestTO.java    |  70 ----
 .../common/lib/types/FlowableEntitlement.java   |  14 +-
 .../lib/types/UserRequestFormPropertyType.java  |   3 +-
 .../core/flowable/api/BpmnProcessManager.java   |   4 +-
 .../flowable/api/DropdownValueProvider.java     |  31 ++
 .../core/flowable/api/UserRequestHandler.java   |  30 +-
 .../impl/FlowableBpmnProcessManager.java        |   9 +-
 .../flowable/impl/FlowableRuntimeUtils.java     |  50 +--
 .../impl/FlowableUserRequestHandler.java        | 345 ++++++++++++-------
 .../support/DomainProcessEngineFactoryBean.java |   6 +
 .../support/DropdownAwareJsonConverter.java     |  31 ++
 .../DropdownAwareUserTaskJsonConverter.java     |  98 ++++++
 .../core/flowable/support/DropdownFormType.java |  59 ++++
 .../support/SyncopeFormHandlerHelper.java       |  56 +++
 .../support/SyncopeTaskFormHandler.java         | 112 ++++++
 .../main/resources/workflowFlowableContext.xml  |   4 +
 .../syncope/core/logic/BpmnProcessLogic.java    |   8 +-
 .../syncope/core/logic/UserRequestLogic.java    | 115 +++++--
 .../rest/api/beans/UserRequestFormQuery.java    |  18 +
 .../common/rest/api/beans/UserRequestQuery.java |  50 +++
 .../rest/api/service/BpmnProcessService.java    |  20 +-
 .../rest/api/service/UserRequestService.java    |  73 ++--
 .../api/service/UserWorkflowTaskService.java    |  14 +
 .../cxf/service/BpmnProcessServiceImpl.java     |   4 +-
 .../cxf/service/UserRequestServiceImpl.java     |  38 +-
 fit/core-reference/pom.xml                      |  20 ++
 .../reference/flowable/AssignDirectorGroup.java |  65 ++++
 .../reference/flowable/CreateARelationship.java |  71 ++++
 .../flowable/PrintersValueProvider.java         |  70 ++++
 .../fit/core/reference/AssignDirectorGroup.java |  63 ----
 .../main/resources/all/workflowTestContext.xml  |   7 +-
 .../resources/assignPrinterRequest.bpmn20.xml   |  92 +++++
 .../syncope/fit/core/AuthenticationITCase.java  |   4 +-
 .../syncope/fit/core/BpmnProcessITCase.java     |   4 +-
 .../syncope/fit/core/UserRequestITCase.java     | 135 +++++++-
 .../apache/syncope/fit/core/UserSelfITCase.java |  45 +--
 pom.xml                                         |  10 +-
 75 files changed, 1909 insertions(+), 657 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
index 2845105..92d060d 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
@@ -23,33 +23,28 @@ import java.util.Map;
 import org.apache.wicket.markup.html.form.IChoiceRenderer;
 import org.apache.wicket.model.IModel;
 
-public class MapChoiceRenderer<T, K> implements IChoiceRenderer<T> {
+public class MapChoiceRenderer implements IChoiceRenderer<String> {
 
     private static final long serialVersionUID = -7452881117778186644L;
 
-    private final Map<T, K> map;
+    private final Map<String, String> map;
 
-    public MapChoiceRenderer(final Map<T, K> map) {
+    public MapChoiceRenderer(final Map<String, String> map) {
         this.map = map;
     }
 
     @Override
-    public Object getDisplayValue(final T key) {
+    public Object getDisplayValue(final String key) {
         return map.get(key);
     }
 
     @Override
-    public String getIdValue(final T key, final int index) {
-        return key.toString();
+    public String getIdValue(final String key, final int index) {
+        return key;
     }
 
     @Override
-    public T getObject(final String id, final IModel<? extends List<? extends T>> choices) {
-        for (Map.Entry<T, K> entry : map.entrySet()) {
-            if (entry.getValue() != null && entry.getValue().toString().equals(id)) {
-                return entry.getKey();
-            }
-        }
-        return null;
+    public String getObject(final String id, final IModel<? extends List<? extends String>> choices) {
+        return id;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java
index 193c0ad..c52efac 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java
@@ -44,8 +44,7 @@ public class AjaxDropDownChoicePanel<T extends Serializable> extends FieldPanel<
 
         super(id, name, model);
 
-        field = new BootstrapSelect<>(
-                "dropDownChoiceField", model, Collections.<T>emptyList(), new ChoiceRenderer<>());
+        field = new BootstrapSelect<>("dropDownChoiceField", model, Collections.<T>emptyList(), new ChoiceRenderer<>());
         add(field.setLabel(new Model<>(name)).setOutputMarkupId(true));
 
         if (enableOnBlur) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
index 06e126b..bfbdc1d 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
@@ -136,14 +136,13 @@ public class Relationships extends WizardStep implements ICondition {
                 public Panel getPanel(final String panelId) {
                     return new ListViewPanel.Builder<>(RelationshipTO.class, pageRef).
                             setItems(relationships.get(relationship)).
-                            includes("otherEndType", "otherEndKey").
+                            includes("otherEndType", "otherEndKey", "otherEndName").
                             addAction(new ActionLink<RelationshipTO>() {
 
                                 private static final long serialVersionUID = -6847033126124401556L;
 
                                 @Override
-                                public void onClick(
-                                        final AjaxRequestTarget target, final RelationshipTO modelObject) {
+                                public void onClick(final AjaxRequestTarget target, final RelationshipTO modelObject) {
                                     removeRelationships(relationships, modelObject);
                                     send(Relationships.this, Broadcast.DEPTH, new ListViewReload<>(target));
                                 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships.properties
index cfefe54..45e8a78 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships.properties
@@ -16,3 +16,6 @@
 # under the License.
 relationships.empty.list=No relationships defined
 any.relationships=Relationships
+otherEndType=AnyType
+otherEndKey=Key
+otherEndName=Name

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_it.properties
index 5260a62..cdc900f 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_it.properties
@@ -16,3 +16,6 @@
 # under the License.
 relationships.empty.list=Nessuna relazione specificata
 any.relationships=Relazioni
+otherEndType=AnyType
+otherEndKey=Chiave
+otherEndName=Nome

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ja.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ja.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ja.properties
index c0f26ae..5561099 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ja.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ja.properties
@@ -16,3 +16,6 @@
 # under the License.
 relationships.empty.list=\u95a2\u4fc2\u306f\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u307e\u305b\u3093
 any.relationships=\u95a2\u4fc2
+otherEndType=AnyType
+otherEndKey=Key
+otherEndName=Name

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_pt_BR.properties
index 44f4ac8..c0c71dc 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_pt_BR.properties
@@ -16,3 +16,6 @@
 # under the License.
 relationships.empty.list=N\u00e3o h\u00e1 relacionamentos definidos
 any.relationships=Relationships
+otherEndType=AnyType
+otherEndKey=Key
+otherEndName=Name

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ru.properties
index 93a15fb..9fcb63a 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships_ru.properties
@@ -17,3 +17,6 @@
 
 relationships.empty.list=\u0421\u0432\u044f\u0437\u0438 \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u044b
 any.relationships=\u0421\u0432\u044f\u0437\u0438
+otherEndType=AnyType
+otherEndKey=Key
+otherEndName=Name

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
index 015e18c..06dbd0d 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
@@ -43,6 +43,13 @@ public class RelationshipTO extends AbstractBaseBean {
             return this;
         }
 
+        public Builder otherEnd(final String otherEndType, final String otherEndKey, final String otherEndName) {
+            instance.setOtherEndType(otherEndType);
+            instance.setOtherEndKey(otherEndKey);
+            instance.setOtherEndName(otherEndName);
+            return this;
+        }
+
         public RelationshipTO build() {
             return instance;
         }
@@ -54,6 +61,8 @@ public class RelationshipTO extends AbstractBaseBean {
 
     private String otherEndKey;
 
+    private String otherEndName;
+
     public String getType() {
         return type;
     }
@@ -78,4 +87,11 @@ public class RelationshipTO extends AbstractBaseBean {
         this.otherEndKey = otherEndKey;
     }
 
+    public String getOtherEndName() {
+        return otherEndName;
+    }
+
+    public void setOtherEndName(final String otherEndName) {
+        this.otherEndName = otherEndName;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
index f001204..f8f05f9 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
@@ -46,7 +46,7 @@ public interface AnyObjectDAO extends AnyDAO<AnyObject> {
 
     List<Group> findDynGroups(String key);
 
-    List<Relationship<Any<?>, Any<?>>> findAllRelationships(AnyObject anyObject);
+    List<Relationship<Any<?>, AnyObject>> findAllRelationships(AnyObject anyObject);
 
     Collection<Group> findAllGroups(AnyObject anyObject);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
index 4d8aaea..a7211de 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
@@ -168,20 +168,20 @@ public class JPAAnyObjectDAO extends AbstractAnyDAO<AnyObject> implements AnyObj
     }
 
     @Override
-    public List<Relationship<Any<?>, Any<?>>> findAllRelationships(final AnyObject anyObject) {
-        List<Relationship<Any<?>, Any<?>>> result = new ArrayList<>();
+    public List<Relationship<Any<?>, AnyObject>> findAllRelationships(final AnyObject anyObject) {
+        List<Relationship<Any<?>, AnyObject>> result = new ArrayList<>();
 
         @SuppressWarnings("unchecked")
-        TypedQuery<Relationship<Any<?>, Any<?>>> aquery =
-                (TypedQuery<Relationship<Any<?>, Any<?>>>) entityManager().createQuery(
+        TypedQuery<Relationship<Any<?>, AnyObject>> aquery =
+                (TypedQuery<Relationship<Any<?>, AnyObject>>) entityManager().createQuery(
                         "SELECT e FROM " + JPAARelationship.class.getSimpleName()
                         + " e WHERE e.rightEnd=:anyObject OR e.leftEnd=:anyObject");
         aquery.setParameter("anyObject", anyObject);
         result.addAll(aquery.getResultList());
 
         @SuppressWarnings("unchecked")
-        TypedQuery<Relationship<Any<?>, Any<?>>> uquery =
-                (TypedQuery<Relationship<Any<?>, Any<?>>>) entityManager().createQuery(
+        TypedQuery<Relationship<Any<?>, AnyObject>> uquery =
+                (TypedQuery<Relationship<Any<?>, AnyObject>>) entityManager().createQuery(
                         "SELECT e FROM " + JPAURelationship.class.getSimpleName()
                         + " e WHERE e.rightEnd=:anyObject");
         uquery.setParameter("anyObject", anyObject);

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index fb05d94..5a41085 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -253,14 +253,14 @@ under the License.
   <SyncopeRole_entitlements entitlement="ANYTYPE_READ" role_id="User manager"/>
   <SyncopeRole_entitlements entitlement="ANYTYPECLASS_LIST" role_id="User manager"/>
   <SyncopeRole_entitlements entitlement="ANYTYPECLASS_READ" role_id="User manager"/>
-  <SyncopeRole_entitlements entitlement="WORKFLOW_FORM_CLAIM" role_id="User manager"/>
-  <SyncopeRole_entitlements entitlement="WORKFLOW_FORM_SUBMIT" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="USER_REQUEST_FORM_CLAIM" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="USER_REQUEST_FORM_SUBMIT" role_id="User manager"/>
   <SyncopeRole_Realm role_id="User manager" realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"/>
 
   <SyncopeRole id="Other"/>
   <SyncopeRole_entitlements entitlement="SCHEMA_READ" role_id="Other"/>
   <SyncopeRole_entitlements entitlement="GROUP_READ" role_id="Other"/>
-  <SyncopeRole_entitlements entitlement="WORKFLOW_FORM_CLAIM" role_id="Other"/>
+  <SyncopeRole_entitlements entitlement="USER_REQUEST_FORM_CLAIM" role_id="Other"/>
   <SyncopeRole_Realm role_id="Other" realm_id="722f3d84-9c2b-4525-8f6e-e4b82c55a36c"/>
   <SyncopeRole_Privilege role_id="Other" privilege_id="postMighty"/>
   

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
index b6c63e3..33077fe 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
@@ -770,11 +770,14 @@ public class MappingManagerImpl implements MappingManager {
                 default:
             }
         } else if (intAttrName.getSchemaType() != null && attr != null) {
-            GroupableRelatableTO groupableTO = null;
-            Group group = null;
+            GroupableRelatableTO groupableTO;
+            Group group;
             if (anyTO instanceof GroupableRelatableTO && intAttrName.getMembershipOfGroup() != null) {
                 groupableTO = (GroupableRelatableTO) anyTO;
                 group = groupDAO.findByName(intAttrName.getMembershipOfGroup());
+            } else {
+                groupableTO = null;
+                group = null;
             }
 
             switch (intAttrName.getSchemaType()) {
@@ -798,29 +801,28 @@ public class MappingManagerImpl implements MappingManager {
                     if (groupableTO == null || group == null) {
                         anyTO.getPlainAttrs().add(attrTO);
                     } else {
-                        Optional<MembershipTO> membership = groupableTO.getMembership(group.getKey());
-                        if (!membership.isPresent()) {
-                            membership = Optional.of(
-                                    new MembershipTO.Builder().group(group.getKey(), group.getName()).build());
-                            groupableTO.getMemberships().add(membership.get());
-                        }
-                        membership.get().getPlainAttrs().add(attrTO);
+                        MembershipTO membership = groupableTO.getMembership(group.getKey()).orElseGet(() -> {
+                            MembershipTO newMemb = new MembershipTO.Builder().group(group.getKey()).build();
+                            groupableTO.getMemberships().add(newMemb);
+                            return newMemb;
+                        });
+                        membership.getPlainAttrs().add(attrTO);
                     }
                     break;
 
                 case DERIVED:
                     attrTO = new AttrTO();
                     attrTO.setSchema(intAttrName.getSchemaName());
+
                     if (groupableTO == null || group == null) {
                         anyTO.getDerAttrs().add(attrTO);
                     } else {
-                        Optional<MembershipTO> membership = groupableTO.getMembership(group.getKey());
-                        if (!membership.isPresent()) {
-                            membership = Optional.of(
-                                    new MembershipTO.Builder().group(group.getKey(), group.getName()).build());
-                            groupableTO.getMemberships().add(membership.get());
-                        }
-                        membership.get().getDerAttrs().add(attrTO);
+                        MembershipTO membership = groupableTO.getMembership(group.getKey()).orElseGet(() -> {
+                            MembershipTO newMemb = new MembershipTO.Builder().group(group.getKey()).build();
+                            groupableTO.getMemberships().add(newMemb);
+                            return newMemb;
+                        });
+                        membership.getDerAttrs().add(attrTO);
                     }
                     break;
 
@@ -838,13 +840,12 @@ public class MappingManagerImpl implements MappingManager {
                     if (groupableTO == null || group == null) {
                         anyTO.getVirAttrs().add(attrTO);
                     } else {
-                        Optional<MembershipTO> membership = groupableTO.getMembership(group.getKey());
-                        if (!membership.isPresent()) {
-                            membership = Optional.of(
-                                    new MembershipTO.Builder().group(group.getKey(), group.getName()).build());
-                            groupableTO.getMemberships().add(membership.get());
-                        }
-                        membership.get().getVirAttrs().add(attrTO);
+                        MembershipTO membership = groupableTO.getMembership(group.getKey()).orElseGet(() -> {
+                            MembershipTO newMemb = new MembershipTO.Builder().group(group.getKey()).build();
+                            groupableTO.getMemberships().add(newMemb);
+                            return newMemb;
+                        });
+                        membership.getVirAttrs().add(attrTO);
                     }
                     break;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index 5c134df..c7499a8 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -69,6 +69,7 @@ import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
@@ -571,9 +572,9 @@ abstract class AbstractAnyDataBinder {
         anyTO.getResources().addAll(resources.stream().map(Entity::getKey).collect(Collectors.toSet()));
     }
 
-    protected RelationshipTO getRelationshipTO(final String relationshipType, final Any<?> otherEnd) {
+    protected RelationshipTO getRelationshipTO(final String relationshipType, final AnyObject otherEnd) {
         return new RelationshipTO.Builder().
-                type(relationshipType).otherEnd(otherEnd.getType().getKey(), otherEnd.getKey()).
+                type(relationshipType).otherEnd(otherEnd.getType().getKey(), otherEnd.getKey(), otherEnd.getName()).
                 build();
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
index 129d0e4..1dd6194 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
@@ -101,11 +101,12 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
 
             // relationships
             anyObjectTO.getRelationships().addAll(
-                    anyObjectDAO.findAllRelationships(anyObject).stream().map(relationship -> getRelationshipTO(
-                    relationship.getType().getKey(),
-                    relationship.getLeftEnd().getKey().equals(anyObject.getKey())
-                    ? relationship.getRightEnd()
-                    : relationship.getLeftEnd())).
+                    anyObjectDAO.findAllRelationships(anyObject).stream().
+                            map(relationship -> getRelationshipTO(
+                            relationship.getType().getKey(),
+                            relationship.getLeftEnd().getKey().equals(anyObject.getKey())
+                            ? relationship.getRightEnd()
+                            : anyObject)).
                             collect(Collectors.toList()));
 
             // memberships

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index d328c43..58c2d7d 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -602,10 +602,9 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
                     flatMap(role -> role.getPrivileges().stream()).map(Entity::getKey).collect(Collectors.toSet()));
 
             // relationships
-            userTO.getRelationships().addAll(
-                    user.getRelationships().stream().map(relationship -> getRelationshipTO(
-                    relationship.getType().getKey(), relationship.getRightEnd())).
-                            collect(Collectors.toList()));
+            userTO.getRelationships().addAll(user.getRelationships().stream().
+                    map(relationship -> getRelationshipTO(relationship.getType().getKey(), relationship.getRightEnd())).
+                    collect(Collectors.toList()));
 
             // memberships
             userTO.getMemberships().addAll(

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/pom.xml
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/pom.xml b/ext/flowable/client-console/pom.xml
index ef2e989..f076186 100644
--- a/ext/flowable/client-console/pom.xml
+++ b/ext/flowable/client-console/pom.xml
@@ -83,35 +83,37 @@ under the License.
               <target>
                 <unzip src="${settings.localRepository}/org/flowable/flowable-ui-modeler-app/${flowable.version}/flowable-ui-modeler-app-${flowable.version}.war" dest="${flowable-modeler.directory}">
                   <patternset>
-                    <include name="WEB-INF/classes/static/**" />
-                    <include name="WEB-INF/lib/flowable-ui-modeler-logic-${flowable.version}.jar" />
+                    <include name="WEB-INF/classes/static/**"/>
+                    <include name="WEB-INF/lib/flowable-ui-modeler-logic-${flowable.version}.jar"/>
                   </patternset>
                 </unzip>
                 
                 <unzip src="${flowable-modeler.directory}/WEB-INF/lib/flowable-ui-modeler-logic-${flowable.version}.jar" dest="${flowable-modeler.directory}">
                   <patternset>
-                    <include name="stencilset_bpmn.json" />
+                    <include name="stencilset_bpmn.json"/>
                   </patternset>
                 </unzip>
                 
                 <move todir="${flowable-modeler.directory}">
                   <fileset dir="${flowable-modeler.directory}/WEB-INF/classes/static/">
-                    <include name="**" />
+                    <include name="**"/>
                   </fileset>
                 </move>
-                <delete dir="${flowable-modeler.directory}/WEB-INF" />
+                <delete dir="${flowable-modeler.directory}/WEB-INF"/>
                 
-                <replace file="${flowable-modeler.directory}/index.html" token="&lt;/head&gt;" value="&lt;script type=&quot;text/javascript&quot;&gt;window.onunload = refreshParent; function refreshParent() { window.opener.location.reload(); }&lt;/script&gt;&lt;/head&gt;" />
-                <replace file="${flowable-modeler.directory}/index.html" token=" ng-click=&quot;backToLanding()&quot;" value=" disabled=&quot;disabled&quot;" />
-                <replace file="${flowable-modeler.directory}/index.html" token="&lt;ul class=&quot;nav navbar-nav&quot; id=&quot;main-nav&quot;" value="&lt;ul class=&quot;nav navbar-nav&quot; id=&quot;main-nav&quot; style=&quot;display: none;&quot;" />
-                <replace file="${flowable-modeler.directory}/index.html" token="&lt;div class=&quot;pull-right" value="&lt;div style=&quot;display: none;&quot; class=&quot;pull-right" />
-                <replace file="${flowable-modeler.directory}/editor-app/editor.html" token="&lt;div class=&quot;btn-group pull-right&quot;" value="&lt;div style=&quot;display: none;&quot; class=&quot;btn-group pull-right&quot;" />
-                <replace file="${flowable-modeler.directory}/editor-app/configuration/toolbar-default-actions.js" token="$location.path('/processes');" value="window.close();" />
+                <replace file="${flowable-modeler.directory}/index.html" token="&lt;/head&gt;" value="&lt;script type=&quot;text/javascript&quot;&gt;window.onunload = refreshParent; function refreshParent() { window.opener.location.reload(); }&lt;/script&gt;&lt;/head&gt;"/>
+                <replace file="${flowable-modeler.directory}/index.html" token=" ng-click=&quot;backToLanding()&quot;" value=" disabled=&quot;disabled&quot;"/>
+                <replace file="${flowable-modeler.directory}/index.html" token="&lt;ul class=&quot;nav navbar-nav&quot; id=&quot;main-nav&quot;" value="&lt;ul class=&quot;nav navbar-nav&quot; id=&quot;main-nav&quot; style=&quot;display: none;&quot;"/>
+                <replace file="${flowable-modeler.directory}/index.html" token="&lt;div class=&quot;pull-right" value="&lt;div style=&quot;display: none;&quot; class=&quot;pull-right"/>
+                <replace file="${flowable-modeler.directory}/editor-app/editor.html" token="&lt;div class=&quot;btn-group pull-right&quot;" value="&lt;div style=&quot;display: none;&quot; class=&quot;btn-group pull-right&quot;"/>
+                <replace file="${flowable-modeler.directory}/editor-app/configuration/toolbar-default-actions.js" token="$location.path('/processes');" value="window.close();"/>
  
-                <copy file="${basedir}/src/main/resources/app-cfg.js" todir="${flowable-modeler.directory}/scripts" overwrite="true" />
-                <copy file="${basedir}/src/main/resources/url-config.js" todir="${flowable-modeler.directory}/editor-app/configuration" overwrite="true" />
-                <copy file="${basedir}/src/main/resources/toolbar.js" todir="${flowable-modeler.directory}/editor-app/configuration" overwrite="true" />
-                <copy file="${basedir}/src/main/resources/save-model.html" todir="${flowable-modeler.directory}/editor-app/popups" overwrite="true" />
+                <copy file="${basedir}/src/main/resources/app-cfg.js" todir="${flowable-modeler.directory}/scripts" overwrite="true"/>
+                <copy file="${basedir}/src/main/resources/url-config.js" todir="${flowable-modeler.directory}/editor-app/configuration" overwrite="true"/>
+                <copy file="${basedir}/src/main/resources/toolbar.js" todir="${flowable-modeler.directory}/editor-app/configuration" overwrite="true"/>
+                <copy file="${basedir}/src/main/resources/save-model.html" todir="${flowable-modeler.directory}/editor-app/popups" overwrite="true"/>
+
+                <patch patchfile="${basedir}/src/main/resources/dropdown.diff" dir="${flowable-modeler.directory}" strip="1"/>
               </target>
             </configuration>
             <goals>

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/Approval.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/Approval.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/Approval.java
index 3bea1a9..6a66afc 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/Approval.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/Approval.java
@@ -45,7 +45,6 @@ import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.LoadableDetachableModel;
-import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -103,7 +102,7 @@ public abstract class Approval extends Panel {
                         break;
 
                     case Date:
-                        final FastDateFormat formatter = FastDateFormat.getInstance(prop.getDatePattern());
+                        FastDateFormat formatter = FastDateFormat.getInstance(prop.getDatePattern());
                         field = new AjaxDateTimeFieldPanel("value", label, new PropertyModel<Date>(prop, "value") {
 
                             private static final long serialVersionUID = -3743432456095828573L;
@@ -111,11 +110,9 @@ public abstract class Approval extends Panel {
                             @Override
                             public Date getObject() {
                                 try {
-                                    if (StringUtils.isBlank(prop.getValue())) {
-                                        return null;
-                                    } else {
-                                        return formatter.parse(prop.getValue());
-                                    }
+                                    return StringUtils.isBlank(prop.getValue())
+                                            ? null
+                                            : formatter.parse(prop.getValue());
                                 } catch (ParseException e) {
                                     LOG.error("Unparsable date: {}", prop.getValue(), e);
                                     return null;
@@ -131,19 +128,17 @@ public abstract class Approval extends Panel {
                         break;
 
                     case Enum:
-                        MapChoiceRenderer<String, String> enumCR = new MapChoiceRenderer<>(prop.getEnumValues());
-
                         field = new AjaxDropDownChoicePanel(
                                 "value", label, new PropertyModel<String>(prop, "value"), false).
-                                setChoiceRenderer(enumCR).setChoices(new Model<ArrayList<String>>() {
-
-                            private static final long serialVersionUID = -858521070366432018L;
+                                setChoiceRenderer(new MapChoiceRenderer(prop.getEnumValues())).
+                                setChoices(new ArrayList<>(prop.getEnumValues().keySet()));
+                        break;
 
-                            @Override
-                            public ArrayList<String> getObject() {
-                                return new ArrayList<>(prop.getEnumValues().keySet());
-                            }
-                        });
+                    case Dropdown:
+                        field = new AjaxDropDownChoicePanel(
+                                "value", label, new PropertyModel<String>(prop, "value"), false).
+                                setChoiceRenderer(new MapChoiceRenderer(prop.getDropdownValues())).
+                                setChoices(new ArrayList<>(prop.getDropdownValues().keySet()));
                         break;
 
                     case Long:

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/ApprovalDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/ApprovalDirectoryPanel.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/ApprovalDirectoryPanel.java
index e16f5c2..577ea65 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/ApprovalDirectoryPanel.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/approvals/ApprovalDirectoryPanel.java
@@ -113,7 +113,7 @@ public class ApprovalDirectoryPanel
 
         initResultTable();
 
-        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, FlowableEntitlement.WORKFLOW_FORM_SUBMIT);
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, FlowableEntitlement.USER_REQUEST_FORM_SUBMIT);
     }
 
     @Override
@@ -121,7 +121,7 @@ public class ApprovalDirectoryPanel
         List<IColumn<UserRequestForm, String>> columns = new ArrayList<>();
 
         columns.add(new PropertyColumn<>(
-                new ResourceModel("taskId"), "taskId", "taskId"));
+                new ResourceModel("bpmnProcess"), "bpmnProcess", "bpmnProcess"));
         columns.add(new PropertyColumn<>(
                 new ResourceModel("key"), "formKey", "formKey"));
         columns.add(new PropertyColumn<>(
@@ -151,7 +151,7 @@ public class ApprovalDirectoryPanel
                 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
                 target.add(container);
             }
-        }, ActionLink.ActionType.CLAIM, FlowableEntitlement.WORKFLOW_FORM_CLAIM);
+        }, ActionLink.ActionType.CLAIM, FlowableEntitlement.USER_REQUEST_FORM_CLAIM);
 
         panel.add(new ActionLink<UserRequestForm>() {
 
@@ -190,7 +190,7 @@ public class ApprovalDirectoryPanel
                         equals(model.getObject().getOwner());
             }
 
-        }, ActionLink.ActionType.MANAGE_APPROVAL, FlowableEntitlement.WORKFLOW_FORM_READ);
+        }, ActionLink.ActionType.MANAGE_APPROVAL, FlowableEntitlement.USER_REQUEST_FORM_SUBMIT);
 
         // SYNCOPE-1200 edit user while in approval state
         panel.add(new ActionLink<UserRequestForm>() {
@@ -239,7 +239,7 @@ public class ApprovalDirectoryPanel
                         equals(model.getObject().getOwner());
             }
 
-        }, ActionLink.ActionType.EDIT_APPROVAL, FlowableEntitlement.WORKFLOW_FORM_SUBMIT);
+        }, ActionLink.ActionType.EDIT_APPROVAL, FlowableEntitlement.USER_REQUEST_FORM_SUBMIT);
 
         return panel;
     }
@@ -326,8 +326,6 @@ public class ApprovalDirectoryPanel
         protected Serializable onApplyInternal(final AnyWrapper<UserTO> modelObject) {
             UserTO inner = modelObject.getInnerObject();
 
-            ProvisioningResult<UserTO> result;
-
             UserPatch patch = AnyOperations.diff(inner, formTO.getUserTO(), false);
 
             if (StringUtils.isNotBlank(inner.getPassword())) {
@@ -337,16 +335,15 @@ public class ApprovalDirectoryPanel
                         build();
                 patch.setPassword(passwordPatch);
             }
+
             // update just if it is changed
+            ProvisioningResult<UserTO> result;
             if (patch.isEmpty()) {
                 result = new ProvisioningResult<>();
                 result.setEntity(inner);
             } else {
                 result = userRestClient.update(getOriginalItem().getInnerObject().getETagValue(), patch);
-                UserRequestForm workFlowTO = restClient.getForms(result.getEntity().getKey()).get(0);
-                if (workFlowTO != null) {
-                    claimForm(workFlowTO.getTaskId());
-                }
+                restClient.getForm(result.getEntity().getKey()).ifPresent(form -> claimForm(form.getTaskId()));
             }
 
             return result;

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/pages/Flowable.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/pages/Flowable.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/pages/Flowable.java
index 562aad1..8062a77 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/pages/Flowable.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/pages/Flowable.java
@@ -23,7 +23,7 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.annotations.ExtPage;
 import org.apache.syncope.client.console.panels.BpmnProcessDirectoryPanel;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
-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.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -48,7 +48,7 @@ public class Flowable extends BaseExtPage {
         disabled.setOutputMarkupPlaceholderTag(true);
         content.add(disabled);
 
-        WizardMgtPanel<BpmnProcessTO> bpmnProcessesPanel = new BpmnProcessDirectoryPanel.Builder(getPageReference()) {
+        WizardMgtPanel<BpmnProcess> bpmnProcessesPanel = new BpmnProcessDirectoryPanel.Builder(getPageReference()) {
 
             private static final long serialVersionUID = -5960765294082359003L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/panels/BpmnProcessDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/panels/BpmnProcessDirectoryPanel.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/panels/BpmnProcessDirectoryPanel.java
index b7914bb..8f4d566 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/panels/BpmnProcessDirectoryPanel.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/panels/BpmnProcessDirectoryPanel.java
@@ -43,7 +43,7 @@ import org.apache.syncope.client.console.wicket.markup.html.form.XMLEditorPanel;
 import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
-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.wicket.Page;
 import org.apache.wicket.PageReference;
@@ -65,7 +65,7 @@ import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.util.io.IOUtils;
 
 public class BpmnProcessDirectoryPanel extends DirectoryPanel<
-        BpmnProcessTO, BpmnProcessTO, BpmProcessDataProvider, BpmnProcessRestClient> {
+        BpmnProcess, BpmnProcess, BpmProcessDataProvider, BpmnProcessRestClient> {
 
     private static final long serialVersionUID = 2705668831139984998L;
 
@@ -76,13 +76,13 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
     protected BpmnProcessDirectoryPanel(final String id, final Builder builder) {
         super(id, builder);
 
-        this.addNewItemPanelBuilder(new AjaxWizardBuilder<BpmnProcessTO>(new BpmnProcessTO(), pageRef) {
+        this.addNewItemPanelBuilder(new AjaxWizardBuilder<BpmnProcess>(new BpmnProcess(), pageRef) {
 
             private static final long serialVersionUID = 1633859795677053912L;
 
             @Override
             protected WizardModel buildModelSteps(
-                    final BpmnProcessTO modelObject, final WizardModel wizardModel) {
+                    final BpmnProcess modelObject, final WizardModel wizardModel) {
 
                 return wizardModel;
             }
@@ -133,8 +133,8 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
     }
 
     @Override
-    protected List<IColumn<BpmnProcessTO, String>> getColumns() {
-        List<IColumn<BpmnProcessTO, String>> columns = new ArrayList<>();
+    protected List<IColumn<BpmnProcess, String>> getColumns() {
+        List<IColumn<BpmnProcess, String>> columns = new ArrayList<>();
 
         columns.add(new PropertyColumn<>(new ResourceModel("key"), "key"));
         columns.add(new PropertyColumn<>(new ResourceModel("name"), "name", "name"));
@@ -143,15 +143,15 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
     }
 
     @Override
-    public ActionsPanel<BpmnProcessTO> getActions(final IModel<BpmnProcessTO> model) {
-        final ActionsPanel<BpmnProcessTO> panel = super.getActions(model);
+    public ActionsPanel<BpmnProcess> getActions(final IModel<BpmnProcess> model) {
+        final ActionsPanel<BpmnProcess> panel = super.getActions(model);
 
-        panel.add(new ActionLink<BpmnProcessTO>() {
+        panel.add(new ActionLink<BpmnProcess>() {
 
             private static final long serialVersionUID = -184018732772021627L;
 
             @Override
-            public void onClick(final AjaxRequestTarget target, final BpmnProcessTO ignore) {
+            public void onClick(final AjaxRequestTarget target, final BpmnProcess ignore) {
                 final IModel<String> wfDefinition = new Model<>();
                 try {
                     wfDefinition.setObject(IOUtils.toString(restClient.getDefinition(
@@ -189,12 +189,12 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
             }
         }, ActionLink.ActionType.EDIT, FlowableEntitlement.BPMN_PROCESS_SET);
 
-        panel.add(new ActionLink<BpmnProcessTO>() {
+        panel.add(new ActionLink<BpmnProcess>() {
 
             private static final long serialVersionUID = 3109256773218160485L;
 
             @Override
-            public void onClick(final AjaxRequestTarget target, final BpmnProcessTO ignore) {
+            public void onClick(final AjaxRequestTarget target, final BpmnProcess ignore) {
                 modal.header(Model.of(model.getObject().getKey()));
                 modal.setContent(new ImageModalPanel<>(
                         modal, restClient.getDiagram(model.getObject().getKey()), pageRef));
@@ -203,7 +203,7 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
             }
         }, ActionLink.ActionType.VIEW, FlowableEntitlement.BPMN_PROCESS_GET);
 
-        panel.add(new ActionLink<BpmnProcessTO>() {
+        panel.add(new ActionLink<BpmnProcess>() {
 
             private static final long serialVersionUID = -184018732772021627L;
 
@@ -222,22 +222,22 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
             }
 
             @Override
-            public void onClick(final AjaxRequestTarget target, final BpmnProcessTO ignore) {
+            public void onClick(final AjaxRequestTarget target, final BpmnProcess ignore) {
                 // do nothing
             }
         }, ActionLink.ActionType.EXTERNAL_EDITOR, FlowableEntitlement.BPMN_PROCESS_SET);
 
-        panel.add(new ActionLink<BpmnProcessTO>() {
+        panel.add(new ActionLink<BpmnProcess>() {
 
             private static final long serialVersionUID = -7978723352517770644L;
 
             @Override
-            protected boolean statusCondition(final BpmnProcessTO modelObject) {
+            protected boolean statusCondition(final BpmnProcess modelObject) {
                 return !modelObject.isUserWorkflow();
             }
 
             @Override
-            public void onClick(final AjaxRequestTarget target, final BpmnProcessTO ignore) {
+            public void onClick(final AjaxRequestTarget target, final BpmnProcess ignore) {
                 try {
                     restClient.deleteDefinition(model.getObject().getKey());
                     SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
@@ -260,7 +260,7 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
     }
 
     public abstract static class Builder
-            extends DirectoryPanel.Builder<BpmnProcessTO, BpmnProcessTO, BpmnProcessRestClient> {
+            extends DirectoryPanel.Builder<BpmnProcess, BpmnProcess, BpmnProcessRestClient> {
 
         private static final long serialVersionUID = 5088962796986706805L;
 
@@ -269,16 +269,16 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
         }
 
         @Override
-        protected WizardMgtPanel<BpmnProcessTO> newInstance(final String id, final boolean wizardInModal) {
+        protected WizardMgtPanel<BpmnProcess> newInstance(final String id, final boolean wizardInModal) {
             return new BpmnProcessDirectoryPanel(id, this);
         }
     }
 
-    protected class BpmProcessDataProvider extends DirectoryDataProvider<BpmnProcessTO> {
+    protected class BpmProcessDataProvider extends DirectoryDataProvider<BpmnProcess> {
 
         private static final long serialVersionUID = 1764153405387687592L;
 
-        private final SortableDataProviderComparator<BpmnProcessTO> comparator;
+        private final SortableDataProviderComparator<BpmnProcess> comparator;
 
         private final BpmnProcessRestClient restClient = new BpmnProcessRestClient();
 
@@ -289,8 +289,8 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
         }
 
         @Override
-        public Iterator<BpmnProcessTO> iterator(final long first, final long count) {
-            List<BpmnProcessTO> result = restClient.getDefinitions();
+        public Iterator<BpmnProcess> iterator(final long first, final long count) {
+            List<BpmnProcess> result = restClient.getDefinitions();
             Collections.sort(result, comparator);
             return result.subList((int) first, (int) first + (int) count).iterator();
         }
@@ -301,7 +301,7 @@ public class BpmnProcessDirectoryPanel extends DirectoryPanel<
         }
 
         @Override
-        public IModel<BpmnProcessTO> model(final BpmnProcessTO object) {
+        public IModel<BpmnProcess> model(final BpmnProcess object) {
             return new CompoundPropertyModel<>(object);
         }
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/AbstractBpmnProcessResource.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/AbstractBpmnProcessResource.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/AbstractBpmnProcessResource.java
index 91a42e3..7ad5f24 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/AbstractBpmnProcessResource.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/AbstractBpmnProcessResource.java
@@ -21,7 +21,7 @@ package org.apache.syncope.client.console.resources;
 import javax.ws.rs.NotFoundException;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.rest.BpmnProcessRestClient;
-import org.apache.syncope.common.lib.to.BpmnProcessTO;
+import org.apache.syncope.common.lib.to.BpmnProcess;
 import org.apache.wicket.request.resource.AbstractResource;
 import org.apache.wicket.util.string.StringValue;
 import org.slf4j.Logger;
@@ -35,10 +35,10 @@ abstract class AbstractBpmnProcessResource extends AbstractResource {
 
     protected final BpmnProcessRestClient restClient = new BpmnProcessRestClient();
 
-    protected BpmnProcessTO getBpmnProcess(final Attributes attributes) {
+    protected BpmnProcess getBpmnProcess(final Attributes attributes) {
         StringValue modelId = attributes.getRequest().getQueryParameters().getParameterValue(Constants.MODEL_ID_PARAM);
 
-        BpmnProcessTO bpmnProcess = modelId == null || modelId.isNull()
+        BpmnProcess bpmnProcess = modelId == null || modelId.isNull()
                 ? null
                 : restClient.getDefinitions().stream().
                         filter(object -> modelId.toString().equals(object.getModelId())).findAny().orElse(null);

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessGETResource.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessGETResource.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessGETResource.java
index ba34502..dfe633e 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessGETResource.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessGETResource.java
@@ -23,7 +23,7 @@ import java.nio.charset.StandardCharsets;
 import javax.ws.rs.core.MediaType;
 import org.apache.syncope.client.console.annotations.Resource;
 import org.apache.syncope.client.console.rest.BpmnProcessRestClient;
-import org.apache.syncope.common.lib.to.BpmnProcessTO;
+import org.apache.syncope.common.lib.to.BpmnProcess;
 import org.apache.wicket.util.io.IOUtils;
 
 /**
@@ -36,7 +36,7 @@ public class BpmnProcessGETResource extends AbstractBpmnProcessResource {
 
     @Override
     protected ResourceResponse newResourceResponse(final Attributes attributes) {
-        final BpmnProcessTO toGet = getBpmnProcess(attributes);
+        final BpmnProcess toGet = getBpmnProcess(attributes);
 
         ResourceResponse response = new ResourceResponse();
         response.disableCaching();

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessPUTResource.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessPUTResource.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessPUTResource.java
index d583396..1031ce8 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessPUTResource.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/resources/BpmnProcessPUTResource.java
@@ -24,7 +24,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.cxf.common.util.UrlUtils;
 import org.apache.syncope.client.console.annotations.Resource;
-import org.apache.syncope.common.lib.to.BpmnProcessTO;
+import org.apache.syncope.common.lib.to.BpmnProcess;
 import org.apache.wicket.util.io.IOUtils;
 
 /**
@@ -52,7 +52,7 @@ public class BpmnProcessPUTResource extends AbstractBpmnProcessResource {
             LOG.error("Could not extract BPMN process", e);
         }
 
-        BpmnProcessTO toSet = getBpmnProcess(attributes);
+        BpmnProcess toSet = getBpmnProcess(attributes);
 
         if (definition == null || toSet == null) {
             return new ResourceResponse().setStatusCode(Response.Status.BAD_REQUEST.getStatusCode()).

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/BpmnProcessRestClient.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/BpmnProcessRestClient.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/BpmnProcessRestClient.java
index 2b7c368..9e88431 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/BpmnProcessRestClient.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/BpmnProcessRestClient.java
@@ -25,7 +25,7 @@ import javax.ws.rs.core.Response;
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.common.lib.to.BpmnProcessTO;
+import org.apache.syncope.common.lib.to.BpmnProcess;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.BpmnProcessService;
 
@@ -37,7 +37,7 @@ public class BpmnProcessRestClient extends BaseRestClient {
         return SyncopeConsoleSession.get().getService(mediaType, BpmnProcessService.class);
     }
 
-    public List<BpmnProcessTO> getDefinitions() {
+    public List<BpmnProcess> getDefinitions() {
         return getService(BpmnProcessService.class).list();
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/UserRequestRestClient.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/UserRequestRestClient.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/UserRequestRestClient.java
index 555555b..e3a179f 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/UserRequestRestClient.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/UserRequestRestClient.java
@@ -19,6 +19,8 @@
 package org.apache.syncope.client.console.rest;
 
 import java.util.List;
+import java.util.Optional;
+import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.UserRequestForm;
 import org.apache.syncope.common.rest.api.beans.UserRequestFormQuery;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
@@ -40,8 +42,13 @@ public class UserRequestRestClient extends BaseRestClient {
                 getResult();
     }
 
-    public List<UserRequestForm> getForms(final String userKey) {
-        return getService(UserRequestService.class).getForms(userKey);
+    public Optional<UserRequestForm> getForm(final String userKey) {
+        PagedResult<UserRequestForm> forms = getService(UserRequestService.class).
+                getForms(new UserRequestFormQuery.Builder().user(userKey).page(1).size(1).build());
+        UserRequestForm form = forms.getResult().isEmpty()
+                ? null
+                : forms.getResult().get(0);
+        return Optional.ofNullable(form);
     }
 
     public UserRequestForm claimForm(final String taskKey) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/widgets/ApprovalsWidget.java
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/widgets/ApprovalsWidget.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/widgets/ApprovalsWidget.java
index 8f8329e..9a9fd2d 100644
--- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/widgets/ApprovalsWidget.java
+++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/widgets/ApprovalsWidget.java
@@ -87,8 +87,7 @@ public class ApprovalsWidget extends ExtAlertWidget<UserRequestForm> {
 
     @Override
     protected int getLatestAlertsSize() {
-        return SyncopeConsoleSession.get().owns(FlowableEntitlement.WORKFLOW_FORM_LIST)
-                && SyncopeConsoleSession.get().owns(FlowableEntitlement.WORKFLOW_FORM_READ)
+        return SyncopeConsoleSession.get().owns(FlowableEntitlement.USER_REQUEST_FORM_LIST)
                 ? restClient.countForms()
                 : 0;
     }
@@ -102,9 +101,7 @@ public class ApprovalsWidget extends ExtAlertWidget<UserRequestForm> {
             @Override
             public List<UserRequestForm> getObject() {
                 List<UserRequestForm> updatedApprovals;
-                if (SyncopeConsoleSession.get().owns(FlowableEntitlement.WORKFLOW_FORM_LIST)
-                        && SyncopeConsoleSession.get().owns(FlowableEntitlement.WORKFLOW_FORM_READ)) {
-
+                if (SyncopeConsoleSession.get().owns(FlowableEntitlement.USER_REQUEST_FORM_LIST)) {
                     updatedApprovals = restClient.getForms(1, MAX_SIZE, new SortParam<>("createTime", true));
                 } else {
                     updatedApprovals = Collections.<UserRequestForm>emptyList();
@@ -118,7 +115,8 @@ public class ApprovalsWidget extends ExtAlertWidget<UserRequestForm> {
     @Override
     protected AbstractLink getEventsLink(final String linkid) {
         BookmarkablePageLink<Approvals> approvals = BookmarkablePageLinkBuilder.build(linkid, Approvals.class);
-        MetaDataRoleAuthorizationStrategy.authorize(approvals, WebPage.ENABLE, FlowableEntitlement.WORKFLOW_FORM_LIST);
+        MetaDataRoleAuthorizationStrategy.authorize(
+                approvals, WebPage.ENABLE, FlowableEntitlement.USER_REQUEST_FORM_LIST);
         return approvals;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/resources/dropdown.diff
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/resources/dropdown.diff b/ext/flowable/client-console/src/main/resources/dropdown.diff
new file mode 100644
index 0000000..80fe1e7
--- /dev/null
+++ b/ext/flowable/client-console/src/main/resources/dropdown.diff
@@ -0,0 +1,139 @@
+# 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.
+diff --git a/editor-app/configuration/properties-form-properties-controller.js b/editor-app/configuration/properties-form-properties-controller.js
+index ca8f051..fc02151 100644
+--- a/editor-app/configuration/properties-form-properties-controller.js
++++ b/editor-app/configuration/properties-form-properties-controller.js
+@@ -102,6 +102,20 @@ angular.module('flowableModeler').controller('FlowableFormPropertiesPopupCtrl',
+                 { field: 'name', displayName: $scope.labels.nameLabel}]
+             }
+ 
++            $scope.dropdownGridOptions = {
++    		    data: $scope.enumValues,
++                headerRowHeight: 28,
++                enableRowSelection: true,
++                enableRowHeaderSelection: false,
++                multiSelect: false,
++                modifierKeysToMultiSelect: false,
++                enableHorizontalScrollbar: 0,
++                enableColumnMenus: false,
++                enableSorting: false,
++                columnDefs: [{ field: 'id', displayName: $scope.labels.idLabel },
++                { field: 'name', displayName: $scope.labels.nameLabel}]
++            }
++
+             $scope.gridOptions.onRegisterApi = function (gridApi) {
+                 //set gridApi on scope
+                 $scope.gridApi = gridApi;
+@@ -124,6 +138,13 @@ angular.module('flowableModeler').controller('FlowableFormPropertiesPopupCtrl',
+                     $scope.selectedEnumValue = row.entity;
+                 });
+             };
++            $scope.dropdownGridOptions.onRegisterApi = function (gridApi) {
++                //set gridApi on scope
++                $scope.dropdownGridApi = gridApi;
++                gridApi.selection.on.rowSelectionChanged($scope, function (row) {
++                    $scope.selectedDropdownValue = row.entity;
++                });
++            };
+         });
+ 
+         // Handler for when the value of the type dropdown changes
+@@ -143,7 +164,12 @@ angular.module('flowableModeler').controller('FlowableFormPropertiesPopupCtrl',
+                 for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {
+                     $scope.enumValues.push($scope.selectedProperty.enumValues[i]);
+                 }
+-                
++            } else if ($scope.selectedProperty.type === 'dropdown') {
++                $scope.selectedProperty.enumValues = [ {id: 'dropdownValueProvider', name: 'provider'}];
++                $scope.enumValues.length = 0;
++                for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {
++                    $scope.enumValues.push($scope.selectedProperty.enumValues[i]);
++                }
+             } else {
+                 delete $scope.selectedProperty.enumValues;
+                 $scope.enumValues.length = 0;
+@@ -324,4 +350,4 @@ angular.module('flowableModeler').controller('FlowableFormPropertiesPopupCtrl',
+         };
+ 
+     }])
+-;
+\ No newline at end of file
++;
+diff --git a/editor-app/configuration/properties/form-properties-popup.html b/editor-app/configuration/properties/form-properties-popup.html
+index 17c5ca8..57a24e5 100644
+--- a/editor-app/configuration/properties/form-properties-popup.html
++++ b/editor-app/configuration/properties/form-properties-popup.html
+@@ -42,6 +42,7 @@
+                                     <option>boolean</option>
+                                     <option>date</option>
+                                     <option>enum</option>
++                                    <option>dropdown</option>
+                                 </select>
+             				</div>
+                            	<div class="form-group" ng-show="selectedProperty.datePattern">
+@@ -80,6 +81,38 @@
+                                     </div>
+                                 </div>    
+             				</div>
++                            <div ng-show="selectedProperty.type == 'dropdown'" style="padding-bottom:10px">
++                                <div class="row row-no-gutter">
++                                    <div class="col-xs-6">
++                                        <div ng-if="translationsRetrieved" class="kis-listener-grid" ui-grid="dropdownGridOptions" ui-grid-selection ui-grid-auto-resize></div>
++                                        <!--<div class="pull-right">
++                                            <div class="btn-group">
++                                                <a class="btn btn-icon btn-lg" rel="tooltip" data-title="{{ACTION.MOVE.UP | translate}}" data-placement="bottom" data-original-title="" title="" ng-click="moveEnumValueUp()"><i class="glyphicon glyphicon-arrow-up"></i></a>
++                                                <a class="btn btn-icon btn-lg" rel="tooltip" data-title="{{ACTION.MOVE.DOWN | translate}}" data-placement="bottom" data-original-title="" title="" ng-click="moveEnumValueDown()"><i class="glyphicon glyphicon-arrow-down"></i></a>
++                                            </div>
++                                            <div class="btn-group">
++                                                <a class="btn btn-icon btn-lg" rel="tooltip" data-title="{{ACTION.ADD | translate}}" data-placement="bottom" data-original-title="" title="" ng-click="addNewEnumValue()"><i class="glyphicon glyphicon-plus"></i></a>
++                                                <a class="btn btn-icon btn-lg" rel="tooltip" data-title="{{ACTION.REMOVE | translate}}" data-placement="bottom" data-original-title="" title="" ng-click="removeEnumValue()"><i class="glyphicon glyphicon-minus"></i></a>
++                                            </div>
++                                        </div>-->
++                                    </div>
++                            
++                                    <div class="col-xs-6">
++                                        <div ng-show="selectedDropdownValue">
++                            
++                                            <div class="form-group">
++                                                <label for="classField">{{'PROPERTY.FORMPROPERTIES.VALUES.ID' | translate}}</label>
++                                                <input type="text" id="classField" class="form-control" ng-model="selectedDropdownValue.id" placeholder="{{'PROPERTY.FORMPROPERTIES.VALUES.ID.PLACEHOLDER' | translate}}" />
++                                            </div>
++                                            <div class="form-group">
++                                                <label for="classField">{{'PROPERTY.FORMPROPERTIES.VALUES.NAME' | translate}}</label>
++                                                <input type="text" id="classField" class="form-control" ng-model="selectedDropdownValue.name" placeholder="{{'PROPERTY.FORMPROPERTIES.VALUES.NAME.PLACEHOLDER' | translate}}" />
++                                            </div>
++                                        </div>
++                                        <div ng-show="!selectedDropdownValue" class="muted no-property-selected" translate>PROPERTY.FORMPROPERTIES.DROPDOWNVALUES.EMPTY</div>
++                                    </div>
++                                </div>    
++            				</div>
+                             <div class="form-group">
+             			   		<label for="expressionField">{{'PROPERTY.FORMPROPERTIES.EXPRESSION' | translate}}</label>
+             			   		<input id="expressionField" class="form-control" type="text" ng-model="selectedProperty.expression" placeholder="{{'PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER' | translate }}" />
+diff --git a/i18n/en.json b/i18n/en.json
+index 7d0e40a..1067dad 100644
+--- a/i18n/en.json
++++ b/i18n/en.json
+@@ -824,6 +824,7 @@
+     "PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER" : "Enter date pattern",
+     "PROPERTY.FORMPROPERTIES.VALUES" : "Values",
+     "PROPERTY.FORMPROPERTIES.ENUMVALUES.EMPTY" : "No enum value selected",
++    "PROPERTY.FORMPROPERTIES.DROPDOWNVALUES.EMPTY" : "No dropdown value selected",
+     "PROPERTY.FORMPROPERTIES.VALUES.ID" : "Id",
+     "PROPERTY.FORMPROPERTIES.VALUES.NAME" : "Name",
+     "PROPERTY.FORMPROPERTIES.VALUES.ID.PLACEHOLDER" : "Enter id of a value",

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals.properties
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals.properties
index 1ea8063..84b9c85 100644
--- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals.properties
+++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals.properties
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-taskId=Task
+bpmnProcess=User Request
 key=Key
 description=Description
 createTime=Create Time

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_it.properties
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_it.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_it.properties
index 7e12ce5..f25abd8 100644
--- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_it.properties
+++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_it.properties
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-taskId=Task
+bpmnProcess=User Request
 key=Chiave
 description=Descrizione
 createTime=Data di creazione

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ja.properties
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ja.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ja.properties
index b2ff626..dcca6e1 100644
--- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ja.properties
+++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ja.properties
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-taskId=\u30bf\u30b9\u30af
+bpmnProcess=User Request
 key=\u30ad\u30fc
 description=\u8aac\u660e
 createTime=\u4f5c\u6210\u6642\u523b

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_pt_BR.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_pt_BR.properties
index e5ff74c..88a9e05 100644
--- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_pt_BR.properties
+++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_pt_BR.properties
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-taskId=Tarefa
+bpmnProcess=User Request
 key=Chave
 description=Descri\u00e7\u00e3o
 createTime=Tempo de Cria\u00e7\u00e3o

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ru.properties
----------------------------------------------------------------------
diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ru.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ru.properties
index 6f4fb58..2e7a199 100644
--- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ru.properties
+++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/Approvals_ru.properties
@@ -16,7 +16,7 @@
 # under the License.
 #
 # taskId=\u00d0\u0097\u00d0\u00b0\u00d1\u008f\u00d0\u00b2\u00d0\u00ba\u00d0\u00b0
-taskId=\u0417\u0430\u044f\u0432\u043a\u0430
+bpmnProcess=User Request
 # key=\u00d0\u0098\u00d0\u00b4\u00d0\u00b5\u00d0\u00bd\u00d1\u0082\u00d0\u00b8\u00d1\u0084\u00d0\u00b8\u00d0\u00ba\u00d0\u00b0\u00d1\u0082\u00d0\u00be\u00d1\u0080
 key=\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440
 # description=\u00d0\u009e\u00d0\u00bf\u00d0\u00b8\u00d1\u0081\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/BpmnProcess.java
----------------------------------------------------------------------
diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/BpmnProcess.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/BpmnProcess.java
new file mode 100644
index 0000000..35a7883
--- /dev/null
+++ b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/BpmnProcess.java
@@ -0,0 +1,72 @@
+/*
+ * 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 = "bpmnProcess")
+@XmlType
+public class BpmnProcess extends AbstractBaseBean implements EntityTO {
+
+    private static final long serialVersionUID = -7044543391316529128L;
+
+    private String key;
+
+    private String modelId;
+
+    private String name;
+
+    private boolean userWorkflow;
+
+    @Override
+    public String getKey() {
+        return key;
+    }
+
+    @Override
+    public void setKey(final String key) {
+        this.key = key;
+    }
+
+    public String getModelId() {
+        return modelId;
+    }
+
+    public void setModelId(final String modelId) {
+        this.modelId = modelId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public boolean isUserWorkflow() {
+        return userWorkflow;
+    }
+
+    public void setUserWorkflow(final boolean userWorkflow) {
+        this.userWorkflow = userWorkflow;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/BpmnProcessTO.java
----------------------------------------------------------------------
diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/BpmnProcessTO.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/BpmnProcessTO.java
deleted file mode 100644
index bb67e3e..0000000
--- a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/BpmnProcessTO.java
+++ /dev/null
@@ -1,72 +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 = "bpmnProcess")
-@XmlType
-public class BpmnProcessTO extends AbstractBaseBean implements EntityTO {
-
-    private static final long serialVersionUID = -7044543391316529128L;
-
-    private String key;
-
-    private String modelId;
-
-    private String name;
-
-    private boolean userWorkflow;
-
-    @Override
-    public String getKey() {
-        return key;
-    }
-
-    @Override
-    public void setKey(final String key) {
-        this.key = key;
-    }
-
-    public String getModelId() {
-        return modelId;
-    }
-
-    public void setModelId(final String modelId) {
-        this.modelId = modelId;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(final String name) {
-        this.name = name;
-    }
-
-    public boolean isUserWorkflow() {
-        return userWorkflow;
-    }
-
-    public void setUserWorkflow(final boolean userWorkflow) {
-        this.userWorkflow = userWorkflow;
-    }
-}