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 2015/11/25 12:26:06 UTC

[3/5] syncope git commit: [SYNCOPE-119] Added search options and checks to match assignable conditions, for usage with memberships and relationships

[SYNCOPE-119] Added search options and checks to match assignable conditions, for usage with memberships and relationships


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

Branch: refs/heads/master
Commit: bbb051feb43291de74d7cec215c63d2d68cbca03
Parents: 7b1cb89
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Wed Nov 25 11:43:25 2015 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Wed Nov 25 12:09:02 2015 +0100

----------------------------------------------------------------------
 .../syncope/client/lib/SyncopeClient.java       |   5 +-
 .../AnyObjectFiqlSearchConditionBuilder.java    | 110 ++++++++++++-
 .../common/lib/search/AnyObjectProperty.java    |  16 ++
 .../search/GroupFiqlSearchConditionBuilder.java |  21 ++-
 .../common/lib/search/GroupProperty.java        |   4 +
 .../syncope/common/lib/search/SpecialAttr.java  |  31 +++-
 .../search/UserFiqlSearchConditionBuilder.java  |  80 ++++++++--
 .../syncope/common/lib/search/UserProperty.java |   8 +
 .../common/lib/types/ClientExceptionType.java   |   2 +
 .../core/misc/search/SearchCondVisitor.java     |  29 +++-
 .../misc/search/SearchCondConverterTest.java    |  50 +++++-
 .../core/persistence/api/dao/AnySearchDAO.java  |   8 +
 .../core/persistence/api/dao/RealmDAO.java      |   3 +
 .../api/dao/search/AssignableCond.java          |  39 +++++
 .../api/dao/search/RelationshipTypeCond.java    |  39 +++++
 .../persistence/api/dao/search/SearchCond.java  |  42 ++++-
 .../persistence/jpa/dao/JPAAnySearchDAO.java    | 154 +++++++++++++------
 .../core/persistence/jpa/dao/JPARealmDAO.java   |  11 +-
 .../src/main/resources/views.xml                |   4 +-
 .../persistence/jpa/inner/AnySearchTest.java    | 116 +++++++++++++-
 .../core/persistence/jpa/inner/GroupTest.java   |   2 +-
 .../core/persistence/jpa/outer/RealmTest.java   |  11 ++
 .../test/resources/domains/MasterContent.xml    |   9 +-
 .../provisioning/api/data/GroupDataBinder.java  |   2 +-
 .../java/data/AbstractAnyDataBinder.java        |  24 +--
 .../java/data/AnyObjectDataBinderImpl.java      | 116 ++++++++++----
 .../java/data/GroupDataBinderImpl.java          |  24 ++-
 .../java/data/UserDataBinderImpl.java           | 116 ++++++++++----
 .../rest/cxf/service/AnyObjectServiceImpl.java  |   2 +-
 .../fit/core/reference/AnyObjectITCase.java     |  22 +++
 .../fit/core/reference/SearchITCase.java        | 135 ++++++++++++++--
 .../fit/core/reference/SyncTaskITCase.java      |   4 +-
 .../syncope/fit/core/reference/UserITCase.java  |   2 +-
 33 files changed, 1031 insertions(+), 210 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
