syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject [4/5] syncope git commit: [SYNCOPE-862] Preliminary work
Date Wed, 01 Jun 2016 12:04:24 GMT
[SYNCOPE-862] Preliminary work


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

Branch: refs/heads/SYNCOPE-862
Commit: 38ae5776f1353d445e713cf453e2ffb85351c98c
Parents: 4e16b02
Author: Francesco Chicchiriccò <ilgrosso@apache.org>
Authored: Tue May 31 17:59:00 2016 +0200
Committer: Francesco Chicchiriccò <ilgrosso@apache.org>
Committed: Wed Jun 1 14:03:47 2016 +0200

----------------------------------------------------------------------
 .../AnyObjectDisplayAttributesModalPanel.java   |   2 +-
 .../panels/ConnObjectDirectoryPanel.java        |   8 +-
 .../html/repeater/data/table/AttrColumn.java    |  19 +-
 .../data/table/ConnObjectAttrColumn.java        |  63 +++++
 .../console/wizards/any/ConnObjectPanel.java    |   4 +-
 .../client/console/wizards/any/Groups.java      |   1 -
 .../wizards/resources/ResourceMappingPanel.java |   1 +
 .../syncope/common/lib/AnyOperations.java       |  90 +++++--
 .../common/lib/patch/AnyObjectPatch.java        |  10 +
 .../syncope/common/lib/patch/AnyPatch.java      |  10 +-
 .../common/lib/patch/AttributablePatch.java     |  38 +++
 .../common/lib/patch/MembershipPatch.java       |  33 ++-
 .../syncope/common/lib/to/AnyObjectTO.java      |  10 +
 .../org/apache/syncope/common/lib/to/AnyTO.java |  34 ++-
 .../syncope/common/lib/to/AttributableTO.java   |  53 ++++
 .../syncope/common/lib/to/ConnObjectTO.java     |   9 +-
 .../syncope/common/lib/to/MembershipTO.java     |  75 +++++-
 .../syncope/common/lib/to/RelationshipTO.java   |  26 --
 .../common/lib/types/EntityViolationType.java   |   4 +-
 .../common/lib/types/IntMappingType.java        |   8 +-
 .../persistence/api/dao/AllowedSchemas.java     | 114 +++++++++
 .../core/persistence/api/dao/AnyDAO.java        |   3 +-
 .../core/persistence/api/dao/AnyObjectDAO.java  |   4 +
 .../core/persistence/api/entity/Any.java        |   2 +
 .../core/persistence/api/entity/AnyUtils.java   |   3 +-
 .../api/entity/GroupablePlainAttr.java          |  26 ++
 .../api/entity/GroupableRelatable.java          | 100 ++++++++
 .../api/entity/anyobject/APlainAttr.java        |   4 +-
 .../api/entity/anyobject/AnyObject.java         |  24 +-
 .../persistence/api/entity/user/UPlainAttr.java |   4 +-
 .../core/persistence/api/entity/user/User.java  |  32 +--
 .../persistence/jpa/dao/AbstractAnyDAO.java     |  56 +++--
 .../persistence/jpa/dao/JPAAnyObjectDAO.java    |  34 +++
 .../core/persistence/jpa/dao/JPAConfDAO.java    |  12 +-
 .../core/persistence/jpa/dao/JPAGroupDAO.java   |  32 ++-
 .../persistence/jpa/dao/JPAPlainAttrDAO.java    |   2 +-
 .../persistence/jpa/entity/AbstractAny.java     |  28 ---
 .../jpa/entity/AbstractGroupableRelatable.java  | 158 ++++++++++++
 .../persistence/jpa/entity/JPAAnyUtils.java     |  13 +-
 .../jpa/entity/anyobject/JPAAPlainAttr.java     |  22 +-
 .../jpa/entity/anyobject/JPAAnyObject.java      |  95 +++----
 .../persistence/jpa/entity/conf/JPAConf.java    |   8 +-
 .../jpa/entity/group/JPAGPlainAttr.java         |   4 +-
 .../persistence/jpa/entity/group/JPAGroup.java  |  45 +++-
 .../jpa/entity/resource/JPAMappingItem.java     |   4 +
 .../jpa/entity/user/JPAUPlainAttr.java          |  22 +-
 .../persistence/jpa/entity/user/JPAUser.java    |  73 ++----
 .../jpa/validation/entity/AnyValidator.java     |  55 ++--
 .../entity/EntityValidationListener.java        |   5 +-
 .../entity/PlainAttrValueValidator.java         |   2 +-
 .../persistence/jpa/inner/AnyObjectTest.java    |   1 +
 .../persistence/jpa/inner/PlainAttrTest.java    |   2 +-
 .../core/persistence/jpa/outer/ConfTest.java    |  72 ++++++
 .../core/persistence/jpa/outer/GroupTest.java   |   1 +
 .../core/persistence/jpa/outer/UserTest.java    |  91 ++++++-
 .../test/resources/domains/MasterContent.xml    |  11 +-
 .../core/provisioning/api/DerAttrHandler.java   |  23 +-
 .../core/provisioning/api/VirAttrHandler.java   |  28 ++-
 .../provisioning/java/DerAttrHandlerImpl.java   |  32 ++-
 .../provisioning/java/MappingManagerImpl.java   |  20 ++
 .../provisioning/java/VirAttrHandlerImpl.java   |  36 ++-
 .../java/data/AbstractAnyDataBinder.java        | 248 ++++++++++++-------
 .../java/data/AnyObjectDataBinderImpl.java      | 115 +++++++--
 .../java/data/GroupDataBinderImpl.java          |   6 +-
 .../java/data/UserDataBinderImpl.java           |  90 +++++--
 .../java/job/SetUMembershipsJob.java            |   3 +-
 .../provisioning/java/pushpull/PullUtils.java   |   8 +
 .../java/utils/ConnObjectUtils.java             |   2 +-
 .../activiti/ActivitiUserWorkflowAdapter.java   |   2 +-
 fit/build-tools/src/main/resources/testdb.sql   |   1 +
 .../syncope/fit/console/AnyObjectsITCase.java   |   6 +-
 .../syncope/fit/console/BulkActionITCase.java   |   2 +-
 .../fit/console/DisplayAttributesITCase.java    |   4 +-
 .../syncope/fit/core/AnyObjectITCase.java       |   1 +
 .../syncope/fit/core/AuthenticationITCase.java  |   1 +
 .../syncope/fit/core/CamelRouteITCase.java      |   6 +-
 .../syncope/fit/core/MembershipITCase.java      | 162 ++++++++++++
 .../org/apache/syncope/fit/core/UserITCase.java |  13 +-
 .../apache/syncope/fit/core/UserSelfITCase.java |   3 +-
 .../resources/scriptedsql/CreateScript.groovy   |   3 +-
 .../resources/scriptedsql/SchemaScript.groovy   |   1 +
 .../resources/scriptedsql/SearchScript.groovy   |   2 +-
 .../resources/scriptedsql/SyncScript.groovy     |   3 +-
 .../resources/scriptedsql/TestScript.groovy     |   2 +-
 .../resources/scriptedsql/UpdateScript.groovy   |   7 +-
 85 files changed, 1945 insertions(+), 547 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java
