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

[17/59] [abbrv] [partial] syncope git commit: [SYNCOPE-620] Re-organization completed

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/AttributableOperations.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/AttributableOperations.java b/common/lib/src/main/java/org/apache/syncope/common/lib/AttributableOperations.java
new file mode 100644
index 0000000..1c53db6
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/AttributableOperations.java
@@ -0,0 +1,508 @@
+/*
+ * 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;
+
+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 org.apache.commons.lang3.SerializationUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.mod.AbstractAttributableMod;
+import org.apache.syncope.common.lib.mod.AbstractSubjectMod;
+import org.apache.syncope.common.lib.mod.AttrMod;
+import org.apache.syncope.common.lib.mod.MembershipMod;
+import org.apache.syncope.common.lib.mod.ReferenceMod;
+import org.apache.syncope.common.lib.mod.RoleMod;
+import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AbstractSubjectTO;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+
+/**
+ * Utility class for manipulating classes extending AbstractAttributableTO and AbstractAttributableMod.
+ *
+ * @see AbstractAttributableTO
+ * @see AbstractAttributableMod
+ */
+public final class AttributableOperations {
+
+    private AttributableOperations() {
+        // empty constructor for static utility classes
+    }
+
+    private static void populate(final Map<String, AttrTO> updatedAttrs,
+            final Map<String, AttrTO> originalAttrs, final AbstractAttributableMod result) {
+
+        populate(updatedAttrs, originalAttrs, result, false);
+    }
+
+    private static void populate(final Map<String, AttrTO> updatedAttrs,
+            final Map<String, AttrTO> originalAttrs, final AbstractAttributableMod result,
+            final boolean virtuals) {
+
+        for (Map.Entry<String, AttrTO> entry : updatedAttrs.entrySet()) {
+            AttrMod mod = new AttrMod();
+            mod.setSchema(entry.getKey());
+
+            Set<String> updatedValues = new HashSet<String>(entry.getValue().getValues());
+
+            Set<String> originalValues = originalAttrs.containsKey(entry.getKey())
+                    ? new HashSet<String>(originalAttrs.get(entry.getKey()).getValues())
+                    : Collections.<String>emptySet();
+
+            if (!originalAttrs.containsKey(entry.getKey())) {
+                // SYNCOPE-459: take care of user virtual attributes without any value
+                updatedValues.remove("");
+                mod.getValuesToBeAdded().addAll(new ArrayList<String>(updatedValues));
+
+                if (virtuals) {
+                    result.getVirAttrsToUpdate().add(mod);
+                } else {
+                    result.getPlainAttrsToUpdate().add(mod);
+                }
+            } else if (!updatedValues.equals(originalValues)) {
+                // avoid unwanted inputs
+                updatedValues.remove("");
+                if (!entry.getValue().isReadonly()) {
+                    mod.getValuesToBeAdded().addAll(updatedValues);
+
+                    if (!mod.isEmpty()) {
+                        if (virtuals) {
+                            result.getVirAttrsToRemove().add(mod.getSchema());
+                        } else {
+                            result.getPlainAttrsToRemove().add(mod.getSchema());
+                        }
+                    }
+                }
+
+                mod.getValuesToBeRemoved().addAll(originalValues);
+
+                if (!mod.isEmpty()) {
+                    if (virtuals) {
+                        result.getVirAttrsToUpdate().add(mod);
+                    } else {
+                        result.getPlainAttrsToUpdate().add(mod);
+                    }
+                }
+            }
+        }
+    }
+
+    private static void diff(
+            final AbstractAttributableTO updated,
+            final AbstractAttributableTO original,
+            final AbstractAttributableMod result,
+            final boolean incremental) {
+
+        // 1. check same id
+        if (updated.getKey() != original.getKey()) {
+            throw new IllegalArgumentException("AttributableTO's id must be the same");
+        }
+        result.setKey(updated.getKey());
+
+        // 2. attributes
+        Map<String, AttrTO> updatedAttrs = new HashMap<>(updated.getPlainAttrMap());
+        Map<String, AttrTO> originalAttrs = new HashMap<>(original.getPlainAttrMap());
+
+        Set<String> originalAttrNames = new HashSet<>(originalAttrs.keySet());
+        originalAttrNames.removeAll(updatedAttrs.keySet());
+
+        if (!incremental) {
+            result.getPlainAttrsToRemove().clear();
+            result.getPlainAttrsToRemove().addAll(originalAttrNames);
+        }
+
+        Set<String> emptyUpdatedAttrs = new HashSet<>();
+        for (Map.Entry<String, AttrTO> entry : updatedAttrs.entrySet()) {
+            if (entry.getValue().getValues() == null || entry.getValue().getValues().isEmpty()) {
+
+                emptyUpdatedAttrs.add(entry.getKey());
+            }
+        }
+        for (String emptyUpdatedAttr : emptyUpdatedAttrs) {
+            updatedAttrs.remove(emptyUpdatedAttr);
+            result.getPlainAttrsToRemove().add(emptyUpdatedAttr);
+        }
+
+        populate(updatedAttrs, originalAttrs, result);
+
+        // 3. derived attributes
+        updatedAttrs = updated.getDerAttrMap();
+        originalAttrs = original.getDerAttrMap();
+
+        originalAttrNames = new HashSet<>(originalAttrs.keySet());
+        originalAttrNames.removeAll(updatedAttrs.keySet());
+
+        if (!incremental) {
+            result.getDerAttrsToRemove().clear();
+            result.getDerAttrsToRemove().addAll(originalAttrNames);
+        }
+
+        Set<String> updatedAttrNames = new HashSet<>(updatedAttrs.keySet());
+        updatedAttrNames.removeAll(originalAttrs.keySet());
+        result.getDerAttrsToAdd().clear();
+        result.getDerAttrsToAdd().addAll(updatedAttrNames);
+
+        // 4. virtual attributes
+        updatedAttrs = updated.getVirAttrMap();
+        originalAttrs = original.getVirAttrMap();
+
+        originalAttrNames = new HashSet<>(originalAttrs.keySet());
+        originalAttrNames.removeAll(updatedAttrs.keySet());
+
+        if (!incremental) {
+            result.getVirAttrsToRemove().clear();
+            result.getVirAttrsToRemove().addAll(originalAttrNames);
+        }
+
+        populate(updatedAttrs, originalAttrs, result, true);
+
+        // 5. resources
+        if (original instanceof AbstractSubjectTO && updated instanceof AbstractSubjectTO
+                && result instanceof AbstractSubjectMod) {
+
+            Set<String> updatedRes = new HashSet<>(((AbstractSubjectTO) updated).getResources());
+            Set<String> originalRes = new HashSet<>(((AbstractSubjectTO) original).getResources());
+
+            updatedRes.removeAll(originalRes);
+            ((AbstractSubjectMod) result).getResourcesToAdd().clear();
+            ((AbstractSubjectMod) result).getResourcesToAdd().addAll(updatedRes);
+
+            originalRes.removeAll(((AbstractSubjectTO) updated).getResources());
+
+            if (!incremental) {
+                ((AbstractSubjectMod) result).getResourcesToRemove().clear();
+                ((AbstractSubjectMod) result).getResourcesToRemove().addAll(originalRes);
+            }
+        }
+    }
+
+    /**
+     * Calculate modifications needed by first in order to be equal to second.
+     *
+     * @param updated updated UserTO
+     * @param original original UserTO
+     * @return UserMod containing differences
+     */
+    public static UserMod diff(final UserTO updated, final UserTO original) {
+        return diff(updated, original, false);
+    }
+
+    /**
+     * Calculate modifications needed by first in order to be equal to second.
+     *
+     * @param updated updated UserTO
+     * @param original original UserTO
+     * @param incremental perform incremental diff (without removing existing info)
+     * @return UserMod containing differences
+     */
+    public static UserMod diff(final UserTO updated, final UserTO original, final boolean incremental) {
+        UserMod result = new UserMod();
+
+        diff(updated, original, result, incremental);
+
+        // 1. password
+        if (updated.getPassword() != null && (original.getPassword() == null
+                || !original.getPassword().equals(updated.getPassword()))) {
+
+            result.setPassword(updated.getPassword());
+        }
+
+        // 2. username
+        if (original.getUsername() != null && !original.getUsername().equals(updated.getUsername())) {
+            result.setUsername(updated.getUsername());
+        }
+
+        // 3. security question / answer
+        if (updated.getSecurityQuestion() == null) {
+            result.setSecurityQuestion(null);
+            result.setSecurityAnswer(null);
+        } else if (!updated.getSecurityQuestion().equals(original.getSecurityQuestion())
+                || StringUtils.isNotBlank(updated.getSecurityAnswer())) {
+
+            result.setSecurityQuestion(updated.getSecurityQuestion());
+            result.setSecurityAnswer(updated.getSecurityAnswer());
+        }
+
+        // 4. memberships
+        Map<Long, MembershipTO> updatedMembs = updated.getMembershipMap();
+        Map<Long, MembershipTO> originalMembs = original.getMembershipMap();
+
+        for (Map.Entry<Long, MembershipTO> entry : updatedMembs.entrySet()) {
+            MembershipMod membMod = new MembershipMod();
+            membMod.setRole(entry.getValue().getRoleId());
+
+            if (originalMembs.containsKey(entry.getKey())) {
+                // if memberships are actually same, just make the isEmpty() call below succeed
+                if (entry.getValue().equals(originalMembs.get(entry.getKey()))) {
+                    membMod.setRole(0);
+                } else {
+                    diff(entry.getValue(), originalMembs.get(entry.getKey()), membMod, false);
+                }
+            } else {
+                for (AttrTO attr : entry.getValue().getPlainAttrs()) {
+                    AttrMod attrMod = new AttrMod();
+                    attrMod.setSchema(attr.getSchema());
+                    attrMod.getValuesToBeAdded().addAll(attr.getValues());
+
+                    if (!attrMod.isEmpty()) {
+                        membMod.getPlainAttrsToUpdate().add(attrMod);
+                        membMod.getPlainAttrsToRemove().add(attrMod.getSchema());
+                    }
+                }
+                for (AttrTO attr : entry.getValue().getDerAttrs()) {
+                    membMod.getDerAttrsToAdd().add(attr.getSchema());
+                }
+                for (AttrTO attr : entry.getValue().getVirAttrs()) {
+                    AttrMod attrMod = new AttrMod();
+                    attrMod.setSchema(attr.getSchema());
+                    attrMod.getValuesToBeAdded().addAll(attr.getValues());
+
+                    if (!attrMod.isEmpty()) {
+                        membMod.getVirAttrsToUpdate().add(attrMod);
+                        membMod.getPlainAttrsToRemove().add(attrMod.getSchema());
+                    }
+                }
+            }
+
+            if (!membMod.isEmpty()) {
+                result.getMembershipsToAdd().add(membMod);
+            }
+        }
+
+        if (!incremental) {
+            Set<Long> originalRoles = new HashSet<>(originalMembs.keySet());
+            originalRoles.removeAll(updatedMembs.keySet());
+            for (Long roleId : originalRoles) {
+                result.getMembershipsToRemove().add(originalMembs.get(roleId).getKey());
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Calculate modifications needed by first in order to be equal to second.
+     *
+     * @param updated updated RoleTO
+     * @param original original RoleTO
+     * @return RoleMod containing differences
+     */
+    public static RoleMod diff(final RoleTO updated, final RoleTO original) {
+        return diff(updated, original, false);
+    }
+
+    /**
+     * Calculate modifications needed by first in order to be equal to second.
+     *
+     * @param updated updated RoleTO
+     * @param original original RoleTO
+     * @param incremental perform incremental diff (without removing existing info)
+     * @return RoleMod containing differences
+     */
+    public static RoleMod diff(final RoleTO updated, final RoleTO original, final boolean incremental) {
+        RoleMod result = new RoleMod();
+
+        diff(updated, original, result, incremental);
+
+        // 1. inheritance
+        result.setInheritOwner(updated.isInheritOwner());
+        result.setInheritTemplates(updated.isInheritTemplates());
+        result.setInheritAccountPolicy(updated.isInheritAccountPolicy());
+        result.setInheritPasswordPolicy(updated.isInheritPasswordPolicy());
+        result.setInheritPlainAttrs(updated.isInheritPlainAttrs());
+        result.setInheritDerAttrs(updated.isInheritDerAttrs());
+        result.setInheritVirAttrs(updated.isInheritVirAttrs());
+
+        // 2. policies
+        result.setAccountPolicy(new ReferenceMod(updated.getAccountPolicy()));
+        result.setPasswordPolicy(new ReferenceMod(updated.getPasswordPolicy()));
+
+        // 3. name
+        if (!original.getName().equals(updated.getName())) {
+            result.setName(updated.getName());
+        }
+
+        // 4. entitlements
+        Set<String> updatedEnts = new HashSet<>(updated.getEntitlements());
+        Set<String> originalEnts = new HashSet<>(original.getEntitlements());
+        if (updatedEnts.equals(originalEnts)) {
+            result.setModEntitlements(false);
+            result.getEntitlements().clear();
+        } else {
+            result.setModEntitlements(true);
+            result.getEntitlements().addAll(updated.getEntitlements());
+        }
+
+        // 5. templates
+        Set<String> updatedTemplates = new HashSet<>(updated.getRPlainAttrTemplates());
+        Set<String> originalTemplates = new HashSet<>(original.getRPlainAttrTemplates());
+        if (updatedTemplates.equals(originalTemplates)) {
+            result.setModRAttrTemplates(false);
+            result.getRPlainAttrTemplates().clear();
+        } else {
+            result.setModRAttrTemplates(true);
+            result.getRPlainAttrTemplates().addAll(updated.getRPlainAttrTemplates());
+        }
+        updatedTemplates = new HashSet<>(updated.getRDerAttrTemplates());
+        originalTemplates = new HashSet<>(original.getRDerAttrTemplates());
+        if (updatedTemplates.equals(originalTemplates)) {
+            result.setModRDerAttrTemplates(false);
+            result.getRDerAttrTemplates().clear();
+        } else {
+            result.setModRDerAttrTemplates(true);
+            result.getRDerAttrTemplates().addAll(updated.getRDerAttrTemplates());
+        }
+        updatedTemplates = new HashSet<>(updated.getRVirAttrTemplates());
+        originalTemplates = new HashSet<>(original.getRVirAttrTemplates());
+        if (updatedTemplates.equals(originalTemplates)) {
+            result.setModRVirAttrTemplates(false);
+            result.getRVirAttrTemplates().clear();
+        } else {
+            result.setModRVirAttrTemplates(true);
+            result.getRVirAttrTemplates().addAll(updated.getRVirAttrTemplates());
+        }
+        updatedTemplates = new HashSet<>(updated.getMPlainAttrTemplates());
+        originalTemplates = new HashSet<>(original.getMPlainAttrTemplates());
+        if (updatedTemplates.equals(originalTemplates)) {
+            result.setModMAttrTemplates(false);
+            result.getMPlainAttrTemplates().clear();
+        } else {
+            result.setModMAttrTemplates(true);
+            result.getMPlainAttrTemplates().addAll(updated.getMPlainAttrTemplates());
+        }
+        updatedTemplates = new HashSet<>(updated.getMDerAttrTemplates());
+        originalTemplates = new HashSet<>(original.getMDerAttrTemplates());
+        if (updatedTemplates.equals(originalTemplates)) {
+            result.setModMDerAttrTemplates(false);
+            result.getMDerAttrTemplates().clear();
+        } else {
+            result.setModMDerAttrTemplates(true);
+            result.getMDerAttrTemplates().addAll(updated.getMDerAttrTemplates());
+        }
+        updatedTemplates = new HashSet<>(updated.getMVirAttrTemplates());
+        originalTemplates = new HashSet<>(original.getMVirAttrTemplates());
+        if (updatedTemplates.equals(originalTemplates)) {
+            result.setModMVirAttrTemplates(false);
+            result.getMVirAttrTemplates().clear();
+        } else {
+            result.setModMVirAttrTemplates(true);
+            result.getMVirAttrTemplates().addAll(updated.getMVirAttrTemplates());
+        }
+
+        // 6. owner
+        result.setUserOwner(new ReferenceMod(updated.getUserOwner()));
+        result.setRoleOwner(new ReferenceMod(updated.getRoleOwner()));
+
+        return result;
+    }
+
+    private static List<AttrTO> getUpdateValues(final Map<String, AttrTO> attrs,
+            final Set<String> attrsToBeRemoved, final Set<AttrMod> attrsToBeUpdated) {
+
+        Map<String, AttrTO> rwattrs = new HashMap<>(attrs);
+        for (String attrName : attrsToBeRemoved) {
+            rwattrs.remove(attrName);
+        }
+        for (AttrMod attrMod : attrsToBeUpdated) {
+            if (rwattrs.containsKey(attrMod.getSchema())) {
+                AttrTO attrTO = rwattrs.get(attrMod.getSchema());
+                attrTO.getValues().removeAll(attrMod.getValuesToBeRemoved());
+                attrTO.getValues().addAll(attrMod.getValuesToBeAdded());
+            } else {
+                AttrTO attrTO = new AttrTO();
+                attrTO.setSchema(attrMod.getSchema());
+                attrTO.getValues().addAll(attrMod.getValuesToBeAdded());
+
+                rwattrs.put(attrMod.getSchema(), attrTO);
+            }
+        }
+
+        return new ArrayList<>(rwattrs.values());
+    }
+
+    private static <T extends AbstractAttributableTO, K extends AbstractAttributableMod> void apply(final T to,
+            final K mod, final T result) {
+
+        // 1. attributes
+        result.getPlainAttrs().addAll(getUpdateValues(to.getPlainAttrMap(),
+                mod.getPlainAttrsToRemove(), mod.getPlainAttrsToUpdate()));
+
+        // 2. derived attributes
+        Map<String, AttrTO> attrs = to.getDerAttrMap();
+        for (String attrName : mod.getDerAttrsToRemove()) {
+            attrs.remove(attrName);
+        }
+        for (String attrName : mod.getDerAttrsToAdd()) {
+            AttrTO attrTO = new AttrTO();
+            attrTO.setSchema(attrName);
+
+            attrs.put(attrName, attrTO);
+        }
+        result.getDerAttrs().addAll(attrs.values());
+
+        // 3. virtual attributes
+        result.getVirAttrs().addAll(getUpdateValues(to.getVirAttrMap(),
+                mod.getVirAttrsToRemove(), mod.getVirAttrsToUpdate()));
+
+        // 4. resources
+        if (result instanceof AbstractSubjectTO && mod instanceof AbstractSubjectMod) {
+            ((AbstractSubjectTO) result).getResources().removeAll(((AbstractSubjectMod) mod).getResourcesToRemove());
+            ((AbstractSubjectTO) result).getResources().addAll(((AbstractSubjectMod) mod).getResourcesToAdd());
+        }
+    }
+
+    public static UserTO apply(final UserTO userTO, final UserMod userMod) {
+        // 1. check same id
+        if (userTO.getKey() != userMod.getKey()) {
+            throw new IllegalArgumentException("UserTO and UserMod ids must be the same");
+        }
+
+        UserTO result = SerializationUtils.clone(userTO);
+        apply(userTO, userMod, result);
+
+        // 1. password
+        result.setPassword(userMod.getPassword());
+
+        // 2. username
+        if (userMod.getUsername() != null) {
+            result.setUsername(userMod.getUsername());
+        }
+        // 3. memberships
+        Map<Long, MembershipTO> membs = result.getMembershipMap();
+        for (Long membId : userMod.getMembershipsToRemove()) {
+            result.getMemberships().remove(membs.get(membId));
+        }
+        for (MembershipMod membMod : userMod.getMembershipsToAdd()) {
+            MembershipTO membTO = new MembershipTO();
+            membTO.setRoleId(membMod.getRole());
+
+            apply(membTO, membMod, membTO);
+        }
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientCompositeException.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientCompositeException.java b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientCompositeException.java
new file mode 100644
index 0000000..7322cc8
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientCompositeException.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+
+public class SyncopeClientCompositeException extends SyncopeClientException {
+
+    private static final long serialVersionUID = 7882118041134372129L;
+
+    private final Set<SyncopeClientException> exceptions = new HashSet<>();
+
+    protected SyncopeClientCompositeException() {
+        super(ClientExceptionType.Composite);
+    }
+
+    public boolean hasExceptions() {
+        return !exceptions.isEmpty();
+    }
+
+    public boolean hasException(final ClientExceptionType exceptionType) {
+        return getException(exceptionType) != null;
+    }
+
+    public SyncopeClientException getException(final ClientExceptionType exceptionType) {
+        boolean found = false;
+        SyncopeClientException syncopeClientException = null;
+        for (Iterator<SyncopeClientException> itor = exceptions.iterator(); itor.hasNext() && !found;) {
+            syncopeClientException = itor.next();
+            if (syncopeClientException.getType().equals(exceptionType)) {
+                found = true;
+            }
+        }
+
+        return found
+                ? syncopeClientException
+                : null;
+    }
+
+    public Set<SyncopeClientException> getExceptions() {
+        return exceptions;
+    }
+
+    public boolean addException(final SyncopeClientException exception) {
+        if (exception.getType() == null) {
+            throw new IllegalArgumentException(exception + " does not have the right "
+                    + ClientExceptionType.class.getName() + " set");
+        }
+
+        return exceptions.add(exception);
+    }
+
+    @Override
+    public String getMessage() {
+        StringBuilder message = new StringBuilder();
+
+        message.append("{");
+        Iterator<SyncopeClientException> iter = getExceptions().iterator();
+        while (iter.hasNext()) {
+            SyncopeClientException e = iter.next();
+            message.append("[");
+            message.append(e.getMessage());
+            message.append("]");
+            if (iter.hasNext()) {
+                message.append(", ");
+            }
+        }
+        message.append("}");
+
+        return message.toString();
+    }
+
+    @Override
+    public String getLocalizedMessage() {
+        return getMessage();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientException.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientException.java b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientException.java
new file mode 100644
index 0000000..2243835
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientException.java
@@ -0,0 +1,97 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+
+public class SyncopeClientException extends RuntimeException {
+
+    private static final long serialVersionUID = 3380920886511913475L;
+
+    private ClientExceptionType type;
+
+    private final List<String> elements = new ArrayList<>();
+
+    public static SyncopeClientException build(final ClientExceptionType type) {
+        if (type == ClientExceptionType.Composite) {
+            throw new IllegalArgumentException("Composite exceptions must be obtained via buildComposite()");
+        }
+        return new SyncopeClientException(type);
+    }
+
+    public static SyncopeClientCompositeException buildComposite() {
+        return new SyncopeClientCompositeException();
+    }
+
+    protected SyncopeClientException(final ClientExceptionType type) {
+        super();
+        setType(type);
+    }
+
+    public boolean isComposite() {
+        return getType() == ClientExceptionType.Composite;
+    }
+
+    public SyncopeClientCompositeException asComposite() {
+        if (!isComposite()) {
+            throw new IllegalArgumentException("This is not a composite exception");
+        }
+
+        return (SyncopeClientCompositeException) this;
+    }
+
+    public ClientExceptionType getType() {
+        return type;
+    }
+
+    public final void setType(final ClientExceptionType type) {
+        this.type = type;
+    }
+
+    public List<String> getElements() {
+        return elements;
+    }
+
+    public boolean isEmpty() {
+        return elements.isEmpty();
+    }
+
+    public int size() {
+        return elements.size();
+    }
+
+    @Override
+    public String getMessage() {
+        StringBuilder message = new StringBuilder();
+
+        message.append(getType());
+        message.append(" ");
+        message.append(getElements());
+
+        return message.toString();
+    }
+
+    @Override
+    public String getLocalizedMessage() {
+        return getMessage();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
new file mode 100644
index 0000000..817b00d
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+import java.util.regex.Pattern;
+
+public class SyncopeConstants {
+
+    public static final String NAMESPACE = "http://syncope.apache.org/2.0";
+
+    public static final String UNAUTHENTICATED = "unauthenticated";
+
+    public static final String ANONYMOUS_ENTITLEMENT = "anonymous";
+
+    public static final String ENUM_VALUES_SEPARATOR = ";";
+
+    public static final String[] DATE_PATTERNS = {
+        "yyyy-MM-dd'T'HH:mm:ssZ",
+        "EEE, dd MMM yyyy HH:mm:ss z",
+        "yyyy-MM-dd'T'HH:mm:ssz",
+        "yyyy-MM-dd HH:mm:ss",
+        "yyyy-MM-dd HH:mm:ss.S", // explicitly added to import date into MySql repository
+        "yyyy-MM-dd" };
+
+    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ";
+
+    public static final String DEFAULT_ENCODING = "UTF-8";
+
+    public static final String ROOT_LOGGER = "ROOT";
+
+    public static final Pattern EMAIL_PATTERN = Pattern.compile(
+            "^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*"
+            + "@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$",
+            Pattern.CASE_INSENSITIVE);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/ClassList.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/ClassList.java b/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/ClassList.java
new file mode 100644
index 0000000..07528ea
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/ClassList.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.common.lib.annotation;
+
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Retention(RUNTIME)
+public @interface ClassList {
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java b/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java
new file mode 100644
index 0000000..2c1c980
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java
@@ -0,0 +1,36 @@
+/*
+ * 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.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.syncope.common.lib.types.IntMappingType;
+
+@Target({ ElementType.FIELD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FormAttributeField {
+
+    boolean userSearch() default false;
+
+    boolean roleSearch() default false;
+
+    IntMappingType schema() default IntMappingType.UserPlainSchema;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/SchemaList.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/SchemaList.java b/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/SchemaList.java
new file mode 100644
index 0000000..7469731
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/SchemaList.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.annotation;
+
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Retention(RUNTIME)
+public @interface SchemaList {
+
+    boolean extended() default false;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractAttributableMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractAttributableMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractAttributableMod.java
new file mode 100644
index 0000000..aa5d442
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractAttributableMod.java
@@ -0,0 +1,111 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.HashSet;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+/**
+ * Abstract base class for objects that can have attributes removed, added or updated.
+ *
+ * Attributes can be regular attributes, derived attributes, virtual attributes and resources.
+ */
+@XmlType
+public abstract class AbstractAttributableMod extends AbstractBaseBean {
+
+    private static final long serialVersionUID = 3241118574016303198L;
+
+    protected long key;
+
+    protected final Set<AttrMod> plainAttrsToUpdate = new HashSet<>();
+
+    protected final Set<String> plainAttrsToRemove = new HashSet<>();
+
+    protected final Set<String> derAttrsToAdd = new HashSet<>();
+
+    protected final Set<String> derAttrsToRemove = new HashSet<>();
+
+    protected final Set<AttrMod> virAttrsToUpdate = new HashSet<>();
+
+    protected final Set<String> virAttrsToRemove = new HashSet<>();
+
+    public long getKey() {
+        return key;
+    }
+
+    public void setKey(final long key) {
+        this.key = key;
+    }
+
+    @XmlElementWrapper(name = "plainAttrsToRemove")
+    @XmlElement(name = "attribute")
+    @JsonProperty("plainAttrsToRemove")
+    public Set<String> getPlainAttrsToRemove() {
+        return plainAttrsToRemove;
+    }
+
+    @XmlElementWrapper(name = "plainAttrsToUpdate")
+    @XmlElement(name = "attributeMod")
+    @JsonProperty("plainAttrsToUpdate")
+    public Set<AttrMod> getPlainAttrsToUpdate() {
+        return plainAttrsToUpdate;
+    }
+
+    @XmlElementWrapper(name = "derAttrsToAdd")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derAttrsToAdd")
+    public Set<String> getDerAttrsToAdd() {
+        return derAttrsToAdd;
+    }
+
+    @XmlElementWrapper(name = "derAttrsToRemove")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derAttrsToRemove")
+    public Set<String> getDerAttrsToRemove() {
+        return derAttrsToRemove;
+    }
+
+    @XmlElementWrapper(name = "virAttrsToRemove")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virAttrsToRemove")
+    public Set<String> getVirAttrsToRemove() {
+        return virAttrsToRemove;
+    }
+
+    @XmlElementWrapper(name = "virAttrsToUpdate")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virAttrsToUpdate")
+    public Set<AttrMod> getVirAttrsToUpdate() {
+        return virAttrsToUpdate;
+    }
+
+    /**
+     * @return true is all backing Sets are empty.
+     */
+    public boolean isEmpty() {
+        return plainAttrsToUpdate.isEmpty() && plainAttrsToRemove.isEmpty()
+                && derAttrsToAdd.isEmpty() && derAttrsToRemove.isEmpty()
+                && virAttrsToUpdate.isEmpty() && virAttrsToRemove.isEmpty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractSubjectMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractSubjectMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractSubjectMod.java
new file mode 100644
index 0000000..96e2a64
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractSubjectMod.java
@@ -0,0 +1,56 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.HashSet;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public abstract class AbstractSubjectMod extends AbstractAttributableMod {
+
+    private static final long serialVersionUID = -6404459635536484024L;
+
+    protected final Set<String> resourcesToAdd = new HashSet<>();
+
+    protected final Set<String> resourcesToRemove = new HashSet<>();
+
+    @XmlElementWrapper(name = "resourcesToAdd")
+    @XmlElement(name = "resource")
+    @JsonProperty("resourcesToAdd")
+    public Set<String> getResourcesToAdd() {
+        return resourcesToAdd;
+    }
+
+    @XmlElementWrapper(name = "resourcesToRemove")
+    @XmlElement(name = "resource")
+    @JsonProperty("resourcesToRemove")
+    public Set<String> getResourcesToRemove() {
+        return resourcesToRemove;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return super.isEmpty() && resourcesToAdd.isEmpty() && resourcesToRemove.isEmpty();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AttrMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AttrMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AttrMod.java
new file mode 100644
index 0000000..b0cee5b
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AttrMod.java
@@ -0,0 +1,76 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+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
+@XmlType
+public class AttrMod extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -913573979137431406L;
+
+    private String schema;
+
+    private List<String> valuesToBeAdded;
+
+    private List<String> valuesToBeRemoved;
+
+    public AttrMod() {
+        super();
+
+        valuesToBeAdded = new ArrayList<>();
+        valuesToBeRemoved = new ArrayList<>();
+    }
+
+    public String getSchema() {
+        return schema;
+    }
+
+    public void setSchema(final String schema) {
+        this.schema = schema;
+    }
+
+    @XmlElementWrapper(name = "valuesToBeAdded")
+    @XmlElement(name = "value")
+    @JsonProperty("valuesToBeAdded")
+    public List<String> getValuesToBeAdded() {
+        return valuesToBeAdded;
+    }
+
+    @XmlElementWrapper(name = "valuesToBeRemoved")
+    @XmlElement(name = "value")
+    @JsonProperty("valuesToBeRemoved")
+    public List<String> getValuesToBeRemoved() {
+        return valuesToBeRemoved;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return valuesToBeAdded.isEmpty() && valuesToBeRemoved.isEmpty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/MembershipMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/MembershipMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/MembershipMod.java
new file mode 100644
index 0000000..bdcfcbf
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/MembershipMod.java
@@ -0,0 +1,46 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement
+@XmlType
+public class MembershipMod extends AbstractAttributableMod {
+
+    private static final long serialVersionUID = 2511869129977331525L;
+
+    private long role;
+
+    public long getRole() {
+        return role;
+    }
+
+    public void setRole(final long role) {
+        this.role = role;
+    }
+
+    @JsonIgnore
+    @Override
+    public boolean isEmpty() {
+        return super.isEmpty() && role == 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/ReferenceMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/ReferenceMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/ReferenceMod.java
new file mode 100644
index 0000000..e8356c2
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/ReferenceMod.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.mod;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+/**
+ * This class is used to specify the willing to modify an external reference id. Use 'null' ReferenceMod to keep the
+ * current reference id; use a ReferenceMod with a null id to try to reset the reference id; use a ReferenceMod with a
+ * not null id to specify a new reference id.
+ */
+@XmlRootElement(name = "referenceMod")
+@XmlType
+public class ReferenceMod extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -4188817853738067677L;
+
+    private Long key;
+
+    public ReferenceMod() {
+        this.key = null;
+    }
+
+    public ReferenceMod(final Long key) {
+        this.key = key;
+    }
+
+    public Long getKey() {
+        return key;
+    }
+
+    public void setKey(final Long key) {
+        this.key = key;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/ResourceAssociationMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/ResourceAssociationMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/ResourceAssociationMod.java
new file mode 100644
index 0000000..6312349
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/ResourceAssociationMod.java
@@ -0,0 +1,80 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+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;
+import org.apache.syncope.common.lib.wrap.ResourceName;
+
+/**
+ * This class is used to specify the willing to create associations between user and external references.
+ * Password can be provided if required by an assign or provisioning operation.
+ *
+ * @see org.apache.syncope.common.types.ResourceAssociationActionType
+ */
+@XmlRootElement(name = "resourceAssociationMod")
+@XmlType
+public class ResourceAssociationMod extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -4188817853738067678L;
+
+    /**
+     * Target external resources.
+     */
+    private final List<ResourceName> targetResources = new ArrayList<ResourceName>();
+
+    /**
+     * Indicate the willing to change password on target external resources.
+     */
+    private boolean changePwd;
+
+    /**
+     * Indicate the new password to be provisioned on target external resources.
+     */
+    private String password;
+
+    @XmlElementWrapper(name = "resources")
+    @XmlElement(name = "resource")
+    @JsonProperty("resources")
+    public List<ResourceName> getTargetResources() {
+        return targetResources;
+    }
+
+    public boolean isChangePwd() {
+        return changePwd;
+    }
+
+    public void setChangePwd(boolean changePwd) {
+        this.changePwd = changePwd;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/RoleMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/RoleMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/RoleMod.java
new file mode 100644
index 0000000..b1b8f4f
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/RoleMod.java
@@ -0,0 +1,300 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "roleMod")
+@XmlType
+public class RoleMod extends AbstractSubjectMod {
+
+    private static final long serialVersionUID = 7455805264680210747L;
+
+    private String name;
+
+    private ReferenceMod userOwner;
+
+    private ReferenceMod roleOwner;
+
+    private Boolean inheritOwner;
+
+    private Boolean inheritTemplates;
+
+    private Boolean inheritPlainAttrs;
+
+    private Boolean inheritDerAttrs;
+
+    private Boolean inheritVirAttrs;
+
+    private Boolean inheritAccountPolicy;
+
+    private Boolean inheritPasswordPolicy;
+
+    private boolean modEntitlements;
+
+    private final List<String> entitlements = new ArrayList<>();
+
+    private boolean modRAttrTemplates;
+
+    private final List<String> rPlainAttrTemplates = new ArrayList<>();
+
+    private boolean modRDerAttrTemplates;
+
+    private final List<String> rDerAttrTemplates = new ArrayList<>();
+
+    private boolean modRVirAttrTemplates;
+
+    private final List<String> rVirAttrTemplates = new ArrayList<>();
+
+    private boolean modMAttrTemplates;
+
+    private final List<String> mPlainAttrTemplates = new ArrayList<>();
+
+    private boolean modMDerAttrTemplates;
+
+    private final List<String> mDerAttrTemplates = new ArrayList<>();
+
+    private boolean modMVirAttrTemplates;
+
+    private final List<String> mVirAttrTemplates = new ArrayList<>();
+
+    private ReferenceMod passwordPolicy;
+
+    private ReferenceMod accountPolicy;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public ReferenceMod getUserOwner() {
+        return userOwner;
+    }
+
+    public void setUserOwner(final ReferenceMod userOwner) {
+        this.userOwner = userOwner;
+    }
+
+    public ReferenceMod getRoleOwner() {
+        return roleOwner;
+    }
+
+    public void setRoleOwner(final ReferenceMod roleOwner) {
+        this.roleOwner = roleOwner;
+    }
+
+    public Boolean getInheritOwner() {
+        return inheritOwner;
+    }
+
+    public void setInheritOwner(final Boolean inheritOwner) {
+        this.inheritOwner = inheritOwner;
+    }
+
+    public Boolean getInheritTemplates() {
+        return inheritTemplates;
+    }
+
+    public void setInheritTemplates(final Boolean inheritTemplates) {
+        this.inheritTemplates = inheritTemplates;
+    }
+
+    public Boolean getInheritPlainAttrs() {
+        return inheritPlainAttrs;
+    }
+
+    public void setInheritPlainAttrs(final Boolean inheritAttrs) {
+        this.inheritPlainAttrs = inheritAttrs;
+    }
+
+    public Boolean getInheritDerAttrs() {
+        return inheritDerAttrs;
+    }
+
+    public void setInheritDerAttrs(final Boolean inheritDerAttrs) {
+        this.inheritDerAttrs = inheritDerAttrs;
+    }
+
+    public Boolean getInheritVirAttrs() {
+        return inheritVirAttrs;
+    }
+
+    public void setInheritVirAttrs(final Boolean inheritVirAttrs) {
+        this.inheritVirAttrs = inheritVirAttrs;
+    }
+
+    public boolean isModEntitlements() {
+        return modEntitlements;
+    }
+
+    public void setModEntitlements(final boolean modEntitlements) {
+        this.modEntitlements = modEntitlements;
+    }
+
+    @XmlElementWrapper(name = "entitlements")
+    @XmlElement(name = "entitlement")
+    @JsonProperty("entitlements")
+    public List<String> getEntitlements() {
+        return entitlements;
+    }
+
+    public boolean isModRAttrTemplates() {
+        return modRAttrTemplates;
+    }
+
+    public void setModRAttrTemplates(final boolean modRAttrTemplates) {
+        this.modRAttrTemplates = modRAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "rPlainAttrTemplates")
+    @XmlElement(name = "rAttrTemplate")
+    @JsonProperty("rPlainAttrTemplates")
+    public List<String> getRPlainAttrTemplates() {
+        return rPlainAttrTemplates;
+    }
+
+    public boolean isModRDerAttrTemplates() {
+        return modRDerAttrTemplates;
+    }
+
+    public void setModRDerAttrTemplates(final boolean modRDerAttrTemplates) {
+        this.modRDerAttrTemplates = modRDerAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "rDerAttrTemplates")
+    @XmlElement(name = "rDerAttrTemplate")
+    @JsonProperty("rDerAttrTemplates")
+    public List<String> getRDerAttrTemplates() {
+        return rDerAttrTemplates;
+    }
+
+    public boolean isModRVirAttrTemplates() {
+        return modRVirAttrTemplates;
+    }
+
+    public void setModRVirAttrTemplates(final boolean modRVirAttrTemplates) {
+        this.modRVirAttrTemplates = modRVirAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "rVirAttrTemplates")
+    @XmlElement(name = "rVirAttrTemplate")
+    @JsonProperty("rVirAttrTemplates")
+    public List<String> getRVirAttrTemplates() {
+        return rVirAttrTemplates;
+    }
+
+    public boolean isModMAttrTemplates() {
+        return modMAttrTemplates;
+    }
+
+    public void setModMAttrTemplates(final boolean modMAttrTemplates) {
+        this.modMAttrTemplates = modMAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "mPlainAttrTemplates")
+    @XmlElement(name = "mAttrTemplate")
+    @JsonProperty("mPlainAttrTemplates")
+    public List<String> getMPlainAttrTemplates() {
+        return mPlainAttrTemplates;
+    }
+
+    public boolean isModMDerAttrTemplates() {
+        return modMDerAttrTemplates;
+    }
+
+    public void setModMDerAttrTemplates(final boolean modMDerAttrTemplates) {
+        this.modMDerAttrTemplates = modMDerAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "mDerAttrTemplates")
+    @XmlElement(name = "mDerAttrTemplate")
+    @JsonProperty("mDerAttrTemplates")
+    public List<String> getMDerAttrTemplates() {
+        return mDerAttrTemplates;
+    }
+
+    public boolean isModMVirAttrTemplates() {
+        return modMVirAttrTemplates;
+    }
+
+    public void setModMVirAttrTemplates(final boolean modMVirAttrTemplates) {
+        this.modMVirAttrTemplates = modMVirAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "mVirAttrTemplates")
+    @XmlElement(name = "mVirAttrTemplate")
+    @JsonProperty("mVirAttrTemplates")
+    public List<String> getMVirAttrTemplates() {
+        return mVirAttrTemplates;
+    }
+
+    public ReferenceMod getPasswordPolicy() {
+        return passwordPolicy;
+    }
+
+    public void setPasswordPolicy(final ReferenceMod passwordPolicy) {
+        this.passwordPolicy = passwordPolicy;
+    }
+
+    public Boolean getInheritPasswordPolicy() {
+        return inheritPasswordPolicy;
+    }
+
+    public void setInheritPasswordPolicy(final Boolean inheritPasswordPolicy) {
+        this.inheritPasswordPolicy = inheritPasswordPolicy;
+    }
+
+    public ReferenceMod getAccountPolicy() {
+        return accountPolicy;
+    }
+
+    public void setAccountPolicy(final ReferenceMod accountPolicy) {
+        this.accountPolicy = accountPolicy;
+    }
+
+    public Boolean getInheritAccountPolicy() {
+        return inheritAccountPolicy;
+    }
+
+    public void setInheritAccountPolicy(final Boolean inheritAccountPolicy) {
+        this.inheritAccountPolicy = inheritAccountPolicy;
+    }
+
+    @JsonIgnore
+    @Override
+    public boolean isEmpty() {
+        return super.isEmpty() && name == null && userOwner == null && roleOwner == null
+                && inheritTemplates == null && inheritOwner == null
+                && inheritAccountPolicy == null && inheritPasswordPolicy == null
+                && inheritPlainAttrs == null && inheritDerAttrs == null && inheritVirAttrs == null
+                && accountPolicy == null && passwordPolicy == null && entitlements.isEmpty()
+                && rPlainAttrTemplates.isEmpty() && rDerAttrTemplates.isEmpty() && rVirAttrTemplates.isEmpty()
+                && mPlainAttrTemplates.isEmpty() && mDerAttrTemplates.isEmpty() && mVirAttrTemplates.isEmpty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/StatusMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/StatusMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/StatusMod.java
new file mode 100644
index 0000000..57ea366
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/StatusMod.java
@@ -0,0 +1,108 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "statusMod")
+@XmlType
+public class StatusMod extends AbstractBaseBean {
+
+    private static final long serialVersionUID = 3230910033784302656L;
+
+    @XmlEnum
+    @XmlType(name = "statusModType")
+    public enum ModType {
+
+        ACTIVATE,
+        SUSPEND,
+        REACTIVATE;
+
+    }
+
+    /**
+     * Key of user to for which status update is requested.
+     */
+    private long key;
+
+    private ModType type;
+
+    /**
+     * Update token (if required).
+     */
+    private String token;
+
+    /**
+     * Whether update should be performed on internal storage.
+     */
+    private boolean onSyncope = true;
+
+    /**
+     * External resources for which update is needed to be propagated.
+     */
+    private final List<String> resourceNames = new ArrayList<>();
+
+    public long getKey() {
+        return key;
+    }
+
+    public void setKey(long key) {
+        this.key = key;
+    }
+
+    public ModType getType() {
+        return type;
+    }
+
+    public void setType(final ModType type) {
+        this.type = type;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(final String token) {
+        this.token = token;
+    }
+
+    public boolean isOnSyncope() {
+        return onSyncope;
+    }
+
+    public void setOnSyncope(final boolean onSyncope) {
+        this.onSyncope = onSyncope;
+    }
+
+    @XmlElementWrapper(name = "resources")
+    @XmlElement(name = "resource")
+    @JsonProperty("resources")
+    public List<String> getResourceNames() {
+        return resourceNames;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/UserMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/UserMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/UserMod.java
new file mode 100644
index 0000000..0f421be
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/UserMod.java
@@ -0,0 +1,123 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.HashSet;
+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;
+
+@XmlRootElement(name = "userMod")
+@XmlType
+public class UserMod extends AbstractSubjectMod {
+
+    private static final long serialVersionUID = 3081848906558106204L;
+
+    private String password;
+
+    private String username;
+
+    private final Set<MembershipMod> membershipsToAdd;
+
+    private final Set<Long> membershipsToRemove;
+
+    private StatusMod pwdPropRequest;
+
+    private Long securityQuestion;
+
+    private String securityAnswer;
+
+    public UserMod() {
+        super();
+
+        membershipsToAdd = new HashSet<>();
+        membershipsToRemove = new HashSet<>();
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(final String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(final String password) {
+        this.password = password;
+    }
+
+    @XmlElementWrapper(name = "membershipsToAdd")
+    @XmlElement(name = "membership")
+    @JsonProperty("membershipsToAdd")
+    public Set<MembershipMod> getMembershipsToAdd() {
+        return membershipsToAdd;
+    }
+
+    @XmlElementWrapper(name = "membershipsToRemove")
+    @XmlElement(name = "membership")
+    @JsonProperty("membershipsToRemove")
+    public Set<Long> getMembershipsToRemove() {
+        return membershipsToRemove;
+    }
+
+    public StatusMod getPwdPropRequest() {
+        return pwdPropRequest;
+    }
+
+    public void setPwdPropRequest(final StatusMod pwdPropRequest) {
+        this.pwdPropRequest = pwdPropRequest;
+    }
+
+    public Long getSecurityQuestion() {
+        return securityQuestion;
+    }
+
+    public void setSecurityQuestion(final Long securityQuestion) {
+        this.securityQuestion = securityQuestion;
+    }
+
+    public String getSecurityAnswer() {
+        return securityAnswer;
+    }
+
+    public void setSecurityAnswer(final String securityAnswer) {
+        this.securityAnswer = securityAnswer;
+    }
+
+    @JsonIgnore
+    @Override
+    public boolean isEmpty() {
+        return super.isEmpty()
+                && password == null
+                && username == null
+                && membershipsToAdd.isEmpty()
+                && membershipsToRemove.isEmpty()
+                && pwdPropRequest == null
+                && securityQuestion == null
+                && securityAnswer == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/mod/package-info.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/package-info.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/package-info.java
new file mode 100644
index 0000000..866b275
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@XmlSchema(namespace = SyncopeConstants.NAMESPACE)
+package org.apache.syncope.common.lib.mod;
+
+import javax.xml.bind.annotation.XmlSchema;
+import org.apache.syncope.common.lib.SyncopeConstants;

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/package-info.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/package-info.java b/common/lib/src/main/java/org/apache/syncope/common/lib/package-info.java
new file mode 100644
index 0000000..8eac5d5
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+@XmlSchema(namespace = SyncopeConstants.NAMESPACE)
+package org.apache.syncope.common.lib;
+
+import javax.xml.bind.annotation.XmlSchema;

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractReportletConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractReportletConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractReportletConf.java
new file mode 100644
index 0000000..0082591
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractReportletConf.java
@@ -0,0 +1,51 @@
+/*
+ * 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.report;
+
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlType
+@XmlSeeAlso({ StaticReportletConf.class, UserReportletConf.class, RoleReportletConf.class })
+public abstract class AbstractReportletConf extends AbstractBaseBean implements ReportletConf {
+
+    private static final long serialVersionUID = -6130008602014516608L;
+
+    private String name;
+
+    public AbstractReportletConf() {
+        this(StringUtils.EMPTY);
+        setName(getClass().getName());
+    }
+
+    public AbstractReportletConf(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public final String getName() {
+        return name;
+    }
+
+    public final void setName(final String name) {
+        this.name = name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/report/ReportletConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/ReportletConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/ReportletConf.java
new file mode 100644
index 0000000..57bcf52
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/ReportletConf.java
@@ -0,0 +1,32 @@
+/*
+ * 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.report;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+public interface ReportletConf {
+
+    /**
+     * Give name of related reportlet instance.
+     *
+     * @return name of this reportlet instance
+     */
+    String getName();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/report/RoleReportletConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/RoleReportletConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/RoleReportletConf.java
new file mode 100644
index 0000000..9f73d3d
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/RoleReportletConf.java
@@ -0,0 +1,109 @@
+/*
+ * 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.report;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.annotation.FormAttributeField;
+import org.apache.syncope.common.lib.types.IntMappingType;
+
+@XmlRootElement(name = "roleReportletConf")
+@XmlType
+public class RoleReportletConf extends AbstractReportletConf {
+
+    private static final long serialVersionUID = -8488503068032439699L;
+
+    @XmlEnum
+    @XmlType(name = "roleReportletConfFeature")
+    public enum Feature {
+
+        key,
+        name,
+        roleOwner,
+        userOwner,
+        entitlements,
+        users,
+        resources
+
+    }
+
+    @FormAttributeField(userSearch = true)
+    private String matchingCond;
+
+    @FormAttributeField(schema = IntMappingType.RolePlainSchema)
+    private final List<String> plainAttrs = new ArrayList<>();
+
+    @FormAttributeField(schema = IntMappingType.RoleDerivedSchema)
+    private final List<String> derAttrs = new ArrayList<>();
+
+    @FormAttributeField(schema = IntMappingType.RoleVirtualSchema)
+    private final List<String> virAttrs = new ArrayList<>();
+
+    private final List<Feature> features = new ArrayList<>();
+
+    public RoleReportletConf() {
+        super();
+    }
+
+    public RoleReportletConf(final String name) {
+        super(name);
+    }
+
+    @XmlElementWrapper(name = "plainAttributes")
+    @XmlElement(name = "plainAttribute")
+    @JsonProperty("plainAttributes")
+    public List<String> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @XmlElementWrapper(name = "derivedAttributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derivedAttributes")
+    public List<String> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @XmlElementWrapper(name = "virtualAttributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virtualAttributes")
+    public List<String> getVirAttrs() {
+        return virAttrs;
+    }
+
+    @XmlElementWrapper(name = "features")
+    @XmlElement(name = "feature")
+    @JsonProperty("features")
+    public List<Feature> getFeatures() {
+        return features;
+    }
+
+    public String getMatchingCond() {
+        return matchingCond;
+    }
+
+    public void setMatchingCond(final String matchingCond) {
+        this.matchingCond = matchingCond;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
new file mode 100644
index 0000000..9160089
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
@@ -0,0 +1,107 @@
+/*
+ * 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.report;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+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.types.TraceLevel;
+
+@XmlRootElement(name = "staticReportletConf")
+@XmlType
+public class StaticReportletConf extends AbstractReportletConf {
+
+    private static final long serialVersionUID = -4814950086361753689L;
+
+    private String stringField;
+
+    private Long longField;
+
+    private Double doubleField;
+
+    private Date dateField;
+
+    private TraceLevel traceLevel;
+
+    private final List<String> listField = new ArrayList<String>();
+
+    public StaticReportletConf() {
+        super();
+    }
+
+    public StaticReportletConf(final String name) {
+        super(name);
+    }
+
+    public Date getDateField() {
+        return dateField == null
+                ? null
+                : new Date(dateField.getTime());
+    }
+
+    public void setDateField(Date dateField) {
+        this.dateField = dateField == null
+                ? null
+                : new Date(dateField.getTime());
+    }
+
+    public Double getDoubleField() {
+        return doubleField;
+    }
+
+    public void setDoubleField(Double doubleField) {
+        this.doubleField = doubleField;
+    }
+
+    @XmlElementWrapper(name = "listField")
+    @XmlElement(name = "field")
+    @JsonProperty("listField")
+    public List<String> getListField() {
+        return listField;
+    }
+
+    public Long getLongField() {
+        return longField;
+    }
+
+    public void setLongField(Long longField) {
+        this.longField = longField;
+    }
+
+    public String getStringField() {
+        return stringField;
+    }
+
+    public void setStringField(String stringField) {
+        this.stringField = stringField;
+    }
+
+    public TraceLevel getTraceLevel() {
+        return traceLevel;
+    }
+
+    public void setTraceLevel(TraceLevel traceLevel) {
+        this.traceLevel = traceLevel;
+    }
+}