You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2017/06/12 09:43:22 UTC

[2/4] syncope git commit: [SYNCOPE-1106] Removed methods returning Map, added methods for getting attribute for specific schema

[SYNCOPE-1106] Removed methods returning Map, added methods for getting attribute for specific schema


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

Branch: refs/heads/2_0_X
Commit: 31cffd4ec3fc6ba0b4ca1a96732299be7d585bab
Parents: ee453d6
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Jun 12 11:43:03 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Jun 12 11:43:03 2017 +0200

----------------------------------------------------------------------
 .../commons/SortableAnyProviderComparator.java  | 20 ++----
 .../console/commons/status/StatusUtils.java     | 14 +---
 .../syncope/client/console/panels/Realm.java    | 22 +++---
 .../html/repeater/data/table/AttrColumn.java    | 17 +++--
 .../data/table/ConnObjectAttrColumn.java        |  7 +-
 .../console/wizards/any/ConnObjectPanel.java    |  6 +-
 .../client/console/wizards/any/DerAttrs.java    |  7 +-
 .../client/console/wizards/any/PlainAttrs.java  |  5 +-
 .../client/console/wizards/any/VirAttrs.java    |  5 +-
 .../resources/UserSelfCreateResource.java       |  7 +-
 .../enduser/resources/UserSelfReadResource.java |  6 +-
 .../resources/UserSelfUpdateResource.java       |  7 +-
 .../enduser/util/UserRequestValidator.java      | 12 ++--
 .../enduser/util/UserRequestValidatorTest.java  |  4 +-
 .../syncope/common/lib/AnyOperations.java       | 14 ++--
 .../syncope/common/lib/EntityTOUtils.java       | 13 ++++
 .../org/apache/syncope/common/lib/to/AnyTO.java | 48 ++++++-------
 .../syncope/common/lib/to/AttributableTO.java   |  7 +-
 .../syncope/common/lib/to/ConnObjectTO.java     | 18 ++---
 .../syncope/common/lib/to/MembershipTO.java     | 50 +++++++-------
 .../test/resources/domains/MasterContent.xml    | 16 ++---
 .../java/DefaultGroupProvisioningManager.java   |  2 +-
 .../java/job/report/GroupReportlet.java         |  7 +-
 .../java/job/report/UserReportlet.java          |  7 +-
 .../provisioning/java/utils/TemplateUtils.java  |  7 +-
 .../provisioning/java/MailTemplateTest.java     |  2 +-
 .../rest/cxf/service/AbstractAnyService.java    |  6 +-
 .../camel/producer/CreateProducer.java          |  2 +-
 .../syncope/fit/core/AnyObjectITCase.java       | 16 ++---
 .../syncope/fit/core/AuthenticationITCase.java  |  4 +-
 .../syncope/fit/core/CamelRouteITCase.java      |  4 +-
 .../apache/syncope/fit/core/DynRealmITCase.java |  2 +-
 .../apache/syncope/fit/core/GroupITCase.java    | 34 +++++-----
 .../syncope/fit/core/MembershipITCase.java      | 39 +++++------
 .../syncope/fit/core/MigrationITCase.java       |  6 +-
 .../syncope/fit/core/PropagationTaskITCase.java |  8 +--
 .../apache/syncope/fit/core/PullTaskITCase.java | 71 ++++++++++----------
 .../apache/syncope/fit/core/ResourceITCase.java |  3 +-
 .../org/apache/syncope/fit/core/UserITCase.java | 29 ++++----
 .../syncope/fit/core/UserIssuesITCase.java      | 69 +++++++++----------
 .../apache/syncope/fit/core/UserSelfITCase.java |  2 +-
 .../apache/syncope/fit/core/VirAttrITCase.java  | 48 ++++++-------
 42 files changed, 336 insertions(+), 337 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableAnyProviderComparator.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableAnyProviderComparator.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableAnyProviderComparator.java
index 52087f7..0eb370d 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableAnyProviderComparator.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableAnyProviderComparator.java
@@ -21,7 +21,6 @@ package org.apache.syncope.client.console.commons;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
@@ -54,18 +53,11 @@ public class SortableAnyProviderComparator<T extends AnyTO> extends SortableData
 
         private static final long serialVersionUID = -7856686374020091808L;
 