----------------------------------------------------------------------
diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
index 198b585..c2d6250 100644
--- a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
@@ -93,10 +93,11 @@ public class SyncopeClient {
     /**
      * Returns a new instance of {@link AnyObjectFiqlSearchConditionBuilder}, for assisted building of FIQL queries.
      *
+     * @param type any type
      * @return default instance of {@link AnyObjectFiqlSearchConditionBuilder}
      */
-    public static AnyObjectFiqlSearchConditionBuilder getAnyObjectSearchConditionBuilder() {
-        return new AnyObjectFiqlSearchConditionBuilder();
+    public static AnyObjectFiqlSearchConditionBuilder getAnyObjectSearchConditionBuilder(final String type) {
+        return new AnyObjectFiqlSearchConditionBuilder(type);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectFiqlSearchConditionBuilder.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectFiqlSearchConditionBuilder.java b/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectFiqlSearchConditionBuilder.java
index 67e7e15..0841de3 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectFiqlSearchConditionBuilder.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectFiqlSearchConditionBuilder.java
@@ -18,8 +18,11 @@
  */
 package org.apache.syncope.common.lib.search;
 
+import java.util.Collections;
 import java.util.Map;
 import org.apache.cxf.jaxrs.ext.search.client.CompleteCondition;
+import org.apache.cxf.jaxrs.ext.search.client.FiqlSearchConditionBuilder;
+import org.apache.cxf.jaxrs.ext.search.fiql.FiqlParser;
 
 /**
  * Extends {@link AbstractFiqlSearchConditionBuilder} by providing some additional facilities for searching
@@ -27,12 +30,11 @@ import org.apache.cxf.jaxrs.ext.search.client.CompleteCondition;
  */
 public class AnyObjectFiqlSearchConditionBuilder extends AbstractFiqlSearchConditionBuilder {
 
-    public AnyObjectFiqlSearchConditionBuilder() {
-        super();
-    }
+    private final String type;
 
-    public AnyObjectFiqlSearchConditionBuilder(final Map<String, String> properties) {
-        super(properties);
+    public AnyObjectFiqlSearchConditionBuilder(final String type) {
+        super();
+        this.type = type;
     }
 
     @Override
@@ -41,15 +43,59 @@ public class AnyObjectFiqlSearchConditionBuilder extends AbstractFiqlSearchCondi
     }
 
     @Override
+    public String query() {
+        return new FiqlSearchConditionBuilder.Builder(Collections.<String, String>emptyMap()).
+                is(SpecialAttr.TYPE.toString()).equalTo(type).query();
+    }
+
+    @Override
     public AnyObjectProperty is(final String property) {
         return newBuilderInstance().is(property);
     }
 
-    public CompleteCondition type(final String type) {
-        return newBuilderInstance().is(SpecialAttr.TYPE.toString()).equalTo(type);
+    public CompleteCondition inGroups(final Long group, final Long... moreGroups) {
+        return newBuilderInstance().
+                is(SpecialAttr.GROUPS.toString()).
+                inGroups(group, moreGroups);
     }
 
-    protected static class Builder extends AbstractFiqlSearchConditionBuilder.Builder
+    public CompleteCondition notInGroups(final Long group, final Long... moreGroups) {
+        return newBuilderInstance().
+                is(SpecialAttr.GROUPS.toString()).
+                notInGroups(group, moreGroups);
+    }
+
+    public CompleteCondition inRelationships(final Long anyType, final Long... moreAnyTypes) {
+        return newBuilderInstance().
+                is(SpecialAttr.RELATIONSHIPS.toString()).
+                inRelationships(anyType, moreAnyTypes);
+    }
+
+    public CompleteCondition notInRelationships(final Long anyType, final Long... moreAnyTypes) {
+        return newBuilderInstance().
+                is(SpecialAttr.RELATIONSHIPS.toString()).
+                notInRelationships(anyType, moreAnyTypes);
+    }
+
+    public CompleteCondition inRelationshipTypes(final String type, final String... moreTypes) {
+        return newBuilderInstance().
+                is(SpecialAttr.RELATIONSHIP_TYPES.toString()).
+                inRelationshipTypes(type, moreTypes);
+    }
+
+    public CompleteCondition notInRelationshipTypes(final String type, final String... moreTypes) {
+        return newBuilderInstance().
+                is(SpecialAttr.RELATIONSHIP_TYPES.toString()).
+                notInRelationshipTypes(type, moreTypes);
+    }
+
+    public CompleteCondition isAssignable(final String realm, final String... moreRealms) {
+        return newBuilderInstance().
+                is(SpecialAttr.ASSIGNABLE.toString()).
+                isAssignable(realm, moreRealms);
+    }
+
+    protected class Builder extends AbstractFiqlSearchConditionBuilder.Builder
             implements AnyObjectProperty, CompleteCondition {
 
         public Builder(final Map<String, String> properties) {
@@ -61,11 +107,59 @@ public class AnyObjectFiqlSearchConditionBuilder extends AbstractFiqlSearchCondi
         }
 
         @Override
+        public String query() {
+            FiqlSearchConditionBuilder.Builder b = new FiqlSearchConditionBuilder.Builder(this);
+            return b.and(SpecialAttr.TYPE.toString()).equalTo(type).query();
+        }
+
+        @Override
         public AnyObjectProperty is(final String property) {
             Builder b = new Builder(this);
             b.result = property;
             return b;
         }
 
+        @Override
+        public CompleteCondition inGroups(final Long group, final Long... moreGroups) {
+            this.result = SpecialAttr.GROUPS.toString();
+            return condition(FiqlParser.EQ, group, (Object[]) moreGroups);
+        }
+
+        @Override
+        public CompleteCondition notInGroups(final Long group, final Long... moreGroups) {
+            this.result = SpecialAttr.GROUPS.toString();
+            return condition(FiqlParser.NEQ, group, (Object[]) moreGroups);
+        }
+
+        @Override
+        public CompleteCondition inRelationships(final Long anyObject, final Long... moreAnyObjects) {
+            this.result = SpecialAttr.RELATIONSHIPS.toString();
+            return condition(FiqlParser.EQ, anyObject, (Object[]) moreAnyObjects);
+        }
+
+        @Override
+        public CompleteCondition notInRelationships(final Long group, final Long... moreRelationships) {
+            this.result = SpecialAttr.RELATIONSHIPS.toString();
+            return condition(FiqlParser.NEQ, group, (Object[]) moreRelationships);
+        }
+
+        @Override
+        public CompleteCondition inRelationshipTypes(final String type, final String... moreTypes) {
+            this.result = SpecialAttr.RELATIONSHIP_TYPES.toString();
+            return condition(FiqlParser.EQ, type, (Object[]) moreTypes);
+        }
+
+        @Override
+        public CompleteCondition notInRelationshipTypes(final String type, final String... moreTypes) {
+            this.result = SpecialAttr.RELATIONSHIP_TYPES.toString();
+            return condition(FiqlParser.NEQ, type, (Object[]) moreTypes);
+        }
+
+        @Override
+        public CompleteCondition isAssignable(final String realm, final String... moreRealms) {
+            this.result = SpecialAttr.ASSIGNABLE.toString();
+            return condition(FiqlParser.EQ, realm, (Object[]) moreRealms);
+        }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectProperty.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectProperty.java b/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectProperty.java
index c675712..47de383 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectProperty.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectProperty.java
@@ -18,6 +18,22 @@
  */
 package org.apache.syncope.common.lib.search;
 
+import org.apache.cxf.jaxrs.ext.search.client.CompleteCondition;
+
 public interface AnyObjectProperty extends SyncopeProperty {
 
+    CompleteCondition inGroups(Long group, Long... moreGroups);
+
+    CompleteCondition notInGroups(Long group, Long... moreGroups);
+
+    CompleteCondition inRelationships(Long anyObject, Long... moreAnyObjects);
+
+    CompleteCondition notInRelationships(Long anyObject, Long... moreAnyObjects);
+
+    CompleteCondition inRelationshipTypes(String type, String... moreTypes);
+
+    CompleteCondition notInRelationshipTypes(String type, String... moreTypes);
+
+    CompleteCondition isAssignable(String realm, String... moreRealms);
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupFiqlSearchConditionBuilder.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupFiqlSearchConditionBuilder.java b/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupFiqlSearchConditionBuilder.java
index aaa56d7..9a2bc3f 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupFiqlSearchConditionBuilder.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupFiqlSearchConditionBuilder.java
@@ -20,6 +20,7 @@ package org.apache.syncope.common.lib.search;
 
 import java.util.Map;
 import org.apache.cxf.jaxrs.ext.search.client.CompleteCondition;
+import org.apache.cxf.jaxrs.ext.search.fiql.FiqlParser;
 
 /**
  * Extends {@link AbstractFiqlSearchConditionBuilder} by providing some additional facilities for searching
@@ -27,14 +28,6 @@ import org.apache.cxf.jaxrs.ext.search.client.CompleteCondition;
  */
 public class GroupFiqlSearchConditionBuilder extends AbstractFiqlSearchConditionBuilder {
 
-    public GroupFiqlSearchConditionBuilder() {
-        super();
-    }
-
-    public GroupFiqlSearchConditionBuilder(final Map<String, String> properties) {
-        super(properties);
-    }
-
     @Override
     protected Builder newBuilderInstance() {
         return new Builder(properties);
@@ -45,6 +38,12 @@ public class GroupFiqlSearchConditionBuilder extends AbstractFiqlSearchCondition
         return newBuilderInstance().is(property);
     }
 
+    public CompleteCondition isAssignable(final String realm, final String... moreRealms) {
+        return newBuilderInstance().
+                is(SpecialAttr.ASSIGNABLE.toString()).
+                isAssignable(realm, moreRealms);
+    }
+
     protected static class Builder extends AbstractFiqlSearchConditionBuilder.Builder
             implements GroupProperty, CompleteCondition {
 
@@ -63,5 +62,11 @@ public class GroupFiqlSearchConditionBuilder extends AbstractFiqlSearchCondition
             return b;
         }
 
+        @Override
+        public CompleteCondition isAssignable(final String realm, final String... moreRealms) {
+            this.result = SpecialAttr.ASSIGNABLE.toString();
+            return condition(FiqlParser.EQ, realm, (Object[]) moreRealms);
+        }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupProperty.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupProperty.java b/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupProperty.java
index 0eb7480..8dc375e 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupProperty.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/search/GroupProperty.java
@@ -18,6 +18,10 @@
  */
 package org.apache.syncope.common.lib.search;
 
+import org.apache.cxf.jaxrs.ext.search.client.CompleteCondition;
+
 public interface GroupProperty extends SyncopeProperty {
 
+    CompleteCondition isAssignable(String realm, String... moreRealms);
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/common/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java b/common/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
index 551a0ad..1b1f484 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
@@ -24,11 +24,40 @@ import org.apache.commons.collections4.Predicate;
 
 public enum SpecialAttr {
 
+    /**
+     * Applies to users, groups and any objects.
+     *//**
+     * Applies to users, groups and any objects.
+     */
     NULL("$null"),
+    /**
+     * Applies to any objects.
+     */
     TYPE("$type"),
+    /**
+     * Applies to users, groups and any objects.
+     */
     RESOURCES("$resources"),
+    /**
+     * Applies to users and any objects.
+     */
     GROUPS("$groups"),
-    ROLES("$roles");
+    /**
+     * Applies to users and any objects.
+     */
+    RELATIONSHIPS("$relationships"),
+    /**
+     * Applies to users and any objects.
+     */
+    RELATIONSHIP_TYPES("$relationshipTypes"),
+    /**
+     * Applies to users.
+     */
+    ROLES("$roles"),
+    /**
+     * Applies to groups and any objects.
+     */
+    ASSIGNABLE("$assignable");
 
     private final String literal;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserFiqlSearchConditionBuilder.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserFiqlSearchConditionBuilder.java b/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserFiqlSearchConditionBuilder.java
index 323e38b..30e89dd 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserFiqlSearchConditionBuilder.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserFiqlSearchConditionBuilder.java
@@ -28,14 +28,6 @@ import org.apache.cxf.jaxrs.ext.search.fiql.FiqlParser;
  */
 public class UserFiqlSearchConditionBuilder extends AbstractFiqlSearchConditionBuilder {
 
-    public UserFiqlSearchConditionBuilder() {
-        super();
-    }
-
-    public UserFiqlSearchConditionBuilder(final Map<String, String> properties) {
-        super(properties);
-    }
-
     @Override
     protected Builder newBuilderInstance() {
         return new Builder(properties);
@@ -47,20 +39,58 @@ public class UserFiqlSearchConditionBuilder extends AbstractFiqlSearchConditionB
     }
 
     public CompleteCondition inGroups(final Long group, final Long... moreGroups) {
-        return newBuilderInstance().is(SpecialAttr.GROUPS.toString()).inGroups(group, moreGroups);
+        return newBuilderInstance().
+                is(SpecialAttr.GROUPS.toString()).
+                inGroups(group, moreGroups);
+    }
+
+    public CompleteCondition notInGroups(final Long group, final Long... moreGroups) {
+        return newBuilderInstance().
+                is(SpecialAttr.GROUPS.toString()).
+                notInGroups(group, moreGroups);
+    }
+
+    public CompleteCondition inRelationships(final Long anyType, final Long... moreAnyTypes) {
+        return newBuilderInstance().
+                is(SpecialAttr.RELATIONSHIPS.toString()).
+                inRelationships(anyType, moreAnyTypes);
+    }
+
+    public CompleteCondition notInRelationships(final Long anyType, final Long... moreAnyTypes) {
+        return newBuilderInstance().
+                is(SpecialAttr.RELATIONSHIPS.toString()).
+                notInRelationships(anyType, moreAnyTypes);
+    }
+
+    public CompleteCondition inRelationshipTypes(final String type, final String... moreTypes) {
+        return newBuilderInstance().
+                is(SpecialAttr.RELATIONSHIP_TYPES.toString()).
+                inRelationshipTypes(type, moreTypes);
+    }
+
+    public CompleteCondition notInRelationshipTypes(final String type, final String... moreTypes) {
+        return newBuilderInstance().
+                is(SpecialAttr.RELATIONSHIP_TYPES.toString()).
+                notInRelationshipTypes(type, moreTypes);
     }
 
     public CompleteCondition inRoles(final String role, final String... moreRoles) {
-        return newBuilderInstance().is(SpecialAttr.ROLES.toString()).inRoles(role, moreRoles);
+        return newBuilderInstance().
+                is(SpecialAttr.ROLES.toString()).
+                inRoles(role, moreRoles);
     }
 
-    public CompleteCondition notInGroups(final Long group, final Long... moreGroups) {
-        return newBuilderInstance().is(SpecialAttr.GROUPS.toString()).notInGroups(group, moreGroups);
+    public CompleteCondition notInRoles(final String role, final String... moreRoles) {
+        return newBuilderInstance().
+                is(SpecialAttr.ROLES.toString()).
+                notInRoles(role, moreRoles);
     }
 
     @Override
     public CompleteCondition hasResources(final String resource, final String... moreResources) {
-        return newBuilderInstance().is(SpecialAttr.RESOURCES.toString()).hasResources(resource, moreResources);
+        return newBuilderInstance().
+                is(SpecialAttr.RESOURCES.toString()).
+                hasResources(resource, moreResources);
     }
 
     @Override
@@ -99,6 +129,30 @@ public class UserFiqlSearchConditionBuilder extends AbstractFiqlSearchConditionB
         }
 
         @Override
+        public CompleteCondition inRelationships(final Long anyObject, final Long... moreAnyObjects) {
+            this.result = SpecialAttr.RELATIONSHIPS.toString();
+            return condition(FiqlParser.EQ, anyObject, (Object[]) moreAnyObjects);
+        }
+
+        @Override
+        public CompleteCondition notInRelationships(final Long anyObject, final Long... moreAnyObjects) {
+            this.result = SpecialAttr.RELATIONSHIPS.toString();
+            return condition(FiqlParser.NEQ, anyObject, (Object[]) moreAnyObjects);
+        }
+
+        @Override
+        public CompleteCondition inRelationshipTypes(final String type, final String... moreTypes) {
+            this.result = SpecialAttr.RELATIONSHIP_TYPES.toString();
+            return condition(FiqlParser.EQ, type, (Object[]) moreTypes);
+        }
+
+        @Override
+        public CompleteCondition notInRelationshipTypes(final String type, final String... moreTypes) {
+            this.result = SpecialAttr.RELATIONSHIP_TYPES.toString();
+            return condition(FiqlParser.NEQ, type, (Object[]) moreTypes);
+        }
+
+        @Override
         public CompleteCondition inRoles(final String role, final String... moreRoles) {
             this.result = SpecialAttr.ROLES.toString();
             return condition(FiqlParser.EQ, role, (Object[]) moreRoles);

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserProperty.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserProperty.java b/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserProperty.java
index 210274c..9294ab0 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserProperty.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/search/UserProperty.java
@@ -26,6 +26,14 @@ public interface UserProperty extends SyncopeProperty {
 
     CompleteCondition notInGroups(Long group, Long... moreGroups);
 
+    CompleteCondition inRelationships(Long anyObject, Long... moreAnyObjects);
+
+    CompleteCondition notInRelationships(Long anyObject, Long... moreAnyObjects);
+
+    CompleteCondition inRelationshipTypes(String type, String... moreTypes);
+
+    CompleteCondition notInRelationshipTypes(String type, String... moreTypes);
+
     CompleteCondition inRoles(String role, String... moreRoles);
 
     CompleteCondition notInRoles(String role, String... moreRoles);

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
index 68ad199..dfc5fe2 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
@@ -40,6 +40,7 @@ public enum ClientExceptionType {
     InvalidProvision(Response.Status.BAD_REQUEST),
     InvalidReport(Response.Status.BAD_REQUEST),
     InvalidReportExec(Response.Status.BAD_REQUEST),
+    InvalidRelationship(Response.Status.BAD_REQUEST),
     InvalidRelationshipType(Response.Status.BAD_REQUEST),
     InvalidAnyType(Response.Status.BAD_REQUEST),
     InvalidAnyObject(Response.Status.BAD_REQUEST),
@@ -52,6 +53,7 @@ public enum ClientExceptionType {
     InvalidDerSchema(Response.Status.BAD_REQUEST),
     InvalidVirSchema(Response.Status.BAD_REQUEST),
     InvalidMapping(Response.Status.BAD_REQUEST),
+    InvalidMembership(Response.Status.BAD_REQUEST),
     InvalidRealm(Response.Status.BAD_REQUEST),
     InvalidRole(Response.Status.BAD_REQUEST),
     InvalidUser(Response.Status.BAD_REQUEST),

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/misc/src/main/java/org/apache/syncope/core/misc/search/SearchCondVisitor.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/search/SearchCondVisitor.java b/core/misc/src/main/java/org/apache/syncope/core/misc/search/SearchCondVisitor.java
index 6b067ca..1fe03d2 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/search/SearchCondVisitor.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/search/SearchCondVisitor.java
@@ -38,6 +38,9 @@ import org.apache.syncope.core.persistence.api.dao.search.RoleCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
+import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
+import org.apache.syncope.core.persistence.api.dao.search.RelationshipCond;
+import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
 
 /**
  * Converts CXF's <tt>SearchCondition</tt> into internal <tt>SearchCond</tt>.
@@ -105,22 +108,40 @@ public class SearchCondVisitor extends AbstractSearchConditionVisitor<SearchBean
                             leaf = SearchCond.getLeafCond(typeCond);
                             break;
 
+                        case RESOURCES:
+                            ResourceCond resourceCond = new ResourceCond();
+                            resourceCond.setResourceName(value);
+                            leaf = SearchCond.getLeafCond(resourceCond);
+                            break;
+
                         case GROUPS:
                             MembershipCond groupCond = new MembershipCond();
                             groupCond.setGroupKey(Long.valueOf(value));
                             leaf = SearchCond.getLeafCond(groupCond);
                             break;
 
+                        case RELATIONSHIPS:
+                            RelationshipCond relationshipCond = new RelationshipCond();
+                            relationshipCond.setAnyObjectKey(Long.valueOf(value));
+                            leaf = SearchCond.getLeafCond(relationshipCond);
+                            break;
+
+                        case RELATIONSHIP_TYPES:
+                            RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond();
+                            relationshipTypeCond.setRelationshipTypeKey(value);
+                            leaf = SearchCond.getLeafCond(relationshipTypeCond);
+                            break;
+
                         case ROLES:
                             RoleCond roleCond = new RoleCond();
                             roleCond.setRoleKey(value);
                             leaf = SearchCond.getLeafCond(roleCond);
                             break;
 
-                        case RESOURCES:
-                            ResourceCond resourceCond = new ResourceCond();
-                            resourceCond.setResourceName(value);
-                            leaf = SearchCond.getLeafCond(resourceCond);
+                        case ASSIGNABLE:
+                            AssignableCond assignableCond = new AssignableCond();
+                            assignableCond.setRealmFullPath(value);
+                            leaf = SearchCond.getLeafCond(assignableCond);
                             break;
 
                         default:

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/misc/src/test/java/org/apache/syncope/core/misc/search/SearchCondConverterTest.java
----------------------------------------------------------------------
diff --git a/core/misc/src/test/java/org/apache/syncope/core/misc/search/SearchCondConverterTest.java b/core/misc/src/test/java/org/apache/syncope/core/misc/search/SearchCondConverterTest.java
index 29f3c64..e081ffa 100644
--- a/core/misc/src/test/java/org/apache/syncope/core/misc/search/SearchCondConverterTest.java
+++ b/core/misc/src/test/java/org/apache/syncope/core/misc/search/SearchCondConverterTest.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.misc.search;
 import static org.junit.Assert.assertEquals;
 
 import org.apache.syncope.common.lib.search.AnyObjectFiqlSearchConditionBuilder;
+import org.apache.syncope.common.lib.search.GroupFiqlSearchConditionBuilder;
 import org.apache.syncope.common.lib.search.SpecialAttr;
 import org.apache.syncope.common.lib.search.UserFiqlSearchConditionBuilder;
 import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
@@ -30,6 +31,9 @@ import org.apache.syncope.core.persistence.api.dao.search.RoleCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
+import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
+import org.apache.syncope.core.persistence.api.dao.search.RelationshipCond;
+import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
 import org.junit.Test;
 
 public class SearchCondConverterTest {
@@ -85,6 +89,35 @@ public class SearchCondConverterTest {
     }
 
     @Test
+    public void relationships() {
+        String fiqlExpression = new UserFiqlSearchConditionBuilder().inRelationships(1L).query();
+        assertEquals(SpecialAttr.RELATIONSHIPS + "==1", fiqlExpression);
+
+        RelationshipCond relationshipCond = new RelationshipCond();
+        relationshipCond.setAnyObjectKey(1L);
+        SearchCond simpleCond = SearchCond.getLeafCond(relationshipCond);
+
+        assertEquals(simpleCond, SearchCondConverter.convert(fiqlExpression));
+    }
+
+    @Test
+    public void relationshipTypes() {
+        String fiqlExpression = new UserFiqlSearchConditionBuilder().inRelationshipTypes("type1").query();
+        assertEquals(SpecialAttr.RELATIONSHIP_TYPES + "==type1", fiqlExpression);
+
+        RelationshipTypeCond relationshipCond = new RelationshipTypeCond();
+        relationshipCond.setRelationshipTypeKey("type1");
+        SearchCond simpleCond = SearchCond.getLeafCond(relationshipCond);
+
+        assertEquals(simpleCond, SearchCondConverter.convert(fiqlExpression));
+
+        fiqlExpression = new AnyObjectFiqlSearchConditionBuilder("PRINTER").inRelationshipTypes("neighborhood").query();
+        assertEquals(
+                SpecialAttr.RELATIONSHIP_TYPES + "==neighborhood;" + SpecialAttr.TYPE + "==PRINTER",
+                fiqlExpression);
+    }
+
+    @Test
     public void groups() {
         String fiqlExpression = new UserFiqlSearchConditionBuilder().inGroups(1L).query();
         assertEquals(SpecialAttr.GROUPS + "==1", fiqlExpression);
@@ -121,8 +154,20 @@ public class SearchCondConverterTest {
     }
 
     @Test
+    public void assignable() {
+        String fiqlExpression = new GroupFiqlSearchConditionBuilder().isAssignable("/even/two").query();
+        assertEquals(SpecialAttr.ASSIGNABLE + "==/even/two", fiqlExpression);
+
+        AssignableCond assignableCond = new AssignableCond();
+        assignableCond.setRealmFullPath("/even/two");
+        SearchCond simpleCond = SearchCond.getLeafCond(assignableCond);
+
+        assertEquals(simpleCond, SearchCondConverter.convert(fiqlExpression));
+    }
+
+    @Test
     public void type() {
-        String fiqlExpression = new AnyObjectFiqlSearchConditionBuilder().type("PRINTER").query();
+        String fiqlExpression = new AnyObjectFiqlSearchConditionBuilder("PRINTER").query();
         assertEquals(SpecialAttr.TYPE + "==PRINTER", fiqlExpression);
 
         AnyTypeCond acond = new AnyTypeCond();
@@ -156,6 +201,9 @@ public class SearchCondConverterTest {
         String fiqlExpression = new UserFiqlSearchConditionBuilder().
                 is("fullname").equalTo("*o*", "*i*", "*ini").query();
         assertEquals("fullname==*o*,fullname==*i*,fullname==*ini", fiqlExpression);
+        fiqlExpression = new UserFiqlSearchConditionBuilder().
+                is("fullname").equalTo("*o*").or("fullname").equalTo("*i*").or("fullname").equalTo("*ini").query();
+        assertEquals("fullname==*o*,fullname==*i*,fullname==*ini", fiqlExpression);
 
         AttributeCond fullnameLeafCond1 = new AttributeCond(AttributeCond.Type.LIKE);
         fullnameLeafCond1.setSchema("fullname");

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
index 401d957..67e85f2 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
@@ -36,6 +36,14 @@ public interface AnySearchDAO extends DAO<Any<?>, Long> {
     int count(Set<String> adminRealms, SearchCond searchCondition, AnyTypeKind kind);
 
     /**
+     * @param realmFullPath for use with {@link org.apache.syncope.core.persistence.api.dao.search.AssignableCond}
+     * @param kind any object
+     * @param <T> any
+     * @return the list of any objects matching the given search condition
+     */
+    <T extends Any<?>> List<T> searchAssignable(String realmFullPath, AnyTypeKind kind);
+
+    /**
      * @param searchCondition the search condition
      * @param kind any object
      * @param <T> any

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
index 515779e..f8c94b6 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
@@ -19,11 +19,14 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
+import java.util.regex.Pattern;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 
 public interface RealmDAO extends DAO<Realm, Long> {
 
+    Pattern PATH_PATTERN = Pattern.compile("^(/[A-Za-z0-9]+)+");
+
     Realm getRoot();
 
     Realm find(Long key);

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AssignableCond.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AssignableCond.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AssignableCond.java
new file mode 100644
index 0000000..0ece01b
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AssignableCond.java
@@ -0,0 +1,39 @@
+/*
+ * 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.dao.search;
+
+public class AssignableCond extends AbstractSearchCond {
+
+    private static final long serialVersionUID = 1237627275756159522L;
+
+    private String realmFullPath;
+
+    public String getRealmFullPath() {
+        return realmFullPath;
+    }
+
+    public void setRealmFullPath(final String realmFullPath) {
+        this.realmFullPath = realmFullPath;
+    }
+
+    @Override
+    public final boolean isValid() {
+        return realmFullPath != null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/RelationshipTypeCond.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/RelationshipTypeCond.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/RelationshipTypeCond.java
new file mode 100644
index 0000000..d120e62
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/RelationshipTypeCond.java
@@ -0,0 +1,39 @@
+/*
+ * 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.dao.search;
+
+public class RelationshipTypeCond extends AbstractSearchCond {
+
+    private static final long serialVersionUID = 906241367466433419L;
+
+    private String relationshipTypeKey;
+
+    public String getRelationshipTypeKey() {
+        return relationshipTypeKey;
+    }
+
+    public void setRelationshipTypeKey(final String relationshipTypeKey) {
+        this.relationshipTypeKey = relationshipTypeKey;
+    }
+
+    @Override
+    public final boolean isValid() {
+        return relationshipTypeKey != null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java
index 14641c1..a33ccf3 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java
@@ -43,12 +43,16 @@ public class SearchCond extends AbstractSearchCond {
 
     private RelationshipCond relationshipCond;
 
+    private RelationshipTypeCond relationshipTypeCond;
+
     private MembershipCond membershipCond;
 
     private RoleCond roleCond;
 
     private ResourceCond resourceCond;
 
+    private AssignableCond assignableCond;
+
     private SearchCond leftNodeCond;
 
     private SearchCond rightNodeCond;
@@ -84,6 +88,15 @@ public class SearchCond extends AbstractSearchCond {
         return nodeCond;
     }
 
+    public static SearchCond getLeafCond(final RelationshipTypeCond relationshipTypeCond) {
+        SearchCond nodeCond = new SearchCond();
+
+        nodeCond.type = Type.LEAF;
+        nodeCond.relationshipTypeCond = relationshipTypeCond;
+
+        return nodeCond;
+    }
+
     public static SearchCond getLeafCond(final MembershipCond membershipCond) {
         SearchCond nodeCond = new SearchCond();
 
@@ -111,6 +124,15 @@ public class SearchCond extends AbstractSearchCond {
         return nodeCond;
     }
 
+    public static SearchCond getLeafCond(final AssignableCond assignableCond) {
+        SearchCond nodeCond = new SearchCond();
+
+        nodeCond.type = Type.LEAF;
+        nodeCond.assignableCond = assignableCond;
+
+        return nodeCond;
+    }
+
     public static SearchCond getNotLeafCond(final AttributeCond attributeCond) {
         SearchCond nodeCond = getLeafCond(attributeCond);
         nodeCond.type = Type.NOT_LEAF;
@@ -216,6 +238,14 @@ public class SearchCond extends AbstractSearchCond {
         this.relationshipCond = relationshipCond;
     }
 
+    public RelationshipTypeCond getRelationshipTypeCond() {
+        return relationshipTypeCond;
+    }
+
+    public void setRelationshipTypeCond(final RelationshipTypeCond relationshipTypeCond) {
+        this.relationshipTypeCond = relationshipTypeCond;
+    }
+
     public MembershipCond getMembershipCond() {
         return membershipCond;
     }
@@ -240,6 +270,14 @@ public class SearchCond extends AbstractSearchCond {
         this.resourceCond = resourceCond;
     }
 
+    public AssignableCond getAssignableCond() {
+        return assignableCond;
+    }
+
+    public void setAssignableCond(final AssignableCond assignableCond) {
+        this.assignableCond = assignableCond;
+    }
+
     public SearchCond getLeftNodeCond() {
         return leftNodeCond;
     }
@@ -307,8 +345,8 @@ public class SearchCond extends AbstractSearchCond {
             case LEAF:
             case NOT_LEAF:
                 isValid = (anyTypeCond != null || anyCond != null || attributeCond != null
-                        || relationshipCond != null || membershipCond != null
-                        || roleCond != null || resourceCond != null)
+                        || relationshipCond != null || relationshipTypeCond != null || membershipCond != null
+                        || roleCond != null || resourceCond != null || assignableCond != null)
                         && (anyTypeCond == null || anyTypeCond.isValid())
                         && (anyCond == null || anyCond.isValid())
                         && (attributeCond == null || attributeCond.isValid())

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 64c850b..c1f6fe2 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -55,7 +55,9 @@ import org.apache.syncope.core.persistence.api.dao.search.RoleCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
+import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.RelationshipCond;
+import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
@@ -65,12 +67,14 @@ import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.ReflectionUtils;
 
 @Repository
 public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySearchDAO {
 
-    private static final String EMPTY_ATTR_QUERY = "SELECT any_id FROM user_search_attr WHERE 1=2";
+    private static final String EMPTY_QUERY = "SELECT any_id FROM user_search_attr WHERE 1=2";
 
     @Autowired
     private RealmDAO realmDAO;
@@ -150,6 +154,14 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
         return ((Number) countQuery.getSingleResult()).intValue();
     }
 
+    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
+    @Override
+    public <T extends Any<?>> List<T> searchAssignable(final String realmFullPath, final AnyTypeKind kind) {
+        AssignableCond assignableCond = new AssignableCond();
+        assignableCond.setRealmFullPath(realmFullPath);
+        return search(SearchCond.getLeafCond(assignableCond), kind);
+    }
+
     @Override
     public <T extends Any<?>> List<T> search(final SearchCond searchCondition, final AnyTypeKind typeKind) {
         return search(searchCondition, Collections.<OrderByClause>emptyList(), typeKind);
@@ -406,7 +418,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
     }
 
     private StringBuilder getQuery(final SearchCond nodeCond, final List<Object> parameters,
-            final AnyTypeKind type, final SearchSupport svs) {
+            final AnyTypeKind anyTypeKind, final SearchSupport svs) {
 
         StringBuilder query = new StringBuilder();
 
@@ -414,51 +426,55 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
 
             case LEAF:
             case NOT_LEAF:
-                if (nodeCond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == type) {
+                if (nodeCond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == anyTypeKind) {
                     query.append(getQuery(nodeCond.getAnyTypeCond(),
                             nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                }
-                if (nodeCond.getRelationshipCond() != null
-                        && (AnyTypeKind.USER == type || AnyTypeKind.ANY_OBJECT == type)) {
+                } else if (nodeCond.getRelationshipTypeCond() != null
+                        && (AnyTypeKind.USER == anyTypeKind || AnyTypeKind.ANY_OBJECT == anyTypeKind)) {
+
+                    query.append(getQuery(nodeCond.getRelationshipTypeCond(),
+                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                } else if (nodeCond.getRelationshipCond() != null
+                        && (AnyTypeKind.USER == anyTypeKind || AnyTypeKind.ANY_OBJECT == anyTypeKind)) {
 
                     query.append(getQuery(nodeCond.getRelationshipCond(),
                             nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                }
-                if (nodeCond.getMembershipCond() != null
-                        && (AnyTypeKind.USER == type || AnyTypeKind.ANY_OBJECT == type)) {
+                } else if (nodeCond.getMembershipCond() != null
+                        && (AnyTypeKind.USER == anyTypeKind || AnyTypeKind.ANY_OBJECT == anyTypeKind)) {
 
                     query.append(getQuery(nodeCond.getMembershipCond(),
                             nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                }
-                if (nodeCond.getRoleCond() != null && AnyTypeKind.USER == type) {
+                } else if (nodeCond.getAssignableCond() != null
+                        && (AnyTypeKind.GROUP == anyTypeKind || AnyTypeKind.ANY_OBJECT == anyTypeKind)) {
+
+                    query.append(getQuery(nodeCond.getAssignableCond(), parameters, anyTypeKind, svs));
+                } else if (nodeCond.getRoleCond() != null && AnyTypeKind.USER == anyTypeKind) {
                     query.append(getQuery(nodeCond.getRoleCond(),
                             nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                }
-                if (nodeCond.getResourceCond() != null) {
+                } else if (nodeCond.getResourceCond() != null) {
                     query.append(getQuery(nodeCond.getResourceCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, type, svs));
-                }
-                if (nodeCond.getAttributeCond() != null) {
+                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, anyTypeKind, svs));
+                } else if (nodeCond.getAttributeCond() != null) {
                     query.append(getQuery(nodeCond.getAttributeCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, type, svs));
-                }
-                if (nodeCond.getAnyCond() != null) {
+                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, anyTypeKind, svs));
+                } else if (nodeCond.getAnyCond() != null) {
                     query.append(getQuery(nodeCond.getAnyCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, type, svs));
+                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, anyTypeKind,
+                            svs));
                 }
                 break;
 
             case AND:
-                query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, type, svs)).
+                query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, anyTypeKind, svs)).
                         append(" AND any_id IN ( ").
-                        append(getQuery(nodeCond.getRightNodeCond(), parameters, type, svs)).
+                        append(getQuery(nodeCond.getRightNodeCond(), parameters, anyTypeKind, svs)).
                         append(")");
                 break;
 
             case OR:
-                query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, type, svs)).
+                query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, anyTypeKind, svs)).
                         append(" OR any_id IN ( ").
-                        append(getQuery(nodeCond.getRightNodeCond(), parameters, type, svs)).
+                        append(getQuery(nodeCond.getRightNodeCond(), parameters, anyTypeKind, svs)).
                         append(")");
                 break;
 
@@ -485,6 +501,29 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
         return query.toString();
     }
 
+    private String getQuery(final RelationshipTypeCond cond, final boolean not, final List<Object> parameters,
+            final SearchSupport svs) {
+
+        StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
+                append(svs.field().name).append(" WHERE ");
+
+        if (not) {
+            query.append("any_id NOT IN (");
+        } else {
+            query.append("any_id IN (");
+        }
+
+        query.append("SELECT any_id ").append("FROM ").
+                append(svs.relationship().name).
+                append(" WHERE type=?").append(setParameter(parameters, cond.getRelationshipTypeKey())).
+                append(" UNION SELECT right_any_id AS any_id FROM ").
+                append(svs.relationship().name).
+                append(" WHERE type=?").append(setParameter(parameters, cond.getRelationshipTypeKey())).
+                append(')');
+
+        return query.toString();
+    }
+
     private String getQuery(final RelationshipCond cond, final boolean not, final List<Object> parameters,
             final SearchSupport svs) {
 
@@ -499,7 +538,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
 
         query.append("SELECT DISTINCT any_id ").append("FROM ").
                 append(svs.relationship().name).append(" WHERE ").
-                append("right_anyObject_id=?").append(setParameter(parameters, cond.getAnyObjectKey())).
+                append("right_any_id=?").append(setParameter(parameters, cond.getAnyObjectKey())).
                 append(')');
 
         return query.toString();
@@ -570,7 +609,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
     private String getQuery(final ResourceCond cond, final boolean not, final List<Object> parameters,
             final AnyTypeKind typeKind, final SearchSupport svs) {
 
-        final StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
+        StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
                 append(svs.field().name).append(" WHERE ");
 
         if (not) {
@@ -596,6 +635,24 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
         return query.toString();
     }
 
+    private String getQuery(final AssignableCond cond, final List<Object> parameters, final AnyTypeKind typeKind,
+            final SearchSupport svs) {
+
+        Realm realm = realmDAO.find(cond.getRealmFullPath());
+        if (realm == null) {
+            return EMPTY_QUERY;
+        }
+
+        StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
+                append(svs.field().name).append(" WHERE ");
+        for (Realm current = realm; current.getParent() != null; current = current.getParent()) {
+            query.append("realm_id=?").append(setParameter(parameters, current.getKey())).append(" OR ");
+        }
+        query.setLength(query.length() - 4);
+
+        return query.toString();
+    }
+
     private void fillAttributeQuery(final StringBuilder query, final PlainAttrValue attrValue,
             final PlainSchema schema, final AttributeCond cond, final boolean not,
             final List<Object> parameters, final SearchSupport svs) {
@@ -696,7 +753,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
         PlainSchema schema = schemaDAO.find(cond.getSchema());
         if (schema == null) {
             LOG.warn("Ignoring invalid schema '{}'", cond.getSchema());
-            return EMPTY_ATTR_QUERY;
+            return EMPTY_QUERY;
         }
 
         PlainAttrValue attrValue = attrUtils.newPlainAttrValue();
@@ -708,27 +765,31 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
             }
         } catch (ValidationException e) {
             LOG.error("Could not validate expression '" + cond.getExpression() + "'", e);
-            return EMPTY_ATTR_QUERY;
+            return EMPTY_QUERY;
         }
 
         StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ");
-        if (cond.getType() == AttributeCond.Type.ISNOTNULL) {
-            query.append(svs.field().name).
-                    append(" WHERE any_id NOT IN (SELECT any_id FROM ").
-                    append(svs.nullAttr().name).
-                    append(" WHERE schema_name='").append(schema.getKey()).append("')");
-        } else if (cond.getType() == AttributeCond.Type.ISNULL) {
-            query.append(svs.nullAttr().name).
-                    append(" WHERE schema_name='").append(schema.getKey()).append("'");
-        } else {
-            if (schema.isUniqueConstraint()) {
-                query.append(svs.uniqueAttr().name);
-            } else {
-                query.append(svs.attr().name);
-            }
-            query.append(" WHERE schema_name='").append(schema.getKey());
+        switch (cond.getType()) {
+            case ISNOTNULL:
+                query.append(svs.field().name).
+                        append(" WHERE any_id NOT IN (SELECT any_id FROM ").
+                        append(svs.nullAttr().name).
+                        append(" WHERE schema_name='").append(schema.getKey()).append("')");
+                break;
 
-            fillAttributeQuery(query, attrValue, schema, cond, not, parameters, svs);
+            case ISNULL:
+                query.append(svs.nullAttr().name).
+                        append(" WHERE schema_name='").append(schema.getKey()).append("'");
+                break;
+
+            default:
+                if (schema.isUniqueConstraint()) {
+                    query.append(svs.uniqueAttr().name);
+                } else {
+                    query.append(svs.attr().name);
+                }
+                query.append(" WHERE schema_name='").append(schema.getKey());
+                fillAttributeQuery(query, attrValue, schema, cond, not, parameters, svs);
         }
 
         return query.toString();
@@ -748,7 +809,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
         Field anyField = ReflectionUtils.findField(attrUtils.anyClass(), cond.getSchema());
         if (anyField == null) {
             LOG.warn("Ignoring invalid schema '{}'", cond.getSchema());
-            return EMPTY_ATTR_QUERY;
+            return EMPTY_QUERY;
         }
 
         PlainSchema schema = new JPAPlainSchema();
@@ -760,7 +821,6 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
         }
 
         // Deal with any Integer fields logically mapping to boolean values
-        // (JPAGroup.inheritPlainAttrs, for example)
         boolean foundBooleanMin = false;
         boolean foundBooleanMax = false;
         if (Integer.class.equals(anyField.getType())) {
@@ -806,7 +866,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea
                 schema.getValidator().validate(cond.getExpression(), attrValue);
             } catch (ValidationException e) {
                 LOG.error("Could not validate expression '" + cond.getExpression() + "'", e);
-                return EMPTY_ATTR_QUERY;
+                return EMPTY_QUERY;
             }
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
index 2733388..1261a5f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
@@ -21,7 +21,6 @@ package org.apache.syncope.core.persistence.jpa.dao;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.regex.Pattern;
 import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
 import org.apache.commons.collections4.CollectionUtils;
@@ -44,8 +43,6 @@ import org.springframework.transaction.annotation.Transactional;
 @Repository
 public class JPARealmDAO extends AbstractDAO<Realm, Long> implements RealmDAO {
 
-    private static final Pattern PATH_PATTERN = Pattern.compile("^(/[A-Za-z0-9]+)+");
-
     @Autowired
     private RoleDAO roleDAO;
 
@@ -124,11 +121,9 @@ public class JPARealmDAO extends AbstractDAO<Realm, Long> implements RealmDAO {
             return Collections.<Realm>emptyList();
         }
 
-        StringBuilder queryString = new StringBuilder("SELECT e FROM ").
-                append(JPARealm.class.getSimpleName()).append(" e WHERE e.").
-                append(policy instanceof AccountPolicy ? "accountPolicy" : "passwordPolicy").append("=:policy");
-
-        TypedQuery<Realm> query = entityManager().createQuery(queryString.toString(), Realm.class);
+        TypedQuery<Realm> query = entityManager().createQuery(
+                "SELECT e FROM " + JPARealm.class.getSimpleName() + " e WHERE e."
+                + (policy instanceof AccountPolicy ? "accountPolicy" : "passwordPolicy") + "=:policy", Realm.class);
         query.setParameter("policy", policy);
 
         List<Realm> result = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-jpa/src/main/resources/views.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/views.xml b/core/persistence-jpa/src/main/resources/views.xml
index fd0bf9c..48c801e 100644
--- a/core/persistence-jpa/src/main/resources/views.xml
+++ b/core/persistence-jpa/src/main/resources/views.xml
@@ -70,7 +70,7 @@ under the License.
   <entry key="user_search_urelationship">
     CREATE VIEW user_search_urelationship AS
 
-    SELECT m.user_id AS any_id, m.anyObject_id AS anyObject_id
+    SELECT m.user_id AS any_id, m.anyObject_id AS right_any_id, m.type_name AS type
     FROM URelationship m
   </entry>
   <entry key="user_search_umembership">
@@ -163,7 +163,7 @@ under the License.
   <entry key="anyObject_search_arelationship">
     CREATE VIEW anyObject_search_arelationship AS
 
-    SELECT m.left_anyObject_id AS any_id, m.right_anyObject_id AS right_anyObject_id
+    SELECT m.left_anyObject_id AS any_id, m.right_anyObject_id AS right_any_id, m.type_name AS type
     FROM ARelationship m
   </entry>
   <entry key="anyObject_search_amembership">

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
index 48c09d6..4045a76 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
@@ -44,7 +44,10 @@ import org.apache.syncope.core.persistence.api.dao.search.RoleCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
+import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.RelationshipCond;
+import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
+import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -73,9 +76,13 @@ public class AnySearchTest extends AbstractTest {
         AnyObject anyObject = anyObjectDAO.find(1L);
         assertNotNull(anyObject);
 
-        RelationshipCond cond = new RelationshipCond();
-        cond.setAnyObjectKey(2L);
-        assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(cond), AnyTypeKind.ANY_OBJECT));
+        RelationshipCond relationshipCond = new RelationshipCond();
+        relationshipCond.setAnyObjectKey(2L);
+        assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipCond), AnyTypeKind.ANY_OBJECT));
+
+        RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond();
+        relationshipTypeCond.setRelationshipTypeKey("neighborhood");
+        assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipTypeCond), AnyTypeKind.ANY_OBJECT));
     }
 
     @Test
@@ -93,6 +100,17 @@ public class AnySearchTest extends AbstractTest {
         RoleCond roleCond = new RoleCond();
         roleCond.setRoleKey("Other");
         assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(roleCond), AnyTypeKind.USER));
+
+        user = userDAO.find(4L);
+        assertNotNull(user);
+
+        RelationshipCond relationshipCond = new RelationshipCond();
+        relationshipCond.setAnyObjectKey(1L);
+        assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipCond), AnyTypeKind.USER));
+
+        RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond();
+        relationshipTypeCond.setRelationshipTypeKey("neighborhood");
+        assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipTypeCond), AnyTypeKind.USER));
     }
 
     @Test
@@ -384,7 +402,7 @@ public class AnySearchTest extends AbstractTest {
 
         List<AnyObject> printers = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
         assertNotNull(printers);
-        assertEquals(2, printers.size());
+        assertEquals(3, printers.size());
 
         tcond.setAnyTypeName("UNEXISTING");
         printers = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
@@ -393,6 +411,51 @@ public class AnySearchTest extends AbstractTest {
     }
 
     @Test
+    public void searchByRelationshipType() {
+        // 1. first search for printers involved in "neighborhood" relationship
+        RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond();
+        relationshipTypeCond.setRelationshipTypeKey("neighborhood");
+
+        AnyTypeCond tcond = new AnyTypeCond();
+        tcond.setAnyTypeName("PRINTER");
+
+        SearchCond searchCondition = SearchCond.getAndCond(
+                SearchCond.getLeafCond(relationshipTypeCond), SearchCond.getLeafCond(tcond));
+        assertTrue(searchCondition.isValid());
+
+        List<Any<?>> matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
+        assertNotNull(matching);
+        assertEquals(2, matching.size());
+        assertTrue(CollectionUtils.exists(matching, new Predicate<Any<?>>() {
+
+            @Override
+            public boolean evaluate(final Any<?> any) {
+                return any.getKey() == 1L;
+            }
+        }));
+        assertTrue(CollectionUtils.exists(matching, new Predicate<Any<?>>() {
+
+            @Override
+            public boolean evaluate(final Any<?> any) {
+                return any.getKey() == 2L;
+            }
+        }));
+
+        // 2. search for users involved in "neighborhood" relationship
+        searchCondition = SearchCond.getLeafCond(relationshipTypeCond);
+        matching = searchDAO.search(searchCondition, AnyTypeKind.USER);
+        assertNotNull(matching);
+        assertEquals(2, matching.size());
+        assertTrue(CollectionUtils.exists(matching, new Predicate<Any<?>>() {
+
+            @Override
+            public boolean evaluate(final Any<?> any) {
+                return any.getKey() == 4L;
+            }
+        }));
+    }
+
+    @Test
     public void userOrderBy() {
         AnyCond usernameLeafCond = new AnyCond(AnyCond.Type.EQ);
         usernameLeafCond.setSchema("username");
@@ -414,7 +477,8 @@ public class AnySearchTest extends AbstractTest {
         orderByClauses.add(orderByClause);
 
         List<User> users = searchDAO.search(searchCondition, orderByClauses, AnyTypeKind.USER);
-        assertEquals(searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER),
+        assertEquals(
+                searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER),
                 users.size());
     }
 
@@ -431,12 +495,50 @@ public class AnySearchTest extends AbstractTest {
 
         List<Group> groups = searchDAO.search(
                 searchCondition, Collections.singletonList(orderByClause), AnyTypeKind.GROUP);
-        assertEquals(searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, AnyTypeKind.GROUP),
+        assertEquals(
+                searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.GROUP),
                 groups.size());
     }
 
     @Test
+    public void assignable() {
+        AssignableCond assignableCond = new AssignableCond();
+        assignableCond.setRealmFullPath("/even/two");
+        SearchCond searchCondition = SearchCond.getLeafCond(assignableCond);
+        assertTrue(searchCondition.isValid());
+
+        List<Group> groups = searchDAO.search(searchCondition, AnyTypeKind.GROUP);
+        assertTrue(CollectionUtils.exists(groups, new Predicate<Group>() {
+
+            @Override
+            public boolean evaluate(final Group group) {
+                return group.getKey().equals(15L);
+            }
+        }));
+        assertFalse(CollectionUtils.exists(groups, new Predicate<Group>() {
+
+            @Override
+            public boolean evaluate(final Group group) {
+                return group.getKey().equals(16L);
+            }
+        }));
+
+        assignableCond = new AssignableCond();
+        assignableCond.setRealmFullPath("/odd");
+        searchCondition = SearchCond.getLeafCond(assignableCond);
+        assertTrue(searchCondition.isValid());
+
+        List<AnyObject> anyObjects = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
+        assertFalse(CollectionUtils.exists(anyObjects, new Predicate<AnyObject>() {
+
+            @Override
+            public boolean evaluate(final AnyObject anyObject) {
+                return anyObject.getKey().equals(3L);
+            }
+        }));
+    }
+
+    @Test
     public void issue202() {
         ResourceCond ws2 = new ResourceCond();
         ws2.setResourceName("ws-target-resource-2");

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/GroupTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/GroupTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/GroupTest.java
index 9d449be..c4dba81 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/GroupTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/GroupTest.java
@@ -48,7 +48,7 @@ public class GroupTest extends AbstractTest {
     @Test
     public void findAll() {
         List<Group> list = groupDAO.findAll();
-        assertEquals("did not get expected number of groups ", 15, list.size());
+        assertEquals("did not get expected number of groups ", 16, list.size());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RealmTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RealmTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RealmTest.java
index 2b67e6a..d1bb773 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RealmTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RealmTest.java
@@ -22,10 +22,12 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.Role;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -40,11 +42,20 @@ public class RealmTest extends AbstractTest {
     @Autowired
     private RoleDAO roleDAO;
 
+    @Autowired
+    private GroupDAO groupDAO;
+
     @Test
     public void test() {
         Realm realm = realmDAO.find("/odd");
         assertNotNull(realm);
 
+        // need to remove this group in order to remove the realm, which is otherwise empty
+        Group group = groupDAO.find(16L);
+        assertNotNull(group);
+        assertEquals(realm, group.getRealm());
+        groupDAO.delete(group);
+
         Role role = roleDAO.find("User reviewer");
         assertTrue(role.getRealms().contains(realm));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/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 b4c5a97..44335eb 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -167,6 +167,9 @@ under the License.
   <AnyObject id="2" realm_id="1" type_name="PRINTER"
              creator="admin" lastModifier="admin" 
              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <AnyObject id="3" realm_id="4" type_name="PRINTER"
+             creator="admin" lastModifier="admin" 
+             creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
   
   <ARelationship id="1" left_anyObject_id="1" right_anyObject_id="2" type_name="neighborhood"/>
   
@@ -280,12 +283,16 @@ under the License.
                 creator="admin" lastModifier="admin" 
                 creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>  
   <SyncopeGroup id="15" name="additional"
-                realm_id="1"
+                realm_id="3"
                 creator="admin" lastModifier="admin" 
                 creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
   <TypeExtension id="1" group_id="15" anyType_name="USER"/>
   <TypeExtension_AnyTypeClass typeExtension_id="1" anyTypeClass_name="csv"/>
   <TypeExtension_AnyTypeClass typeExtension_id="1" anyTypeClass_name="other"/>
+  <SyncopeGroup id="16" name="fake"
+                realm_id="2"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
   
   <URelationship id="1" user_id="4" anyObject_id="1" type_name="neighborhood"/>
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/GroupDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/GroupDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/GroupDataBinder.java
index d2ab1fa..62753f0 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/GroupDataBinder.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/GroupDataBinder.java
@@ -29,7 +29,7 @@ public interface GroupDataBinder {
 
     GroupTO getGroupTO(Group group, boolean details);
 
-    Group create(Group group, GroupTO groupTO);
+    void create(Group group, GroupTO groupTO);
 
     PropagationByResource update(Group group, GroupPatch groupPatch);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/bbb051fe/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 281fc69..3db4fc8 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
@@ -63,6 +63,7 @@ import org.apache.syncope.core.misc.utils.ConnObjectUtils;
 import org.apache.syncope.core.misc.utils.MappingUtils;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
@@ -135,6 +136,9 @@ abstract class AbstractAnyDataBinder {
     protected RelationshipTypeDAO relationshipTypeDAO;
 
     @Autowired
+    protected AnySearchDAO searchDAO;
+
+    @Autowired
     protected EntityFactory entityFactory;
 
     @Autowired
@@ -431,11 +435,6 @@ abstract class AbstractAnyDataBinder {
             scce.addException(requiredValuesMissing);
         }
 
-        // Throw composite exception if there is at least one element set in the composing exceptions
-        if (scce.hasExceptions()) {
-            throw scce;
-        }
-
         return propByRes;
     }
 
@@ -488,15 +487,7 @@ abstract class AbstractAnyDataBinder {
             scce.addException(requiredValuesMissing);
         }
 
-        // 2. realm & resources
-        Realm realm = realmDAO.find(anyTO.getRealm());
-        if (realm == null) {
-            SyncopeClientException noRealm = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
-            noRealm.getElements().add("Invalid or null realm specified: " + anyTO.getRealm());
-            scce.addException(noRealm);
-        }
-        any.setRealm(realm);
-
+        // 2. resources
         for (String resourceName : anyTO.getResources()) {
             ExternalResource resource = resourceDAO.find(resourceName);
             if (resource == null) {
@@ -510,11 +501,6 @@ abstract class AbstractAnyDataBinder {
         if (!requiredValuesMissing.isEmpty()) {
             scce.addException(requiredValuesMissing);
         }
-
-        // Throw composite exception if there is at least one element set in the composing exceptions
-        if (scce.hasExceptions()) {
-            throw scce;
-        }
     }
 
     protected void fillTO(final AnyTO anyTO,