syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject [70/70] syncope git commit: [SYNCOPE-666] All done now
Date Thu, 11 Jun 2015 14:18:00 GMT
[SYNCOPE-666] All done now


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

Branch: refs/heads/master
Commit: d8927ef4c3943a5a1dec1c17985a32fc9bfbae50
Parents: df60b3b
Author: Francesco Chicchiriccò <ilgrosso@apache.org>
Authored: Thu Jun 11 16:04:23 2015 +0200
Committer: Francesco Chicchiriccò <ilgrosso@apache.org>
Committed: Thu Jun 11 16:04:23 2015 +0200

----------------------------------------------------------------------
 .../syncope/common/lib/to/MembershipTO.java     |  16 +-
 .../syncope/common/lib/to/RelationshipTO.java   |  10 +
 .../common/lib/to/RelationshipTypeTO.java       |  53 ++
 .../common/lib/types/ClientExceptionType.java   |   1 +
 .../syncope/common/lib/types/Entitlement.java   |  10 +
 .../api/service/RelationshipTypeService.java    |  96 ++++
 .../core/logic/RelationshipTypeLogic.java       | 134 +++++
 .../api/dao/RelationshipTypeDAO.java            |  33 ++
 .../core/persistence/api/entity/Membership.java |   3 +
 .../persistence/api/entity/MembershipType.java  |  53 ++
 .../persistence/api/entity/Relationship.java    |   4 +
 .../api/entity/RelationshipType.java            |  28 +
 .../api/entity/anyobject/AnyObject.java         |   3 +
 .../api/entity/resource/ExternalResource.java   |   2 +-
 .../core/persistence/api/entity/user/User.java  |   3 +
 .../jpa/dao/JPARelationshipTypeDAO.java         |  95 ++++
 .../jpa/entity/JPAEntityFactory.java            |   3 +
 .../jpa/entity/JPARelationshipType.java         |  62 +++
 .../jpa/entity/anyobject/JPAAMembership.java    |  12 +
 .../jpa/entity/anyobject/JPAARelationship.java  |  25 +-
 .../jpa/entity/anyobject/JPAAnyObject.java      |  12 +
 .../jpa/entity/user/JPAUMembership.java         |  12 +
 .../jpa/entity/user/JPAURelationship.java       |  25 +-
 .../persistence/jpa/entity/user/JPAUser.java    |  12 +
 .../validation/entity/AbstractValidator.java    |   3 -
 .../entity/RelationshipTypeCheck.java           |  41 ++
 .../entity/RelationshipTypeValidator.java       |  41 ++
 .../persistence/jpa/entity/AnyObjectTest.java   |  85 ---
 .../persistence/jpa/entity/AnySearchTest.java   | 520 -------------------
 .../jpa/entity/AnyTypeClassTest.java            |  81 ---
 .../persistence/jpa/entity/AnyTypeTest.java     | 114 ----
 .../core/persistence/jpa/entity/ConfTest.java   | 119 -----
 .../jpa/entity/ConnInstanceTest.java            | 145 ------
 .../persistence/jpa/entity/DerAttrTest.java     | 220 --------
 .../persistence/jpa/entity/DerSchemaTest.java   | 100 ----
 .../core/persistence/jpa/entity/GroupTest.java  |  76 ---
 .../jpa/entity/NotificationTest.java            | 149 ------
 .../persistence/jpa/entity/PlainAttrTest.java   | 237 ---------
 .../persistence/jpa/entity/PlainSchemaTest.java | 152 ------
 .../core/persistence/jpa/entity/PolicyTest.java | 143 -----
 .../core/persistence/jpa/entity/RealmTest.java  | 178 -------
 .../core/persistence/jpa/entity/ReportTest.java |  83 ---
 .../persistence/jpa/entity/ResourceTest.java    | 372 -------------
 .../core/persistence/jpa/entity/RoleTest.java   |  89 ----
 .../jpa/entity/SecurityQuestionTest.java        |  68 ---
 .../persistence/jpa/entity/TaskExecTest.java    |  94 ----
 .../core/persistence/jpa/entity/TaskTest.java   | 117 -----
 .../core/persistence/jpa/entity/UserTest.java   | 241 ---------
 .../persistence/jpa/entity/VirAttrTest.java     | 118 -----
 .../persistence/jpa/entity/VirSchemaTest.java   |  99 ----
 .../persistence/jpa/inner/AnyObjectTest.java    |  85 +++
 .../persistence/jpa/inner/AnySearchTest.java    | 520 +++++++++++++++++++
 .../persistence/jpa/inner/AnyTypeClassTest.java |  81 +++
 .../core/persistence/jpa/inner/AnyTypeTest.java | 114 ++++
 .../core/persistence/jpa/inner/ConfTest.java    | 119 +++++
 .../persistence/jpa/inner/ConnInstanceTest.java | 145 ++++++
 .../core/persistence/jpa/inner/DerAttrTest.java | 220 ++++++++
 .../persistence/jpa/inner/DerSchemaTest.java    | 100 ++++
 .../core/persistence/jpa/inner/GroupTest.java   |  76 +++
 .../persistence/jpa/inner/NotificationTest.java | 149 ++++++
 .../persistence/jpa/inner/PlainAttrTest.java    | 237 +++++++++
 .../persistence/jpa/inner/PlainSchemaTest.java  | 152 ++++++
 .../core/persistence/jpa/inner/PolicyTest.java  | 143 +++++
 .../core/persistence/jpa/inner/RealmTest.java   | 178 +++++++
 .../jpa/inner/RelationshipTypeTest.java         | 104 ++++
 .../core/persistence/jpa/inner/ReportTest.java  |  83 +++
 .../persistence/jpa/inner/ResourceTest.java     | 372 +++++++++++++
 .../core/persistence/jpa/inner/RoleTest.java    |  89 ++++
 .../jpa/inner/SecurityQuestionTest.java         |  68 +++
 .../persistence/jpa/inner/TaskExecTest.java     |  94 ++++
 .../core/persistence/jpa/inner/TaskTest.java    | 117 +++++
 .../core/persistence/jpa/inner/UserTest.java    | 241 +++++++++
 .../core/persistence/jpa/inner/VirAttrTest.java | 118 +++++
 .../persistence/jpa/inner/VirSchemaTest.java    |  99 ++++
 .../persistence/jpa/outer/AnySearchTest.java    | 115 ++++
 .../persistence/jpa/outer/AnyTypeClassTest.java |  62 +++
 .../core/persistence/jpa/outer/AnyTypeTest.java |  61 +++
 .../persistence/jpa/outer/ConnInstanceTest.java | 103 ++++
 .../persistence/jpa/outer/DerSchemaTest.java    |  57 ++
 .../core/persistence/jpa/outer/GroupTest.java   | 328 ++++++++++++
 .../persistence/jpa/outer/PlainAttrTest.java    | 179 +++++++
 .../persistence/jpa/outer/PlainSchemaTest.java  | 170 ++++++
 .../core/persistence/jpa/outer/RealmTest.java   |  60 +++
 .../core/persistence/jpa/outer/ReportTest.java  | 120 +++++
 .../persistence/jpa/outer/ResourceTest.java     | 306 +++++++++++
 .../core/persistence/jpa/outer/RoleTest.java    | 167 ++++++
 .../jpa/outer/SecurityQuestionTest.java         |  61 +++
 .../core/persistence/jpa/outer/TaskTest.java    | 295 +++++++++++
 .../core/persistence/jpa/outer/UserTest.java    | 131 +++++
 .../jpa/relationship/AnySearchTest.java         | 115 ----
 .../jpa/relationship/AnyTypeClassTest.java      |  62 ---
 .../jpa/relationship/AnyTypeTest.java           |  61 ---
 .../jpa/relationship/ConnInstanceTest.java      | 103 ----
 .../jpa/relationship/DerSchemaTest.java         |  57 --
 .../persistence/jpa/relationship/GroupTest.java | 328 ------------
 .../jpa/relationship/PlainAttrTest.java         | 179 -------
 .../jpa/relationship/PlainSchemaTest.java       | 170 ------
 .../persistence/jpa/relationship/RealmTest.java |  60 ---
 .../jpa/relationship/ReportTest.java            | 120 -----
 .../jpa/relationship/ResourceTest.java          | 306 -----------
 .../persistence/jpa/relationship/RoleTest.java  | 167 ------
 .../jpa/relationship/SecurityQuestionTest.java  |  61 ---
 .../persistence/jpa/relationship/TaskTest.java  | 295 -----------
 .../persistence/jpa/relationship/UserTest.java  | 126 -----
 .../src/test/resources/content.xml              |   9 +-
 .../api/data/RelationshipTypeDataBinder.java    |  31 ++
 .../data/RelationshipTypeDataBinderImpl.java    |  64 +++
 .../service/RelationshipTypeServiceImpl.java    |  66 +++
 .../fit/core/reference/AbstractITCase.java      |   4 +
 .../core/reference/RelationshipTypeITCase.java  |  93 ++++
 110 files changed, 6966 insertions(+), 5822 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