-        private final Map<String, AttrTO> plainAttrs;
-
-        private final Map<String, AttrTO> derAttrs;
-
-        private final Map<String, AttrTO> virAttrs;
+        private final AnyTO anyTO;
 
         AttrModel(final AnyTO anyTO) {
             super();
-
-            this.plainAttrs = anyTO.getPlainAttrMap();
-            this.derAttrs = anyTO.getDerAttrMap();
-            this.virAttrs = anyTO.getVirAttrMap();
+            this.anyTO = anyTO;
         }
 
         /**
@@ -91,20 +83,20 @@ public class SortableAnyProviderComparator<T extends AnyTO> extends SortableData
 
             final AttrTO attr;
             if (schemaType == null) {
-                attr = this.plainAttrs.get(schema);
+                attr = this.anyTO.getPlainAttr(schema);
             } else {
                 switch (schemaType) {
                     case PLAIN:
                     default:
-                        attr = this.plainAttrs.get(schema);
+                        attr = this.anyTO.getPlainAttr(schema);
                         break;
 
                     case DERIVED:
-                        attr = this.derAttrs.get(schema);
+                        attr = this.anyTO.getDerAttr(schema);
                         break;
 
                     case VIRTUAL:
-                        attr = this.virAttrs.get(schema);
+                        attr = this.anyTO.getVirAttr(schema);
                         break;
                 }
             }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
index baf5b9b..6da9246 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
@@ -21,9 +21,7 @@ package org.apache.syncope.client.console.commons.status;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.client.console.commons.Constants;
@@ -113,22 +111,14 @@ public class StatusUtils implements Serializable {
     }
 
     private Boolean isEnabled(final ConnObjectTO objectTO) {
-        final Map<String, AttrTO> attributeTOs = objectTO.getAttrMap();
-
-        final AttrTO status = attributeTOs.get(ConnIdSpecialName.ENABLE);
-
+        final AttrTO status = objectTO.getAttr(ConnIdSpecialName.ENABLE);
         return status != null && status.getValues() != null && !status.getValues().isEmpty()
                 ? Boolean.valueOf(status.getValues().get(0))
                 : Boolean.FALSE;
     }
 
     private String getConnObjectLink(final ConnObjectTO objectTO) {
-        final Map<String, AttrTO> attributeTOs = objectTO == null
-                ? Collections.<String, AttrTO>emptyMap()
-                : objectTO.getAttrMap();
-
-        final AttrTO name = attributeTOs.get(ConnIdSpecialName.NAME);
-
+        final AttrTO name = objectTO == null ? null : objectTO.getAttr(ConnIdSpecialName.NAME);
         return name != null && name.getValues() != null && !name.getValues().isEmpty()
                 ? name.getValues().get(0)
                 : null;

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
index 615b393..e6d57cd 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
@@ -25,8 +25,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.commons.lang3.tuple.Triple;
@@ -85,8 +83,8 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
 
         setPageRef(pageRef);
 
-        AjaxBootstrapTabbedPanel<ITab> tabbedPanel
-                = new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList(pageRef));
+        AjaxBootstrapTabbedPanel<ITab> tabbedPanel =
+                new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList(pageRef));
         tabbedPanel.setSelectedTab(selectedIndex);
         addInnerObject(tabbedPanel);
         this.wizardBuilder = new RealmWizardBuilder(pageRef);
@@ -167,15 +165,15 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
             }
         });
 
-        final Triple<UserFormLayoutInfo, GroupFormLayoutInfo, Map<String, AnyObjectFormLayoutInfo>> formLayoutInfo
-                = FormLayoutInfoUtils.fetch(anyTypeTOs);
+        final Triple<UserFormLayoutInfo, GroupFormLayoutInfo, Map<String, AnyObjectFormLayoutInfo>> formLayoutInfo =
+                FormLayoutInfoUtils.fetch(anyTypeTOs);
 
         Collections.sort(anyTypeTOs, new AnyTypeComparator());
         for (final AnyTypeTO anyTypeTO : anyTypeTOs) {
             tabs.add(new ITabComponent(
                     new Model<>(anyTypeTO.getKey()),
                     AnyTypeKind.GROUP.name().equals(anyTypeTO.getKey())
-                    ? null : new String[]{String.format("%s_SEARCH", anyTypeTO.getKey())}) {
+                    ? null : new String[] { String.format("%s_SEARCH", anyTypeTO.getKey()) }) {
 
                 private static final long serialVersionUID = 1169585538404171118L;
 
@@ -223,12 +221,12 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
                 if ("afterObj".equalsIgnoreCase(key)) {
                     ConnObjectTO afterObj = bean.getAfterObj();
                     String remoteId = afterObj == null
-                            || MapUtils.isEmpty(afterObj.getAttrMap())
-                            || !afterObj.getAttrMap().containsKey(ConnIdSpecialName.NAME)
-                            || CollectionUtils.isEmpty(afterObj.getAttrMap().get(ConnIdSpecialName.NAME).getValues())
+                            || afterObj.getAttrs().isEmpty()
+                            || afterObj.getAttr(ConnIdSpecialName.NAME) == null
+                            || afterObj.getAttr(ConnIdSpecialName.NAME).getValues() == null
+                            || afterObj.getAttr(ConnIdSpecialName.NAME).getValues().isEmpty()
                             ? StringUtils.EMPTY
-                            : afterObj.getAttrMap().get(ConnIdSpecialName.NAME).getValues().
-                            iterator().next();
+                            : afterObj.getAttr(ConnIdSpecialName.NAME).getValues().get(0);
 
                     return new Label("field", remoteId);
                 } else if ("status".equalsIgnoreCase(key)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/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 b756a05..1341791 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
@@ -19,6 +19,7 @@
 package org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table;
 
 import java.util.List;
+import org.apache.syncope.common.lib.to.AttrTO;
 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;
@@ -50,27 +51,25 @@ public class AttrColumn<T extends AttributableTO> extends AbstractColumn<T, Stri
 
         List<String> values = null;
 
+        AttrTO attr = null;
         switch (schemaType) {
             case PLAIN:
-                if (rowModel.getObject().getPlainAttrMap().containsKey(name)) {
-                    values = rowModel.getObject().getPlainAttrMap().get(name).getValues();
-                }
+                attr = rowModel.getObject().getPlainAttr(name);
                 break;
 
             case DERIVED:
-                if (rowModel.getObject().getDerAttrMap().containsKey(name)) {
-                    values = rowModel.getObject().getDerAttrMap().get(name).getValues();
-                }
+                attr = rowModel.getObject().getDerAttr(name);
                 break;
 
             case VIRTUAL:
-                if (rowModel.getObject().getVirAttrMap().containsKey(name)) {
-                    values = rowModel.getObject().getVirAttrMap().get(name).getValues();
-                }
+                attr = rowModel.getObject().getVirAttr(name);
                 break;
 
             default:
         }
+        if (attr != null) {
+            values = attr.getValues();
+        }
 
         if (values == null || values.isEmpty()) {
             cellItem.add(new Label(componentId, ""));

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/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
index 907f647..5d9dbd4 100644
--- 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
@@ -19,6 +19,7 @@
 package org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table;
 
 import java.util.List;
+import org.apache.syncope.common.lib.to.AttrTO;
 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;
@@ -47,10 +48,8 @@ public class ConnObjectAttrColumn extends AbstractColumn<ConnObjectTO, String> {
             final String componentId,
             final IModel<ConnObjectTO> rowModel) {
 
-        List<String> values = null;
-        if (rowModel.getObject().getAttrMap().containsKey(name)) {
-            values = rowModel.getObject().getAttrMap().get(name).getValues();
-        }
+        AttrTO attr = rowModel.getObject().getAttr(name);
+        List<String> values = attr == null ? null : attr.getValues();
 
         if (values == null || values.isEmpty()) {
             cellItem.add(new Label(componentId, ""));

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/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 7d3f612..2c75dae 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
@@ -31,6 +31,7 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.wicket.Component;
 import org.apache.wicket.behavior.Behavior;
 import org.apache.wicket.markup.ComponentTag;
@@ -88,11 +89,10 @@ public class ConnObjectPanel extends Panel {
 
         final Map<String, AttrTO> beforeProfile = connObjectTOs == null || connObjectTOs.getLeft() == null
                 ? null
-                : connObjectTOs.getLeft().getAttrMap();
-
+                : EntityTOUtils.buildAttrMap(connObjectTOs.getLeft().getAttrs());
         final Map<String, AttrTO> afterProfile = connObjectTOs == null || connObjectTOs.getRight() == null
                 ? null
-                : connObjectTOs.getRight().getAttrMap();
+                : EntityTOUtils.buildAttrMap(connObjectTOs.getRight().getAttrs());
 
         final ListView<String> propView = new ListView<String>("propView", formProps) {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
index d4edbf0..012a662 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
@@ -25,6 +25,7 @@ import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.DerSchemaTO;
@@ -83,7 +84,7 @@ public class DerAttrs extends AbstractAttrs<DerSchemaTO> {
 
                     @Override
                     public WebMarkupContainer getPanel(final String panelId) {
-                        return new DerAttrs.DerSchemas(panelId, new ListModel<AttrTO>(getAttrsFromTO(membershipTO)));
+                        return new DerAttrs.DerSchemas(panelId, new ListModel<>(getAttrsFromTO(membershipTO)));
                     }
                 }), Model.of(-1)).setOutputMarkupId(true));
             }
@@ -113,7 +114,7 @@ public class DerAttrs extends AbstractAttrs<DerSchemaTO> {
     protected void setAttrs() {
         List<AttrTO> attrs = new ArrayList<>();
 
-        Map<String, AttrTO> attrMap = anyTO.getDerAttrMap();
+        Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getDerAttrs());
 
         for (DerSchemaTO schema : schemas.values()) {
             AttrTO attrTO = new AttrTO();
@@ -133,7 +134,7 @@ public class DerAttrs extends AbstractAttrs<DerSchemaTO> {
     protected void setAttrs(final MembershipTO membershipTO) {
         List<AttrTO> attrs = new ArrayList<>();
 
-        Map<String, AttrTO> attrMap = membershipTO.getDerAttrMap();
+        Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getDerAttrs());
 
         for (DerSchemaTO schema : membershipSchemas.get(membershipTO.getGroupKey()).values()) {
             AttrTO attrTO = new AttrTO();

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
index 5c1291a..80891cf 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/PlainAttrs.java
@@ -37,6 +37,7 @@ import org.apache.syncope.client.console.wicket.markup.html.form.EncryptedFieldP
 import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
@@ -142,7 +143,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
     protected void setAttrs() {
         List<AttrTO> attrs = new ArrayList<>();
 
-        Map<String, AttrTO> attrMap = anyTO.getPlainAttrMap();
+        Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getPlainAttrs());
 
         for (PlainSchemaTO schema : schemas.values()) {
             AttrTO attrTO = new AttrTO();
@@ -167,7 +168,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
     protected void setAttrs(final MembershipTO membershipTO) {
         List<AttrTO> attrs = new ArrayList<>();
 
-        Map<String, AttrTO> attrMap = membershipTO.getPlainAttrMap();
+        Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getPlainAttrs());
 
         for (PlainSchemaTO schema : membershipSchemas.get(membershipTO.getGroupKey()).values()) {
             AttrTO attrTO = new AttrTO();

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
index 5a49b88..4b66f0d 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
@@ -27,6 +27,7 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accor
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
@@ -117,7 +118,7 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
     protected void setAttrs() {
         List<AttrTO> attrs = new ArrayList<>();
 
-        Map<String, AttrTO> attrMap = anyTO.getVirAttrMap();
+        Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getVirAttrs());
 
         for (VirSchemaTO schema : schemas.values()) {
             AttrTO attrTO = new AttrTO();
@@ -139,7 +140,7 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
     protected void setAttrs(final MembershipTO membershipTO) {
         List<AttrTO> attrs = new ArrayList<>();
 
-        Map<String, AttrTO> attrMap = membershipTO.getVirAttrMap();
+        Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getVirAttrs());
 
         for (VirSchemaTO schema : membershipSchemas.get(membershipTO.getGroupKey()).values()) {
             AttrTO attrTO = new AttrTO();

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
index 8b42285..7b2a834 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.client.enduser.resources;
 
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.MediaType;
@@ -31,6 +30,7 @@ import org.apache.syncope.client.enduser.SyncopeEnduserConstants;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.enduser.annotations.Resource;
 import org.apache.syncope.client.enduser.util.UserRequestValidator;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
@@ -114,11 +114,10 @@ public class UserSelfCreateResource extends BaseUserSelfResource {
                     userTO.getPlainAttrs().removeAll(membAttrs);
 
                     // 2. millis -> Date conversion for PLAIN attributes of USER and its MEMBERSHIPS
-                    Map<String, AttrTO> userPlainAttrMap = userTO.getPlainAttrMap();
                     for (PlainSchemaTO plainSchema : SyncopeEnduserSession.get().getDatePlainSchemas()) {
-                        millisToDate(userPlainAttrMap, plainSchema);
+                        millisToDate(EntityTOUtils.buildAttrMap(userTO.getPlainAttrs()), plainSchema);
                         for (MembershipTO membership : userTO.getMemberships()) {
-                            millisToDate(membership.getPlainAttrMap(), plainSchema);
+                            millisToDate(EntityTOUtils.buildAttrMap(membership.getPlainAttrs()), plainSchema);
                         }
                     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
index c4cb6c1..eae1ec7 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
@@ -34,6 +34,7 @@ import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.enduser.annotations.Resource;
 import org.apache.syncope.client.enduser.model.CustomAttribute;
 import org.apache.syncope.client.enduser.model.CustomAttributesInfo;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
@@ -62,13 +63,12 @@ public class UserSelfReadResource extends BaseUserSelfResource {
             }
 
             UserTO userTO = SerializationUtils.clone(SyncopeEnduserSession.get().getSelfTO());
-            Map<String, AttrTO> userPlainAttrMap = userTO.getPlainAttrMap();
 
             // 1. Date -> millis conversion for PLAIN attributes of USER and its MEMBERSHIPS
             for (PlainSchemaTO plainSchema : SyncopeEnduserSession.get().getDatePlainSchemas()) {
-                dateToMillis(userPlainAttrMap, plainSchema);
+                dateToMillis(EntityTOUtils.buildAttrMap(userTO.getPlainAttrs()), plainSchema);
                 for (MembershipTO membership : userTO.getMemberships()) {
-                    dateToMillis(membership.getPlainAttrMap(), plainSchema);
+                    dateToMillis(EntityTOUtils.buildAttrMap(membership.getPlainAttrs()), plainSchema);
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
index 828f323..1e8ede2 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.client.enduser.resources;
 
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.MediaType;
@@ -32,6 +31,7 @@ import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.enduser.annotations.Resource;
 import org.apache.syncope.client.enduser.util.UserRequestValidator;
 import org.apache.syncope.common.lib.AnyOperations;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
@@ -95,11 +95,10 @@ public class UserSelfUpdateResource extends BaseUserSelfResource {
                 userTO.getPlainAttrs().removeAll(membAttrs);
 
                 // 2. millis -> Date conversion for PLAIN attributes of USER and its MEMBERSHIPS
-                Map<String, AttrTO> userPlainAttrMap = userTO.getPlainAttrMap();
                 for (PlainSchemaTO plainSchema : SyncopeEnduserSession.get().getDatePlainSchemas()) {
-                    millisToDate(userPlainAttrMap, plainSchema);
+                    millisToDate(EntityTOUtils.buildAttrMap(userTO.getPlainAttrs()), plainSchema);
                     for (MembershipTO membership : userTO.getMemberships()) {
-                        millisToDate(membership.getPlainAttrMap(), plainSchema);
+                        millisToDate(EntityTOUtils.buildAttrMap(membership.getPlainAttrs()), plainSchema);
                     }
                 }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/enduser/src/main/java/org/apache/syncope/client/enduser/util/UserRequestValidator.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/util/UserRequestValidator.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/util/UserRequestValidator.java
index 350ae17..32f5551 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/util/UserRequestValidator.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/util/UserRequestValidator.java
@@ -23,6 +23,7 @@ import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.client.enduser.model.CustomAttribute;
 import org.apache.syncope.client.enduser.model.CustomAttributesInfo;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.SchemaType;
@@ -43,11 +44,12 @@ public final class UserRequestValidator {
             return true;
         }
 
-        return validateAttributes(userTO.getPlainAttrMap(), customForm.get(SchemaType.PLAIN.name()), checkDefaultValues)
-                && validateAttributes(userTO.getDerAttrMap(), customForm.get(SchemaType.DERIVED.name()),
-                        checkDefaultValues)
-                && validateAttributes(userTO.getVirAttrMap(), customForm.get(SchemaType.VIRTUAL.name()),
-                        checkDefaultValues);
+        return validateAttributes(EntityTOUtils.buildAttrMap(userTO.getPlainAttrs()),
+                customForm.get(SchemaType.PLAIN.name()), checkDefaultValues)
+                && validateAttributes(EntityTOUtils.buildAttrMap(userTO.getDerAttrs()),
+                        customForm.get(SchemaType.DERIVED.name()), checkDefaultValues)
+                && validateAttributes(EntityTOUtils.buildAttrMap(userTO.getVirAttrs()),
+                        customForm.get(SchemaType.VIRTUAL.name()), checkDefaultValues);
     }
 
     private static boolean validateAttributes(final Map<String, AttrTO> attrMap,

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/client/enduser/src/test/java/org/apache/syncope/client/enduser/util/UserRequestValidatorTest.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/test/java/org/apache/syncope/client/enduser/util/UserRequestValidatorTest.java b/client/enduser/src/test/java/org/apache/syncope/client/enduser/util/UserRequestValidatorTest.java
index 70d4fd3..d8c021a 100644
--- a/client/enduser/src/test/java/org/apache/syncope/client/enduser/util/UserRequestValidatorTest.java
+++ b/client/enduser/src/test/java/org/apache/syncope/client/enduser/util/UserRequestValidatorTest.java
@@ -61,11 +61,11 @@ public class UserRequestValidatorTest {
         assertTrue(UserRequestValidator.compliant(userTO, customForm, true));
 
         // firstname must have only one defaultValue
-        userTO.getPlainAttrMap().get("firstname").getValues().add("notAllowedFirstnameValue");
+        userTO.getPlainAttr("firstname").getValues().add("notAllowedFirstnameValue");
         assertFalse(UserRequestValidator.compliant(userTO, customForm, true));
         assertTrue(UserRequestValidator.compliant(userTO, customForm, false));
         // clean
-        userTO.getPlainAttrMap().get("firstname").getValues().remove("notAllowedFirstnameValue");
+        userTO.getPlainAttr("firstname").getValues().remove("notAllowedFirstnameValue");
 
         // derived must not be present
         AttrTO derivedNotAllowed = attrTO("derivedNotAllowed");

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/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 1da4df7..69d373e 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
@@ -89,8 +89,8 @@ public final class AnyOperations {
         result.setGroup(updated.getGroupKey());
 
         // 1. plain attributes
-        Map<String, AttrTO> updatedAttrs = new HashMap<>(updated.getPlainAttrMap());
-        Map<String, AttrTO> originalAttrs = new HashMap<>(original.getPlainAttrMap());
+        Map<String, AttrTO> updatedAttrs = EntityTOUtils.buildAttrMap(updated.getPlainAttrs());
+        Map<String, AttrTO> originalAttrs = EntityTOUtils.buildAttrMap(original.getPlainAttrs());
 
         result.getPlainAttrs().clear();
 
@@ -159,8 +159,8 @@ public final class AnyOperations {
         }
 
         // 3. plain attributes
-        Map<String, AttrTO> updatedAttrs = new HashMap<>(updated.getPlainAttrMap());
-        Map<String, AttrTO> originalAttrs = new HashMap<>(original.getPlainAttrMap());
+        Map<String, AttrTO> updatedAttrs = EntityTOUtils.buildAttrMap(updated.getPlainAttrs());
+        Map<String, AttrTO> originalAttrs = EntityTOUtils.buildAttrMap(original.getPlainAttrs());
 
         result.getPlainAttrs().clear();
 
@@ -483,7 +483,7 @@ public final class AnyOperations {
 
         // 2. plain attributes
         result.getPlainAttrs().clear();
-        result.getPlainAttrs().addAll(patch(to.getPlainAttrMap(), patch.getPlainAttrs()));
+        result.getPlainAttrs().addAll(patch(EntityTOUtils.buildAttrMap(to.getPlainAttrs()), patch.getPlainAttrs()));
 
         // 3. virtual attributes
         result.getVirAttrs().clear();
@@ -571,7 +571,7 @@ public final class AnyOperations {
                         }
                     } else {
                         newMembershipTO.getPlainAttrs().addAll(
-                                patch(memb.getPlainAttrMap(), membPatch.getPlainAttrs()));
+                                patch(EntityTOUtils.buildAttrMap(memb.getPlainAttrs()), membPatch.getPlainAttrs()));
                     }
 
                     // 3. virtual attributes
@@ -637,7 +637,7 @@ public final class AnyOperations {
                         }
                     } else {
                         newMembershipTO.getPlainAttrs().addAll(
-                                patch(memb.getPlainAttrMap(), membPatch.getPlainAttrs()));
+                                patch(EntityTOUtils.buildAttrMap(memb.getPlainAttrs()), membPatch.getPlainAttrs()));
                     }
 
                     // 3. virtual attributes

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java b/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java
index 001e569..d0c04bc 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java
@@ -18,7 +18,11 @@
  */
 package org.apache.syncope.common.lib;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.commons.collections4.Transformer;