index b99a323..39f30ad 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java
@@ -35,7 +35,7 @@ public class AnyObjectDisplayAttributesModalPanel<T extends Serializable> extend
 
     private static final long serialVersionUID = 5194630813773543054L;
 
-    public static final String[] DEFAULT_SELECTION = { "key" };
+    public static final String[] DEFAULT_SELECTION = { "key", "name" };
 
     public AnyObjectDisplayAttributesModalPanel(
             final BaseModal<T> modal,

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectDirectoryPanel.java
index 99dde2e..d80130b 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectDirectoryPanel.java
@@ -30,7 +30,7 @@ import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
 import org.apache.syncope.client.console.panels.ConnObjectDirectoryPanel.ConnObjectDataProvider;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
-import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.AttrColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ConnObjectAttrColumn;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
@@ -101,9 +101,9 @@ public abstract class ConnObjectDirectoryPanel
     protected List<IColumn<ConnObjectTO, String>> getColumns() {
         final List<IColumn<ConnObjectTO, String>> columns = new ArrayList<>();
 
-        columns.add(new AttrColumn<>(ConnIdSpecialAttributeName.UID, SchemaType.PLAIN));
-        columns.add(new AttrColumn<>(ConnIdSpecialAttributeName.NAME, SchemaType.PLAIN));
-        columns.add(new AttrColumn<>(ConnIdSpecialAttributeName.ENABLE, SchemaType.PLAIN));
+        columns.add(new ConnObjectAttrColumn(ConnIdSpecialAttributeName.UID, SchemaType.PLAIN));
+        columns.add(new ConnObjectAttrColumn(ConnIdSpecialAttributeName.NAME, SchemaType.PLAIN));
+        columns.add(new ConnObjectAttrColumn(ConnIdSpecialAttributeName.ENABLE, SchemaType.PLAIN));
 
         columns.add(new ActionColumn<ConnObjectTO, String>(new ResourceModel("actions")) {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java
index 9a90ef6..b756a05 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java
@@ -26,10 +26,9 @@ import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.ResourceModel;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.ConnObjectTO;
+import org.apache.syncope.common.lib.to.AttributableTO;
 
-public class AttrColumn<T extends ConnObjectTO> extends AbstractColumn<T, String> {
+public class AttrColumn<T extends AttributableTO> extends AbstractColumn<T, String> {
 
     private static final long serialVersionUID = 2624734332447371372L;
 
@@ -59,20 +58,14 @@ public class AttrColumn<T extends ConnObjectTO> extends AbstractColumn<T, String
                 break;
 
             case DERIVED:
-                if (rowModel.getObject() instanceof AnyTO) {
-                    AnyTO obj = AnyTO.class.cast(rowModel.getObject());
-                    if (obj.getDerAttrMap().containsKey(name)) {
-                        values = obj.getDerAttrMap().get(name).getValues();
-                    }
+                if (rowModel.getObject().getDerAttrMap().containsKey(name)) {
+                    values = rowModel.getObject().getDerAttrMap().get(name).getValues();
                 }
                 break;
 
             case VIRTUAL:
-                if (rowModel.getObject() instanceof AnyTO) {
-                    AnyTO obj = AnyTO.class.cast(rowModel.getObject());
-                    if (obj.getVirAttrMap().containsKey(name)) {
-                        values = obj.getVirAttrMap().get(name).getValues();
-                    }
+                if (rowModel.getObject().getVirAttrMap().containsKey(name)) {
+                    values = rowModel.getObject().getVirAttrMap().get(name).getValues();
                 }
                 break;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ConnObjectAttrColumn.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ConnObjectAttrColumn.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ConnObjectAttrColumn.java
new file mode 100644
index 0000000..56ead58
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ConnObjectAttrColumn.java
@@ -0,0 +1,63 @@
+/*
+ * 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.client.console.wicket.extensions.markup.html.repeater.data.table;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.syncope.common.lib.to.ConnObjectTO;
+
+public class ConnObjectAttrColumn extends AbstractColumn<ConnObjectTO, String> {
+
+    private static final long serialVersionUID = 2624734332447371372L;
+
+    private final String name;
+
+    public ConnObjectAttrColumn(final String name, final SchemaType schemaType) {
+        // set sortProperty to schematype#name (e.g. derivedSchema#cn, 
+        // for use with SortableUserProviderComparator.AttrModel#getObject)
+        super(new ResourceModel(name, name), schemaType.name() + "#" + name);
+        this.name = name;
+    }
+
+    @Override
+    public void populateItem(
+            final Item<ICellPopulator<ConnObjectTO>> cellItem,
+            final String componentId,
+            final IModel<ConnObjectTO> rowModel) {
+
+        List<String> values = null;
+        if (rowModel.getObject().getPlainAttrMap().containsKey(name)) {
+            values = rowModel.getObject().getPlainAttrMap().get(name).getValues();
+        }
+
+        if (values == null || values.isEmpty()) {
+            cellItem.add(new Label(componentId, ""));
+        } else if (values.size() == 1) {
+            cellItem.add(new Label(componentId, values.get(0)));
+        } else {
+            cellItem.add(new Label(componentId, values.toString()));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
index 14e3e33..49f6801 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
@@ -57,7 +57,7 @@ public class ConnObjectPanel extends Panel {
             protected List<AttrTO> load() {
                 List<AttrTO> attrs = new ArrayList<>(connObjectTOs == null || connObjectTOs.getRight() == null
                         ? Collections.<AttrTO>emptyList()
-                        : connObjectTOs.getRight().getPlainAttrs());
+                        : connObjectTOs.getRight().getAttrs());
 
                 Collections.sort(attrs, new Comparator<AttrTO>() {
 
@@ -77,7 +77,7 @@ public class ConnObjectPanel extends Panel {
             }
         };
 
-        final Map<String, AttrTO> beforeProfile = connObjectTOs.getLeft() == null
+        final Map<String, AttrTO> beforeProfile = connObjectTOs == null || connObjectTOs.getLeft() == null
                 ? null
                 : connObjectTOs.getLeft().getPlainAttrMap();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
index 8c84cda..401f8e0 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
@@ -105,7 +105,6 @@ public class Groups extends WizardStep {
                     public MembershipTO transform(final GroupTO input) {
                         return new MembershipTO.Builder().
                                 group(input.getKey(), input.getName()).
-                                left(anyTO.getKey(), anyTO.getType()).
                                 build();
                     }
                 }, new ArrayList<MembershipTO>());

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
index 5020bd7..06ea7c8 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
@@ -570,6 +570,7 @@ public class ResourceMappingPanel extends Panel {
                 case GroupKey:
                 case GroupName:
                 case AnyObjectKey:
+                case AnyObjectName:
                 default:
                     toBeUpdated.setRequired(false);
                     toBeUpdated.setEnabled(false);

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java b/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
index 39fbc63..1f985a4 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
@@ -25,6 +25,7 @@ import java.util.Set;
 import org.apache.commons.collections4.Closure;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
@@ -173,7 +174,10 @@ public final class AnyOperations {
 
         diff(updated, original, result, incremental);
 
-        // 1. relationships
+        // 1. name
+        result.setName(replacePatchItem(updated.getName(), original.getName(), new StringReplacePatchItem()));
+
+        // 2. relationships
         Map<Pair<String, String>, RelationshipTO> updatedRels = updated.getRelationshipMap();
         Map<Pair<String, String>, RelationshipTO> originalRels = original.getRelationshipMap();
 
@@ -193,21 +197,21 @@ public final class AnyOperations {
             }
         }
 
-        // 2. memberships
+        // 3. memberships
         Map<String, MembershipTO> updatedMembs = updated.getMembershipMap();
         Map<String, MembershipTO> originalMembs = original.getMembershipMap();
 
         for (Map.Entry<String, MembershipTO> entry : updatedMembs.entrySet()) {
             if (!originalMembs.containsKey(entry.getKey())) {
                 result.getMemberships().add(new MembershipPatch.Builder().
-                        operation(PatchOperation.ADD_REPLACE).membershipTO(entry.getValue()).build());
+                        operation(PatchOperation.ADD_REPLACE).group(entry.getValue().getGroupKey()).build());
             }
         }
 
         if (!incremental) {
             for (String key : CollectionUtils.subtract(originalMembs.keySet(), updatedMembs.keySet())) {
                 result.getMemberships().add(new MembershipPatch.Builder().
-                        operation(PatchOperation.DELETE).membershipTO(originalMembs.get(key)).build());
+                        operation(PatchOperation.DELETE).group(originalMembs.get(key).getGroupKey()).build());
             }
         }
 
@@ -294,14 +298,14 @@ public final class AnyOperations {
         for (Map.Entry<String, MembershipTO> entry : updatedMembs.entrySet()) {
             if (!originalMembs.containsKey(entry.getKey())) {
                 result.getMemberships().add(new MembershipPatch.Builder().
-                        operation(PatchOperation.ADD_REPLACE).membershipTO(entry.getValue()).build());
+                        operation(PatchOperation.ADD_REPLACE).group(entry.getValue().getGroupKey()).build());
             }
         }
 
         if (!incremental) {
             for (String key : CollectionUtils.subtract(originalMembs.keySet(), updatedMembs.keySet())) {
                 result.getMemberships().add(new MembershipPatch.Builder().
-                        operation(PatchOperation.DELETE).membershipTO(originalMembs.get(key)).build());
+                        operation(PatchOperation.DELETE).group(originalMembs.get(key).getGroupKey()).build());
             }
         }
 
@@ -410,7 +414,7 @@ public final class AnyOperations {
 
         // 2. plain attributes
         result.getPlainAttrs().clear();
-        result.getPlainAttrs().addAll(AnyOperations.patch(to.getPlainAttrMap(), patch.getPlainAttrs()));
+        result.getPlainAttrs().addAll(patch(to.getPlainAttrMap(), patch.getPlainAttrs()));
 
         // 3. virtual attributes
         result.getVirAttrs().clear();
@@ -432,7 +436,7 @@ public final class AnyOperations {
 
     public static GroupTO patch(final GroupTO groupTO, final GroupPatch groupPatch) {
         GroupTO result = SerializationUtils.clone(groupTO);
-        AnyOperations.patch(groupTO, groupPatch, result);
+        patch(groupTO, groupPatch, result);
 
         if (groupPatch.getName() != null) {
             result.setName(groupPatch.getName().getValue());
@@ -454,10 +458,10 @@ public final class AnyOperations {
 
     public static AnyObjectTO patch(final AnyObjectTO anyObjectTO, final AnyObjectPatch anyObjectPatch) {
         AnyObjectTO result = SerializationUtils.clone(anyObjectTO);
-        AnyOperations.patch(anyObjectTO, anyObjectPatch, result);
+        patch(anyObjectTO, anyObjectPatch, result);
 
         // 1. relationships
-        for (final RelationshipPatch relPatch : anyObjectPatch.getRelationships()) {
+        for (RelationshipPatch relPatch : anyObjectPatch.getRelationships()) {
             if (relPatch.getRelationshipTO() == null) {
                 LOG.warn("Invalid {} specified: {}", RelationshipPatch.class.getName(), relPatch);
             } else {
@@ -470,12 +474,37 @@ public final class AnyOperations {
 
         // 2. memberships
         for (final MembershipPatch membPatch : anyObjectPatch.getMemberships()) {
-            if (membPatch.getMembershipTO() == null) {
+            if (membPatch.getGroup() == null) {
                 LOG.warn("Invalid {} specified: {}", MembershipPatch.class.getName(), membPatch);
             } else {
-                result.getMemberships().remove(membPatch.getMembershipTO());
+                MembershipTO memb = IterableUtils.find(result.getMemberships(), new Predicate<MembershipTO>() {
+
+                    @Override
+                    public boolean evaluate(final MembershipTO object) {
+                        return membPatch.getGroup().equals(object.getGroupKey());
+                    }
+                });
+                if (memb != null) {
+                    result.getMemberships().remove(memb);
+                }
+
                 if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
-                    result.getMemberships().add(membPatch.getMembershipTO());
+                    MembershipTO newMembershipTO = new MembershipTO();
+                    newMembershipTO.setGroupKey(membPatch.getGroup());
+
+                    if (memb == null) {
+                        for (AttrPatch attrPatch : membPatch.getPlainAttrs()) {
+                            newMembershipTO.getPlainAttrs().add(attrPatch.getAttrTO());
+                        }
+                    } else {
+                        newMembershipTO.getPlainAttrs().addAll(
+                                patch(memb.getPlainAttrMap(), membPatch.getPlainAttrs()));
+                    }
+
+                    // 3. virtual attributes
+                    newMembershipTO.getVirAttrs().addAll(membPatch.getVirAttrs());
+
+                    result.getMemberships().add(newMembershipTO);
                 }
             }
         }
@@ -485,7 +514,7 @@ public final class AnyOperations {
 
     public static UserTO patch(final UserTO userTO, final UserPatch userPatch) {
         UserTO result = SerializationUtils.clone(userTO);
-        AnyOperations.patch(userTO, userPatch, result);
+        patch(userTO, userPatch, result);
 
         // 1. password
         if (userPatch.getPassword() != null) {
@@ -498,7 +527,7 @@ public final class AnyOperations {
         }
 
         // 3. relationships
-        for (final RelationshipPatch relPatch : userPatch.getRelationships()) {
+        for (RelationshipPatch relPatch : userPatch.getRelationships()) {
             if (relPatch.getRelationshipTO() == null) {
                 LOG.warn("Invalid {} specified: {}", RelationshipPatch.class.getName(), relPatch);
             } else {
@@ -511,12 +540,37 @@ public final class AnyOperations {
 
         // 4. memberships
         for (final MembershipPatch membPatch : userPatch.getMemberships()) {
-            if (membPatch.getMembershipTO() == null) {
+            if (membPatch.getGroup() == null) {
                 LOG.warn("Invalid {} specified: {}", MembershipPatch.class.getName(), membPatch);
             } else {
-                result.getMemberships().remove(membPatch.getMembershipTO());
+                MembershipTO memb = IterableUtils.find(result.getMemberships(), new Predicate<MembershipTO>() {
+
+                    @Override
+                    public boolean evaluate(final MembershipTO object) {
+                        return membPatch.getGroup().equals(object.getGroupKey());
+                    }
+                });
+                if (memb != null) {
+                    result.getMemberships().remove(memb);
+                }
+
                 if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
-                    result.getMemberships().add(membPatch.getMembershipTO());
+                    MembershipTO newMembershipTO = new MembershipTO();
+                    newMembershipTO.setGroupKey(membPatch.getGroup());
+
+                    if (memb == null) {
+                        for (AttrPatch attrPatch : membPatch.getPlainAttrs()) {
+                            newMembershipTO.getPlainAttrs().add(attrPatch.getAttrTO());
+                        }
+                    } else {
+                        newMembershipTO.getPlainAttrs().addAll(
+                                patch(memb.getPlainAttrMap(), membPatch.getPlainAttrs()));
+                    }
+
+                    // 3. virtual attributes
+                    newMembershipTO.getVirAttrs().addAll(membPatch.getVirAttrs());
+
+                    result.getMemberships().add(newMembershipTO);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java
index e473e06..ddb4ac3 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java
@@ -32,10 +32,20 @@ public class AnyObjectPatch extends AnyPatch {
 
     private static final long serialVersionUID = -1644118942622556097L;
 
+    private StringReplacePatchItem name;
+
     private final Set<RelationshipPatch> relationships = new HashSet<>();
 
     private final Set<MembershipPatch> memberships = new HashSet<>();
 
+    public StringReplacePatchItem getName() {
+        return name;
+    }
+
+    public void setName(final StringReplacePatchItem name) {
+        this.name = name;
+    }
+
     @XmlElementWrapper(name = "relationships")
     @XmlElement(name = "relationship")
     @JsonProperty("relationships")

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
index 3ec141d..78e61dd 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
@@ -30,7 +30,7 @@ import org.apache.syncope.common.lib.AbstractBaseBean;
 import org.apache.syncope.common.lib.to.AttrTO;
 
 @XmlType
-public abstract class AnyPatch extends AbstractBaseBean {
+public abstract class AnyPatch extends AbstractBaseBean implements AttributablePatch {
 
     private static final long serialVersionUID = -7445489774552440544L;
 
@@ -70,16 +70,12 @@ public abstract class AnyPatch extends AbstractBaseBean {
         return auxClasses;
     }
 
-    @XmlElementWrapper(name = "plainAttrs")
-    @XmlElement(name = "attribute")
-    @JsonProperty("plainAttrs")
+    @Override
     public Set<AttrPatch> getPlainAttrs() {
         return plainAttrs;
     }
 
-    @XmlElementWrapper(name = "virAttrs")
-    @XmlElement(name = "attribute")
-    @JsonProperty("virAttrs")
+    @Override
     public Set<AttrTO> getVirAttrs() {
         return virAttrs;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AttributablePatch.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AttributablePatch.java b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AttributablePatch.java
new file mode 100644
index 0000000..fa9d189
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AttributablePatch.java
@@ -0,0 +1,38 @@
+/*
+ * 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.patch;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import org.apache.syncope.common.lib.to.AttrTO;
+
+public interface AttributablePatch {
+
+    @XmlElementWrapper(name = "plainAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("plainAttrs")
+    Set<AttrPatch> getPlainAttrs();
+
+    @XmlElementWrapper(name = "virAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virAttrs")
+    Set<AttrTO> getVirAttrs();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java
index b29a6de..0ed42c1 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java
@@ -18,13 +18,15 @@
  */
 package org.apache.syncope.common.lib.patch;
 
+import java.util.HashSet;
+import java.util.Set;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.AttrTO;
 
 @XmlRootElement(name = "membershipPatch")
 @XmlType
-public class MembershipPatch extends AbstractPatch {
+public class MembershipPatch extends AbstractPatch implements AttributablePatch {
 
     private static final long serialVersionUID = -6783121761221554433L;
 
@@ -35,20 +37,33 @@ public class MembershipPatch extends AbstractPatch {
             return new MembershipPatch();
         }
 
-        public Builder membershipTO(final MembershipTO membershipTO) {
-            getInstance().setMembershipTO(membershipTO);
+        public Builder group(final String group) {
+            getInstance().setGroup(group);
             return this;
         }
     }
 
-    private MembershipTO membershipTO;
+    private String group;
 
-    public MembershipTO getMembershipTO() {
-        return membershipTO;
+    private final Set<AttrPatch> plainAttrs = new HashSet<>();
+
+    private final Set<AttrTO> virAttrs = new HashSet<>();
+
+    public String getGroup() {
+        return group;
     }
 
-    public void setMembershipTO(final MembershipTO membershipTO) {
-        this.membershipTO = membershipTO;
+    public void setGroup(final String group) {
+        this.group = group;
     }
 
+    @Override
+    public Set<AttrPatch> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public Set<AttrTO> getVirAttrs() {
+        return virAttrs;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
index f652d76..d0bf7d4 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
@@ -37,12 +37,22 @@ public class AnyObjectTO extends AnyTO implements RelatableTO, GroupableTO {
 
     private static final long serialVersionUID = 8841697496476959639L;
 
+    private String name;
+
     private final List<RelationshipTO> relationships = new ArrayList<>();
 
     private final List<MembershipTO> memberships = new ArrayList<>();
 
     private final List<String> dynGroups = new ArrayList<>();
 
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
     @XmlElementWrapper(name = "relationships")
     @XmlElement(name = "relationship")
     @JsonProperty("relationships")

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
index 4651835..7732bcc 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.common.lib.to;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import java.util.ArrayList;
@@ -30,15 +29,13 @@ import java.util.Map;
 import java.util.Set;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlType;
 
-@XmlRootElement(name = "any")
 @XmlType
 @XmlSeeAlso({ UserTO.class, GroupTO.class, AnyObjectTO.class })
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
-public abstract class AnyTO extends ConnObjectTO implements EntityTO {
+public abstract class AnyTO extends AbstractAnnotatedBean implements EntityTO, AttributableTO {
 
     private static final long serialVersionUID = -754311920679872084L;
 
@@ -52,6 +49,8 @@ public abstract class AnyTO extends ConnObjectTO implements EntityTO {
 
     private final List<String> auxClasses = new ArrayList<>();
 
+    private final Set<AttrTO> plainAttrs = new HashSet<>();
+
     private final Set<AttrTO> derAttrs = new HashSet<>();
 
     private final Set<AttrTO> virAttrs = new HashSet<>();
@@ -99,14 +98,27 @@ public abstract class AnyTO extends ConnObjectTO implements EntityTO {
         return auxClasses;
     }
 
-    @XmlElementWrapper(name = "derAttrs")
-    @XmlElement(name = "attribute")
-    @JsonProperty("derAttrs")
+    @Override
+    public Set<AttrTO> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public Map<String, AttrTO> getPlainAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(plainAttrs.size());
+        for (AttrTO attributeTO : plainAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+
+        return Collections.unmodifiableMap(result);
+    }
+
+    @Override
     public Set<AttrTO> getDerAttrs() {
         return derAttrs;
     }
 
-    @JsonIgnore
+    @Override
     public Map<String, AttrTO> getDerAttrMap() {
         Map<String, AttrTO> result = new HashMap<>(derAttrs.size());
         for (AttrTO attributeTO : derAttrs) {
@@ -116,14 +128,12 @@ public abstract class AnyTO extends ConnObjectTO implements EntityTO {
         return Collections.unmodifiableMap(result);
     }
 
-    @XmlElementWrapper(name = "virAttrs")
-    @XmlElement(name = "attribute")
-    @JsonProperty("virAttrs")
+    @Override
     public Set<AttrTO> getVirAttrs() {
         return virAttrs;
     }
 
-    @JsonIgnore
+    @Override
     public Map<String, AttrTO> getVirAttrMap() {
         Map<String, AttrTO> result = new HashMap<>(virAttrs.size());
         for (AttrTO attributeTO : virAttrs) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttributableTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttributableTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttributableTO.java
new file mode 100644
index 0000000..51ee0fc
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttributableTO.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 com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+public interface AttributableTO {
+
+    @XmlElementWrapper(name = "plainAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("plainAttrs")
+    Set<AttrTO> getPlainAttrs();
+
+    @JsonIgnore
+    Map<String, AttrTO> getPlainAttrMap();
+
+    @XmlElementWrapper(name = "derAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derAttrs")
+    Set<AttrTO> getDerAttrs();
+
+    @JsonIgnore
+    Map<String, AttrTO> getDerAttrMap();
+
+    @XmlElementWrapper(name = "virAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virAttrs")
+    Set<AttrTO> getVirAttrs();
+
+    @JsonIgnore
+    Map<String, AttrTO> getVirAttrMap();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
index 82878f8..8f65b70 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
@@ -29,19 +29,20 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
 
 @XmlRootElement(name = "connObject")
 @XmlType
-public class ConnObjectTO extends AbstractAnnotatedBean {
+public class ConnObjectTO extends AbstractBaseBean {
 
     private static final long serialVersionUID = 5139554911265442497L;
 
     private final Set<AttrTO> attrs = new LinkedHashSet<>();
 
-    @XmlElementWrapper(name = "plainAttrs")
+    @XmlElementWrapper(name = "attrs")
     @XmlElement(name = "attribute")
-    @JsonProperty("plainAttrs")
-    public Set<AttrTO> getPlainAttrs() {
+    @JsonProperty("attrs")
+    public Set<AttrTO> getAttrs() {
         return attrs;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/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 6ded46b..58f3d9d 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
@@ -18,13 +18,19 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 @XmlRootElement(name = "membership")
 @XmlType
-public class MembershipTO extends RelationshipTO {
+public class MembershipTO extends RelationshipTO implements AttributableTO {
 
     private static final long serialVersionUID = 5992828670273935861L;
 
@@ -32,12 +38,6 @@ public class MembershipTO extends RelationshipTO {
 
         private final MembershipTO instance = new MembershipTO();
 
-        public Builder left(final String leftType, final String leftKey) {
-            instance.setLeftType(leftType);
-            instance.setLeftKey(leftKey);
-            return this;
-        }
-
         public Builder group(final String groupKey) {
             instance.setRightKey(groupKey);
             return this;
@@ -56,6 +56,12 @@ public class MembershipTO extends RelationshipTO {
 
     private String groupName;
 
+    private final Set<AttrTO> plainAttrs = new HashSet<>();
+
+    private final Set<AttrTO> derAttrs = new HashSet<>();
+
+    private final Set<AttrTO> virAttrs = new HashSet<>();
+
     @Override
     public String getType() {
         return "Membership";
@@ -76,6 +82,15 @@ public class MembershipTO extends RelationshipTO {
         // ignore
     }
 
+    @JsonIgnore
+    public String getGroupKey() {
+        return getRightKey();
+    }
+
+    public void setGroupKey(final String groupKey) {
+        setRightKey(groupKey);
+    }
+
     public String getGroupName() {
         return groupName;
     }
@@ -83,4 +98,50 @@ public class MembershipTO extends RelationshipTO {
     public void setGroupName(final String groupName) {
         this.groupName = groupName;
     }
+
+    @Override
+    public Set<AttrTO> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public Map<String, AttrTO> getPlainAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(plainAttrs.size());
+        for (AttrTO attributeTO : plainAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+
+        return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public Set<AttrTO> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @Override
+    public Map<String, AttrTO> getDerAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(derAttrs.size());
+        for (AttrTO attributeTO : derAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+
+        return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public Set<AttrTO> getVirAttrs() {
+        return virAttrs;
+    }
+
+    @Override
+    public Map<String, AttrTO> getVirAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(virAttrs.size());
+        for (AttrTO attributeTO : virAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+
+        return Collections.unmodifiableMap(result);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/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 29326c2..fc5de4f 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
@@ -37,12 +37,6 @@ public class RelationshipTO extends AbstractBaseBean {
             return this;
         }
 
-        public Builder left(final String leftType, final String leftKey) {
-            instance.setLeftType(leftType);
-            instance.setLeftKey(leftKey);
-            return this;
-        }
-
         public Builder right(final String rightType, final String rightKey) {
             instance.setRightType(rightType);
             instance.setRightKey(rightKey);
@@ -56,10 +50,6 @@ public class RelationshipTO extends AbstractBaseBean {
 
     private String type;
 
-    private String leftType;
-
-    private String leftKey;
-
     private String rightType;
 
     private String rightKey;
@@ -72,22 +62,6 @@ public class RelationshipTO extends AbstractBaseBean {
         this.type = type;
     }
 
-    public String getLeftType() {
-        return leftType;
-    }
-
-    public void setLeftType(final String leftType) {
-        this.leftType = leftType;
-    }
-
-    public String getLeftKey() {
-        return leftKey;
-    }
-
-    public void setLeftKey(final String leftKey) {
-        this.leftKey = leftKey;
-    }
-
     public String getRightType() {
         return rightType;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
index 7532730..db3e329 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
@@ -43,9 +43,7 @@ public enum EntityViolationType {
     InvalidSchemaMultivalueUnique("org.apache.syncope.core.persistence.validation.schema.multivalueUnique"),
     InvalidSchedTask("org.apache.syncope.core.persistence.validation.schedtask"),
     InvalidProvisioningTask("org.apache.syncope.core.persistence.validation.provisioningtask"),
-    InvalidPlainSchema("org.apache.syncope.core.persistence.validation.attrvalue.plainSchema"),
-    InvalidDerSchema("org.apache.syncope.core.persistence.validation.attrvalue.derSchema"),
-    InvalidVirSchema("org.apache.syncope.core.persistence.validation.attrvalue.virSchema"),
+    InvalidPlainAttr("org.apache.syncope.core.persistence.validation.plainattr"),
     InvalidUsername("org.apache.syncope.core.persistence.validation.user.username"),
     InvalidValueList("org.apache.syncope.core.persistence.validation.attr.valueList"),
     MoreThanOneNonNull("org.apache.syncope.core.persistence.validation.attrvalue.moreThanOneNonNull");

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
index eccb89d..8553348 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
@@ -56,7 +56,8 @@ public enum IntMappingType {
     AnyObjectPlainSchema(AnyTypeKind.ANY_OBJECT),
     AnyObjectDerivedSchema(AnyTypeKind.ANY_OBJECT),
     AnyObjectVirtualSchema(AnyTypeKind.ANY_OBJECT),
-    AnyObjectKey(AnyTypeKind.ANY_OBJECT);
+    AnyObjectKey(AnyTypeKind.ANY_OBJECT),
+    AnyObjectName(AnyTypeKind.ANY_OBJECT);
 
     private final AnyTypeKind anyTypeKind;
 
@@ -119,7 +120,7 @@ public enum IntMappingType {
     public static Set<IntMappingType> getEmbedded() {
         return EnumSet.of(IntMappingType.UserKey, IntMappingType.Username, IntMappingType.Password,
                 IntMappingType.GroupKey, IntMappingType.GroupName, IntMappingType.GroupOwnerSchema,
-                IntMappingType.AnyObjectKey);
+                IntMappingType.AnyObjectKey, IntMappingType.AnyObjectName);
     }
 
     /**
@@ -195,7 +196,8 @@ public enum IntMappingType {
         AnyObjectPlainSchema,
         AnyObjectDerivedSchema,
         AnyObjectVirtualSchema,
-        AnyObjectKey;
+        AnyObjectKey,
+        AnyObjectName;
 
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AllowedSchemas.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AllowedSchemas.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AllowedSchemas.java
new file mode 100644
index 0000000..6c04ac4
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AllowedSchemas.java
@@ -0,0 +1,114 @@
+/*
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.commons.collections4.PredicateUtils;
+import org.apache.commons.collections4.SetUtils;
+import org.apache.syncope.core.persistence.api.entity.Schema;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+
+public class AllowedSchemas<S extends Schema> {
+
+    private final Set<S> forSelf = new HashSet<>();
+
+    private final Map<Group, Set<S>> forMemberships = new HashMap<>();
+
+    public Set<S> getForSelf() {
+        return forSelf;
+    }
+
+    public Set<S> getForMembership(final Group group) {
+        return SetUtils.emptyIfNull(forMemberships.get(group));
+    }
+
+    public Map<Group, Set<S>> getForMemberships() {
+        return forMemberships;
+    }
+
+    public boolean forSelfContains(final S schema) {
+        return forSelf.contains(schema);
+    }
+
+    public boolean forSelfContains(final String schema) {
+        return IterableUtils.matchesAny(forSelf, new KeyMatches(schema));
+    }
+
+    public boolean forMembershipsContains(final Group group, final S schema) {
+        return IterableUtils.matchesAny(forMemberships.get(group), PredicateUtils.equalPredicate(schema));
+    }
+
+    public boolean forMembershipsContains(final S schema) {
+        for (Map.Entry<Group, Set<S>> entry : forMemberships.entrySet()) {
+            if (entry.getValue().contains(schema)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean forMembershipsContains(final Group group, final String schema) {
+        return IterableUtils.matchesAny(forMemberships.get(group), new KeyMatches(schema));
+    }
+
+    public boolean forMembershipsContains(final String schema) {
+        KeyMatches keyMatches = new KeyMatches(schema);
+
+        for (Map.Entry<Group, Set<S>> entry : forMemberships.entrySet()) {
+            if (IterableUtils.matchesAny(entry.getValue(), keyMatches)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean contains(final S schema) {
+        if (forSelfContains(schema)) {
+            return true;
+        }
+        return forMembershipsContains(schema);
+    }
+
+    public boolean contains(final String schema) {
+        if (forSelfContains(schema)) {
+            return true;
+        }
+        return forMembershipsContains(schema);
+    }
+
+    private class KeyMatches implements Predicate<S> {
+
+        private final String schema;
+
+        KeyMatches(final String schema) {
+            this.schema = schema;
+        }
+
+        @Override
+        public boolean evaluate(final S object) {
+            return object.getKey().equals(schema);
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
index b6d78fd..6b2fd4e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.core.persistence.api.dao;
 
-import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
@@ -72,7 +71,7 @@ public interface AnyDAO<A extends Any<?>> extends DAO<A> {
      */
     List<A> findAll(Set<String> adminRealms, int page, int itemsPerPage, List<OrderByClause> orderBy);
 
-    <S extends Schema> Collection<S> findAllowedSchemas(A any, Class<S> reference);
+    <S extends Schema> AllowedSchemas<S> findAllowedSchemas(A any, Class<S> reference);
 
     int count(Set<String> adminRealms);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
index bdf9642..c24b37d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
@@ -40,6 +40,10 @@ public interface AnyObjectDAO extends AnyDAO<AnyObject> {
 
     Map<String, Integer> countByRealm(AnyType anyType);
 
+    AnyObject findByName(String name);
+
+    AnyObject authFindByName(String name);
+
     List<Group> findDynGroupMemberships(AnyObject anyObject);
 
     List<ARelationship> findARelationships(AnyObject anyObject);

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
index b1580e3..82359e9 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
@@ -41,6 +41,8 @@ public interface Any<P extends PlainAttr<?>> extends AnnotatedEntity {
 
     boolean add(P attr);
 
+    boolean remove(P attr);
+
     P getPlainAttr(String plainSchemaName);
 
     List<? extends P> getPlainAttrs();

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
index 377f7fe..0e0c8cc 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
@@ -22,6 +22,7 @@ import java.util.Set;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 
 public interface AnyUtils {
@@ -52,5 +53,5 @@ public interface AnyUtils {
 
     Set<ExternalResource> getAllResources(Any<?> any);
 
-    <S extends Schema> Set<S> getAllowedSchemas(Any<?> any, Class<S> reference);
+    <S extends Schema> AllowedSchemas<S> getAllowedSchemas(Any<?> any, Class<S> reference);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupablePlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupablePlainAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupablePlainAttr.java
new file mode 100644
index 0000000..7e345a5
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupablePlainAttr.java
@@ -0,0 +1,26 @@
+/*
+ * 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 GroupablePlainAttr<A extends Any<?>, M extends Membership<A>> extends PlainAttr<A> {
+
+    M getMembership();
+
+    void setMembership(M membership);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupableRelatable.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupableRelatable.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupableRelatable.java
new file mode 100644
index 0000000..147f469
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupableRelatable.java
@@ -0,0 +1,100 @@
+/*
+ * 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;
+
+import java.util.Collection;
+import java.util.List;
+
+public interface GroupableRelatable<
+        L extends Any<P>, 
+        M extends Membership<L>, 
+        P extends GroupablePlainAttr<L, M>,
+        R extends Any<?>,
+        REL extends Relationship<L, R>> extends Any<P> {
+
+    @Override
+    boolean add(final P attr);
+
+    @Override
+    boolean remove(final P attr);
+
+    /**
+     * Returns the plain attribute for this instance and the given schema name - if found, {@code NULL} otherwise.
+     * <b>IMPORTANT:</b> This method won't return any attribute related to memberships.
+     *
+     * @param plainSchemaName plain schema name
+     * @return plain attribute for this instance and the given schema name - if found, {@code NULL} otherwise
+     */
+    @Override
+    P getPlainAttr(String plainSchemaName);
+
+    /**
+     * Returns the plain attribute for this instance, the given schema name and the given membership -
+     * if found, {@code NULL} otherwise.
+     *
+     * @param plainSchemaName plain schema name
+     * @param membership membership
+     * @return plain attribute for this instance, the given schema name and the given membership -
+     * if found, {@code NULL} otherwise
+     */
+    P getPlainAttr(String plainSchemaName, Membership<?> membership);
+
+    /**
+     * Returns the plain attributes for this instance.
+     * <b>IMPORTANT:</b> This method won't return any attribute related to memberships.
+     *
+     * @return plain attribute for this instance
+     */
+    @Override
+    List<? extends P> getPlainAttrs();
+
+    /**
+     * Returns the list of plain attributes for this instance and the given schema name (including membeship attributes,
+     * as opposite to {@link Any#getPlainAttr(java.lang.String)}).
+     *
+     * @param plainSchemaName plain schema name
+     * @return list of plain attributes for this instance and the given schema name (including membeship attributes)
+     */
+    Collection<? extends P> getPlainAttrs(String plainSchemaName);
+
+    /**
+     * Returns the list of plain attributes for this instance and the given membership.
+     *
+     * @param membership membership
+     * @return list of plain attributes for this instance and the given membership
+     */
+    Collection<? extends P> getPlainAttrs(Membership<?> membership);
+
+    boolean add(M membership);
+
+    M getMembership(String groupKey);
+
+    List<? extends M> getMemberships();
+
+    boolean add(REL relationship);
+
+    REL getRelationship(RelationshipType relationshipType, String otherEndKey);
+
+    Collection<? extends REL> getRelationships(String otherEndKey);
+
+    Collection<? extends REL> getRelationships(RelationshipType relationshipType);
+
+    List<? extends REL> getRelationships();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java
index 46d2297..64a58ce 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java
@@ -19,9 +19,9 @@
 package org.apache.syncope.core.persistence.api.entity.anyobject;
 
 import java.util.List;
-import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.GroupablePlainAttr;
 
-public interface APlainAttr extends PlainAttr<AnyObject> {
+public interface APlainAttr extends GroupablePlainAttr<AnyObject, AMembership> {
 
     @Override
     List<? extends APlainAttrValue> getValues();

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/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 ac5fda0..7b0f434 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
@@ -18,27 +18,13 @@
  */
 package org.apache.syncope.core.persistence.api.entity.anyobject;
 
-import java.util.Collection;
-import java.util.List;
-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.GroupableRelatable;
 
-public interface AnyObject extends Any<APlainAttr> {
+public interface AnyObject extends
+        GroupableRelatable<AnyObject, AMembership, APlainAttr, AnyObject, ARelationship> {
 
-    boolean add(ARelationship relationship);
+    String getName();
 
-    ARelationship getRelationship(RelationshipType relationshipType, String anyObjectKey);
-
-    Collection<? extends ARelationship> getRelationships(String anyObjectKey);
-
-    Collection<? extends ARelationship> getRelationships(RelationshipType relationshipType);
-
-    List<? extends ARelationship> getRelationships();
-
-    boolean add(AMembership membership);
-
-    AMembership getMembership(String membershipKey);
-
-    List<? extends AMembership> getMemberships();
+    void setName(String name);
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java
index 5c91acf..503352f 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java
@@ -19,9 +19,9 @@
 package org.apache.syncope.core.persistence.api.entity.user;
 
 import java.util.List;
-import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.GroupablePlainAttr;
 
-public interface UPlainAttr extends PlainAttr<User> {
+public interface UPlainAttr extends GroupablePlainAttr<User, UMembership> {
 
     @Override
     List<? extends UPlainAttrValue> getValues();

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/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 b7e14bf..fa81fd1 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
@@ -18,15 +18,15 @@
  */
 package org.apache.syncope.core.persistence.api.entity.user;
 
-import java.util.Collection;
 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;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
 
-public interface User extends Any<UPlainAttr> {
+public interface User extends
+        GroupableRelatable<User, UMembership, UPlainAttr, AnyObject, URelationship> {
 
     String getUsername();
 
@@ -92,32 +92,8 @@ public interface User extends Any<UPlainAttr> {
 
     void setMustChangePassword(boolean mustChangePassword);
 
-    @Override
-    boolean add(UPlainAttr attr);
-
-    @Override
-    UPlainAttr getPlainAttr(String plainSchemaName);
-
-    @Override
-    List<? extends UPlainAttr> getPlainAttrs();
-
     boolean add(Role role);
 
     List<? extends Role> getRoles();
 
-    boolean add(URelationship relationship);
-
-    URelationship getRelationship(RelationshipType relationshipType, String anyObjectKey);
-
-    Collection<? extends URelationship> getRelationships(String anyObjectKey);
-
-    Collection<? extends URelationship> getRelationships(RelationshipType relationshipType);
-
-    List<? extends URelationship> getRelationships();
-
-    boolean add(UMembership membership);
-
-    UMembership getMembership(String groupKey);
-
-    List<? extends UMembership> getMemberships();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
index 379d386..0eb38ac 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
@@ -23,8 +23,10 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
 import javax.persistence.NoResultException;
@@ -35,6 +37,7 @@ import org.apache.commons.jexl3.parser.ParserConstants;
 import org.apache.commons.jexl3.parser.Token;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.dao.AnyDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
@@ -54,6 +57,7 @@ import org.apache.syncope.core.persistence.api.entity.Schema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 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;
 import org.apache.syncope.core.persistence.api.entity.group.TypeExtension;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
@@ -420,33 +424,55 @@ public abstract class AbstractAnyDAO<A extends Any<?>> extends AbstractDAO<A> im
     @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
     @Override
     @SuppressWarnings("unchecked")
-    public <S extends Schema> Collection<S> findAllowedSchemas(final A any, final Class<S> reference) {
-        Set<AnyTypeClass> classes = new HashSet<>();
-        classes.addAll(any.getType().getClasses());
-        classes.addAll(any.getAuxClasses());
+    public <S extends Schema> AllowedSchemas<S> findAllowedSchemas(final A any, final Class<S> reference) {
+        AllowedSchemas<S> result = new AllowedSchemas<>();
+
+        // schemas given by type and aux classes
+        Set<AnyTypeClass> typeOwnClasses = new HashSet<>();
+        typeOwnClasses.addAll(any.getType().getClasses());
+        typeOwnClasses.addAll(any.getAuxClasses());
+
+        for (AnyTypeClass typeClass : typeOwnClasses) {
+            if (reference.equals(PlainSchema.class)) {
+                result.getForSelf().addAll((Collection<? extends S>) typeClass.getPlainSchemas());
+            } else if (reference.equals(DerSchema.class)) {
+                result.getForSelf().addAll((Collection<? extends S>) typeClass.getDerSchemas());
+            } else if (reference.equals(VirSchema.class)) {
+                result.getForSelf().addAll((Collection<? extends S>) typeClass.getVirSchemas());
+            }
+        }
+
+        // schemas given by type extensions
+        Map<Group, List<? extends AnyTypeClass>> typeExtensionClasses = new HashMap<>();
         if (any instanceof User) {
             for (UMembership memb : ((User) any).getMemberships()) {
                 for (TypeExtension typeExtension : memb.getRightEnd().getTypeExtensions()) {
-                    classes.addAll(typeExtension.getAuxClasses());
+                    typeExtensionClasses.put(memb.getRightEnd(), typeExtension.getAuxClasses());
                 }
             }
         } else if (any instanceof AnyObject) {
             for (AMembership memb : ((AnyObject) any).getMemberships()) {
                 for (TypeExtension typeExtension : memb.getRightEnd().getTypeExtensions()) {
-                    classes.addAll(typeExtension.getAuxClasses());
+                    if (any.getType().equals(typeExtension.getAnyType())) {
+                        typeExtensionClasses.put(memb.getRightEnd(), typeExtension.getAuxClasses());
+                    }
                 }
             }
         }
 
-        Set<S> result = new HashSet<>();
-
-        for (AnyTypeClass typeClass : classes) {
-            if (reference.equals(PlainSchema.class)) {
-                result.addAll((Collection<? extends S>) typeClass.getPlainSchemas());
-            } else if (reference.equals(DerSchema.class)) {
-                result.addAll((Collection<? extends S>) typeClass.getDerSchemas());
-            } else if (reference.equals(VirSchema.class)) {
-                result.addAll((Collection<? extends S>) typeClass.getVirSchemas());
+        for (Map.Entry<Group, List<? extends AnyTypeClass>> entry : typeExtensionClasses.entrySet()) {
+            result.getForMemberships().put(entry.getKey(), new HashSet<S>());
+            for (AnyTypeClass typeClass : entry.getValue()) {
+                if (reference.equals(PlainSchema.class)) {
+                    result.getForMemberships().get(entry.getKey()).
+                            addAll((Collection<? extends S>) typeClass.getPlainSchemas());
+                } else if (reference.equals(DerSchema.class)) {
+                    result.getForMemberships().get(entry.getKey()).
+                            addAll((Collection<? extends S>) typeClass.getDerSchemas());
+                } else if (reference.equals(VirSchema.class)) {
+                    result.getForMemberships().get(entry.getKey()).
+                            addAll((Collection<? extends S>) typeClass.getVirSchemas());
+                }
             }
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
index 60be1fe..5280c3c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
@@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import javax.persistence.NoResultException;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
 import org.apache.commons.collections4.CollectionUtils;
@@ -40,6 +41,7 @@ import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
 import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
 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.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
@@ -124,6 +126,38 @@ public class JPAAnyObjectDAO extends AbstractAnyDAO<AnyObject> implements AnyObj
     }
 
     @Override
+    public AnyObject findByName(final String name) {
+        TypedQuery<AnyObject> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAAnyObject.class.getSimpleName() + " e WHERE e.name = :name", AnyObject.class);
+        query.setParameter("name", name);
+
+        AnyObject result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No any object found with name {}", name, e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public AnyObject authFindByName(final String name) {
+        if (name == null) {
+            throw new NotFoundException("Null name");
+        }
+
+        AnyObject anyObject = findByName(name);
+        if (anyObject == null) {
+            throw new NotFoundException("Any Object " + name);
+        }
+
+        securityChecks(anyObject);
+
+        return anyObject;
+    }
+
+    @Override
     public List<ARelationship> findARelationships(final AnyObject anyObject) {
         TypedQuery<ARelationship> query = entityManager().createQuery(
                 "SELECT e FROM " + JPAARelationship.class.getSimpleName()

http://git-wip-us.apache.org/repos/asf/syncope/blob/38ae5776/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
index 07e18e2..d1df518 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.jpa.dao;
 
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
-import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
@@ -40,9 +39,6 @@ public class JPAConfDAO extends AbstractDAO<Conf> implements ConfDAO {
     @Autowired
     private PlainSchemaDAO schemaDAO;
 
-    @Autowired
-    private PlainAttrDAO attrDAO;
-
     @Override
     public Conf get() {
         Conf instance = entityManager().find(JPAConf.class, KEY);
@@ -96,8 +92,8 @@ public class JPAConfDAO extends AbstractDAO<Conf> implements ConfDAO {
         if (old != null && (!attr.getSchema().isUniqueConstraint()
                 || (!attr.getUniqueValue().getStringValue().equals(old.getUniqueValue().getStringValue())))) {
 
-            instance.getPlainAttrs().remove(old);
-            attrDAO.delete(old.getKey(), CPlainAttr.class);
+            old.setOwner(null);
+            instance.remove(old);
         }
 
         instance.add(attr);
@@ -111,8 +107,8 @@ public class JPAConfDAO extends AbstractDAO<Conf> implements ConfDAO {
         Conf instance = get();
         CPlainAttr attr = instance.getPlainAttr(key);
         if (attr != null) {
-            instance.getPlainAttrs().remove(attr);
-            attrDAO.delete(attr.getKey(), CPlainAttr.class);
+            attr.setOwner(null);
+            instance.remove(attr);
 
             instance = entityManager().merge(instance);
         }


Mime
View raw message