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 2017/08/25 12:22:57 UTC

[1/2] syncope git commit: [SYNCOPE-1201] Conditions are now set seprated for each available AnyType

Repository: syncope
Updated Branches:
  refs/heads/2_0_X 1aacfe137 -> d8c105e9e
  refs/heads/master 95268987f -> 126a323f5


[SYNCOPE-1201] Conditions are now set seprated for each available AnyType


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

Branch: refs/heads/2_0_X
Commit: d8c105e9e97aa59dada5613505cba14d7fca5e56
Parents: 1aacfe1
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Aug 25 14:01:31 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Aug 25 14:22:40 2017 +0200

----------------------------------------------------------------------
 .../console/panels/DynRealmModalPanel.java      | 62 ++++++++++++---
 .../client/console/wizards/DynRealmWrapper.java | 42 ++++++++---
 .../console/wizards/any/DynamicMemberships.java |  4 +-
 .../console/panels/DynRealmModalPanel.html      |  4 +-
 .../syncope/common/lib/to/DynRealmTO.java       | 20 +++--
 .../core/persistence/api/entity/DynRealm.java   | 10 ++-
 .../api/entity/DynRealmMembership.java          | 31 ++++++++
 .../persistence/jpa/dao/JPADynRealmDAO.java     | 35 ++-------
 .../persistence/jpa/entity/JPADynRealm.java     | 35 +++++++--
 .../jpa/entity/JPADynRealmMembership.java       | 79 ++++++++++++++++++++
 .../jpa/entity/JPAEntityFactory.java            |  3 +
 .../persistence/jpa/outer/DynRealmTest.java     | 14 +++-
 .../java/data/DynRealmDataBinderImpl.java       | 63 +++++++++++++---
 .../java/data/GroupDataBinderImpl.java          |  7 +-
 .../apache/syncope/fit/core/DynRealmITCase.java |  6 +-
 15 files changed, 333 insertions(+), 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
index 734bd62..a5e3c68 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
@@ -24,27 +24,36 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.panels.search.AnyObjectSearchPanel;
+import org.apache.syncope.client.console.panels.search.GroupSearchPanel;
+import org.apache.syncope.client.console.panels.search.MapOfListModel;
 import org.apache.syncope.client.console.panels.search.SearchClause;
 import org.apache.syncope.client.console.panels.search.UserSearchPanel;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.DynRealmRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wizards.DynRealmWrapper;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.ResourceModel;
 
 public class DynRealmModalPanel extends AbstractModalPanel<DynRealmWrapper> {
 
     private static final long serialVersionUID = -3773196441177699452L;
 
+    private final AnyTypeRestClient anyTypeRestClient = new AnyTypeRestClient();
+
     private final DynRealmRestClient restClient = new DynRealmRestClient();
 
     private final DynRealmWrapper dynRealmWrapper;
@@ -68,18 +77,53 @@ public class DynRealmModalPanel extends AbstractModalPanel<DynRealmWrapper> {
         key.setRequired(true);
         add(key);
 
-        add(new Accordion("cond", Collections.<ITab>singletonList(
-                new AbstractTab(new ResourceModel("cond", "Dynamic Condition")) {
+        final LoadableDetachableModel<List<AnyTypeTO>> types = new LoadableDetachableModel<List<AnyTypeTO>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<AnyTypeTO> load() {
+                return anyTypeRestClient.listAnyTypes();
+            }
+        };
+
+        add(new ListView<AnyTypeTO>("dynMembershipCond", types) {
 
-            private static final long serialVersionUID = 1037272333056449378L;
+            private static final long serialVersionUID = 9101744072914090143L;
 
             @Override
-            public Panel getPanel(final String panelId) {
-                return new UserSearchPanel.Builder(
-                        new PropertyModel<List<SearchClause>>(dynRealmWrapper, "dynClauses")).
-                        required(false).build(panelId);
+            protected void populateItem(final ListItem<AnyTypeTO> item) {
+                final String key = item.getModelObject().getKey();
+                item.add(new Accordion("dynMembershipCond", Collections.<ITab>singletonList(
+                        new AbstractTab(Model.of(key + " Dynamic Condition")) {
+
+                    private static final long serialVersionUID = 1037272333056449378L;
+
+                    @Override
+                    public Panel getPanel(final String panelId) {
+                        switch (item.getModelObject().getKind()) {
+                            case USER:
+                                return new UserSearchPanel.Builder(
+                                        new MapOfListModel<SearchClause>(dynRealmWrapper, "dynClauses", key)).
+                                        required(false).build(panelId);
+
+                            case GROUP:
+                                return new GroupSearchPanel.Builder(
+                                        new MapOfListModel<SearchClause>(dynRealmWrapper, "dynClauses", key)).
+                                        required(false).build(panelId);
+
+                            case ANY_OBJECT:
+                            default:
+                                return new AnyObjectSearchPanel.Builder(
+                                        key,
+                                        new MapOfListModel<SearchClause>(dynRealmWrapper, "dynClauses", key)).
+                                        required(false).build(panelId);
+                        }
+                    }
+                }), Model.of(StringUtils.isBlank(dynRealmWrapper.getDynMembershipConds().get(key)) ? -1 : 0)).
+                        setOutputMarkupId(true));
             }
-        }), Model.of(StringUtils.isBlank(dynRealmWrapper.getCond()) ? -1 : 0)).setOutputMarkupId(true));
+        });
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java
index e9f5acc..fc46416 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java
@@ -19,12 +19,16 @@
 package org.apache.syncope.client.console.wizards;
 
 import java.io.Serializable;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.syncope.client.console.panels.search.SearchClause;
 import org.apache.syncope.client.console.panels.search.SearchUtils;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder;
 import org.apache.syncope.common.lib.to.DynRealmTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 public class DynRealmWrapper implements Serializable {
 
@@ -32,34 +36,50 @@ public class DynRealmWrapper implements Serializable {
 
     private final DynRealmTO dynRealmTO;
 
-    private List<SearchClause> dynClauses;
+    private Map<String, List<SearchClause>> dynClauses;
 
     public DynRealmWrapper(final DynRealmTO dynRealmTO) {
         this.dynRealmTO = dynRealmTO;
         getDynClauses();
     }
 
-    public final List<SearchClause> getDynClauses() {
+    public final Map<String, List<SearchClause>> getDynClauses() {
         if (this.dynClauses == null) {
-            this.dynClauses = SearchUtils.getSearchClauses(this.dynRealmTO.getCond());
+            this.dynClauses = SearchUtils.getSearchClauses(this.dynRealmTO.getDynMembershipConds());
         }
         return this.dynClauses;
     }
 
-    public void setDynClauses(final List<SearchClause> dynClauses) {
-        this.dynClauses = dynClauses;
+    public void setDynClauses(final Map<String, List<SearchClause>> dynClauses) {
+        this.dynClauses.clear();
+        this.dynClauses.putAll(dynClauses);
     }
 
-    public String getCond() {
-        if (CollectionUtils.isEmpty(this.dynClauses)) {
-            return null;
-        } else {
-            return SearchUtils.buildFIQL(this.dynClauses, SyncopeClient.getUserSearchConditionBuilder());
+    public Map<String, String> getDynMembershipConds() {
+        final Map<String, String> res = new HashMap<>();
+        if (this.dynClauses != null && !this.dynClauses.isEmpty()) {
+            for (Map.Entry<String, List<SearchClause>> entry : this.dynClauses.entrySet()) {
+                if (CollectionUtils.isNotEmpty(entry.getValue())) {
+                    AbstractFiqlSearchConditionBuilder builder = AnyTypeKind.USER.name().equals(entry.getKey())
+                            ? SyncopeClient.getUserSearchConditionBuilder()
+                            : AnyTypeKind.GROUP.name().equals(entry.getKey())
+                            ? SyncopeClient.getGroupSearchConditionBuilder()
+                            : SyncopeClient.getAnyObjectSearchConditionBuilder(entry.getKey());
+
+                    String fiql = SearchUtils.buildFIQL(entry.getValue(), builder);
+                    if (fiql != null) {
+                        res.put(entry.getKey(), fiql);
+                    }
+                }
+            }
         }
+
+        return res;
     }
 
     public DynRealmTO fillDynamicConditions() {
-        this.dynRealmTO.setCond(this.getCond());
+        this.dynRealmTO.getDynMembershipConds().clear();
+        this.dynRealmTO.getDynMembershipConds().putAll(this.getDynMembershipConds());
         return this.dynRealmTO;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
index 5da9273..9dc04e5 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
@@ -107,8 +107,8 @@ public class DynamicMemberships extends WizardStep {
                                 key, new MapOfListModel<SearchClause>(groupWrapper, "aDynClauses", key)).
                                 required(false).build(panelId);
                     }
-                }), Model.of(StringUtils.isBlank(groupWrapper.getADynMembershipConds().get(key)) ? -1 : 0))
-                        .setOutputMarkupId(true));
+                }), Model.of(StringUtils.isBlank(groupWrapper.getADynMembershipConds().get(key)) ? -1 : 0)).
+                        setOutputMarkupId(true));
             }
         });
         // ------------------------

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html
index 3200d9d..9f8fa4c 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html
@@ -20,7 +20,9 @@ under the License.
   <wicket:extend>
     <div class="form-group">
       <span wicket:id="key"/>