+import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 
 public final class EntityTOUtils {
@@ -33,6 +37,15 @@ public final class EntityTOUtils {
         };
     }
 
+    public static Map<String, AttrTO> buildAttrMap(final Collection<AttrTO> attrs) {
+        Map<String, AttrTO> result = new HashMap<>(attrs.size());
+        for (AttrTO attributeTO : attrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+
+        return result;
+    }
+
     /**
      * Private default constructor, for static-only classes.
      */

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/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 47f1d9b..7796b62 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
@@ -22,16 +22,15 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
-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.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 
 @XmlType
 @XmlSeeAlso({ UserTO.class, GroupTO.class, AnyObjectTO.class })
@@ -46,7 +45,7 @@ public abstract class AnyTO extends AbstractAnnotatedBean implements EntityTO, A
 
     private String realm;
 
-    private List<String> dynRealms = new ArrayList<>();
+    private final List<String> dynRealms = new ArrayList<>();
 
     private String status;
 
@@ -118,13 +117,14 @@ public abstract class AnyTO extends AbstractAnnotatedBean implements EntityTO, A
 
     @JsonIgnore
     @Override
-    public Map<String, AttrTO> getPlainAttrMap() {
-        Map<String, AttrTO> result = new HashMap<>(plainAttrs.size());
-        for (AttrTO attributeTO : plainAttrs) {
-            result.put(attributeTO.getSchema(), attributeTO);
-        }
+    public AttrTO getPlainAttr(final String schema) {
+        return IterableUtils.find(plainAttrs, new Predicate<AttrTO>() {
 
-        return Collections.unmodifiableMap(result);
+            @Override
+            public boolean evaluate(final AttrTO object) {
+                return object.getSchema().equals(schema);
+            }
+        });
     }
 
     @XmlElementWrapper(name = "derAttrs")
@@ -137,13 +137,14 @@ public abstract class AnyTO extends AbstractAnnotatedBean implements EntityTO, A
 
     @JsonIgnore
     @Override
-    public Map<String, AttrTO> getDerAttrMap() {
-        Map<String, AttrTO> result = new HashMap<>(derAttrs.size());
-        for (AttrTO attributeTO : derAttrs) {
-            result.put(attributeTO.getSchema(), attributeTO);
-        }
+    public AttrTO getDerAttr(final String schema) {
+        return IterableUtils.find(derAttrs, new Predicate<AttrTO>() {
 
-        return Collections.unmodifiableMap(result);
+            @Override
+            public boolean evaluate(final AttrTO object) {
+                return object.getSchema().equals(schema);
+            }
+        });
     }
 
     @XmlElementWrapper(name = "virAttrs")
@@ -156,13 +157,14 @@ public abstract class AnyTO extends AbstractAnnotatedBean implements EntityTO, A
 
     @JsonIgnore
     @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);
+    public AttrTO getVirAttr(final String schema) {
+        return IterableUtils.find(virAttrs, new Predicate<AttrTO>() {
+
+            @Override
+            public boolean evaluate(final AttrTO object) {
+                return object.getSchema().equals(schema);
+            }
+        });
     }
 
     @XmlElementWrapper(name = "resources")

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/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
index da2f7a1..79e57b8 100644
--- 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
@@ -18,20 +18,19 @@
  */
 package org.apache.syncope.common.lib.to;
 
-import java.util.Map;
 import java.util.Set;
 
 public interface AttributableTO {
 
     Set<AttrTO> getPlainAttrs();
 
-    Map<String, AttrTO> getPlainAttrMap();
+    AttrTO getPlainAttr(String schema);
 
     Set<AttrTO> getDerAttrs();
 
-    Map<String, AttrTO> getDerAttrMap();
+    AttrTO getDerAttr(String schema);
 
     Set<AttrTO> getVirAttrs();
 
-    Map<String, AttrTO> getVirAttrMap();
+    AttrTO getVirAttr(String schema);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/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 09784c8..6301d68 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
@@ -20,15 +20,14 @@ package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.LinkedHashSet;
-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.XmlType;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.AbstractBaseBean;
 
 @XmlRootElement(name = "connObject")
@@ -47,12 +46,13 @@ public class ConnObjectTO extends AbstractBaseBean {
     }
 
     @JsonIgnore
-    public Map<String, AttrTO> getAttrMap() {
-        Map<String, AttrTO> result = new HashMap<>(attrs.size());
-        for (AttrTO attributeTO : attrs) {
-            result.put(attributeTO.getSchema(), attributeTO);
-        }
+    public AttrTO getAttr(final String schema) {
+        return IterableUtils.find(attrs, new Predicate<AttrTO>() {
 
-        return Collections.unmodifiableMap(result);
+            @Override
+            public boolean evaluate(final AttrTO object) {
+                return object.getSchema().equals(schema);
+            }
+        });
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/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 a970dec..5737c7f 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
@@ -20,15 +20,14 @@ package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
-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.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 @XmlRootElement(name = "membership")
@@ -112,13 +111,14 @@ public class MembershipTO extends RelationshipTO implements AttributableTO {
 
     @JsonIgnore
     @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);
+    public AttrTO getPlainAttr(final String schema) {
+        return IterableUtils.find(plainAttrs, new Predicate<AttrTO>() {
+
+            @Override
+            public boolean evaluate(final AttrTO object) {
+                return object.getSchema().equals(schema);
+            }
+        });
     }
 
     @XmlElementWrapper(name = "derAttrs")
@@ -131,13 +131,14 @@ public class MembershipTO extends RelationshipTO implements AttributableTO {
 
     @JsonIgnore
     @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);
+    public AttrTO getDerAttr(final String schema) {
+        return IterableUtils.find(derAttrs, new Predicate<AttrTO>() {
+
+            @Override
+            public boolean evaluate(final AttrTO object) {
+                return object.getSchema().equals(schema);
+            }
+        });
     }
 
     @XmlElementWrapper(name = "virAttrs")
@@ -150,12 +151,13 @@ public class MembershipTO extends RelationshipTO implements AttributableTO {
 
     @JsonIgnore
     @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);
+    public AttrTO getVirAttr(final String schema) {
+        return IterableUtils.find(virAttrs, new Predicate<AttrTO>() {
+
+            @Override
+            public boolean evaluate(final AttrTO object) {
+                return object.getSchema().equals(schema);
+            }
+        });
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 4521db6..ec97437 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -1264,15 +1264,15 @@ we are happy to inform you that the password request was successfully executed f
 &lt;/html&gt;"/>
   <MailTemplate id="test"/>
   <MailTemplate id="optin"
-                textTemplate="Hi ${user.plainAttrMap[&quot;firstname&quot;].values[0]} ${user.plainAttrMap[&quot;surname&quot;].values[0]}, welcome to Syncope!
+                textTemplate="Hi ${user.getPlainAttr(&quot;firstname&quot;).values[0]} ${user.getPlainAttr(&quot;surname&quot;).values[0]}, welcome to Syncope!
 
 Your username is ${user.username}.
-Your email address is ${user.plainAttrMap[&quot;email&quot;].values[0]}.
-Your email address inside a link: http://localhost/?email=${user.plainAttrMap[&quot;email&quot;].values[0].replace('@', '%40')}
+Your email address is ${user.getPlainAttr(&quot;email&quot;).values[0]}.
+Your email address inside a link: http://localhost/?email=${user.getPlainAttr(&quot;email&quot;).values[0].replace('@', '%40')}
 
 This message was sent to the following recipients:&#10;
 $$ for (recipient: recipients) {&#10;
-  * ${recipient.plainAttrMap[&quot;email&quot;].values[0]}&#10;
+  * ${recipient.getPlainAttr(&quot;email&quot;).values[0]}&#10;
 $$ }&#10;
 &#10;
 because one of the following events occurred:&#10;
@@ -1288,19 +1288,19 @@ $$ }&#10;
 $$ }&#10;"
                 htmlTemplate="&lt;html&gt;
 &lt;body&gt;
-&lt;h3&gt;Hi ${user.plainAttrMap[&quot;firstname&quot;].values[0]} ${user.plainAttrMap[&quot;surname&quot;].values[0]}, welcome to Syncope!&lt;/h3&gt;
+&lt;h3&gt;Hi ${user.getPlainAttr(&quot;firstname&quot;).values[0]} ${user.getPlainAttr(&quot;surname&quot;).values[0]}, welcome to Syncope!&lt;/h3&gt;
 
 &lt;p&gt;
    Your username is ${user.username}.&lt;br/&gt;
-   Your email address is ${user.plainAttrMap[&quot;email&quot;].values[0]}.
-   Your email address inside a &lt;a href=&quot;http://localhost/?email=${user.plainAttrMap[&quot;email&quot;].values[0].replace('@', '%40')}&quot;&gt;link&lt;/a&gt;.
+   Your email address is ${user.getPlainAttr(&quot;email&quot;).values[0]}.
+   Your email address inside a &lt;a href=&quot;http://localhost/?email=${user.getPlainAttr(&quot;email&quot;).values[0].replace('@', '%40')}&quot;&gt;link&lt;/a&gt;.
 &lt;/p&gt;
 
 &lt;p&gt;
     This message was sent to the following recipients:
 &lt;ul&gt;&#10;
 $$ for (recipient: recipients) {&#10;Na
-  &lt;li&gt;${recipient.plainAttrMap[&quot;email&quot;].values[0]}&lt;/li&gt;&#10;
+  &lt;li&gt;${recipient.getPlainAttr(&quot;email&quot;).values[0]}&lt;/li&gt;&#10;
 $$ }&#10;
 &lt;/ul&gt;&#10;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
index 13f19a0..2e213f7 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
@@ -95,7 +95,7 @@ public class DefaultGroupProvisioningManager implements GroupProvisioningManager
         WorkflowResult<String> created = gwfAdapter.create(groupTO);
 
         // see ConnObjectUtils#getAnyTOFromConnObject for GroupOwnerSchema
-        AttrTO groupOwner = groupTO.getPlainAttrMap().get(StringUtils.EMPTY);
+        AttrTO groupOwner = groupTO.getPlainAttr(StringUtils.EMPTY);
         if (groupOwner != null) {
             groupOwnerMap.put(created.getResult(), groupOwner.getValues().iterator().next());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/GroupReportlet.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/GroupReportlet.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/GroupReportlet.java
index fa558b6..44a4dfa 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/GroupReportlet.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/GroupReportlet.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.report.GroupReportletConf;
 import org.apache.syncope.common.lib.report.GroupReportletConf.Feature;
@@ -86,7 +87,7 @@ public class GroupReportlet extends AbstractReportlet {
 
         AttributesImpl atts = new AttributesImpl();
         if (!attrs.isEmpty()) {
-            Map<String, AttrTO> attrMap = anyTO.getPlainAttrMap();
+            Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getPlainAttrs());
 
             handler.startElement("", "", "attributes", null);
             for (String attrName : attrs) {
@@ -112,7 +113,7 @@ public class GroupReportlet extends AbstractReportlet {
         }
 
         if (!derAttrs.isEmpty()) {
-            Map<String, AttrTO> derAttrMap = anyTO.getDerAttrMap();
+            Map<String, AttrTO> derAttrMap = EntityTOUtils.buildAttrMap(anyTO.getDerAttrs());
 
             handler.startElement("", "", "derivedAttributes", null);
             for (String attrName : derAttrs) {
@@ -138,7 +139,7 @@ public class GroupReportlet extends AbstractReportlet {
         }
 
         if (!virAttrs.isEmpty()) {
-            Map<String, AttrTO> virAttrMap = anyTO.getVirAttrMap();
+            Map<String, AttrTO> virAttrMap = EntityTOUtils.buildAttrMap(anyTO.getVirAttrs());
 
             handler.startElement("", "", "virtualAttributes", null);
             for (String attrName : virAttrs) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/UserReportlet.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/UserReportlet.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/UserReportlet.java
index 200f64a..2e4314d 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/UserReportlet.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/UserReportlet.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.report.UserReportletConf;
@@ -98,7 +99,7 @@ public class UserReportlet extends AbstractReportlet {
 
         AttributesImpl atts = new AttributesImpl();
         if (!attrs.isEmpty()) {
-            Map<String, AttrTO> attrMap = anyTO.getPlainAttrMap();
+            Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getPlainAttrs());
 
             handler.startElement("", "", "attributes", null);
             for (String attrName : attrs) {
@@ -124,7 +125,7 @@ public class UserReportlet extends AbstractReportlet {
         }
 
         if (!derAttrs.isEmpty()) {
-            Map<String, AttrTO> derAttrMap = anyTO.getDerAttrMap();
+            Map<String, AttrTO> derAttrMap = EntityTOUtils.buildAttrMap(anyTO.getDerAttrs());
 
             handler.startElement("", "", "derivedAttributes", null);
             for (String attrName : derAttrs) {
@@ -150,7 +151,7 @@ public class UserReportlet extends AbstractReportlet {
         }
 
         if (!virAttrs.isEmpty()) {
-            Map<String, AttrTO> virAttrMap = anyTO.getVirAttrMap();
+            Map<String, AttrTO> virAttrMap = EntityTOUtils.buildAttrMap(anyTO.getVirAttrs());
 
             handler.startElement("", "", "virtualAttributes", null);
             for (String attrName : virAttrs) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java
index de0480f..69485e4 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import org.apache.commons.jexl3.MapContext;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
@@ -75,7 +76,7 @@ public class TemplateUtils {
             }
         }
 
-        Map<String, AttrTO> currentAttrMap = anyTO.getPlainAttrMap();
+        Map<String, AttrTO> currentAttrMap = EntityTOUtils.buildAttrMap(anyTO.getPlainAttrs());
         for (AttrTO templatePlainAttr : template.getPlainAttrs()) {
             if (!templatePlainAttr.getValues().isEmpty()
                     && (!currentAttrMap.containsKey(templatePlainAttr.getSchema())
@@ -85,14 +86,14 @@ public class TemplateUtils {
             }
         }
 
-        currentAttrMap = anyTO.getDerAttrMap();
+        currentAttrMap = EntityTOUtils.buildAttrMap(anyTO.getDerAttrs());
         for (AttrTO templateDerAttr : template.getDerAttrs()) {
             if (!currentAttrMap.containsKey(templateDerAttr.getSchema())) {
                 anyTO.getDerAttrs().add(templateDerAttr);
             }
         }
 
-        currentAttrMap = anyTO.getVirAttrMap();
+        currentAttrMap = EntityTOUtils.buildAttrMap(anyTO.getVirAttrs());
         for (AttrTO templateVirAttr : template.getVirAttrs()) {
             if (!templateVirAttr.getValues().isEmpty()
                     && (!currentAttrMap.containsKey(templateVirAttr.getSchema())

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MailTemplateTest.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MailTemplateTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MailTemplateTest.java
index 37c37d1..cb9177a 100644
--- a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MailTemplateTest.java
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MailTemplateTest.java
@@ -111,7 +111,7 @@ public class MailTemplateTest extends AbstractTest {
         ctx.put("input", input);
 
         UserTO recipient = SerializationUtils.clone(user);
-        recipient.getPlainAttrMap().get("email").getValues().set(0, "another@syncope.apache.org");
+        recipient.getPlainAttr("email").getValues().set(0, "another@syncope.apache.org");
         ctx.put("recipients", Collections.singletonList(recipient));
 
         String htmlBody = evaluate(

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
index 7a66c3d..0574d82 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
@@ -87,16 +87,16 @@ public abstract class AbstractAnyService<TO extends AnyTO, P extends AnyPatch>
         AttrTO result;
         switch (schemaType) {
             case DERIVED:
-                result = any.getDerAttrMap().get(schema);
+                result = any.getDerAttr(schema);
                 break;
 
             case VIRTUAL:
-                result = any.getVirAttrMap().get(schema);
+                result = any.getVirAttr(schema);
                 break;
 
             case PLAIN:
             default:
-                result = any.getPlainAttrMap().get(schema);
+                result = any.getPlainAttr(schema);
         }
 
         if (result == null) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/producer/CreateProducer.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/producer/CreateProducer.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/producer/CreateProducer.java
index 8193e3e..612844b 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/producer/CreateProducer.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/producer/CreateProducer.java
@@ -72,7 +72,7 @@ public class CreateProducer extends AbstractProducer {
 
                 if (actual instanceof GroupTO && isPull()) {
                     Map<String, String> groupOwnerMap = exchange.getProperty("groupOwnerMap", Map.class);
-                    AttrTO groupOwner = ((GroupTO) actual).getPlainAttrMap().get(StringUtils.EMPTY);
+                    AttrTO groupOwner = ((GroupTO) actual).getPlainAttr(StringUtils.EMPTY);
                     if (groupOwner != null) {
                         groupOwnerMap.put(created.getResult(), groupOwner.getValues().iterator().next());
                     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
index 95325a9..ffd55b1 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
@@ -67,10 +67,10 @@ public class AnyObjectITCase extends AbstractITCase {
         ConnObjectTO connObjectTO =
                 resourceService.readConnObject(RESOURCE_NAME_DBSCRIPTED, anyObjectTO.getType(), anyObjectTO.getKey());
         assertNotNull(connObjectTO);
-        assertNotNull(connObjectTO.getAttrMap().get("LOCATION"));
+        assertNotNull(connObjectTO.getAttr("LOCATION"));
         assertEquals(
-                anyObjectTO.getPlainAttrMap().get("location").getValues(),
-                connObjectTO.getAttrMap().get("LOCATION").getValues());
+                anyObjectTO.getPlainAttr("location").getValues(),
+                connObjectTO.getAttr("LOCATION").getValues());
     }
 
     @Test
@@ -123,8 +123,8 @@ public class AnyObjectITCase extends AbstractITCase {
     public void list() {
         PagedResult<AnyObjectTO> anyObjectTOs = anyObjectService.search(
                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
-                fiql(SyncopeClient.getAnyObjectSearchConditionBuilder("PRINTER").query()).
-                build());
+                        fiql(SyncopeClient.getAnyObjectSearchConditionBuilder("PRINTER").query()).
+                        build());
         assertNotNull(anyObjectTOs);
         assertTrue(anyObjectTOs.getResult().size() >= 2);
         for (AnyObjectTO anyObjectTO : anyObjectTOs.getResult()) {
@@ -154,7 +154,7 @@ public class AnyObjectITCase extends AbstractITCase {
 
         anyObjectTO = updateAnyObject(anyObjectPatch).getEntity();
 
-        assertEquals(newLocation, anyObjectTO.getPlainAttrMap().get("location").getValues().get(0));
+        assertEquals(newLocation, anyObjectTO.getPlainAttr("location").getValues().get(0));
     }
 
     @Test
@@ -167,7 +167,7 @@ public class AnyObjectITCase extends AbstractITCase {
         assertEquals(anyObjectTO.getPlainAttrs(), attrs);
 
         AttrTO location = anyObjectService.read(anyObjectTO.getKey(), SchemaType.PLAIN, "location");
-        assertEquals(anyObjectTO.getPlainAttrMap().get("location"), location);
+        assertEquals(anyObjectTO.getPlainAttr("location"), location);
     }
 
     @Test
@@ -190,7 +190,7 @@ public class AnyObjectITCase extends AbstractITCase {
         AnyObjectTO anyObjectTO = getSampleTO("deleteAttr");
         anyObjectTO = createAnyObject(anyObjectTO).getEntity();
         assertNotNull(anyObjectTO);
-        assertNotNull(anyObjectTO.getPlainAttrMap().get("location"));
+        assertNotNull(anyObjectTO.getPlainAttr("location"));
 
         anyObjectService.delete(anyObjectTO.getKey(), SchemaType.PLAIN, "location");
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java
index 55d0cd3..50fa799 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java
@@ -278,7 +278,7 @@ public class AuthenticationITCase extends AbstractITCase {
 
             user = response.readEntity(new GenericType<ProvisioningResult<UserTO>>() {
             }).getEntity();
-            assertEquals("surname", user.getPlainAttrMap().get("surname").getValues().get(0));
+            assertEquals("surname", user.getPlainAttr("surname").getValues().get(0));
 
             // 5. as delegated, update user attempting to move under realm / -> fail
             UserPatch userPatch = new UserPatch();
@@ -301,7 +301,7 @@ public class AuthenticationITCase extends AbstractITCase {
 
             user = response.readEntity(new GenericType<ProvisioningResult<UserTO>>() {
             }).getEntity();
-            assertEquals("surname2", user.getPlainAttrMap().get("surname").getValues().get(0));
+            assertEquals("surname2", user.getPlainAttr("surname").getValues().get(0));
 
             // 7. as delegated, delete user
             delegatedUserService.delete(user.getKey());

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java
index 66fbcc1..4f4f475 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java
@@ -120,7 +120,7 @@ public class CamelRouteITCase extends AbstractITCase {
                 + "    </setProperty>\n"
                 + "    <setBody>\n"
                 + "     <groovy>\n"
-                + "request.body.getPlainAttrMap().get(\"camelAttribute\").getValues().set(0,\"true\")\n"
+                + "request.body.getPlainAttr(\"camelAttribute\").getValues().set(0,\"true\")\n"
                 + "       return request.body\n"
                 + "     </groovy>\n"
                 + "    </setBody>\n"
@@ -165,7 +165,7 @@ public class CamelRouteITCase extends AbstractITCase {
 
             userTO = createUser(userTO).getEntity();
             assertNotNull(userTO);
-            assertEquals("true", userTO.getPlainAttrMap().get("camelAttribute").getValues().get(0));
+            assertEquals("true", userTO.getPlainAttr("camelAttribute").getValues().get(0));
         } finally {
             doUpdate(oldRoute.getKey(), oldRoute.getContent());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
index caf1623..88d08f9 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
@@ -210,7 +210,7 @@ public class DynRealmITCase extends AbstractITCase {
                     readEntity(new GenericType<ProvisioningResult<GroupTO>>() {
                     }).getEntity();
             assertNotNull(group);
-            assertEquals("modified", group.getPlainAttrMap().get("icon").getValues().get(0));
+            assertEquals("modified", group.getPlainAttr("icon").getValues().get(0));
         } finally {
             if (role != null) {
                 roleService.delete(role.getKey());

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
index 1d8c528..3dff239 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
@@ -44,6 +44,7 @@ import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.AnyOperations;
+import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.patch.AnyObjectPatch;
@@ -119,17 +120,16 @@ public class GroupITCase extends AbstractITCase {
         groupTO = createGroup(groupTO).getEntity();
         assertNotNull(groupTO);
 
-        assertNotNull(groupTO.getVirAttrMap());
-        assertNotNull(groupTO.getVirAttrMap().get("rvirtualdata").getValues());
-        assertFalse(groupTO.getVirAttrMap().get("rvirtualdata").getValues().isEmpty());
-        assertEquals("rvirtualvalue", groupTO.getVirAttrMap().get("rvirtualdata").getValues().get(0));
+        assertNotNull(groupTO.getVirAttr("rvirtualdata").getValues());
+        assertFalse(groupTO.getVirAttr("rvirtualdata").getValues().isEmpty());
+        assertEquals("rvirtualvalue", groupTO.getVirAttr("rvirtualdata").getValues().get(0));
 
         assertTrue(groupTO.getResources().contains(RESOURCE_NAME_LDAP));
 
         ConnObjectTO connObjectTO =
                 resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
         assertNotNull(connObjectTO);
-        assertNotNull(connObjectTO.getAttrMap().get("owner"));
+        assertNotNull(connObjectTO.getAttr("owner"));
 
         // SYNCOPE-515: remove ownership
         GroupPatch groupPatch = new GroupPatch();
@@ -240,12 +240,12 @@ public class GroupITCase extends AbstractITCase {
         assertEquals(modName, groupTO.getName());
         assertEquals(2, groupTO.getPlainAttrs().size());
 
-        groupTO.getPlainAttrMap().get("show").getValues().clear();
+        groupTO.getPlainAttr("show").getValues().clear();
 
         groupTO = groupService.update(groupTO).readEntity(new GenericType<ProvisioningResult<GroupTO>>() {
         }).getEntity();
 
-        assertFalse(groupTO.getPlainAttrMap().containsKey("show"));
+        assertNull(groupTO.getPlainAttr("show"));
     }
 
     @Test
@@ -269,7 +269,7 @@ public class GroupITCase extends AbstractITCase {
         GroupPatch patch = AnyOperations.diff(updated, original, true);
         GroupTO group = updateGroup(patch).getEntity();
 
-        Map<String, AttrTO> attrs = group.getPlainAttrMap();
+        Map<String, AttrTO> attrs = EntityTOUtils.buildAttrMap(group.getPlainAttrs());
         assertFalse(attrs.containsKey("icon"));
         assertFalse(attrs.containsKey("show"));
         assertEquals(Collections.singletonList("sx"), attrs.get("rderived_sx").getValues());
@@ -574,10 +574,10 @@ public class GroupITCase extends AbstractITCase {
 
         // 2. create a group *without* an attribute for that schema: it works
         GroupTO groupTO = getSampleTO("lastGroup");
-        assertFalse(groupTO.getPlainAttrMap().containsKey(badge.getKey()));
+        assertNull(groupTO.getPlainAttr(badge.getKey()));
         groupTO = createGroup(groupTO).getEntity();
         assertNotNull(groupTO);
-        assertFalse(groupTO.getPlainAttrMap().containsKey(badge.getKey()));
+        assertNull(groupTO.getPlainAttr(badge.getKey()));
 
         // 3. add the new mandatory schema to the default group type
         AnyTypeTO type = anyTypeService.read(AnyTypeKind.GROUP.name());
@@ -605,7 +605,7 @@ public class GroupITCase extends AbstractITCase {
 
             groupTO = updateGroup(groupPatch).getEntity();
             assertNotNull(groupTO);
-            assertTrue(groupTO.getPlainAttrMap().containsKey(badge.getKey()));
+            assertNotNull(groupTO.getPlainAttr(badge.getKey()));
         } finally {
             // restore the original group class
             typeClass.getPlainSchemas().remove(badge.getKey());
@@ -669,7 +669,7 @@ public class GroupITCase extends AbstractITCase {
         AnyObjectTO newAny = AnyObjectITCase.getSampleTO("aDynMembership");
         newAny.getResources().clear();
         newAny = createAnyObject(newAny).getEntity();
-        assertNotNull(newAny.getPlainAttrMap().get("location"));
+        assertNotNull(newAny.getPlainAttr("location"));
         assertTrue(anyObjectService.read(
                 "fc6dbc3a-6c07-4965-8781-921e7401a4a5").getDynGroups().contains(group.getKey()));
         assertTrue(anyObjectService.read(
@@ -697,7 +697,7 @@ public class GroupITCase extends AbstractITCase {
                 attrTO(new AttrTO.Builder().schema("location").build()).
                 build());
         newAny = updateAnyObject(anyPatch).getEntity();
-        assertNull(newAny.getPlainAttrMap().get("location"));
+        assertNull(newAny.getPlainAttr("location"));
         assertFalse(anyObjectService.read(
                 "fc6dbc3a-6c07-4965-8781-921e7401a4a5").getDynGroups().contains(group.getKey()));
         assertFalse(anyObjectService.read(
@@ -1036,7 +1036,7 @@ public class GroupITCase extends AbstractITCase {
 
         groupTO = createGroup(groupTO).getEntity();
         assertNotNull(groupTO);
-        assertEquals("11.23", groupTO.getPlainAttrMap().get(doubleSchemaName).getValues().get(0));
+        assertEquals("11.23", groupTO.getPlainAttr(doubleSchemaName).getValues().get(0));
 
         // 3. update schema, set conversion pattern
         schema = schemaService.read(SchemaType.PLAIN, schema.getKey());
@@ -1046,7 +1046,7 @@ public class GroupITCase extends AbstractITCase {
         // 4. re-read group, verify that pattern was applied
         groupTO = groupService.read(groupTO.getKey());
         assertNotNull(groupTO);
-        assertEquals("11.230", groupTO.getPlainAttrMap().get(doubleSchemaName).getValues().get(0));
+        assertEquals("11.230", groupTO.getPlainAttr(doubleSchemaName).getValues().get(0));
 
         // 5. modify group with new double value
         GroupPatch patch = new GroupPatch();
@@ -1055,7 +1055,7 @@ public class GroupITCase extends AbstractITCase {
 
         groupTO = updateGroup(patch).getEntity();
         assertNotNull(groupTO);
-        assertEquals("11.257", groupTO.getPlainAttrMap().get(doubleSchemaName).getValues().get(0));
+        assertEquals("11.257", groupTO.getPlainAttr(doubleSchemaName).getValues().get(0));
 
         // 6. update schema, unset conversion pattern
         schema.setConversionPattern(null);
@@ -1068,7 +1068,7 @@ public class GroupITCase extends AbstractITCase {
 
         groupTO = updateGroup(patch).getEntity();
         assertNotNull(groupTO);
-        assertEquals("11.23", groupTO.getPlainAttrMap().get(doubleSchemaName).getValues().get(0));
+        assertEquals("11.23", groupTO.getPlainAttr(doubleSchemaName).getValues().get(0));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
index 74a78d3..e150bb2 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
@@ -21,6 +21,7 @@ package org.apache.syncope.fit.core;
 import static org.junit.Assert.assertEquals;
 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 static org.junit.Assert.fail;
 
@@ -74,7 +75,7 @@ public class MembershipITCase extends AbstractITCase {
         UserTO user = UserITCase.getUniqueSampleTO("memb@apache.org");
         user.setRealm("/even/two");
         user.getPlainAttrs().add(new AttrTO.Builder().schema("aLong").value("1976").build());
-        user.getPlainAttrs().remove(user.getPlainAttrMap().get("ctype"));
+        user.getPlainAttrs().remove(user.getPlainAttr("ctype"));
 
         // the group 034740a9-fa10-453b-af37-dc7897e98fb1 has USER type extensions for 'csv' and 'other' 
         // any type classes
@@ -107,19 +108,19 @@ public class MembershipITCase extends AbstractITCase {
             user = createUser(user).getEntity();
 
             // 1. verify that 'aLong' is correctly populated for user
-            assertEquals(1, user.getPlainAttrMap().get("aLong").getValues().size());
-            assertEquals("1976", user.getPlainAttrMap().get("aLong").getValues().get(0));
+            assertEquals(1, user.getPlainAttr("aLong").getValues().size());
+            assertEquals("1976", user.getPlainAttr("aLong").getValues().get(0));
 
             // 2. verify that 'aLong' is correctly populated for user's membership
             assertEquals(1, user.getMemberships().size());
             membership = user.getMembershipMap().get("034740a9-fa10-453b-af37-dc7897e98fb1");
             assertNotNull(membership);
-            assertEquals(1, membership.getPlainAttrMap().get("aLong").getValues().size());
-            assertEquals("1977", membership.getPlainAttrMap().get("aLong").getValues().get(0));
+            assertEquals(1, membership.getPlainAttr("aLong").getValues().size());
+            assertEquals("1977", membership.getPlainAttr("aLong").getValues().get(0));
 
             // 3. verify that derived attrbutes from 'csv' and 'other' are also populated for user's membership
-            assertFalse(membership.getDerAttrMap().get("csvuserid").getValues().isEmpty());
-            assertFalse(membership.getDerAttrMap().get("noschema").getValues().isEmpty());
+            assertFalse(membership.getDerAttr("csvuserid").getValues().isEmpty());
+            assertFalse(membership.getDerAttr("noschema").getValues().isEmpty());
 
             // update user - change some values and add new membership attribute
             UserPatch userPatch = new UserPatch();
@@ -138,19 +139,19 @@ public class MembershipITCase extends AbstractITCase {
             user = updateUser(userPatch).getEntity();
 
             // 4. verify that 'aLong' is correctly populated for user
-            assertEquals(1, user.getPlainAttrMap().get("aLong").getValues().size());
-            assertEquals("1977", user.getPlainAttrMap().get("aLong").getValues().get(0));
-            assertFalse(user.getPlainAttrMap().containsKey("ctype"));
+            assertEquals(1, user.getPlainAttr("aLong").getValues().size());
+            assertEquals("1977", user.getPlainAttr("aLong").getValues().get(0));
+            assertNull(user.getPlainAttr("ctype"));
 
             // 5. verify that 'aLong' is correctly populated for user's membership
             assertEquals(1, user.getMemberships().size());
             membership = user.getMembershipMap().get("034740a9-fa10-453b-af37-dc7897e98fb1");
             assertNotNull(membership);
-            assertEquals(1, membership.getPlainAttrMap().get("aLong").getValues().size());
-            assertEquals("1976", membership.getPlainAttrMap().get("aLong").getValues().get(0));
+            assertEquals(1, membership.getPlainAttr("aLong").getValues().size());
+            assertEquals("1976", membership.getPlainAttr("aLong").getValues().get(0));
 
             // 6. verify that 'ctype' is correctly populated for user's membership
-            assertEquals("membership type", membership.getPlainAttrMap().get("ctype").getValues().get(0));
+            assertEquals("membership type", membership.getPlainAttr("ctype").getValues().get(0));
 
             // finally remove membership
             userPatch = new UserPatch();
@@ -212,12 +213,12 @@ public class MembershipITCase extends AbstractITCase {
         assertEquals(1, user.getMemberships().size());
         membership = user.getMembershipMap().get(groupTO.getKey());
         assertNotNull(membership);
-        assertEquals(1, membership.getPlainAttrMap().get("aLong").getValues().size());
-        assertEquals("1454", membership.getPlainAttrMap().get("aLong").getValues().get(0));
+        assertEquals(1, membership.getPlainAttr("aLong").getValues().size());
+        assertEquals("1454", membership.getPlainAttr("aLong").getValues().get(0));
 
         // verify that derived attrbutes from 'csv' and 'other' are also populated for user's membership
-        assertFalse(membership.getDerAttrMap().get("csvuserid").getValues().isEmpty());
-        assertFalse(membership.getDerAttrMap().get("noschema").getValues().isEmpty());
+        assertFalse(membership.getDerAttr("csvuserid").getValues().isEmpty());
+        assertFalse(membership.getDerAttr("noschema").getValues().isEmpty());
 
         // now remove the group -> all related memberships should have been removed as well
         groupService.delete(groupTO.getKey());
@@ -264,7 +265,7 @@ public class MembershipITCase extends AbstractITCase {
             // 1. create user with new resource assigned
             UserTO user = UserITCase.getUniqueSampleTO("memb@apache.org");
             user.setRealm("/even/two");
-            user.getPlainAttrs().remove(user.getPlainAttrMap().get("ctype"));
+            user.getPlainAttrs().remove(user.getPlainAttr("ctype"));
             user.getResources().clear();
             user.getResources().add(newResource.getKey());
 
@@ -310,7 +311,7 @@ public class MembershipITCase extends AbstractITCase {
             assertEquals(1, users.getTotalCount());
             assertEquals(1, users.getResult().get(0).getMemberships().size());
             assertEquals("5432", users.getResult().get(0).getMemberships().get(0).
-                    getPlainAttrMap().get("aLong").getValues().get(0));
+                    getPlainAttr("aLong").getValues().get(0));
         } catch (Exception e) {
             LOG.error("Unexpected error", e);
             fail(e.getMessage());

http://git-wip-us.apache.org/repos/asf/syncope/blob/31cffd4e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
index ed8d0df..9017a9b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
@@ -518,8 +518,8 @@ public class MigrationITCase extends AbstractTaskITCase {
         assertEquals("/" + MIGRATION_REALM, group.getRealm());
 
         // 4a. user plain attrs
-        assertEquals("Gioacchino", user.getPlainAttrMap().get("firstname").getValues().get(0));
-        assertEquals("Rossini", user.getPlainAttrMap().get("surname").getValues().get(0));
+        assertEquals("Gioacchino", user.getPlainAttr("firstname").getValues().get(0));
+        assertEquals("Rossini", user.getPlainAttr("surname").getValues().get(0));
 
         // 4b. user resources
         assertTrue(user.getResources().contains(RESOURCE_NAME_TESTDB2));
@@ -528,7 +528,7 @@ public class MigrationITCase extends AbstractTaskITCase {
         assertNotNull(clientFactory.create("bellini12", ADMIN_PWD).self());
 
         // 4d. group plain attrs
-        assertEquals("r12", group.getPlainAttrMap().get("title").getValues().get(0));
+        assertEquals("r12", group.getPlainAttr("title").getValues().get(0));
 
         // 4e. group resources
         assertTrue(group.getResources().contains(RESOURCE_NAME_CSV));