index ef70589..d535c34 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
@@ -30,9 +30,19 @@ public class MembershipTO extends RelationshipTO {
 
     private String groupName;
 
-    public MembershipTO() {
-        super();
-        super.setRightType(AnyTypeKind.GROUP.name());
+    @Override
+    public String getRelationshipType() {
+        return "Membership";
+    }
+
+    @Override
+    public void setRelationshipType(final String relationshipType) {
+        // ignore
+    }
+
+    @Override
+    public String getRightType() {
+        return AnyTypeKind.GROUP.name();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
index d769719..6468dab 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
@@ -28,6 +28,8 @@ public class RelationshipTO extends AbstractBaseBean {
 
     private static final long serialVersionUID = 360672942026613929L;
 
+    private String relationshipType;
+
     private String leftType;
 
     private long leftKey;
@@ -36,6 +38,14 @@ public class RelationshipTO extends AbstractBaseBean {
 
     private long rightKey;
 
+    public String getRelationshipType() {
+        return relationshipType;
+    }
+
+    public void setRelationshipType(final String relationshipType) {
+        this.relationshipType = relationshipType;
+    }
+
     public String getLeftType() {
         return leftType;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTypeTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTypeTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTypeTO.java
new file mode 100644
index 0000000..d1d72f7
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTypeTO.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.to;
+
+import javax.ws.rs.Path;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "relationshipType")
+@XmlType
+public class RelationshipTypeTO extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -1884088415277925817L;
+
+    private String key;
+
+    private String description;
+
+    public String getKey() {
+        return key;
+    }
+
+    @Path("{key}")
+    public void setKey(final String key) {
+        this.key = key;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(final String description) {
+        this.description = description;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/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 8e96942..3fcef86 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),
+    InvalidRelationshipType(Response.Status.BAD_REQUEST),
     InvalidAnyType(Response.Status.BAD_REQUEST),
     InvalidAnyObject(Response.Status.BAD_REQUEST),
     InvalidGroup(Response.Status.BAD_REQUEST),

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
index 6ffe318..806aaa4 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
@@ -56,6 +56,16 @@ public final class Entitlement {
 
     public static final String ANYTYPE_DELETE = "ANYTYPE_DELETE";
 
+    public static final String RELATIONSHIPTYPE_LIST = "RELATIONSHIPTYPE_LIST";
+
+    public static final String RELATIONSHIPTYPE_CREATE = "RELATIONSHIPTYPE_CREATE";
+
+    public static final String RELATIONSHIPTYPE_READ = "RELATIONSHIPTYPE_READ";
+
+    public static final String RELATIONSHIPTYPE_UPDATE = "RELATIONSHIPTYPE_UPDATE";
+
+    public static final String RELATIONSHIPTYPE_DELETE = "RELATIONSHIPTYPE_DELETE";
+
     public static final String ROLE_LIST = "ROLE_LIST";
 
     public static final String ROLE_CREATE = "ROLE_CREATE";

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RelationshipTypeService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RelationshipTypeService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RelationshipTypeService.java
new file mode 100644
index 0000000..178bb6c
--- /dev/null
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RelationshipTypeService.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.rest.api.service;
+
+import java.util.List;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.cxf.jaxrs.model.wadl.Description;
+import org.apache.cxf.jaxrs.model.wadl.Descriptions;
+import org.apache.cxf.jaxrs.model.wadl.DocTarget;
+import org.apache.syncope.common.lib.to.RelationshipTypeTO;
+
+/**
+ * REST operations for relationship types.
+ */
+@Path("relationshipTypes")
+public interface RelationshipTypeService extends JAXRSService {
+
+    /**
+     * Returns a list of all relationshipTypes.
+     *
+     * @return list of all relationshipTypes.
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    List<RelationshipTypeTO> list();
+
+    /**
+     * Returns relationshipType with matching key.
+     *
+     * @param key relationshipType key to be read
+     * @return relationshipType with matching key
+     */
+    @GET
+    @Path("{key}")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    RelationshipTypeTO read(@NotNull @PathParam("key") String key);
+
+    /**
+     * Creates a new relationshipType.
+     *
+     * @param relationshipTypeTO relationshipType to be created
+     * @return <tt>Response</tt> object featuring <tt>Location</tt> header of created relationshipType
+     */
+    @Descriptions({
+        @Description(target = DocTarget.RESPONSE,
+                value = "Featuring <tt>Location</tt> header of created relationshipType")
+    })
+    @POST
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    Response create(@NotNull RelationshipTypeTO relationshipTypeTO);
+
+    /**
+     * Updates the relationshipType matching the provided key.
+     *
+     * @param relationshipTypeTO relationshipType to be stored
+     */
+    @PUT
+    @Path("{key}")
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    void update(@NotNull RelationshipTypeTO relationshipTypeTO);
+
+    /**
+     * Deletes the relationshipType matching the provided key.
+     *
+     * @param key relationshipType key to be deleted
+     */
+    @DELETE
+    @Path("{key}")
+    void delete(@NotNull @PathParam("key") String key);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/logic/src/main/java/org/apache/syncope/core/logic/RelationshipTypeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/RelationshipTypeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/RelationshipTypeLogic.java
new file mode 100644
index 0000000..7df2755
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/RelationshipTypeLogic.java
@@ -0,0 +1,134 @@
+/*
+ * 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 RELATIONSHIP
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.RelationshipTypeTO;
+import org.apache.syncope.common.lib.types.Entitlement;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.RelationshipTypeDAO;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
+import org.apache.syncope.core.provisioning.api.data.RelationshipTypeDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RelationshipTypeLogic extends AbstractTransactionalLogic<RelationshipTypeTO> {
+
+    @Autowired
+    private RelationshipTypeDataBinder binder;
+
+    @Autowired
+    private RelationshipTypeDAO relationshipTypeDAO;
+
+    @PreAuthorize("hasRole('" + Entitlement.RELATIONSHIPTYPE_READ + "')")
+    public RelationshipTypeTO read(final String key) {
+        RelationshipType relationshipType = relationshipTypeDAO.find(key);
+        if (relationshipType == null) {
+            LOG.error("Could not find relationshipType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        return binder.getRelationshipTypeTO(relationshipType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.RELATIONSHIPTYPE_LIST + "')")
+    public List<RelationshipTypeTO> list() {
+        return CollectionUtils.collect(relationshipTypeDAO.findAll(),
+                new Transformer<RelationshipType, RelationshipTypeTO>() {
+
+                    @Override
+                    public RelationshipTypeTO transform(final RelationshipType input) {
+                        return binder.getRelationshipTypeTO(input);
+                    }
+                }, new ArrayList<RelationshipTypeTO>());
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.RELATIONSHIPTYPE_CREATE + "')")
+    public RelationshipTypeTO create(final RelationshipTypeTO relationshipTypeTO) {
+        return binder.getRelationshipTypeTO(relationshipTypeDAO.save(binder.create(relationshipTypeTO)));
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.RELATIONSHIPTYPE_UPDATE + "')")
+    public RelationshipTypeTO update(final RelationshipTypeTO relationshipTypeTO) {
+        RelationshipType relationshipType = relationshipTypeDAO.find(relationshipTypeTO.getKey());
+        if (relationshipType == null) {
+            LOG.error("Could not find relationshipType '" + relationshipTypeTO.getKey() + "'");
+            throw new NotFoundException(String.valueOf(relationshipTypeTO.getKey()));
+        }
+
+        binder.update(relationshipType, relationshipTypeTO);
+        relationshipType = relationshipTypeDAO.save(relationshipType);
+
+        return binder.getRelationshipTypeTO(relationshipType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.RELATIONSHIPTYPE_DELETE + "')")
+    public RelationshipTypeTO delete(final String key) {
+        RelationshipType relationshipType = relationshipTypeDAO.find(key);
+        if (relationshipType == null) {
+            LOG.error("Could not find relationshipType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        RelationshipTypeTO deleted = binder.getRelationshipTypeTO(relationshipType);
+
+        relationshipTypeDAO.delete(key);
+
+        return deleted;
+    }
+
+    @Override
+    protected RelationshipTypeTO resolveReference(final Method method, final Object... args)
+            throws UnresolvedReferenceException {
+
+        String key = null;
+
+        if (ArrayUtils.isNotEmpty(args)) {
+            for (int i = 0; key == null && i < args.length; i++) {
+                if (args[i] instanceof Long) {
+                    key = (String) args[i];
+                } else if (args[i] instanceof RelationshipTypeTO) {
+                    key = ((RelationshipTypeTO) args[i]).getKey();
+                }
+            }
+        }
+
+        if (StringUtils.isNotBlank(key)) {
+            try {
+                return binder.getRelationshipTypeTO(relationshipTypeDAO.find(key));
+            } catch (Throwable ignore) {
+                LOG.debug("Unresolved reference", ignore);
+                throw new UnresolvedReferenceException(ignore);
+            }
+        }
+
+        throw new UnresolvedReferenceException();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RelationshipTypeDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RelationshipTypeDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RelationshipTypeDAO.java
new file mode 100644
index 0000000..e7d14b9
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RelationshipTypeDAO.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
+
+public interface RelationshipTypeDAO extends DAO<RelationshipType, String> {
+
+    RelationshipType find(String key);
+
+    List<RelationshipType> findAll();
+
+    RelationshipType save(RelationshipType anyType);
+
+    void delete(String key);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java
index 8c040ab..55ac640 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java
@@ -22,4 +22,7 @@ import org.apache.syncope.core.persistence.api.entity.group.Group;
 
 public interface Membership<L extends Any<?, ?, ?>> extends Relationship<L, Group> {
 
+    @Override
+    MembershipType getType();
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/MembershipType.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/MembershipType.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/MembershipType.java
new file mode 100644
index 0000000..d49b4dd
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/MembershipType.java
@@ -0,0 +1,53 @@
+/*
+ * 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 final class MembershipType implements RelationshipType {
+
+    private static final long serialVersionUID = -2767173479992170853L;
+
+    private static final MembershipType INSTANCE = new MembershipType();
+
+    public static MembershipType getInstance() {
+        return INSTANCE;
+    }
+
+    private MembershipType() {
+    }
+
+    @Override
+    public String getKey() {
+        return "Membership";
+    }
+
+    @Override
+    public void setKey(final String key) {
+        // cannot be changed
+    }
+
+    @Override
+    public String getDescription() {
+        return null;
+    }
+
+    @Override
+    public void setDescription(final String description) {
+        // cannot be changed
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java
index df4d7ff..0549714 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java
@@ -20,6 +20,10 @@ package org.apache.syncope.core.persistence.api.entity;
 
 public interface Relationship<L extends Any<?, ?, ?>, R extends Any<?, ?, ?>> extends Entity<Long> {
 
+    RelationshipType getType();
+
+    void setType(RelationshipType type);
+
     L getLeftEnd();
 
     void setLeftEnd(L leftEnd);

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/RelationshipType.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/RelationshipType.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/RelationshipType.java
new file mode 100644
index 0000000..71f1155
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/RelationshipType.java
@@ -0,0 +1,28 @@
+/*
+ * 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 RelationshipType extends Entity<String> {
+
+    void setKey(String key);
+
+    String getDescription();
+
+    void setDescription(String description);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
index 19d0f6b..ffb61a3 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
@@ -20,6 +20,7 @@ package org.apache.syncope.core.persistence.api.entity.anyobject;
 
 import java.util.List;
 import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 
 public interface AnyObject extends Any<APlainAttr, ADerAttr, AVirAttr> {
 
@@ -27,6 +28,8 @@ public interface AnyObject extends Any<APlainAttr, ADerAttr, AVirAttr> {
 
     boolean remove(ARelationship relationship);
 
+    ARelationship getRelationship(RelationshipType relationshipType);
+
     ARelationship getRelationship(Long relationshipKey);
 
     List<? extends ARelationship> getRelationships();

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
index da545e4..63047a1 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
@@ -33,7 +33,7 @@ import org.identityconnectors.framework.common.objects.ObjectClass;
 
 public interface ExternalResource extends AnnotatedEntity<String> {
 
-    void setKey(String name);
+    void setKey(String key);
 
     ConnInstance getConnector();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
index f02c555..c3b0ca6 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
@@ -22,6 +22,7 @@ import java.util.Date;
 import java.util.List;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.Role;
 
 public interface User extends Any<UPlainAttr, UDerAttr, UVirAttr> {
@@ -134,6 +135,8 @@ public interface User extends Any<UPlainAttr, UDerAttr, UVirAttr> {
 
     URelationship getRelationship(Long anyObjectKey);
 
+    URelationship getRelationship(RelationshipType relationshipType);
+
     List<? extends URelationship> getRelationships();
 
     boolean add(UMembership membership);

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARelationshipTypeDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARelationshipTypeDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARelationshipTypeDAO.java
new file mode 100644
index 0000000..37ce107
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARelationshipTypeDAO.java
@@ -0,0 +1,95 @@
+/*
+ * 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.dao;
+
+import java.util.Collection;
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.syncope.core.persistence.api.dao.RelationshipTypeDAO;
+import org.apache.syncope.core.persistence.api.entity.Relationship;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
+import org.apache.syncope.core.persistence.api.entity.anyobject.ARelationship;
+import org.apache.syncope.core.persistence.api.entity.user.UMembership;
+import org.apache.syncope.core.persistence.api.entity.user.URelationship;
+import org.apache.syncope.core.persistence.jpa.entity.JPARelationshipType;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAARelationship;
+import org.apache.syncope.core.persistence.jpa.entity.user.JPAURelationship;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPARelationshipTypeDAO extends AbstractDAO<RelationshipType, String> implements RelationshipTypeDAO {
+
+    @Override
+    public RelationshipType find(final String key) {
+        return entityManager.find(JPARelationshipType.class, key);
+    }
+
+    @Override
+    public List<RelationshipType> findAll() {
+        TypedQuery<RelationshipType> query = entityManager.createQuery(
+                "SELECT e FROM " + JPARelationshipType.class.getSimpleName() + " e ", RelationshipType.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public RelationshipType save(final RelationshipType anyType) {
+        return entityManager.merge(anyType);
+    }
+
+    private Collection<? extends Relationship<?, ?>> findRelationshipsByType(final RelationshipType type) {
+        TypedQuery<ARelationship> aquery = entityManager.createQuery(
+                "SELECT e FROM " + JPAARelationship.class.getSimpleName() + " e WHERE e.type=:type",
+                ARelationship.class);
+        aquery.setParameter("type", type);
+        TypedQuery<URelationship> uquery = entityManager.createQuery(
+                "SELECT e FROM " + JPAURelationship.class.getSimpleName() + " e WHERE e.type=:type",
+                URelationship.class);
+        uquery.setParameter("type", type);
+
+        return CollectionUtils.union(aquery.getResultList(), uquery.getResultList());
+    }
+
+    @Override
+    public void delete(final String key) {
+        RelationshipType type = find(key);
+        if (type == null) {
+            return;
+        }
+
+        for (Relationship<?, ?> relationship : findRelationshipsByType(type)) {
+            if (relationship instanceof URelationship) {
+                ((URelationship) relationship).getLeftEnd().remove((URelationship) relationship);
+            } else if (relationship instanceof UMembership) {
+                ((UMembership) relationship).getLeftEnd().remove((UMembership) relationship);
+            } else if (relationship instanceof ARelationship) {
+                ((ARelationship) relationship).getLeftEnd().remove((ARelationship) relationship);
+            } else if (relationship instanceof AMembership) {
+                ((AMembership) relationship).getLeftEnd().remove((AMembership) relationship);
+            }
+
+            relationship.setLeftEnd(null);
+            entityManager.remove(relationship);
+        }
+
+        entityManager.remove(type);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/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 6a152b0..ad6304e 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
@@ -37,6 +37,7 @@ import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.PushPolicy;
 import org.apache.syncope.core.persistence.api.entity.Realm;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.Report;
 import org.apache.syncope.core.persistence.api.entity.ReportExec;
 import org.apache.syncope.core.persistence.api.entity.ReportletConfInstance;
@@ -150,6 +151,8 @@ public class JPAEntityFactory implements EntityFactory {
             result = (T) new JPAUser();
         } else if (reference.equals(Group.class)) {
             result = (T) new JPAGroup();
+        } else if (reference.equals(RelationshipType.class)) {
+            result = (T) new JPARelationshipType();
         } else if (reference.equals(ARelationship.class)) {
             result = (T) new JPAARelationship();
         } else if (reference.equals(URelationship.class)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARelationshipType.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARelationshipType.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARelationshipType.java
new file mode 100644
index 0000000..f3fc882
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARelationshipType.java
@@ -0,0 +1,62 @@
+/*
+ * 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.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
+import org.apache.syncope.core.persistence.jpa.validation.entity.RelationshipTypeCheck;
+
+@Entity
+@Table(name = JPARelationshipType.TABLE)
+@RelationshipTypeCheck
+@Cacheable
+public class JPARelationshipType extends AbstractEntity<String> implements RelationshipType {
+
+    private static final long serialVersionUID = -753673974614737065L;
+
+    public static final String TABLE = "RelationshipType";
+
+    @Id
+    private String name;
+
+    private String description;
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public void setDescription(final String description) {
+        this.description = description;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAMembership.java
index e770e33..28ee49b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAMembership.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAMembership.java
@@ -23,6 +23,8 @@ import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.MembershipType;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
@@ -54,6 +56,16 @@ public class JPAAMembership extends AbstractEntity<Long> implements AMembership
     }
 
     @Override
+    public MembershipType getType() {
+        return MembershipType.getInstance();
+    }
+
+    @Override
+    public void setType(final RelationshipType type) {
+        // cannot be changed
+    }
+
+    @Override
     public AnyObject getLeftEnd() {
         return leftEnd;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAARelationship.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAARelationship.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAARelationship.java
index 93a7941..e12f8d8 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAARelationship.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAARelationship.java
@@ -20,15 +20,21 @@ package org.apache.syncope.core.persistence.jpa.entity.anyobject;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import org.apache.syncope.core.persistence.api.entity.MembershipType;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ARelationship;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
+import org.apache.syncope.core.persistence.jpa.entity.JPARelationshipType;
 
 @Entity
-@Table(name = JPAARelationship.TABLE)
+@Table(name = JPAARelationship.TABLE, uniqueConstraints =
+        @UniqueConstraint(columnNames = { "type_name", "left_anyObject_id", "right_anyObject_id" }))
 public class JPAARelationship extends AbstractEntity<Long> implements ARelationship {
 
     private static final long serialVersionUID = 6608821135023815357L;
@@ -38,6 +44,9 @@ public class JPAARelationship extends AbstractEntity<Long> implements ARelations
     @Id
     private Long id;
 
+    @ManyToOne(fetch = FetchType.EAGER, optional = false)
+    private JPARelationshipType type;
+
     @ManyToOne
     @Column(name = "left_anyObject_id")
     private JPAAnyObject leftEnd;
@@ -52,6 +61,20 @@ public class JPAARelationship extends AbstractEntity<Long> implements ARelations
     }
 
     @Override
+    public RelationshipType getType() {
+        return type;
+    }
+
+    @Override
+    public void setType(final RelationshipType type) {
+        if (MembershipType.getInstance().getKey().equalsIgnoreCase(type.getKey())) {
+            throw new IllegalArgumentException("This is not a membership");
+        }
+        checkType(type, JPARelationshipType.class);
+        this.type = (JPARelationshipType) type;
+    }
+
+    @Override
     public AnyObject getLeftEnd() {
         return leftEnd;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
index a8e842b..d32ec02 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
@@ -36,6 +36,7 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ADerAttr;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
 import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
@@ -198,6 +199,17 @@ public class JPAAnyObject extends AbstractAny<APlainAttr, ADerAttr, AVirAttr> im
     }
 
     @Override
+    public ARelationship getRelationship(final RelationshipType relationshipType) {
+        return CollectionUtils.find(getRelationships(), new Predicate<ARelationship>() {
+
+            @Override
+            public boolean evaluate(final ARelationship relationship) {
+                return relationshipType != null && relationshipType.equals(relationship.getType());
+            }
+        });
+    }
+
+    @Override
     public ARelationship getRelationship(final Long anyObjectKey) {
         return CollectionUtils.find(getRelationships(), new Predicate<ARelationship>() {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUMembership.java
index dd79434..879ee87 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUMembership.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUMembership.java
@@ -23,6 +23,8 @@ import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.MembershipType;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -54,6 +56,16 @@ public class JPAUMembership extends AbstractEntity<Long> implements UMembership
     }
 
     @Override
+    public MembershipType getType() {
+        return MembershipType.getInstance();
+    }
+
+    @Override
+    public void setType(final RelationshipType type) {
+        // cannot be changed
+    }
+
+    @Override
     public JPAUser getLeftEnd() {
         return leftEnd;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAURelationship.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAURelationship.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAURelationship.java
index d4c8bb3..25fd3a1 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAURelationship.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAURelationship.java
@@ -20,17 +20,23 @@ package org.apache.syncope.core.persistence.jpa.entity.user;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import org.apache.syncope.core.persistence.api.entity.MembershipType;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.user.URelationship;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
+import org.apache.syncope.core.persistence.jpa.entity.JPARelationshipType;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAnyObject;
 
 @Entity
-@Table(name = JPAURelationship.TABLE)
+@Table(name = JPAURelationship.TABLE, uniqueConstraints =
+        @UniqueConstraint(columnNames = { "type_name", "user_id", "anyObject_id" }))
 public class JPAURelationship extends AbstractEntity<Long> implements URelationship {
 
     private static final long serialVersionUID = 2778494939240083204L;
@@ -40,6 +46,9 @@ public class JPAURelationship extends AbstractEntity<Long> implements URelations
     @Id
     private Long id;
 
+    @ManyToOne(fetch = FetchType.EAGER, optional = false)
+    private JPARelationshipType type;
+
     @ManyToOne
     @Column(name = "user_id")
     private JPAUser leftEnd;
@@ -54,6 +63,20 @@ public class JPAURelationship extends AbstractEntity<Long> implements URelations
     }
 
     @Override
+    public RelationshipType getType() {
+        return type;
+    }
+
+    @Override
+    public void setType(final RelationshipType type) {
+        if (MembershipType.getInstance().getKey().equalsIgnoreCase(type.getKey())) {
+            throw new IllegalArgumentException("This is not a membership");
+        }
+        checkType(type, JPARelationshipType.class);
+        this.type = (JPARelationshipType) type;
+    }
+
+    @Override
     public JPAUser getLeftEnd() {
         return leftEnd;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
index 06d8f04..88c86fb 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
@@ -64,6 +64,7 @@ import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.Role;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.URelationship;
@@ -537,6 +538,17 @@ public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr, UVirAttr> impleme
     }
 
     @Override
+    public URelationship getRelationship(final RelationshipType relationshipType) {
+        return CollectionUtils.find(getRelationships(), new Predicate<URelationship>() {
+
+            @Override
+            public boolean evaluate(final URelationship relationship) {
+                return relationshipType != null && relationshipType.equals(relationship.getType());
+            }
+        });
+    }
+
+    @Override
     public URelationship getRelationship(final Long anyObjectKey) {
         return CollectionUtils.find(getRelationships(), new Predicate<URelationship>() {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java
index 4308de6..f1a70dc 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java
@@ -27,9 +27,6 @@ import org.slf4j.LoggerFactory;
 
 public abstract class AbstractValidator<A extends Annotation, T> implements ConstraintValidator<A, T> {
 
-    /**
-     * Logger.
-     */
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractValidator.class);
 
     protected static final Pattern NAME_PATTERN =

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeCheck.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeCheck.java
new file mode 100644
index 0000000..9574e53
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.validation.entity;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = RelationshipTypeValidator.class)
+@Documented
+public @interface RelationshipTypeCheck {
+
+    String message() default "{org.apache.syncope.core.persistence.validation.relationshiptype}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeValidator.java
new file mode 100644
index 0000000..8051bda
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeValidator.java
@@ -0,0 +1,41 @@
+/*
+ * 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.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.core.persistence.api.entity.MembershipType;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
+
+public class RelationshipTypeValidator extends AbstractValidator<RelationshipTypeCheck, RelationshipType> {
+
+    @Override
+    public boolean isValid(final RelationshipType object, final ConstraintValidatorContext context) {
+        context.disableDefaultConstraintViolation();
+
+        if (MembershipType.getInstance().getKey().equalsIgnoreCase(object.getKey())) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidName, "Invalid RelationshipType name")).
+                    addPropertyNode("name").addConstraintViolation();
+            return false;
+        }
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AnyObjectTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AnyObjectTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AnyObjectTest.java
deleted file mode 100644
index e149969..0000000
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AnyObjectTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
-import org.apache.syncope.core.persistence.api.dao.RealmDAO;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
-import org.apache.syncope.core.persistence.jpa.AbstractTest;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-
-@Transactional
-public class AnyObjectTest extends AbstractTest {
-
-    @Autowired
-    private AnyObjectDAO anyObjectDAO;
-
-    @Autowired
-    private RealmDAO realmDAO;
-
-    @Test
-    public void findAll() {
-        List<AnyObject> list = anyObjectDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 1, 100);
-        assertFalse(list.isEmpty());
-    }
-
-    @Test
-    public void findAllByType() {
-        List<AnyObject> list = anyObjectDAO.findAll("PRINTER", SyncopeConstants.FULL_ADMIN_REALMS, 1, 100);
-        assertFalse(list.isEmpty());
-
-        list = anyObjectDAO.findAll("UNEXISTING", SyncopeConstants.FULL_ADMIN_REALMS, 1, 100);
-        assertTrue(list.isEmpty());
-    }
-
-    @Test
-    public void find() {
-        AnyObject anyObject = anyObjectDAO.find(2L);
-        assertNotNull(anyObject);
-        assertNotNull(anyObject.getType());
-        assertFalse(anyObject.getType().getClasses().isEmpty());
-    }
-
-    @Test
-    public void save() {
-        AnyObject anyObject = entityFactory.newEntity(AnyObject.class);
-        anyObject.setRealm(realmDAO.find(SyncopeConstants.ROOT_REALM));
-
-        anyObject = anyObjectDAO.save(anyObject);
-        assertNotNull(anyObject);
-    }
-
-    @Test
-    public void delete() {
-        AnyObject anyObject = anyObjectDAO.find(2L);
-        anyObjectDAO.delete(anyObject.getKey());
-
-        AnyObject actual = anyObjectDAO.find(2L);
-        assertNull(actual);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8927ef4/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AnySearchTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AnySearchTest.java
deleted file mode 100644
index 018f632..0000000
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AnySearchTest.java
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
-import org.apache.syncope.core.persistence.api.dao.GroupDAO;
-import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
-import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
-import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.dao.search.ResourceCond;
-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.RelationshipCond;
-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;
-import org.apache.syncope.core.persistence.jpa.AbstractTest;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-
-@Transactional
-public class AnySearchTest extends AbstractTest {
-
-    @Autowired
-    private AnyObjectDAO anyObjectDAO;
-
-    @Autowired
-    private UserDAO userDAO;
-
-    @Autowired
-    private GroupDAO groupDAO;
-
-    @Autowired
-    private AnySearchDAO searchDAO;
-
-    @Test
-    public void anyObjectMatch() {
-        AnyObject anyObject = anyObjectDAO.find(1L);
-        assertNotNull(anyObject);
-
-        RelationshipCond cond = new RelationshipCond();
-        cond.setAnyObjectKey(2L);
-        assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(cond), AnyTypeKind.ANY_OBJECT));
-    }
-
-    @Test
-    public void userMatch() {
-        User user = userDAO.find(1L);
-        assertNotNull(user);
-
-        MembershipCond groupCond = new MembershipCond();
-        groupCond.setGroupKey(5L);
-        assertFalse(searchDAO.matches(user, SearchCond.getLeafCond(groupCond), AnyTypeKind.USER));
-
-        groupCond.setGroupKey(1L);
-        assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(groupCond), AnyTypeKind.USER));
-
-        RoleCond roleCond = new RoleCond();
-        roleCond.setRoleKey(3L);
-        assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(roleCond), AnyTypeKind.USER));
-    }
-
-    @Test
-    public void groupMatch() {
-        Group group = groupDAO.find(1L);
-        assertNotNull(group);
-
-        AttributeCond attrCond = new AttributeCond();
-        attrCond.setSchema("show");
-        attrCond.setType(AttributeCond.Type.ISNOTNULL);
-
-        assertTrue(searchDAO.matches(group, SearchCond.getLeafCond(attrCond), AnyTypeKind.GROUP));
-    }
-
-    @Test
-    public void searchWithLikeCondition() {
-        AttributeCond fullnameLeafCond = new AttributeCond(AttributeCond.Type.LIKE);
-        fullnameLeafCond.setSchema("fullname");
-        fullnameLeafCond.setExpression("%o%");
-
-        MembershipCond groupCond = new MembershipCond();
-        groupCond.setGroupKey(1L);
-
-        AttributeCond loginDateCond = new AttributeCond(AttributeCond.Type.EQ);
-        loginDateCond.setSchema("loginDate");
-        loginDateCond.setExpression("2009-05-26");
-
-        SearchCond subCond = SearchCond.getAndCond(
-                SearchCond.getLeafCond(fullnameLeafCond), SearchCond.getLeafCond(groupCond));
-
-        assertTrue(subCond.isValid());
-
-        SearchCond cond = SearchCond.getAndCond(subCond, SearchCond.getLeafCond(loginDateCond));
-
-        assertTrue(cond.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, cond, AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-    }
-
-    @Test
-    public void searchWithNotCondition() {
-        AttributeCond fullnameLeafCond = new AttributeCond(AttributeCond.Type.EQ);
-        fullnameLeafCond.setSchema("fullname");
-        fullnameLeafCond.setExpression("Giuseppe Verdi");
-
-        SearchCond cond = SearchCond.getNotLeafCond(fullnameLeafCond);
-        assertTrue(cond.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, cond, AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(4, users.size());
-
-        Set<Long> ids = new HashSet<>(users.size());
-        for (User user : users) {
-            ids.add(user.getKey());
-        }
-        assertTrue(ids.contains(1L));
-        assertTrue(ids.contains(3L));
-    }
-
-    @Test
-    public void searchByBoolean() {
-        AttributeCond coolLeafCond = new AttributeCond(AttributeCond.Type.EQ);
-        coolLeafCond.setSchema("cool");
-        coolLeafCond.setExpression("true");
-
-        SearchCond cond = SearchCond.getLeafCond(coolLeafCond);
-        assertTrue(cond.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, cond, AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-
-        assertEquals(Long.valueOf(4L), users.get(0).getKey());
-    }
-
-    @Test
-    public void searchByPageAndSize() {
-        AttributeCond fullnameLeafCond = new AttributeCond(AttributeCond.Type.LIKE);
-        fullnameLeafCond.setSchema("fullname");
-        fullnameLeafCond.setExpression("%o%");
-
-        MembershipCond groupCond = new MembershipCond();
-        groupCond.setGroupKey(1L);
-
-        AttributeCond loginDateCond = new AttributeCond(AttributeCond.Type.EQ);
-        loginDateCond.setSchema("loginDate");
-        loginDateCond.setExpression("2009-05-26");
-
-        SearchCond subCond = SearchCond.getAndCond(
-                SearchCond.getLeafCond(fullnameLeafCond), SearchCond.getLeafCond(groupCond));
-
-        assertTrue(subCond.isValid());
-
-        SearchCond cond = SearchCond.getAndCond(subCond, SearchCond.getLeafCond(loginDateCond));
-
-        assertTrue(cond.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                cond, 1, 2, Collections.<OrderByClause>emptyList(),
-                AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-
-        users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                cond, 2, 2, Collections.<OrderByClause>emptyList(),
-                AnyTypeKind.USER);
-        assertNotNull(users);
-        assertTrue(users.isEmpty());
-    }
-
-    @Test
-    public void searchByGroup() {
-        MembershipCond groupCond = new MembershipCond();
-        groupCond.setGroupKey(1L);
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                SearchCond.getLeafCond(groupCond), AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(2, users.size());
-
-        groupCond = new MembershipCond();
-        groupCond.setGroupKey(5L);
-
-        users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                SearchCond.getNotLeafCond(groupCond), AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(5, users.size());
-    }
-
-    @Test
-    public void searchByRole() {
-        RoleCond roleCond = new RoleCond();
-        roleCond.setRoleKey(3L);
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                SearchCond.getLeafCond(roleCond), AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-    }
-
-    @Test
-    public void searchByIsNull() {
-        AttributeCond coolLeafCond = new AttributeCond(AttributeCond.Type.ISNULL);
-        coolLeafCond.setSchema("cool");
-
-        List<User> users = searchDAO.search(
-                SyncopeConstants.FULL_ADMIN_REALMS, SearchCond.getLeafCond(coolLeafCond), AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(4, users.size());
-
-        coolLeafCond = new AttributeCond(AttributeCond.Type.ISNOTNULL);
-        coolLeafCond.setSchema("cool");
-
-        users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                SearchCond.getLeafCond(coolLeafCond), AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-    }
-
-    @Test
-    public void searchByResource() {
-        ResourceCond ws2 = new ResourceCond();
-        ws2.setResourceName("ws-target-resource-2");
-
-        ResourceCond ws1 = new ResourceCond();
-        ws1.setResourceName("ws-target-resource-list-mappings-2");
-
-        SearchCond searchCondition = SearchCond.getAndCond(SearchCond.getNotLeafCond(ws2), SearchCond.getLeafCond(ws1));
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-    }
-
-    @Test
-    public void searchByBooleanAnyCond() {
-        AttributeCond booleanCond = new AttributeCond(AnyCond.Type.EQ);
-        booleanCond.setSchema("show");
-        booleanCond.setExpression("true");
-
-        List<Group> matchingGroups = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                SearchCond.getLeafCond(booleanCond), AnyTypeKind.GROUP);
-        assertNotNull(matchingGroups);
-        assertFalse(matchingGroups.isEmpty());
-    }
-
-    @Test
-    public void searchByUsernameAndKey() {
-        AnyCond usernameLeafCond = new AnyCond(AnyCond.Type.LIKE);
-        usernameLeafCond.setSchema("username");
-        usernameLeafCond.setExpression("%ini");
-
-        AnyCond idRightCond = new AnyCond(AnyCond.Type.LT);
-        idRightCond.setSchema("key");
-        idRightCond.setExpression("2");
-
-        SearchCond searchCondition = SearchCond.getAndCond(
-                SearchCond.getLeafCond(usernameLeafCond),
-                SearchCond.getLeafCond(idRightCond));
-
-        List<User> matchingUsers = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, AnyTypeKind.USER);
-
-        assertNotNull(matchingUsers);
-        assertEquals(1, matchingUsers.size());
-        assertEquals("rossini", matchingUsers.iterator().next().getUsername());
-        assertEquals(1L, matchingUsers.iterator().next().getKey(), 0);
-    }
-
-    @Test
-    public void searchByGroupNameAndKey() {
-        AnyCond groupNameLeafCond = new AnyCond(AnyCond.Type.EQ);
-        groupNameLeafCond.setSchema("name");
-        groupNameLeafCond.setExpression("root");
-
-        AnyCond idRightCond = new AnyCond(AnyCond.Type.LT);
-        idRightCond.setSchema("key");
-        idRightCond.setExpression("2");
-
-        SearchCond searchCondition = SearchCond.getAndCond(
-                SearchCond.getLeafCond(groupNameLeafCond),
-                SearchCond.getLeafCond(idRightCond));
-
-        assertTrue(searchCondition.isValid());
-
-        List<Group> matchingGroups = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, AnyTypeKind.GROUP);
-
-        assertNotNull(matchingGroups);
-        assertEquals(1, matchingGroups.size());
-        assertEquals("root", matchingGroups.iterator().next().getName());
-        assertEquals(1L, matchingGroups.iterator().next().getKey(), 0);
-    }
-
-    @Test
-    public void searchByUsernameAndFullname() {
-        AnyCond usernameLeafCond = new AnyCond(AnyCond.Type.EQ);
-        usernameLeafCond.setSchema("username");
-        usernameLeafCond.setExpression("rossini");
-
-        AttributeCond idRightCond = new AttributeCond(AttributeCond.Type.LIKE);
-        idRightCond.setSchema("fullname");
-        idRightCond.setExpression("Giuseppe V%");
-
-        SearchCond searchCondition = SearchCond.getOrCond(
-                SearchCond.getLeafCond(usernameLeafCond),
-                SearchCond.getLeafCond(idRightCond));
-
-        List<User> matchingUsers = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, AnyTypeKind.USER);
-        assertNotNull(matchingUsers);
-        assertEquals(2, matchingUsers.size());
-    }
-
-    @Test
-    public void searchById() {
-        AnyCond idLeafCond = new AnyCond(AnyCond.Type.LT);
-        idLeafCond.setSchema("id");
-        idLeafCond.setExpression("2");
-
-        SearchCond searchCondition = SearchCond.getLeafCond(idLeafCond);
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-        assertEquals(1L, users.iterator().next().getKey(), 0);
-
-        idLeafCond = new AnyCond(AnyCond.Type.LT);
-        idLeafCond.setSchema("id");
-        idLeafCond.setExpression("4");
-
-        searchCondition = SearchCond.getNotLeafCond(idLeafCond);
-        assertTrue(searchCondition.isValid());
-
-        users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(2, users.size());
-        assertTrue(CollectionUtils.exists(users, new Predicate<User>() {
-
-            @Override
-            public boolean evaluate(User user) {
-                return user.getKey() == 4;
-            }
-        }));
-    }
-
-    @Test
-    public void searchByType() {
-        AnyTypeCond tcond = new AnyTypeCond();
-        tcond.setAnyTypeName("PRINTER");
-
-        SearchCond searchCondition = SearchCond.getLeafCond(tcond);
-        assertTrue(searchCondition.isValid());
-
-        List<AnyObject> printers = searchDAO.search(
-                SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.ANY_OBJECT);
-        assertNotNull(printers);
-        assertEquals(2, printers.size());
-
-        tcond.setAnyTypeName("UNEXISTING");
-        printers = searchDAO.search(
-                SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.ANY_OBJECT);
-        assertNotNull(printers);
-        assertTrue(printers.isEmpty());
-    }
-
-    @Test
-    public void userOrderBy() {
-        AnyCond usernameLeafCond = new AnyCond(AnyCond.Type.EQ);
-        usernameLeafCond.setSchema("username");
-        usernameLeafCond.setExpression("rossini");
-        AttributeCond idRightCond = new AttributeCond(AttributeCond.Type.LIKE);
-        idRightCond.setSchema("fullname");
-        idRightCond.setExpression("Giuseppe V%");
-        SearchCond searchCondition = SearchCond.getOrCond(
-                SearchCond.getLeafCond(usernameLeafCond), SearchCond.getLeafCond(idRightCond));
-
-        List<OrderByClause> orderByClauses = new ArrayList<>();
-        OrderByClause orderByClause = new OrderByClause();
-        orderByClause.setField("username");
-        orderByClause.setDirection(OrderByClause.Direction.DESC);
-        orderByClauses.add(orderByClause);
-        orderByClause = new OrderByClause();
-        orderByClause.setField("fullname");
-        orderByClause.setDirection(OrderByClause.Direction.ASC);
-        orderByClauses.add(orderByClause);
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, orderByClauses, AnyTypeKind.USER);
-        assertEquals(searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER),
-                users.size());
-    }
-
-    @Test
-    public void groupOrderBy() {
-        AnyCond idLeafCond = new AnyCond(AnyCond.Type.LIKE);
-        idLeafCond.setSchema("name");
-        idLeafCond.setExpression("%r");
-        SearchCond searchCondition = SearchCond.getLeafCond(idLeafCond);
-        assertTrue(searchCondition.isValid());
-
-        OrderByClause orderByClause = new OrderByClause();
-        orderByClause.setField("name");
-
-        List<Group> groups = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, Collections.singletonList(orderByClause), AnyTypeKind.GROUP);
-        assertEquals(searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, AnyTypeKind.GROUP),
-                groups.size());
-    }
-
-    @Test
-    public void issue202() {
-        ResourceCond ws2 = new ResourceCond();
-        ws2.setResourceName("ws-target-resource-2");
-
-        ResourceCond ws1 = new ResourceCond();
-        ws1.setResourceName("ws-target-resource-list-mappings-1");
-
-        SearchCond searchCondition =
-                SearchCond.getAndCond(SearchCond.getNotLeafCond(ws2), SearchCond.getNotLeafCond(ws1));
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(2, users.size());
-        assertTrue(CollectionUtils.exists(users, new Predicate<User>() {
-
-            @Override
-            public boolean evaluate(User user) {
-                return user.getKey() == 4;
-            }
-        }));
-    }
-
-    @Test
-    public void issue242() {
-        AnyCond cond = new AnyCond(AttributeCond.Type.LIKE);
-        cond.setSchema("id");
-        cond.setExpression("test%");
-
-        SearchCond searchCondition = SearchCond.getLeafCond(cond);
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER);
-        assertNotNull(users);
-        assertTrue(users.isEmpty());
-    }
-
-    @Test
-    public void issueSYNCOPE46() {
-        AnyCond cond = new AnyCond(AttributeCond.Type.LIKE);
-        cond.setSchema("username");
-        cond.setExpression("%ossin%");
-
-        SearchCond searchCondition = SearchCond.getLeafCond(cond);
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-    }
-
-    @Test
-    public void issueSYNCOPE433() {
-        AttributeCond isNullCond = new AttributeCond(AttributeCond.Type.ISNULL);
-        isNullCond.setSchema("loginDate");
-
-        AnyCond likeCond = new AnyCond(AttributeCond.Type.LIKE);
-        likeCond.setSchema("username");
-        likeCond.setExpression("%ossin%");
-
-        SearchCond searchCond = SearchCond.getOrCond(
-                SearchCond.getLeafCond(isNullCond), SearchCond.getLeafCond(likeCond));
-
-        Integer count = searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, searchCond, AnyTypeKind.USER);
-        assertNotNull(count);
-        assertTrue(count > 0);
-    }
-}


Mime
View raw message