-      <div wicket:id="cond"/>
+      <span wicket:id="dynMembershipCond">
+        <div wicket:id="dynMembershipCond"/>
+      </span>
     </div>
   </wicket:extend>
 </html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java
index c218ec6..d3fff01 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java
@@ -18,10 +18,16 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.HashMap;
+import java.util.Map;
 import javax.ws.rs.PathParam;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
 
 @XmlRootElement(name = "dynRealm")
 @XmlType
@@ -31,7 +37,9 @@ public class DynRealmTO extends AbstractBaseBean implements EntityTO {
 
     private String key;
 
-    private String cond;
+    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
+    @JsonIgnore
+    private final Map<String, String> dynMembershipConds = new HashMap<>();
 
     @Override
     public String getKey() {
@@ -44,12 +52,8 @@ public class DynRealmTO extends AbstractBaseBean implements EntityTO {
         this.key = key;
     }
 
-    public String getCond() {
-        return cond;
+    @JsonProperty
+    public Map<String, String> getDynMembershipConds() {
+        return dynMembershipConds;
     }
-
-    public void setCond(final String cond) {
-        this.cond = cond;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java
index e8be2aa..2cf62f3 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java
@@ -18,6 +18,14 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-public interface DynRealm extends DynMembership<Any<?>>, ProvidedKeyEntity {
+import java.util.List;
+
+public interface DynRealm extends ProvidedKeyEntity {
+
+    boolean add(DynRealmMembership dynRealmMembership);
+
+    DynRealmMembership getDynMembership(AnyType anyType);
+
+    List<? extends DynRealmMembership> getDynMemberships();
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealmMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealmMembership.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealmMembership.java
new file mode 100644
index 0000000..3e26583
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealmMembership.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.persistence.api.entity;
+
+public interface DynRealmMembership extends DynMembership<Any<?>> {
+
+    DynRealm getDynRealm();
+
+    void setDynRealm(DynRealm dynRealm);
+
+    AnyType getAnyType();
+
+    void setAnyType(AnyType anyType);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java
index 874f0d3..dfb3d34 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java
@@ -21,11 +21,11 @@ package org.apache.syncope.core.persistence.jpa.dao;
 import java.util.List;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.DynRealmDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
 import org.apache.syncope.core.persistence.jpa.entity.JPADynRealm;
 import org.apache.syncope.core.provisioning.api.event.AnyCreatedUpdatedEvent;
@@ -72,33 +72,11 @@ public class JPADynRealmDAO extends AbstractDAO<DynRealm> implements DynRealmDAO
         DynRealm merged = entityManager().merge(dynRealm);
 
         // refresh dynamic memberships
-        if (merged.getFIQLCond() != null) {
-            clearDynMembers(merged);
+        clearDynMembers(merged);
 
+        for (DynRealmMembership memb : merged.getDynMemberships()) {
             List<Any<?>> matching = searchDAO().search(
-                    SearchCondConverter.convert(merged.getFIQLCond()), AnyTypeKind.USER);
-            for (Any<?> any : matching) {
-                Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
-                insert.setParameter(1, any.getKey());
-                insert.setParameter(2, merged.getKey());
-                insert.executeUpdate();
-
-                publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, any, AuthContextUtils.getDomain()));
-            }
-
-            matching = searchDAO().search(
-                    SearchCondConverter.convert(merged.getFIQLCond()), AnyTypeKind.GROUP);
-            for (Any<?> any : matching) {
-                Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
-                insert.setParameter(1, any.getKey());
-                insert.setParameter(2, merged.getKey());
-                insert.executeUpdate();
-
-                publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, any, AuthContextUtils.getDomain()));
-            }
-
-            matching = searchDAO().search(
-                    SearchCondConverter.convert(merged.getFIQLCond()), AnyTypeKind.ANY_OBJECT);
+                    SearchCondConverter.convert(memb.getFIQLCond()), memb.getAnyType().getKind());
             for (Any<?> any : matching) {
                 Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
                 insert.setParameter(1, any.getKey());
@@ -135,14 +113,15 @@ public class JPADynRealmDAO extends AbstractDAO<DynRealm> implements DynRealmDAO
     @Override
     public void refreshDynMemberships(final Any<?> any) {
         for (DynRealm dynRealm : findAll()) {
-            if (dynRealm.getFIQLCond() != null) {
+            DynRealmMembership memb = dynRealm.getDynMembership(any.getType());
+            if (memb != null) {
                 Query delete = entityManager().createNativeQuery(
                         "DELETE FROM " + DYNMEMB_TABLE + " WHERE dynRealm_id=? AND any_id=?");
                 delete.setParameter(1, dynRealm.getKey());
                 delete.setParameter(2, any.getKey());
                 delete.executeUpdate();
 
-                if (searchDAO().matches(any, SearchCondConverter.convert(dynRealm.getFIQLCond()))) {
+                if (searchDAO().matches(any, SearchCondConverter.convert(memb.getFIQLCond()))) {
                     Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
                     insert.setParameter(1, any.getKey());
                     insert.setParameter(2, dynRealm.getKey());

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java
index 3a0aaa1..04888e8 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java
@@ -18,11 +18,19 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
+import java.util.ArrayList;
+import java.util.List;
 import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.OneToMany;
 import javax.persistence.Table;
-import javax.validation.constraints.NotNull;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.jpa.validation.entity.DynRealmCheck;
 
 @Entity
@@ -35,16 +43,29 @@ public class JPADynRealm extends AbstractProvidedKeyEntity implements DynRealm {
 
     public static final String TABLE = "DynRealm";
 
-    @NotNull
-    private String fiql;
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "dynRealm")
+    private List<JPADynRealmMembership> dynMemberships = new ArrayList<>();
 
     @Override
-    public String getFIQLCond() {
-        return fiql;
+    public boolean add(final DynRealmMembership dynRealmMembership) {
+        checkType(dynRealmMembership, JPADynRealmMembership.class);
+        return this.dynMemberships.add((JPADynRealmMembership) dynRealmMembership);
     }
 
     @Override
-    public void setFIQLCond(final String fiql) {
-        this.fiql = fiql;
+    public DynRealmMembership getDynMembership(final AnyType anyType) {
+        return IterableUtils.find(dynMemberships, new Predicate<DynRealmMembership>() {
+
+            @Override
+            public boolean evaluate(final DynRealmMembership dynRealmMembership) {
+                return anyType != null && anyType.equals(dynRealmMembership.getAnyType());
+            }
+        });
     }
+
+    @Override
+    public List<? extends DynRealmMembership> getDynMemberships() {
+        return dynMemberships;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealmMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealmMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealmMembership.java
new file mode 100644
index 0000000..c97773a
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealmMembership.java
@@ -0,0 +1,79 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
+
+@Entity
+@Table(name = JPADynRealmMembership.TABLE)
+public class JPADynRealmMembership extends AbstractGeneratedKeyEntity implements DynRealmMembership {
+
+    private static final long serialVersionUID = 8157856850557493134L;
+
+    public static final String TABLE = "DynRealmMembership";
+
+    @OneToOne
+    private JPADynRealm dynRealm;
+
+    @ManyToOne
+    private JPAAnyType anyType;
+
+    @NotNull
+    private String fiql;
+
+    @Override
+    public DynRealm getDynRealm() {
+        return dynRealm;
+    }
+
+    @Override
+    public void setDynRealm(final DynRealm dynRealm) {
+        checkType(dynRealm, JPADynRealm.class);
+        this.dynRealm = (JPADynRealm) dynRealm;
+    }
+
+    @Override
+    public AnyType getAnyType() {
+        return anyType;
+    }
+
+    @Override
+    public void setAnyType(final AnyType anyType) {
+        checkType(anyType, JPAAnyType.class);
+        this.anyType = (JPAAnyType) anyType;
+    }
+
+    @Override
+    public String getFIQLCond() {
+        return fiql;
+    }
+
+    @Override
+    public void setFIQLCond(final String fiql) {
+        this.fiql = fiql;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
index 66894e5..985bfa0 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
@@ -126,6 +126,7 @@ import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAOrgUnit;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResourceHistoryConf;
 import org.apache.syncope.core.persistence.api.entity.resource.OrgUnitItem;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResourceHistoryConf;
@@ -145,6 +146,8 @@ public class JPAEntityFactory implements EntityFactory {
             result = (E) new JPARealm();
         } else if (reference.equals(DynRealm.class)) {
             result = (E) new JPADynRealm();
+        } else if (reference.equals(DynRealmMembership.class)) {
+            result = (E) new JPADynRealmMembership();
         } else if (reference.equals(AnyTemplateRealm.class)) {
             result = (E) new JPAAnyTemplateRealm();
         } else if (reference.equals(AccountPolicy.class)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java
index 307b865..db47035 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java
@@ -26,11 +26,13 @@ import static org.junit.Assert.fail;
 import java.util.List;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.DynRealmDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
 import org.junit.Test;
@@ -41,6 +43,9 @@ import org.springframework.transaction.annotation.Transactional;
 public class DynRealmTest extends AbstractTest {
 
     @Autowired
+    private AnyTypeDAO anyTypeDAO;
+
+    @Autowired
     private DynRealmDAO dynRealmDAO;
 
     @Autowired
@@ -53,7 +58,14 @@ public class DynRealmTest extends AbstractTest {
     public void misc() {
         DynRealm dynRealm = entityFactory.newEntity(DynRealm.class);
         dynRealm.setKey("/name");
-        dynRealm.setFIQLCond("cool==true");
+
+        DynRealmMembership memb = entityFactory.newEntity(DynRealmMembership.class);
+        memb.setDynRealm(dynRealm);
+        memb.setAnyType(anyTypeDAO.findUser());
+        memb.setFIQLCond("cool==true");
+        
+        dynRealm.add(memb);
+        memb.setDynRealm(dynRealm);
 
         // invalid key (starts with /)
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java
index 9a61f17..cf324ea 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java
@@ -18,46 +18,84 @@
  */
 package org.apache.syncope.core.provisioning.java.data;
 
+import java.util.Iterator;
+import java.util.Map;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.DynRealmTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.DynRealmDAO;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
 import org.apache.syncope.core.provisioning.api.data.DynRealmDataBinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 @Component
 public class DynRealmDataBinderImpl implements DynRealmDataBinder {
 
+    private static final Logger LOG = LoggerFactory.getLogger(DynRealmDataBinder.class);
+
+    @Autowired
+    private AnyTypeDAO anyTypeDAO;
+
     @Autowired
     private DynRealmDAO dynRealmDAO;
 
     @Autowired
     private EntityFactory entityFactory;
 
+    private void setDynMembership(final DynRealm dynRealm, final AnyType anyType, final String dynMembershipFIQL) {
+        SearchCond dynMembershipCond = SearchCondConverter.convert(dynMembershipFIQL);
+        if (!dynMembershipCond.isValid()) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSearchExpression);
+            sce.getElements().add(dynMembershipFIQL);
+            throw sce;
+        }
+
+        DynRealmMembership dynMembership;
+        if (dynRealm.getDynMembership(anyType) == null) {
+            dynMembership = entityFactory.newEntity(DynRealmMembership.class);
+            dynMembership.setDynRealm(dynRealm);
+            dynMembership.setAnyType(anyType);
+            dynRealm.add(dynMembership);
+        } else {
+            dynMembership = dynRealm.getDynMembership(anyType);
+        }
+        dynMembership.setFIQLCond(dynMembershipFIQL);
+    }
+
     @Override
     public DynRealm create(final DynRealmTO dynRealmTO) {
         return update(entityFactory.newEntity(DynRealm.class), dynRealmTO);
     }
 
     @Override
-    public DynRealm update(final DynRealm dynRealm, final DynRealmTO dynRealmTO) {
-        dynRealm.setKey(dynRealmTO.getKey());
+    public DynRealm update(final DynRealm toBeUpdated, final DynRealmTO dynRealmTO) {
+        toBeUpdated.setKey(dynRealmTO.getKey());
+        DynRealm dynRealm = dynRealmDAO.save(toBeUpdated);
 
-        SearchCond cond = null;
-        if (dynRealmTO.getCond() != null) {
-            cond = SearchCondConverter.convert(dynRealmTO.getCond());
+        for (Iterator<? extends DynRealmMembership> itor = dynRealm.getDynMemberships().iterator(); itor.hasNext();) {
+            DynRealmMembership memb = itor.next();
+            memb.setDynRealm(null);
+            itor.remove();
         }
-        if (cond == null || !cond.isValid()) {
-            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSearchExpression);
-            sce.getElements().add(dynRealmTO.getCond());
-            throw sce;
+        dynRealmDAO.clearDynMembers(dynRealm);
+
+        for (Map.Entry<String, String> entry : dynRealmTO.getDynMembershipConds().entrySet()) {
+            AnyType anyType = anyTypeDAO.find(entry.getKey());
+            if (anyType == null) {
+                LOG.warn("Ignoring invalid {}: {}", AnyType.class.getSimpleName(), entry.getKey());
+            } else {
+                setDynMembership(dynRealm, anyType, entry.getValue());
+            }
         }
-        dynRealm.setFIQLCond(dynRealmTO.getCond());
 
         return dynRealmDAO.save(dynRealm);
     }
@@ -67,7 +105,10 @@ public class DynRealmDataBinderImpl implements DynRealmDataBinder {
         DynRealmTO dynRealmTO = new DynRealmTO();
 
         dynRealmTO.setKey(dynRealm.getKey());
-        dynRealmTO.setCond(dynRealm.getFIQLCond());
+
+        for (DynRealmMembership memb : dynRealm.getDynMemberships()) {
+            dynRealmTO.getDynMembershipConds().put(memb.getAnyType().getKey(), memb.getFIQLCond());
+        }
 
         return dynRealmTO;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
index 787353c..92fd3ab 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
@@ -72,13 +72,18 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
             sce.getElements().add(dynMembershipFIQL);
             throw sce;
         }
+        if (anyType.getKind() == AnyTypeKind.GROUP) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidAnyType);
+            sce.getElements().add(anyType.getKind().name());
+            throw sce;
+        }
 
         DynGroupMembership<?> dynMembership;
         if (anyType.getKind() == AnyTypeKind.ANY_OBJECT && group.getADynMembership(anyType) == null) {
             dynMembership = entityFactory.newEntity(ADynGroupMembership.class);
             dynMembership.setGroup(group);
-            group.add((ADynGroupMembership) dynMembership);
             ((ADynGroupMembership) dynMembership).setAnyType(anyType);
+            group.add((ADynGroupMembership) dynMembership);
         } else if (anyType.getKind() == AnyTypeKind.USER && group.getUDynMembership() == null) {
             dynMembership = entityFactory.newEntity(UDynGroupMembership.class);
             dynMembership.setGroup(group);

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c105e9/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
index 7d745a7..91ac3c5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
@@ -40,6 +40,7 @@ import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.RoleTO;
 import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
@@ -58,7 +59,7 @@ public class DynRealmITCase extends AbstractITCase {
         try {
             dynRealm = new DynRealmTO();
             dynRealm.setKey("/name" + getUUIDString());
-            dynRealm.setCond("cool==true");
+            dynRealm.getDynMembershipConds().put(AnyTypeKind.USER.name(), "cool==true");
 
             // invalid key (starts with /)
             try {
@@ -95,7 +96,8 @@ public class DynRealmITCase extends AbstractITCase {
             // 1. create dynamic realm for all users and groups having resource-ldap assigned
             dynRealm = new DynRealmTO();
             dynRealm.setKey("LDAPLovers" + getUUIDString());
-            dynRealm.setCond("$resources==resource-ldap");
+            dynRealm.getDynMembershipConds().put(AnyTypeKind.USER.name(), "$resources==resource-ldap");
+            dynRealm.getDynMembershipConds().put(AnyTypeKind.GROUP.name(), "$resources==resource-ldap");
 
             Response response = dynRealmService.create(dynRealm);
             dynRealm = getObject(response.getLocation(), DynRealmService.class, DynRealmTO.class);


[2/2] syncope git commit: [SYNCOPE-1201] Conditions are now set seprated for each available AnyType

Posted by il...@apache.org.
[SYNCOPE-1201] Conditions are now set seprated for each available AnyType


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

Branch: refs/heads/master
Commit: 126a323f5c99bd2f62965492188cff84847fd526
Parents: 9526898
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Aug 25 14:01:31 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Aug 25 14:22:46 2017 +0200

----------------------------------------------------------------------
 .../console/panels/DynRealmModalPanel.java      | 65 +++++++++++++---
 .../client/console/wizards/DynRealmWrapper.java | 41 +++++++---
 .../console/wizards/any/DynamicMemberships.java |  4 +-
 .../console/panels/DynRealmModalPanel.html      |  4 +-
 .../syncope/common/lib/to/DynRealmTO.java       | 20 +++--
 .../core/persistence/api/entity/DynRealm.java   | 11 ++-
 .../api/entity/DynRealmMembership.java          | 31 ++++++++
 .../persistence/jpa/dao/JPADynRealmDAO.java     | 64 ++++++----------
 .../persistence/jpa/entity/JPADynRealm.java     | 30 ++++++--
 .../jpa/entity/JPADynRealmMembership.java       | 79 ++++++++++++++++++++
 .../jpa/entity/JPAEntityFactory.java            |  3 +
 .../persistence/jpa/entity/group/JPAGroup.java  | 10 ++-
 .../persistence/jpa/outer/DynRealmTest.java     | 14 +++-
 .../java/data/DynRealmDataBinderImpl.java       | 64 +++++++++++++---
 .../java/data/GroupDataBinderImpl.java          |  7 +-
 .../apache/syncope/fit/core/DynRealmITCase.java |  6 +-
 16 files changed, 350 insertions(+), 103 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
index 734bd62..f1a0b69 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
@@ -24,27 +24,35 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.panels.search.SearchClause;
+import org.apache.syncope.client.console.panels.search.AnyObjectSearchPanel;
+import org.apache.syncope.client.console.panels.search.GroupSearchPanel;
+import org.apache.syncope.client.console.panels.search.MapOfListModel;
 import org.apache.syncope.client.console.panels.search.UserSearchPanel;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.DynRealmRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wizards.DynRealmWrapper;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.ResourceModel;
 
 public class DynRealmModalPanel extends AbstractModalPanel<DynRealmWrapper> {
 
     private static final long serialVersionUID = -3773196441177699452L;
 
+    private final AnyTypeRestClient anyTypeRestClient = new AnyTypeRestClient();
+
     private final DynRealmRestClient restClient = new DynRealmRestClient();
 
     private final DynRealmWrapper dynRealmWrapper;
@@ -63,23 +71,58 @@ public class DynRealmModalPanel extends AbstractModalPanel<DynRealmWrapper> {
         modal.setFormModel(dynRealmWrapper);
 
         AjaxTextFieldPanel key = new AjaxTextFieldPanel(
-                "key", "key", new PropertyModel<String>(dynRealmWrapper.getInnerObject(), "key"), false);
+                "key", "key", new PropertyModel<>(dynRealmWrapper.getInnerObject(), "key"), false);
         key.setReadOnly(!create);
         key.setRequired(true);
         add(key);
 
-        add(new Accordion("cond", Collections.<ITab>singletonList(
-                new AbstractTab(new ResourceModel("cond", "Dynamic Condition")) {
+        final LoadableDetachableModel<List<AnyTypeTO>> types = new LoadableDetachableModel<List<AnyTypeTO>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<AnyTypeTO> load() {
+                return anyTypeRestClient.listAnyTypes();
+            }
+        };
+
+        add(new ListView<AnyTypeTO>("dynMembershipCond", types) {
 
-            private static final long serialVersionUID = 1037272333056449378L;
+            private static final long serialVersionUID = 9101744072914090143L;
 
             @Override
-            public Panel getPanel(final String panelId) {
-                return new UserSearchPanel.Builder(
-                        new PropertyModel<List<SearchClause>>(dynRealmWrapper, "dynClauses")).
-                        required(false).build(panelId);
+            protected void populateItem(final ListItem<AnyTypeTO> item) {
+                final String key = item.getModelObject().getKey();
+                item.add(new Accordion("dynMembershipCond", Collections.<ITab>singletonList(
+                        new AbstractTab(Model.of(key + " Dynamic Condition")) {
+
+                    private static final long serialVersionUID = 1037272333056449378L;
+
+                    @Override
+                    public Panel getPanel(final String panelId) {
+                        switch (item.getModelObject().getKind()) {
+                            case USER:
+                                return new UserSearchPanel.Builder(
+                                        new MapOfListModel<>(dynRealmWrapper, "dynClauses", key)).
+                                        required(false).build(panelId);
+
+                            case GROUP:
+                                return new GroupSearchPanel.Builder(
+                                        new MapOfListModel<>(dynRealmWrapper, "dynClauses", key)).
+                                        required(false).build(panelId);
+
+                            case ANY_OBJECT:
+                            default:
+                                return new AnyObjectSearchPanel.Builder(
+                                        key,
+                                        new MapOfListModel<>(dynRealmWrapper, "dynClauses", key)).
+                                        required(false).build(panelId);
+                        }
+                    }
+                }), Model.of(StringUtils.isBlank(dynRealmWrapper.getDynMembershipConds().get(key)) ? -1 : 0)).
+                        setOutputMarkupId(true));
             }
-        }), Model.of(StringUtils.isBlank(dynRealmWrapper.getCond()) ? -1 : 0)).setOutputMarkupId(true));
+        });
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java
index e9f5acc..de013a9 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/DynRealmWrapper.java
@@ -19,12 +19,16 @@
 package org.apache.syncope.client.console.wizards;
 
 import java.io.Serializable;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.syncope.client.console.panels.search.SearchClause;
 import org.apache.syncope.client.console.panels.search.SearchUtils;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder;
 import org.apache.syncope.common.lib.to.DynRealmTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 public class DynRealmWrapper implements Serializable {
 
@@ -32,34 +36,49 @@ public class DynRealmWrapper implements Serializable {
 
     private final DynRealmTO dynRealmTO;
 
-    private List<SearchClause> dynClauses;
+    private Map<String, List<SearchClause>> dynClauses;
 
     public DynRealmWrapper(final DynRealmTO dynRealmTO) {
         this.dynRealmTO = dynRealmTO;
         getDynClauses();
     }
 
-    public final List<SearchClause> getDynClauses() {
+    public final Map<String, List<SearchClause>> getDynClauses() {
         if (this.dynClauses == null) {
-            this.dynClauses = SearchUtils.getSearchClauses(this.dynRealmTO.getCond());
+            this.dynClauses = SearchUtils.getSearchClauses(this.dynRealmTO.getDynMembershipConds());
         }
         return this.dynClauses;
     }
 
-    public void setDynClauses(final List<SearchClause> dynClauses) {
-        this.dynClauses = dynClauses;
+    public void setDynClauses(final Map<String, List<SearchClause>> dynClauses) {
+        this.dynClauses.clear();
+        this.dynClauses.putAll(dynClauses);
     }
 
-    public String getCond() {
-        if (CollectionUtils.isEmpty(this.dynClauses)) {
-            return null;
-        } else {
-            return SearchUtils.buildFIQL(this.dynClauses, SyncopeClient.getUserSearchConditionBuilder());
+    public Map<String, String> getDynMembershipConds() {
+        final Map<String, String> res = new HashMap<>();
+        if (this.dynClauses != null && !this.dynClauses.isEmpty()) {
+            this.dynClauses.entrySet().stream().
+                    filter(entry -> (CollectionUtils.isNotEmpty(entry.getValue()))).
+                    forEachOrdered(entry -> {
+                        AbstractFiqlSearchConditionBuilder builder = AnyTypeKind.USER.name().equals(entry.getKey())
+                                ? SyncopeClient.getUserSearchConditionBuilder()
+                                : AnyTypeKind.GROUP.name().equals(entry.getKey())
+                                ? SyncopeClient.getGroupSearchConditionBuilder()
+                                : SyncopeClient.getAnyObjectSearchConditionBuilder(entry.getKey());
+                        String fiql = SearchUtils.buildFIQL(entry.getValue(), builder);
+                        if (fiql != null) {
+                            res.put(entry.getKey(), fiql);
+                        }
+                    });
         }
+
+        return res;
     }
 
     public DynRealmTO fillDynamicConditions() {
-        this.dynRealmTO.setCond(this.getCond());
+        this.dynRealmTO.getDynMembershipConds().clear();
+        this.dynRealmTO.getDynMembershipConds().putAll(this.getDynMembershipConds());
         return this.dynRealmTO;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
index da95dac..bf59b5f 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
@@ -100,8 +100,8 @@ public class DynamicMemberships extends WizardStep {
                                 key, new MapOfListModel<>(groupWrapper, "aDynClauses", key)).
                                 required(false).build(panelId);
                     }
-                }), Model.of(StringUtils.isBlank(groupWrapper.getADynMembershipConds().get(key)) ? -1 : 0))
-                        .setOutputMarkupId(true));
+                }), Model.of(StringUtils.isBlank(groupWrapper.getADynMembershipConds().get(key)) ? -1 : 0)).
+                        setOutputMarkupId(true));
             }
         });
         // ------------------------

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html
index 3200d9d..9f8fa4c 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/DynRealmModalPanel.html
@@ -20,7 +20,9 @@ under the License.
   <wicket:extend>
     <div class="form-group">
       <span wicket:id="key"/>
-      <div wicket:id="cond"/>
+      <span wicket:id="dynMembershipCond">
+        <div wicket:id="dynMembershipCond"/>
+      </span>
     </div>
   </wicket:extend>
 </html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java
index c218ec6..d3fff01 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DynRealmTO.java
@@ -18,10 +18,16 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.HashMap;
+import java.util.Map;
 import javax.ws.rs.PathParam;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
 
 @XmlRootElement(name = "dynRealm")
 @XmlType
@@ -31,7 +37,9 @@ public class DynRealmTO extends AbstractBaseBean implements EntityTO {
 
     private String key;
 
-    private String cond;
+    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
+    @JsonIgnore
+    private final Map<String, String> dynMembershipConds = new HashMap<>();
 
     @Override
     public String getKey() {
@@ -44,12 +52,8 @@ public class DynRealmTO extends AbstractBaseBean implements EntityTO {
         this.key = key;
     }
 
-    public String getCond() {
-        return cond;
+    @JsonProperty
+    public Map<String, String> getDynMembershipConds() {
+        return dynMembershipConds;
     }
-
-    public void setCond(final String cond) {
-        this.cond = cond;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java
index e8be2aa..711d251 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealm.java
@@ -18,6 +18,15 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-public interface DynRealm extends DynMembership<Any<?>>, ProvidedKeyEntity {
+import java.util.List;
+import java.util.Optional;
+
+public interface DynRealm extends ProvidedKeyEntity {
+
+    boolean add(DynRealmMembership dynRealmMembership);
+
+    Optional<? extends DynRealmMembership> getDynMembership(AnyType anyType);
+
+    List<? extends DynRealmMembership> getDynMemberships();
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealmMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealmMembership.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealmMembership.java
new file mode 100644
index 0000000..3e26583
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynRealmMembership.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.persistence.api.entity;
+
+public interface DynRealmMembership extends DynMembership<Any<?>> {
+
+    DynRealm getDynRealm();
+
+    void setDynRealm(DynRealm dynRealm);
+
+    AnyType getAnyType();
+
+    void setAnyType(AnyType anyType);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java
index 874f0d3..1c84be5 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADynRealmDAO.java
@@ -19,13 +19,14 @@
 package org.apache.syncope.core.persistence.jpa.dao;
 
 import java.util.List;
+import java.util.Optional;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.DynRealmDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
 import org.apache.syncope.core.persistence.jpa.entity.JPADynRealm;
 import org.apache.syncope.core.provisioning.api.event.AnyCreatedUpdatedEvent;
@@ -72,42 +73,21 @@ public class JPADynRealmDAO extends AbstractDAO<DynRealm> implements DynRealmDAO
         DynRealm merged = entityManager().merge(dynRealm);
 
         // refresh dynamic memberships
-        if (merged.getFIQLCond() != null) {
-            clearDynMembers(merged);
-
-            List<Any<?>> matching = searchDAO().search(
-                    SearchCondConverter.convert(merged.getFIQLCond()), AnyTypeKind.USER);
-            for (Any<?> any : matching) {
-                Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
-                insert.setParameter(1, any.getKey());
-                insert.setParameter(2, merged.getKey());
-                insert.executeUpdate();
-
-                publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, any, AuthContextUtils.getDomain()));
-            }
-
-            matching = searchDAO().search(
-                    SearchCondConverter.convert(merged.getFIQLCond()), AnyTypeKind.GROUP);
-            for (Any<?> any : matching) {
-                Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
-                insert.setParameter(1, any.getKey());
-                insert.setParameter(2, merged.getKey());
-                insert.executeUpdate();
-
-                publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, any, AuthContextUtils.getDomain()));
-            }
-
-            matching = searchDAO().search(
-                    SearchCondConverter.convert(merged.getFIQLCond()), AnyTypeKind.ANY_OBJECT);
-            for (Any<?> any : matching) {
-                Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
-                insert.setParameter(1, any.getKey());
-                insert.setParameter(2, merged.getKey());
-                insert.executeUpdate();
-
-                publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, any, AuthContextUtils.getDomain()));
-            }
-        }
+        clearDynMembers(merged);
+
+        merged.getDynMemberships().stream().map(memb -> searchDAO().search(
+                SearchCondConverter.convert(memb.getFIQLCond()), memb.getAnyType().getKind())).
+                forEachOrdered(matching -> {
+                    matching.forEach(any -> {
+                        Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE
+                                + " VALUES(?, ?)");
+                        insert.setParameter(1, any.getKey());
+                        insert.setParameter(2, merged.getKey());
+                        insert.executeUpdate();
+
+                        publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, any, AuthContextUtils.getDomain()));
+                    });
+                });
 
         return merged;
     }
@@ -134,22 +114,22 @@ public class JPADynRealmDAO extends AbstractDAO<DynRealm> implements DynRealmDAO
     @Transactional
     @Override
     public void refreshDynMemberships(final Any<?> any) {
-        for (DynRealm dynRealm : findAll()) {
-            if (dynRealm.getFIQLCond() != null) {
+        findAll().forEach(dynRealm -> {
+            Optional<? extends DynRealmMembership> memb = dynRealm.getDynMembership(any.getType());
+            if (memb.isPresent()) {
                 Query delete = entityManager().createNativeQuery(
                         "DELETE FROM " + DYNMEMB_TABLE + " WHERE dynRealm_id=? AND any_id=?");
                 delete.setParameter(1, dynRealm.getKey());
                 delete.setParameter(2, any.getKey());
                 delete.executeUpdate();
-
-                if (searchDAO().matches(any, SearchCondConverter.convert(dynRealm.getFIQLCond()))) {
+                if (searchDAO().matches(any, SearchCondConverter.convert(memb.get().getFIQLCond()))) {
                     Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
                     insert.setParameter(1, any.getKey());
                     insert.setParameter(2, dynRealm.getKey());
                     insert.executeUpdate();
                 }
             }
-        }
+        });
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java
index 3a0aaa1..a92cb41 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealm.java
@@ -18,11 +18,18 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
 import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.OneToMany;
 import javax.persistence.Table;
-import javax.validation.constraints.NotNull;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.jpa.validation.entity.DynRealmCheck;
 
 @Entity
@@ -35,16 +42,25 @@ public class JPADynRealm extends AbstractProvidedKeyEntity implements DynRealm {
 
     public static final String TABLE = "DynRealm";
 
-    @NotNull
-    private String fiql;
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "dynRealm")
+    private List<JPADynRealmMembership> dynMemberships = new ArrayList<>();
 
     @Override
-    public String getFIQLCond() {
-        return fiql;
+    public boolean add(final DynRealmMembership dynRealmMembership) {
+        checkType(dynRealmMembership, JPADynRealmMembership.class);
+        return this.dynMemberships.add((JPADynRealmMembership) dynRealmMembership);
     }
 
     @Override
-    public void setFIQLCond(final String fiql) {
-        this.fiql = fiql;
+    public Optional<? extends DynRealmMembership> getDynMembership(final AnyType anyType) {
+        return dynMemberships.stream().
+                filter(dynRealmMembership -> anyType != null && anyType.equals(dynRealmMembership.getAnyType())).
+                findFirst();
     }
+
+    @Override
+    public List<? extends DynRealmMembership> getDynMemberships() {
+        return dynMemberships;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealmMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealmMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealmMembership.java
new file mode 100644
index 0000000..c97773a
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADynRealmMembership.java
@@ -0,0 +1,79 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
+
+@Entity
+@Table(name = JPADynRealmMembership.TABLE)
+public class JPADynRealmMembership extends AbstractGeneratedKeyEntity implements DynRealmMembership {
+
+    private static final long serialVersionUID = 8157856850557493134L;
+
+    public static final String TABLE = "DynRealmMembership";
+
+    @OneToOne
+    private JPADynRealm dynRealm;
+
+    @ManyToOne
+    private JPAAnyType anyType;
+
+    @NotNull
+    private String fiql;
+
+    @Override
+    public DynRealm getDynRealm() {
+        return dynRealm;
+    }
+
+    @Override
+    public void setDynRealm(final DynRealm dynRealm) {
+        checkType(dynRealm, JPADynRealm.class);
+        this.dynRealm = (JPADynRealm) dynRealm;
+    }
+
+    @Override
+    public AnyType getAnyType() {
+        return anyType;
+    }
+
+    @Override
+    public void setAnyType(final AnyType anyType) {
+        checkType(anyType, JPAAnyType.class);
+        this.anyType = (JPAAnyType) anyType;
+    }
+
+    @Override
+    public String getFIQLCond() {
+        return fiql;
+    }
+
+    @Override
+    public void setFIQLCond(final String fiql) {
+        this.fiql = fiql;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
index 66894e5..985bfa0 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
@@ -126,6 +126,7 @@ import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAOrgUnit;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResourceHistoryConf;
 import org.apache.syncope.core.persistence.api.entity.resource.OrgUnitItem;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResourceHistoryConf;
@@ -145,6 +146,8 @@ public class JPAEntityFactory implements EntityFactory {
             result = (E) new JPARealm();
         } else if (reference.equals(DynRealm.class)) {
             result = (E) new JPADynRealm();
+        } else if (reference.equals(DynRealmMembership.class)) {
+            result = (E) new JPADynRealmMembership();
         } else if (reference.equals(AnyTemplateRealm.class)) {
             result = (E) new JPAAnyTemplateRealm();
         } else if (reference.equals(AccountPolicy.class)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
index 2bddf1c..53ef4fb 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
@@ -209,8 +209,9 @@ public class JPAGroup extends AbstractAny<GPlainAttr> implements Group {
 
     @Override
     public Optional<? extends ADynGroupMembership> getADynMembership(final AnyType anyType) {
-        return aDynMemberships.stream().filter(dynGroupMembership
-                -> anyType != null && anyType.equals(dynGroupMembership.getAnyType())).findFirst();
+        return aDynMemberships.stream().
+                filter(dynGroupMembership -> anyType != null && anyType.equals(dynGroupMembership.getAnyType())).
+                findFirst();
     }
 
     @Override
@@ -226,8 +227,9 @@ public class JPAGroup extends AbstractAny<GPlainAttr> implements Group {
 
     @Override
     public Optional<? extends TypeExtension> getTypeExtension(final AnyType anyType) {
-        return typeExtensions.stream().filter(typeExtension
-                -> typeExtension.getAnyType().equals(anyType)).findFirst();
+        return typeExtensions.stream().
+                filter(typeExtension -> typeExtension.getAnyType().equals(anyType)).
+                findFirst();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java
index 307b865..db47035 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/DynRealmTest.java
@@ -26,11 +26,13 @@ import static org.junit.Assert.fail;
 import java.util.List;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.DynRealmDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
 import org.junit.Test;
@@ -41,6 +43,9 @@ import org.springframework.transaction.annotation.Transactional;
 public class DynRealmTest extends AbstractTest {
 
     @Autowired
+    private AnyTypeDAO anyTypeDAO;
+
+    @Autowired
     private DynRealmDAO dynRealmDAO;
 
     @Autowired
@@ -53,7 +58,14 @@ public class DynRealmTest extends AbstractTest {
     public void misc() {
         DynRealm dynRealm = entityFactory.newEntity(DynRealm.class);
         dynRealm.setKey("/name");
-        dynRealm.setFIQLCond("cool==true");
+
+        DynRealmMembership memb = entityFactory.newEntity(DynRealmMembership.class);
+        memb.setDynRealm(dynRealm);
+        memb.setAnyType(anyTypeDAO.findUser());
+        memb.setFIQLCond("cool==true");
+        
+        dynRealm.add(memb);
+        memb.setDynRealm(dynRealm);
 
         // invalid key (starts with /)
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java
index 9a61f17..6973e1e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DynRealmDataBinderImpl.java
@@ -18,46 +18,83 @@
  */
 package org.apache.syncope.core.provisioning.java.data;
 
+import java.util.Iterator;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.DynRealmTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.DynRealmDAO;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
+import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
 import org.apache.syncope.core.provisioning.api.data.DynRealmDataBinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 @Component
 public class DynRealmDataBinderImpl implements DynRealmDataBinder {
 
+    private static final Logger LOG = LoggerFactory.getLogger(DynRealmDataBinder.class);
+
+    @Autowired
+    private AnyTypeDAO anyTypeDAO;
+
     @Autowired
     private DynRealmDAO dynRealmDAO;
 
     @Autowired
     private EntityFactory entityFactory;
 
+    private void setDynMembership(final DynRealm dynRealm, final AnyType anyType, final String dynMembershipFIQL) {
+        SearchCond dynMembershipCond = SearchCondConverter.convert(dynMembershipFIQL);
+        if (!dynMembershipCond.isValid()) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSearchExpression);
+            sce.getElements().add(dynMembershipFIQL);
+            throw sce;
+        }
+
+        DynRealmMembership dynMembership;
+        if (dynRealm.getDynMembership(anyType).isPresent()) {
+            dynMembership = dynRealm.getDynMembership(anyType).get();
+        } else {
+            dynMembership = entityFactory.newEntity(DynRealmMembership.class);
+            dynMembership.setDynRealm(dynRealm);
+            dynMembership.setAnyType(anyType);
+            dynRealm.add(dynMembership);
+        }
+        dynMembership.setFIQLCond(dynMembershipFIQL);
+    }
+
     @Override
     public DynRealm create(final DynRealmTO dynRealmTO) {
         return update(entityFactory.newEntity(DynRealm.class), dynRealmTO);
     }
 
     @Override
-    public DynRealm update(final DynRealm dynRealm, final DynRealmTO dynRealmTO) {
-        dynRealm.setKey(dynRealmTO.getKey());
+    public DynRealm update(final DynRealm toBeUpdated, final DynRealmTO dynRealmTO) {
+        toBeUpdated.setKey(dynRealmTO.getKey());
+        DynRealm dynRealm = dynRealmDAO.save(toBeUpdated);
 
-        SearchCond cond = null;
-        if (dynRealmTO.getCond() != null) {
-            cond = SearchCondConverter.convert(dynRealmTO.getCond());
+        for (Iterator<? extends DynRealmMembership> itor = dynRealm.getDynMemberships().iterator(); itor.hasNext();) {
+            DynRealmMembership memb = itor.next();
+            memb.setDynRealm(null);
+            itor.remove();
         }
-        if (cond == null || !cond.isValid()) {
-            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSearchExpression);
-            sce.getElements().add(dynRealmTO.getCond());
-            throw sce;
-        }
-        dynRealm.setFIQLCond(dynRealmTO.getCond());
+        dynRealmDAO.clearDynMembers(dynRealm);
+
+        dynRealmTO.getDynMembershipConds().entrySet().forEach(entry -> {
+            AnyType anyType = anyTypeDAO.find(entry.getKey());
+            if (anyType == null) {
+                LOG.warn("Ignoring invalid {}: {}", AnyType.class.getSimpleName(), entry.getKey());
+            } else {
+                setDynMembership(dynRealm, anyType, entry.getValue());
+            }
+        });
 
         return dynRealmDAO.save(dynRealm);
     }
@@ -67,7 +104,10 @@ public class DynRealmDataBinderImpl implements DynRealmDataBinder {
         DynRealmTO dynRealmTO = new DynRealmTO();
 
         dynRealmTO.setKey(dynRealm.getKey());
-        dynRealmTO.setCond(dynRealm.getFIQLCond());
+
+        dynRealm.getDynMemberships().forEach(memb -> {
+            dynRealmTO.getDynMembershipConds().put(memb.getAnyType().getKey(), memb.getFIQLCond());
+        });
 
         return dynRealmTO;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
index 3105e19..8ba464e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
@@ -69,13 +69,18 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
             sce.getElements().add(dynMembershipFIQL);
             throw sce;
         }
+        if (anyType.getKind() == AnyTypeKind.GROUP) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidAnyType);
+            sce.getElements().add(anyType.getKind().name());
+            throw sce;
+        }
 
         DynGroupMembership<?> dynMembership;
         if (anyType.getKind() == AnyTypeKind.ANY_OBJECT && !group.getADynMembership(anyType).isPresent()) {
             dynMembership = entityFactory.newEntity(ADynGroupMembership.class);
             dynMembership.setGroup(group);
-            group.add((ADynGroupMembership) dynMembership);
             ((ADynGroupMembership) dynMembership).setAnyType(anyType);
+            group.add((ADynGroupMembership) dynMembership);
         } else if (anyType.getKind() == AnyTypeKind.USER && group.getUDynMembership() == null) {
             dynMembership = entityFactory.newEntity(UDynGroupMembership.class);
             dynMembership.setGroup(group);

http://git-wip-us.apache.org/repos/asf/syncope/blob/126a323f/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
index 3506b8d..2772092 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
@@ -38,6 +38,7 @@ import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.RoleTO;
 import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
@@ -56,7 +57,7 @@ public class DynRealmITCase extends AbstractITCase {
         try {
             dynRealm = new DynRealmTO();
             dynRealm.setKey("/name" + getUUIDString());
-            dynRealm.setCond("cool==true");
+            dynRealm.getDynMembershipConds().put(AnyTypeKind.USER.name(), "cool==true");
 
             // invalid key (starts with /)
             try {
@@ -93,7 +94,8 @@ public class DynRealmITCase extends AbstractITCase {
             // 1. create dynamic realm for all users and groups having resource-ldap assigned
             dynRealm = new DynRealmTO();
             dynRealm.setKey("LDAPLovers" + getUUIDString());
-            dynRealm.setCond("$resources==resource-ldap");
+            dynRealm.getDynMembershipConds().put(AnyTypeKind.USER.name(), "$resources==resource-ldap");
+            dynRealm.getDynMembershipConds().put(AnyTypeKind.GROUP.name(), "$resources==resource-ldap");
 
             Response response = dynRealmService.create(dynRealm);
             dynRealm = getObject(response.getLocation(), DynRealmService.class, DynRealmTO.class);