http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
----------------------------------------------------------------------
diff --git 
a/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java 
b/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
deleted file mode 100644
index ebacf04..0000000
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.logic;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.Resource;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.mod.RoleMod;
-import org.apache.syncope.common.lib.to.BulkAction;
-import org.apache.syncope.common.lib.to.BulkActionResult;
-import org.apache.syncope.common.lib.to.PropagationStatus;
-import org.apache.syncope.common.lib.to.RoleTO;
-import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.SubjectType;
-import org.apache.syncope.core.persistence.api.RoleEntitlementUtil;
-import org.apache.syncope.core.persistence.api.dao.NotFoundException;
-import org.apache.syncope.core.persistence.api.dao.RoleDAO;
-import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
-import org.apache.syncope.core.persistence.api.entity.role.Role;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.provisioning.api.AttributableTransformer;
-import org.apache.syncope.core.provisioning.api.RoleProvisioningManager;
-import org.apache.syncope.core.provisioning.api.data.RoleDataBinder;
-import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
-import 
org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
-import org.apache.syncope.core.misc.security.AuthContextUtil;
-import org.apache.syncope.core.misc.security.UnauthorizedRoleException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.transaction.interceptor.TransactionInterceptor;
-
-/**
- * Note that this controller does not extend {@link 
AbstractTransactionalLogic}, hence does not provide any
- * Spring's Transactional logic at class level.
- */
-@Component
-public class RoleLogic extends AbstractSubjectLogic<RoleTO, RoleMod> {
-
-    @Autowired
-    protected RoleDAO roleDAO;
-
-    @Autowired
-    protected UserDAO userDAO;
-
-    @Autowired
-    protected SubjectSearchDAO searchDAO;
-
-    @Autowired
-    protected RoleDataBinder binder;
-
-    @Autowired
-    protected PropagationManager propagationManager;
-
-    @Autowired
-    protected PropagationTaskExecutor taskExecutor;
-
-    @Autowired
-    protected AttributableTransformer attrTransformer;
-
-    @Resource(name = "anonymousUser")
-    protected String anonymousUser;
-
-    @Autowired
-    protected RoleProvisioningManager provisioningManager;
-
-    @PreAuthorize("hasAnyRole('ROLE_READ', 
T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT)")
-    @Transactional(readOnly = true)
-    @Override
-    public RoleTO read(final Long roleKey) {
-        Role role;
-        // bypass role entitlements check
-        if (anonymousUser.equals(AuthContextUtil.getAuthenticatedUsername())) {
-            role = roleDAO.find(roleKey);
-        } else {
-            role = roleDAO.authFetch(roleKey);
-        }
-
-        if (role == null) {
-            throw new NotFoundException("Role " + roleKey);
-        }
-
-        return binder.getRoleTO(role);
-    }
-
-    @PreAuthorize("isAuthenticated() "
-            + "and 
not(hasRole(T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT))")
-    @Transactional(readOnly = true)
-    public RoleTO readSelf(final Long roleKey) {
-        // Explicit search instead of using binder.getRoleFromId() in order to 
bypass auth checks - will do here
-        Role role = roleDAO.find(roleKey);
-        if (role == null) {
-            throw new NotFoundException("Role " + roleKey);
-        }
-
-        Set<Long> ownedRoleIds;
-        User authUser = 
userDAO.find(AuthContextUtil.getAuthenticatedUsername());
-        if (authUser == null) {
-            ownedRoleIds = Collections.<Long>emptySet();
-        } else {
-            ownedRoleIds = authUser.getRoleKeys();
-        }
-
-        Set<Long> allowedRoleIds = 
RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
-        allowedRoleIds.addAll(ownedRoleIds);
-        if (!allowedRoleIds.contains(role.getKey())) {
-            throw new UnauthorizedRoleException(role.getKey());
-        }
-
-        return binder.getRoleTO(role);
-    }
-
-    @PreAuthorize("hasRole('ROLE_READ')")
-    @Transactional(readOnly = true)
-    public RoleTO parent(final Long roleKey) {
-        Role role = roleDAO.authFetch(roleKey);
-
-        Set<Long> allowedRoleIds = 
RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
-        if (role.getParent() != null && 
!allowedRoleIds.contains(role.getParent().getKey())) {
-            throw new UnauthorizedRoleException(role.getParent().getKey());
-        }
-
-        RoleTO result = role.getParent() == null
-                ? null
-                : binder.getRoleTO(role.getParent());
-
-        return result;
-    }
-
-    @PreAuthorize("hasRole('ROLE_READ')")
-    @Transactional(readOnly = true)
-    public List<RoleTO> children(final Long roleKey) {
-        Role role = roleDAO.authFetch(roleKey);
-
-        Set<Long> allowedRoleIds = 
RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
-
-        List<Role> children = roleDAO.findChildren(role);
-        List<RoleTO> childrenTOs = new ArrayList<>(children.size());
-        for (Role child : children) {
-            if (allowedRoleIds.contains(child.getKey())) {
-                childrenTOs.add(binder.getRoleTO(child));
-            }
-        }
-
-        return childrenTOs;
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    @Transactional(readOnly = true, rollbackFor = { Throwable.class })
-    @Override
-    public int count() {
-        return roleDAO.count();
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    @Transactional(readOnly = true)
-    @Override
-    public List<RoleTO> list(final int page, final int size, final 
List<OrderByClause> orderBy) {
-        List<Role> roles = roleDAO.findAll(page, size, orderBy);
-
-        List<RoleTO> roleTOs = new ArrayList<>(roles.size());
-        for (Role role : roles) {
-            roleTOs.add(binder.getRoleTO(role));
-        }
-
-        return roleTOs;
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    @Transactional(readOnly = true, rollbackFor = { Throwable.class })
-    @Override
-    public int searchCount(final SearchCond searchCondition) {
-        final Set<Long> adminRoleIds = 
RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
-        return searchDAO.count(adminRoleIds, searchCondition, 
SubjectType.ROLE);
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    @Transactional(readOnly = true, rollbackFor = { Throwable.class })
-    @Override
-    public List<RoleTO> search(final SearchCond searchCondition, final int 
page, final int size,
-            final List<OrderByClause> orderBy) {
-
-        final List<Role> matchingRoles = searchDAO.search(
-                
RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames()),
-                searchCondition, page, size, orderBy, SubjectType.ROLE);
-
-        final List<RoleTO> result = new ArrayList<>(matchingRoles.size());
-        for (Role role : matchingRoles) {
-            result.add(binder.getRoleTO(role));
-        }
-
-        return result;
-    }
-
-    @PreAuthorize("hasRole('ROLE_CREATE')")
-    public RoleTO create(final RoleTO roleTO) {
-        // Check that this operation is allowed to be performed by caller
-        Set<Long> allowedRoleIds = 
RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
-        if (roleTO.getParent() != 0 && 
!allowedRoleIds.contains(roleTO.getParent())) {
-            throw new UnauthorizedRoleException(roleTO.getParent());
-        }
-
-        // Attributable transformation (if configured)
-        RoleTO actual = attrTransformer.transform(roleTO);
-        LOG.debug("Transformed: {}", actual);
-
-        /*
-         * Actual operations: workflow, propagation
-         */
-        Map.Entry<Long, List<PropagationStatus>> created = 
provisioningManager.create(roleTO);
-        final RoleTO savedTO = binder.getRoleTO(created.getKey());
-        savedTO.getPropagationStatusTOs().addAll(created.getValue());
-        return savedTO;
-    }
-
-    @PreAuthorize("hasRole('ROLE_UPDATE')")
-    @Override
-    public RoleTO update(final RoleMod roleMod) {
-        // Check that this operation is allowed to be performed by caller
-        roleDAO.authFetch(roleMod.getKey());
-
-        // Attribute value transformation (if configured)
-        RoleMod actual = attrTransformer.transform(roleMod);
-        LOG.debug("Transformed: {}", actual);
-
-        Map.Entry<Long, List<PropagationStatus>> updated = 
provisioningManager.update(roleMod);
-
-        final RoleTO updatedTO = binder.getRoleTO(updated.getKey());
-        updatedTO.getPropagationStatusTOs().addAll(updated.getValue());
-        return updatedTO;
-    }
-
-    @PreAuthorize("hasRole('ROLE_DELETE')")
-    @Override
-    public RoleTO delete(final Long roleKey) {
-        List<Role> ownedRoles = roleDAO.findOwnedByRole(roleKey);
-        if (!ownedRoles.isEmpty()) {
-            List<String> owned = new ArrayList<String>(ownedRoles.size());
-            for (Role role : ownedRoles) {
-                owned.add(role.getKey() + " " + role.getName());
-            }
-
-            SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.RoleOwnership);
-            sce.getElements().addAll(owned);
-            throw sce;
-        }
-
-        List<PropagationStatus> statuses = provisioningManager.delete(roleKey);
-
-        RoleTO roleTO = new RoleTO();
-        roleTO.setKey(roleKey);
-
-        roleTO.getPropagationStatusTOs().addAll(statuses);
-
-        return roleTO;
-    }
-
-    @PreAuthorize("(hasRole('ROLE_DELETE') and #bulkAction.operation == 
#bulkAction.operation.DELETE)")
-    public BulkActionResult bulk(final BulkAction bulkAction) {
-        BulkActionResult res = new BulkActionResult();
-
-        if (bulkAction.getOperation() == BulkAction.Type.DELETE) {
-            for (String roleKey : bulkAction.getTargets()) {
-                try {
-                    res.add(delete(Long.valueOf(roleKey)).getKey(), 
BulkActionResult.Status.SUCCESS);
-                } catch (Exception e) {
-                    LOG.error("Error performing delete for role {}", roleKey, 
e);
-                    res.add(roleKey, BulkActionResult.Status.FAILURE);
-                }
-            }
-        } else {
-            LOG.warn("Unsupported bulk action: {}", bulkAction.getOperation());
-        }
-
-        return res;
-    }
-
-    @PreAuthorize("hasRole('ROLE_UPDATE')")
-    @Transactional(rollbackFor = { Throwable.class })
-    @Override
-    public RoleTO unlink(final Long roleKey, final Collection<String> 
resources) {
-        final RoleMod roleMod = new RoleMod();
-        roleMod.setKey(roleKey);
-        roleMod.getResourcesToRemove().addAll(resources);
-        final Long updatedResult = provisioningManager.unlink(roleMod);
-
-        return binder.getRoleTO(updatedResult);
-    }
-
-    @PreAuthorize("hasRole('ROLE_UPDATE')")
-    @Transactional(rollbackFor = { Throwable.class })
-    @Override
-    public RoleTO link(final Long roleKey, final Collection<String> resources) 
{
-        final RoleMod roleMod = new RoleMod();
-        roleMod.setKey(roleKey);
-        roleMod.getResourcesToAdd().addAll(resources);
-        return binder.getRoleTO(provisioningManager.link(roleMod));
-    }
-
-    @PreAuthorize("hasRole('ROLE_UPDATE')")
-    @Transactional(rollbackFor = { Throwable.class })
-    @Override
-    public RoleTO unassign(final Long roleKey, final Collection<String> 
resources) {
-        final RoleMod roleMod = new RoleMod();
-        roleMod.setKey(roleKey);
-        roleMod.getResourcesToRemove().addAll(resources);
-        return update(roleMod);
-    }
-
-    @PreAuthorize("hasRole('ROLE_UPDATE')")
-    @Transactional(rollbackFor = { Throwable.class })
-    @Override
-    public RoleTO assign(
-            final Long roleKey, final Collection<String> resources, final 
boolean changePwd, final String password) {
-
-        final RoleMod userMod = new RoleMod();
-        userMod.setKey(roleKey);
-        userMod.getResourcesToAdd().addAll(resources);
-        return update(userMod);
-    }
-
-    @PreAuthorize("hasRole('ROLE_UPDATE')")
-    @Transactional(rollbackFor = { Throwable.class })
-    @Override
-    public RoleTO deprovision(final Long roleKey, final Collection<String> 
resources) {
-        final Role role = roleDAO.authFetch(roleKey);
-
-        List<PropagationStatus> statuses = 
provisioningManager.deprovision(roleKey, resources);
-
-        final RoleTO updatedTO = binder.getRoleTO(role);
-        updatedTO.getPropagationStatusTOs().addAll(statuses);
-        return updatedTO;
-    }
-
-    @PreAuthorize("hasRole('ROLE_UPDATE')")
-    @Transactional(rollbackFor = { Throwable.class })
-    @Override
-    public RoleTO provision(
-            final Long roleKey, final Collection<String> resources, final 
boolean changePwd, final String password) {
-        final RoleTO original = binder.getRoleTO(roleKey);
-
-        //trick: assign and retrieve propagation statuses ...
-        original.getPropagationStatusTOs().addAll(
-                assign(roleKey, resources, changePwd, 
password).getPropagationStatusTOs());
-
-        // .... rollback.
-        TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
-        return original;
-    }
-
-    @Override
-    protected RoleTO resolveReference(final Method method, final Object... 
args) throws UnresolvedReferenceException {
-        Long key = null;
-
-        if (ArrayUtils.isNotEmpty(args)) {
-            for (int i = 0; key == null && i < args.length; i++) {
-                if (args[i] instanceof Long) {
-                    key = (Long) args[i];
-                } else if (args[i] instanceof RoleTO) {
-                    key = ((RoleTO) args[i]).getKey();
-                } else if (args[i] instanceof RoleMod) {
-                    key = ((RoleMod) args[i]).getKey();
-                }
-            }
-        }
-
-        if ((key != null) && !key.equals(0l)) {
-            try {
-                return binder.getRoleTO(key);
-            } catch (Throwable ignore) {
-                LOG.debug("Unresolved reference", ignore);
-                throw new UnresolvedReferenceException(ignore);
-            }
-        }
-
-        throw new UnresolvedReferenceException();
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
----------------------------------------------------------------------
diff --git 
a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java 
b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
index 153b45a..8084cd4 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
@@ -32,10 +32,10 @@ import 
org.apache.syncope.core.misc.spring.ResourceWithFallbackLoader;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
 import org.apache.syncope.core.provisioning.api.AttributableTransformer;
 import org.apache.syncope.core.provisioning.api.ConnIdBundleManager;
-import org.apache.syncope.core.provisioning.api.RoleProvisioningManager;
+import org.apache.syncope.core.provisioning.api.GroupProvisioningManager;
 import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
 import 
org.apache.syncope.core.provisioning.java.notification.NotificationManagerImpl;
-import org.apache.syncope.core.workflow.api.RoleWorkflowAdapter;
+import org.apache.syncope.core.workflow.api.GroupWorkflowAdapter;
 import org.apache.syncope.core.workflow.api.UserWorkflowAdapter;
 import org.springframework.aop.support.AopUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -62,13 +62,13 @@ public class SyncopeLogic extends AbstractLogic<SyncopeTO> {
     private UserWorkflowAdapter uwfAdapter;
 
     @Autowired
-    private RoleWorkflowAdapter rwfAdapter;
+    private GroupWorkflowAdapter gwfAdapter;
 
     @Autowired
     private UserProvisioningManager uProvisioningManager;
 
     @Autowired
-    private RoleProvisioningManager rProvisioningManager;
+    private GroupProvisioningManager gProvisioningManager;
 
     @Autowired
     private ImplementationClassNamesLoader classNamesLoader;
@@ -110,10 +110,10 @@ public class SyncopeLogic extends 
AbstractLogic<SyncopeTO> {
         
syncopeTO.setAttributableTransformer(attrTransformer.getClass().getName());
 
         
syncopeTO.setUserWorkflowAdapter(AopUtils.getTargetClass(uwfAdapter).getName());
-        
syncopeTO.setRoleWorkflowAdapter(AopUtils.getTargetClass(rwfAdapter).getName());
+        
syncopeTO.setGroupWorkflowAdapter(AopUtils.getTargetClass(gwfAdapter).getName());
 
         
syncopeTO.setUserProvisioningManager(uProvisioningManager.getClass().getName());
-        
syncopeTO.setRoleProvisioningManager(rProvisioningManager.getClass().getName());
+        
syncopeTO.setGroupProvisioningManager(gProvisioningManager.getClass().getName());
 
         syncopeTO.getReportlets().addAll(
                 
classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.REPORTLET));

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
----------------------------------------------------------------------
diff --git 
a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java 
b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
index 17e577b..c86525e 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.logic;
 
-import org.apache.syncope.core.misc.security.UnauthorizedRoleException;
+import org.apache.syncope.core.misc.security.UnauthorizedGroupException;
 import java.lang.reflect.Method;
 import java.security.AccessControlException;
 import java.util.ArrayList;
@@ -41,14 +41,14 @@ import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.SubjectType;
-import org.apache.syncope.core.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.core.persistence.api.GroupEntitlementUtil;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
-import org.apache.syncope.core.persistence.api.dao.RoleDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
-import org.apache.syncope.core.persistence.api.entity.role.Role;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.AttributableTransformer;
 import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
@@ -74,7 +74,7 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, 
UserMod> {
     protected UserDAO userDAO;
 
     @Autowired
-    protected RoleDAO roleDAO;
+    protected GroupDAO groupDAO;
 
     @Autowired
     protected SubjectSearchDAO searchDAO;
@@ -114,14 +114,14 @@ public class UserLogic extends 
AbstractSubjectLogic<UserTO, UserMod> {
     @Transactional(readOnly = true, rollbackFor = { Throwable.class })
     @Override
     public int count() {
-        return 
userDAO.count(RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames()));
+        return 
userDAO.count(GroupEntitlementUtil.getGroupKeys(AuthContextUtil.getOwnedEntitlementNames()));
     }
 
     @PreAuthorize("hasRole('USER_LIST')")
     @Transactional(readOnly = true, rollbackFor = { Throwable.class })
     @Override
     public int searchCount(final SearchCond searchCondition) {
-        return 
searchDAO.count(RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames()),
+        return 
searchDAO.count(GroupEntitlementUtil.getGroupKeys(AuthContextUtil.getOwnedEntitlementNames()),
                 searchCondition, SubjectType.USER);
     }
 
@@ -129,9 +129,9 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, 
UserMod> {
     @Transactional(readOnly = true, rollbackFor = { Throwable.class })
     @Override
     public List<UserTO> list(final int page, final int size, final 
List<OrderByClause> orderBy) {
-        Set<Long> adminRoleIds = 
RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
+        Set<Long> adminGroupIds = 
GroupEntitlementUtil.getGroupKeys(AuthContextUtil.getOwnedEntitlementNames());
 
-        List<User> users = userDAO.findAll(adminRoleIds, page, size, orderBy);
+        List<User> users = userDAO.findAll(adminGroupIds, page, size, orderBy);
         List<UserTO> userTOs = new ArrayList<>(users.size());
         for (User user : users) {
             userTOs.add(binder.getUserTO(user));
@@ -160,8 +160,7 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, 
UserMod> {
     public List<UserTO> search(final SearchCond searchCondition, final int 
page, final int size,
             final List<OrderByClause> orderBy) {
 
-        final List<User> matchingUsers = searchDAO.search(
-                
RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames()),
+        final List<User> matchingUsers = 
searchDAO.search(GroupEntitlementUtil.getGroupKeys(AuthContextUtil.getOwnedEntitlementNames()),
                 searchCondition, page, size, orderBy, SubjectType.USER);
 
         final List<UserTO> result = new ArrayList<>(matchingUsers.size());
@@ -179,14 +178,14 @@ public class UserLogic extends 
AbstractSubjectLogic<UserTO, UserMod> {
 
     @PreAuthorize("hasRole('USER_CREATE')")
     public UserTO create(final UserTO userTO, final boolean storePassword) {
-        Set<Long> requestRoleIds = new 
HashSet<>(userTO.getMemberships().size());
+        Set<Long> requestGroupIds = new 
HashSet<>(userTO.getMemberships().size());
         for (MembershipTO membership : userTO.getMemberships()) {
-            requestRoleIds.add(membership.getRoleId());
+            requestGroupIds.add(membership.getGroupId());
         }
-        Set<Long> adminRoleIds = 
RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
-        requestRoleIds.removeAll(adminRoleIds);
-        if (!requestRoleIds.isEmpty()) {
-            throw new UnauthorizedRoleException(requestRoleIds);
+        Set<Long> adminGroupIds = 
GroupEntitlementUtil.getGroupKeys(AuthContextUtil.getOwnedEntitlementNames());
+        requestGroupIds.removeAll(adminGroupIds);
+        if (!requestGroupIds.isEmpty()) {
+            throw new UnauthorizedGroupException(requestGroupIds);
         }
 
         return doCreate(userTO, storePassword);
@@ -321,14 +320,14 @@ public class UserLogic extends 
AbstractSubjectLogic<UserTO, UserMod> {
     @PreAuthorize("hasRole('USER_DELETE')")
     @Override
     public UserTO delete(final Long key) {
-        List<Role> ownedRoles = roleDAO.findOwnedByUser(key);
-        if (!ownedRoles.isEmpty()) {
-            List<String> owned = new ArrayList<>(ownedRoles.size());
-            for (Role role : ownedRoles) {
-                owned.add(role.getKey() + " " + role.getName());
+        List<Group> ownedGroups = groupDAO.findOwnedByUser(key);
+        if (!ownedGroups.isEmpty()) {
+            List<String> owned = new ArrayList<>(ownedGroups.size());
+            for (Group group : ownedGroups) {
+                owned.add(group.getKey() + " " + group.getName());
             }
 
-            SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.RoleOwnership);
+            SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.GroupOwnership);
             sce.getElements().addAll(owned);
             throw sce;
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java
----------------------------------------------------------------------
diff --git 
a/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java 
b/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java
index c8dcc93..8c6426d 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/WorkflowLogic.java
@@ -22,7 +22,7 @@ import java.io.OutputStream;
 import java.lang.reflect.Method;
 import javax.ws.rs.core.MediaType;
 import org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.core.workflow.api.RoleWorkflowAdapter;
+import org.apache.syncope.core.workflow.api.GroupWorkflowAdapter;
 import org.apache.syncope.core.workflow.api.UserWorkflowAdapter;
 import org.apache.syncope.core.workflow.api.WorkflowAdapter;
 import org.apache.syncope.core.workflow.api.WorkflowDefinitionFormat;
@@ -39,7 +39,7 @@ public class WorkflowLogic extends 
AbstractTransactionalLogic<AbstractBaseBean>
     private UserWorkflowAdapter uwfAdapter;
 
     @Autowired
-    private RoleWorkflowAdapter rwfAdapter;
+    private GroupWorkflowAdapter gwfAdapter;
 
     private void exportDefinition(
             final WorkflowAdapter adapter, final WorkflowDefinitionFormat 
format, final OutputStream os)
@@ -64,10 +64,10 @@ public class WorkflowLogic extends 
AbstractTransactionalLogic<AbstractBaseBean>
 
     @PreAuthorize("hasRole('WORKFLOW_DEF_READ')")
     @Transactional(readOnly = true)
-    public void exportRoleDefinition(final MediaType format, final 
OutputStream os)
+    public void exportGroupDefinition(final MediaType format, final 
OutputStream os)
             throws WorkflowException {
 
-        exportDefinition(rwfAdapter, getFormat(format), os);
+        exportDefinition(gwfAdapter, getFormat(format), os);
     }
 
     private void exportDiagram(final WorkflowAdapter adapter, final 
OutputStream os)
@@ -85,10 +85,10 @@ public class WorkflowLogic extends 
AbstractTransactionalLogic<AbstractBaseBean>
 
     @PreAuthorize("hasRole('WORKFLOW_DEF_READ')")
     @Transactional(readOnly = true)
-    public void exportRoleDiagram(final OutputStream os)
+    public void exportGroupDiagram(final OutputStream os)
             throws WorkflowException {
 
-        exportDiagram(rwfAdapter, os);
+        exportDiagram(gwfAdapter, os);
     }
 
     private void importDefinition(
@@ -103,8 +103,8 @@ public class WorkflowLogic extends 
AbstractTransactionalLogic<AbstractBaseBean>
     }
 
     @PreAuthorize("hasRole('WORKFLOW_DEF_UPDATE')")
-    public void importRoleDefinition(final MediaType format, final String 
definition) {
-        importDefinition(rwfAdapter, getFormat(format), definition);
+    public void importGroupDefinition(final MediaType format, final String 
definition) {
+        importDefinition(gwfAdapter, getFormat(format), definition);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
----------------------------------------------------------------------
diff --git 
a/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
 
b/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
new file mode 100644
index 0000000..38c96c6
--- /dev/null
+++ 
b/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
@@ -0,0 +1,328 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic.report;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.report.GroupReportletConf;
+import org.apache.syncope.common.lib.report.GroupReportletConf.Feature;
+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.GroupTO;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.core.persistence.api.GroupEntitlementUtil;
+import org.apache.syncope.core.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.persistence.api.entity.membership.Membership;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.misc.search.SearchCondConverter;
+import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+@ReportletConfClass(GroupReportletConf.class)
+public class GroupReportlet extends AbstractReportlet<GroupReportletConf> {
+
+    private static final int PAGE_SIZE = 10;
+
+    @Autowired
+    private EntitlementDAO entitlementDAO;
+
+    @Autowired
+    private GroupDAO groupDAO;
+
+    @Autowired
+    private SubjectSearchDAO searchDAO;
+
+    @Autowired
+    private GroupDataBinder groupDataBinder;
+
+    private List<Group> getPagedgroups(final int page) {
+        final Set<Long> adminGroupIds = 
GroupEntitlementUtil.getGroupKeys(entitlementDAO.findAll());
+        final List<Group> result;
+        if (StringUtils.isBlank(conf.getMatchingCond())) {
+            result = groupDAO.findAll();
+        } else {
+            result = searchDAO.search(adminGroupIds, 
SearchCondConverter.convert(conf.getMatchingCond()),
+                    page, PAGE_SIZE, Collections.<OrderByClause>emptyList(), 
SubjectType.GROUP);
+        }
+
+        return result;
+    }
+
+    private int count() {
+        Set<Long> adminGroupIds = 
GroupEntitlementUtil.getGroupKeys(entitlementDAO.findAll());
+
+        return StringUtils.isBlank(conf.getMatchingCond())
+                ? groupDAO.findAll().size()
+                : searchDAO.count(adminGroupIds,
+                        SearchCondConverter.convert(conf.getMatchingCond()), 
SubjectType.GROUP);
+    }
+
+    private void doExtractResources(final ContentHandler handler, final 
AbstractSubjectTO subjectTO)
+            throws SAXException {
+
+        if (subjectTO.getResources().isEmpty()) {
+            LOG.debug("No resources found for {}[{}]", 
subjectTO.getClass().getSimpleName(), subjectTO.getKey());
+        } else {
+            AttributesImpl atts = new AttributesImpl();
+            handler.startElement("", "", "resources", null);
+
+            for (String resourceName : subjectTO.getResources()) {
+                atts.clear();
+
+                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, 
ReportXMLConst.XSD_STRING, resourceName);
+                handler.startElement("", "", "resource", atts);
+                handler.endElement("", "", "resource");
+            }
+
+            handler.endElement("", "", "resources");
+        }
+    }
+
+    private void doExtractAttributes(final ContentHandler handler, final 
AbstractAttributableTO attributableTO,
+            final Collection<String> attrs, final Collection<String> derAttrs, 
final Collection<String> virAttrs)
+            throws SAXException {
+
+        AttributesImpl atts = new AttributesImpl();
+        if (!attrs.isEmpty()) {
+            Map<String, AttrTO> attrMap = attributableTO.getPlainAttrMap();
+
+            handler.startElement("", "", "attributes", null);
+            for (String attrName : attrs) {
+                atts.clear();
+
+                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, 
ReportXMLConst.XSD_STRING, attrName);
+                handler.startElement("", "", "attribute", atts);
+
+                if (attrMap.containsKey(attrName)) {
+                    for (String value : attrMap.get(attrName).getValues()) {
+                        handler.startElement("", "", "value", null);
+                        handler.characters(value.toCharArray(), 0, 
value.length());
+                        handler.endElement("", "", "value");
+                    }
+                } else {
+                    LOG.debug("{} not found for {}[{}]", attrName,
+                            attributableTO.getClass().getSimpleName(), 
attributableTO.getKey());
+                }
+
+                handler.endElement("", "", "attribute");
+            }
+            handler.endElement("", "", "attributes");
+        }
+
+        if (!derAttrs.isEmpty()) {
+            Map<String, AttrTO> derAttrMap = attributableTO.getDerAttrMap();
+
+            handler.startElement("", "", "derivedAttributes", null);
+            for (String attrName : derAttrs) {
+                atts.clear();
+
+                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, 
ReportXMLConst.XSD_STRING, attrName);
+                handler.startElement("", "", "derivedAttribute", atts);
+
+                if (derAttrMap.containsKey(attrName)) {
+                    for (String value : derAttrMap.get(attrName).getValues()) {
+                        handler.startElement("", "", "value", null);
+                        handler.characters(value.toCharArray(), 0, 
value.length());
+                        handler.endElement("", "", "value");
+                    }
+                } else {
+                    LOG.debug("{} not found for {}[{}]", attrName,
+                            attributableTO.getClass().getSimpleName(), 
attributableTO.getKey());
+                }
+
+                handler.endElement("", "", "derivedAttribute");
+            }
+            handler.endElement("", "", "derivedAttributes");
+        }
+
+        if (!virAttrs.isEmpty()) {
+            Map<String, AttrTO> virAttrMap = attributableTO.getVirAttrMap();
+
+            handler.startElement("", "", "virtualAttributes", null);
+            for (String attrName : virAttrs) {
+                atts.clear();
+
+                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, 
ReportXMLConst.XSD_STRING, attrName);
+                handler.startElement("", "", "virtualAttribute", atts);
+
+                if (virAttrMap.containsKey(attrName)) {
+                    for (String value : virAttrMap.get(attrName).getValues()) {
+                        handler.startElement("", "", "value", null);
+                        handler.characters(value.toCharArray(), 0, 
value.length());
+                        handler.endElement("", "", "value");
+                    }
+                } else {
+                    LOG.debug("{} not found for {}[{}]", attrName,
+                            attributableTO.getClass().getSimpleName(), 
attributableTO.getKey());
+                }
+
+                handler.endElement("", "", "virtualAttribute");
+            }
+            handler.endElement("", "", "virtualAttributes");
+        }
+    }
+
+    private void doExtract(final ContentHandler handler, final List<Group> 
groups)
+            throws SAXException, ReportException {
+
+        AttributesImpl atts = new AttributesImpl();
+        for (Group group : groups) {
+            atts.clear();
+
+            for (Feature feature : conf.getFeatures()) {
+                String type = null;
+                String value = null;
+                switch (feature) {
+                    case key:
+                        type = ReportXMLConst.XSD_LONG;
+                        value = String.valueOf(group.getKey());
+                        break;
+
+                    case name:
+                        type = ReportXMLConst.XSD_STRING;
+                        value = String.valueOf(group.getName());
+                        break;
+
+                    case groupOwner:
+                        type = ReportXMLConst.XSD_LONG;
+                        value = String.valueOf(group.getGroupOwner());
+                        break;
+
+                    case userOwner:
+                        type = ReportXMLConst.XSD_LONG;
+                        value = String.valueOf(group.getUserOwner());
+                        break;
+
+                    default:
+                }
+
+                if (type != null && value != null) {
+                    atts.addAttribute("", "", feature.name(), type, value);
+                }
+            }
+
+            handler.startElement("", "", "group", atts);
+
+            // Using GroupTO for attribute values, since the conversion logic 
of
+            // values to String is already encapsulated there
+            GroupTO groupTO = groupDataBinder.getGroupTO(group);
+
+            doExtractAttributes(handler, groupTO, conf.getPlainAttrs(), 
conf.getDerAttrs(), conf.getVirAttrs());
+
+            if (conf.getFeatures().contains(Feature.entitlements)) {
+                handler.startElement("", "", "entitlements", null);
+
+                for (String ent : groupTO.getEntitlements()) {
+                    atts.clear();
+
+                    atts.addAttribute("", "", "id", ReportXMLConst.XSD_STRING, 
String.valueOf(ent));
+
+                    handler.startElement("", "", "entitlement", atts);
+                    handler.endElement("", "", "entitlement");
+                }
+
+                handler.endElement("", "", "entitlements");
+            }
+            // to get resources associated to a group
+            if (conf.getFeatures().contains(Feature.resources)) {
+                doExtractResources(handler, groupTO);
+            }
+            //to get users asscoiated to a group is preferred GroupDAO to 
GroupTO
+            if (conf.getFeatures().contains(Feature.users)) {
+                handler.startElement("", "", "users", null);
+
+                for (Membership memb : groupDAO.findMemberships(group)) {
+                    atts.clear();
+
+                    atts.addAttribute("", "", "key", ReportXMLConst.XSD_LONG,
+                            String.valueOf(memb.getUser().getKey()));
+                    atts.addAttribute("", "", "username", 
ReportXMLConst.XSD_STRING,
+                            String.valueOf(memb.getUser().getUsername()));
+
+                    handler.startElement("", "", "user", atts);
+                    handler.endElement("", "", "user");
+                }
+
+                handler.endElement("", "", "users");
+            }
+
+            handler.endElement("", "", "group");
+        }
+    }
+
+    private void doExtractConf(final ContentHandler handler) throws 
SAXException {
+        if (conf == null) {
+            LOG.debug("Report configuration is not present");
+        }
+
+        AttributesImpl atts = new AttributesImpl();
+        handler.startElement("", "", "configurations", null);
+        handler.startElement("", "", "groupAttributes", atts);
+
+        for (Feature feature : conf.getFeatures()) {
+            atts.clear();
+            handler.startElement("", "", "feature", atts);
+            handler.characters(feature.name().toCharArray(), 0, 
feature.name().length());
+            handler.endElement("", "", "feature");
+        }
+
+        for (String attr : conf.getPlainAttrs()) {
+            atts.clear();
+            handler.startElement("", "", "attribute", atts);
+            handler.characters(attr.toCharArray(), 0, attr.length());
+            handler.endElement("", "", "attribute");
+        }
+
+        for (String derAttr : conf.getDerAttrs()) {
+            atts.clear();
+            handler.startElement("", "", "derAttribute", atts);
+            handler.characters(derAttr.toCharArray(), 0, derAttr.length());
+            handler.endElement("", "", "derAttribute");
+        }
+
+        for (String virAttr : conf.getVirAttrs()) {
+            atts.clear();
+            handler.startElement("", "", "virAttribute", atts);
+            handler.characters(virAttr.toCharArray(), 0, virAttr.length());
+            handler.endElement("", "", "virAttribute");
+        }
+
+        handler.endElement("", "", "groupAttributes");
+        handler.endElement("", "", "configurations");
+    }
+
+    @Override
+    protected void doExtract(final ContentHandler handler) throws 
SAXException, ReportException {
+        doExtractConf(handler);
+        for (int i = 1; i <= (count() / PAGE_SIZE) + 1; i++) {
+            doExtract(handler, getPagedgroups(i));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/java/org/apache/syncope/core/logic/report/RoleReportlet.java
----------------------------------------------------------------------
diff --git 
a/core/logic/src/main/java/org/apache/syncope/core/logic/report/RoleReportlet.java
 
b/core/logic/src/main/java/org/apache/syncope/core/logic/report/RoleReportlet.java
deleted file mode 100644
index 5bada5d..0000000
--- 
a/core/logic/src/main/java/org/apache/syncope/core/logic/report/RoleReportlet.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.logic.report;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.report.RoleReportletConf;
-import org.apache.syncope.common.lib.report.RoleReportletConf.Feature;
-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.RoleTO;
-import org.apache.syncope.common.lib.types.SubjectType;
-import org.apache.syncope.core.persistence.api.RoleEntitlementUtil;
-import org.apache.syncope.core.persistence.api.dao.EntitlementDAO;
-import org.apache.syncope.core.persistence.api.dao.RoleDAO;
-import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
-import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.entity.membership.Membership;
-import org.apache.syncope.core.persistence.api.entity.role.Role;
-import org.apache.syncope.core.provisioning.java.data.RoleDataBinderImpl;
-import org.apache.syncope.core.misc.search.SearchCondConverter;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-
-@ReportletConfClass(RoleReportletConf.class)
-public class RoleReportlet extends AbstractReportlet<RoleReportletConf> {
-
-    private static final int PAGE_SIZE = 10;
-
-    @Autowired
-    private EntitlementDAO entitlementDAO;
-
-    @Autowired
-    private RoleDAO roleDAO;
-
-    @Autowired
-    private SubjectSearchDAO searchDAO;
-
-    @Autowired
-    private RoleDataBinderImpl roleDataBinder;
-
-    private List<Role> getPagedRoles(final int page) {
-        final Set<Long> adminRoleIds = 
RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll());
-        final List<Role> result;
-        if (StringUtils.isBlank(conf.getMatchingCond())) {
-            result = roleDAO.findAll();
-        } else {
-            result = searchDAO.search(adminRoleIds, 
SearchCondConverter.convert(conf.getMatchingCond()),
-                    page, PAGE_SIZE, Collections.<OrderByClause>emptyList(), 
SubjectType.ROLE);
-        }
-
-        return result;
-    }
-
-    private int count() {
-        Set<Long> adminRoleIds = 
RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll());
-
-        return StringUtils.isBlank(conf.getMatchingCond())
-                ? roleDAO.findAll().size()
-                : searchDAO.count(adminRoleIds, 
SearchCondConverter.convert(conf.getMatchingCond()), SubjectType.ROLE);
-    }
-
-    private void doExtractResources(final ContentHandler handler, final 
AbstractSubjectTO subjectTO)
-            throws SAXException {
-
-        if (subjectTO.getResources().isEmpty()) {
-            LOG.debug("No resources found for {}[{}]", 
subjectTO.getClass().getSimpleName(), subjectTO.getKey());
-        } else {
-            AttributesImpl atts = new AttributesImpl();
-            handler.startElement("", "", "resources", null);
-
-            for (String resourceName : subjectTO.getResources()) {
-                atts.clear();
-
-                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, 
ReportXMLConst.XSD_STRING, resourceName);
-                handler.startElement("", "", "resource", atts);
-                handler.endElement("", "", "resource");
-            }
-
-            handler.endElement("", "", "resources");
-        }
-    }
-
-    private void doExtractAttributes(final ContentHandler handler, final 
AbstractAttributableTO attributableTO,
-            final Collection<String> attrs, final Collection<String> derAttrs, 
final Collection<String> virAttrs)
-            throws SAXException {
-
-        AttributesImpl atts = new AttributesImpl();
-        if (!attrs.isEmpty()) {
-            Map<String, AttrTO> attrMap = attributableTO.getPlainAttrMap();
-
-            handler.startElement("", "", "attributes", null);
-            for (String attrName : attrs) {
-                atts.clear();
-
-                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, 
ReportXMLConst.XSD_STRING, attrName);
-                handler.startElement("", "", "attribute", atts);
-
-                if (attrMap.containsKey(attrName)) {
-                    for (String value : attrMap.get(attrName).getValues()) {
-                        handler.startElement("", "", "value", null);
-                        handler.characters(value.toCharArray(), 0, 
value.length());
-                        handler.endElement("", "", "value");
-                    }
-                } else {
-                    LOG.debug("{} not found for {}[{}]", attrName,
-                            attributableTO.getClass().getSimpleName(), 
attributableTO.getKey());
-                }
-
-                handler.endElement("", "", "attribute");
-            }
-            handler.endElement("", "", "attributes");
-        }
-
-        if (!derAttrs.isEmpty()) {
-            Map<String, AttrTO> derAttrMap = attributableTO.getDerAttrMap();
-
-            handler.startElement("", "", "derivedAttributes", null);
-            for (String attrName : derAttrs) {
-                atts.clear();
-
-                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, 
ReportXMLConst.XSD_STRING, attrName);
-                handler.startElement("", "", "derivedAttribute", atts);
-
-                if (derAttrMap.containsKey(attrName)) {
-                    for (String value : derAttrMap.get(attrName).getValues()) {
-                        handler.startElement("", "", "value", null);
-                        handler.characters(value.toCharArray(), 0, 
value.length());
-                        handler.endElement("", "", "value");
-                    }
-                } else {
-                    LOG.debug("{} not found for {}[{}]", attrName,
-                            attributableTO.getClass().getSimpleName(), 
attributableTO.getKey());
-                }
-
-                handler.endElement("", "", "derivedAttribute");
-            }
-            handler.endElement("", "", "derivedAttributes");
-        }
-
-        if (!virAttrs.isEmpty()) {
-            Map<String, AttrTO> virAttrMap = attributableTO.getVirAttrMap();
-
-            handler.startElement("", "", "virtualAttributes", null);
-            for (String attrName : virAttrs) {
-                atts.clear();
-
-                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, 
ReportXMLConst.XSD_STRING, attrName);
-                handler.startElement("", "", "virtualAttribute", atts);
-
-                if (virAttrMap.containsKey(attrName)) {
-                    for (String value : virAttrMap.get(attrName).getValues()) {
-                        handler.startElement("", "", "value", null);
-                        handler.characters(value.toCharArray(), 0, 
value.length());
-                        handler.endElement("", "", "value");
-                    }
-                } else {
-                    LOG.debug("{} not found for {}[{}]", attrName,
-                            attributableTO.getClass().getSimpleName(), 
attributableTO.getKey());
-                }
-
-                handler.endElement("", "", "virtualAttribute");
-            }
-            handler.endElement("", "", "virtualAttributes");
-        }
-    }
-
-    private void doExtract(final ContentHandler handler, final List<Role> 
roles)
-            throws SAXException, ReportException {
-
-        AttributesImpl atts = new AttributesImpl();
-        for (Role role : roles) {
-            atts.clear();
-
-            for (Feature feature : conf.getFeatures()) {
-                String type = null;
-                String value = null;
-                switch (feature) {
-                    case key:
-                        type = ReportXMLConst.XSD_LONG;
-                        value = String.valueOf(role.getKey());
-                        break;
-
-                    case name:
-                        type = ReportXMLConst.XSD_STRING;
-                        value = String.valueOf(role.getName());
-                        break;
-
-                    case roleOwner:
-                        type = ReportXMLConst.XSD_LONG;
-                        value = String.valueOf(role.getRoleOwner());
-                        break;
-
-                    case userOwner:
-                        type = ReportXMLConst.XSD_LONG;
-                        value = String.valueOf(role.getUserOwner());
-                        break;
-
-                    default:
-                }
-
-                if (type != null && value != null) {
-                    atts.addAttribute("", "", feature.name(), type, value);
-                }
-            }
-
-            handler.startElement("", "", "role", atts);
-
-            // Using RoleTO for attribute values, since the conversion logic of
-            // values to String is already encapsulated there
-            RoleTO roleTO = roleDataBinder.getRoleTO(role);
-
-            doExtractAttributes(handler, roleTO, conf.getPlainAttrs(), 
conf.getDerAttrs(), conf.getVirAttrs());
-
-            if (conf.getFeatures().contains(Feature.entitlements)) {
-                handler.startElement("", "", "entitlements", null);
-
-                for (String ent : roleTO.getEntitlements()) {
-                    atts.clear();
-
-                    atts.addAttribute("", "", "id", ReportXMLConst.XSD_STRING, 
String.valueOf(ent));
-
-                    handler.startElement("", "", "entitlement", atts);
-                    handler.endElement("", "", "entitlement");
-                }
-
-                handler.endElement("", "", "entitlements");
-            }
-            // to get resources associated to a role
-            if (conf.getFeatures().contains(Feature.resources)) {
-                doExtractResources(handler, roleTO);
-            }
-            //to get users asscoiated to a role is preferred RoleDAO to RoleTO
-            if (conf.getFeatures().contains(Feature.users)) {
-                handler.startElement("", "", "users", null);
-
-                for (Membership memb : roleDAO.findMemberships(role)) {
-                    atts.clear();
-
-                    atts.addAttribute("", "", "key", ReportXMLConst.XSD_LONG,
-                            String.valueOf(memb.getUser().getKey()));
-                    atts.addAttribute("", "", "username", 
ReportXMLConst.XSD_STRING,
-                            String.valueOf(memb.getUser().getUsername()));
-
-                    handler.startElement("", "", "user", atts);
-                    handler.endElement("", "", "user");
-                }
-
-                handler.endElement("", "", "users");
-            }
-
-            handler.endElement("", "", "role");
-        }
-    }
-
-    private void doExtractConf(final ContentHandler handler) throws 
SAXException {
-        if (conf == null) {
-            LOG.debug("Report configuration is not present");
-        }
-
-        AttributesImpl atts = new AttributesImpl();
-        handler.startElement("", "", "configurations", null);
-        handler.startElement("", "", "roleAttributes", atts);
-
-        for (Feature feature : conf.getFeatures()) {
-            atts.clear();
-            handler.startElement("", "", "feature", atts);
-            handler.characters(feature.name().toCharArray(), 0, 
feature.name().length());
-            handler.endElement("", "", "feature");
-        }
-
-        for (String attr : conf.getPlainAttrs()) {
-            atts.clear();
-            handler.startElement("", "", "attribute", atts);
-            handler.characters(attr.toCharArray(), 0, attr.length());
-            handler.endElement("", "", "attribute");
-        }
-
-        for (String derAttr : conf.getDerAttrs()) {
-            atts.clear();
-            handler.startElement("", "", "derAttribute", atts);
-            handler.characters(derAttr.toCharArray(), 0, derAttr.length());
-            handler.endElement("", "", "derAttribute");
-        }
-
-        for (String virAttr : conf.getVirAttrs()) {
-            atts.clear();
-            handler.startElement("", "", "virAttribute", atts);
-            handler.characters(virAttr.toCharArray(), 0, virAttr.length());
-            handler.endElement("", "", "virAttribute");
-        }
-
-        handler.endElement("", "", "roleAttributes");
-        handler.endElement("", "", "configurations");
-    }
-
-    @Override
-    protected void doExtract(final ContentHandler handler) throws 
SAXException, ReportException {
-        doExtractConf(handler);
-        for (int i = 1; i <= (count() / PAGE_SIZE) + 1; i++) {
-            doExtract(handler, getPagedRoles(i));
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
----------------------------------------------------------------------
diff --git 
a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
 
b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
index 76efe89..f0023fc 100644
--- 
a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
+++ 
b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
@@ -32,7 +32,7 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.SubjectType;
-import org.apache.syncope.core.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.core.persistence.api.GroupEntitlementUtil;
 import org.apache.syncope.core.persistence.api.dao.EntitlementDAO;
 import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
@@ -41,7 +41,7 @@ import 
org.apache.syncope.core.persistence.api.entity.membership.Membership;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.misc.search.SearchCondConverter;
 import org.apache.syncope.core.misc.DataFormat;
-import org.apache.syncope.core.provisioning.api.data.RoleDataBinder;
+import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
 import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.xml.sax.ContentHandler;
@@ -66,16 +66,16 @@ public class UserReportlet extends 
AbstractReportlet<UserReportletConf> {
     private UserDataBinder userDataBinder;
 
     @Autowired
-    private RoleDataBinder roleDataBinder;
+    private GroupDataBinder groupDataBinder;
 
     private List<User> getPagedUsers(final int page) {
-        final Set<Long> adminRoleIds = 
RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll());
+        final Set<Long> adminGroupIds = 
GroupEntitlementUtil.getGroupKeys(entitlementDAO.findAll());
 
         final List<User> result;
         if (StringUtils.isBlank(conf.getMatchingCond())) {
-            result = userDAO.findAll(adminRoleIds, page, PAGE_SIZE);
+            result = userDAO.findAll(adminGroupIds, page, PAGE_SIZE);
         } else {
-            result = searchDAO.search(adminRoleIds, 
SearchCondConverter.convert(conf.getMatchingCond()),
+            result = searchDAO.search(adminGroupIds, 
SearchCondConverter.convert(conf.getMatchingCond()),
                     page, PAGE_SIZE, Collections.<OrderByClause>emptyList(), 
SubjectType.USER);
         }
 
@@ -83,11 +83,11 @@ public class UserReportlet extends 
AbstractReportlet<UserReportletConf> {
     }
 
     private int count() {
-        Set<Long> adminRoleIds = 
RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll());
+        Set<Long> adminGroupIds = 
GroupEntitlementUtil.getGroupKeys(entitlementDAO.findAll());
 
         return StringUtils.isBlank(conf.getMatchingCond())
-                ? userDAO.count(adminRoleIds)
-                : searchDAO.count(adminRoleIds, 
SearchCondConverter.convert(conf.getMatchingCond()), SubjectType.USER);
+                ? userDAO.count(adminGroupIds)
+                : searchDAO.count(adminGroupIds, 
SearchCondConverter.convert(conf.getMatchingCond()), SubjectType.USER);
     }
 
     private void doExtractResources(final ContentHandler handler, final 
AbstractSubjectTO subjectTO)
@@ -280,20 +280,20 @@ public class UserReportlet extends 
AbstractReportlet<UserReportletConf> {
                     atts.clear();
 
                     atts.addAttribute("", "", "id", ReportXMLConst.XSD_LONG, 
String.valueOf(memb.getKey()));
-                    atts.addAttribute("", "", "roleId", 
ReportXMLConst.XSD_LONG, String.valueOf(memb.getRoleId()));
-                    atts.addAttribute("", "", "roleName", 
ReportXMLConst.XSD_STRING, String.valueOf(memb.getRoleName()));
+                    atts.addAttribute("", "", "groupId", 
ReportXMLConst.XSD_LONG, String.valueOf(memb.getGroupId()));
+                    atts.addAttribute("", "", "groupName", 
ReportXMLConst.XSD_STRING, String.valueOf(memb.getGroupName()));
                     handler.startElement("", "", "membership", atts);
 
                     doExtractAttributes(handler, memb, 
memb.getPlainAttrMap().keySet(), memb.getDerAttrMap()
                             .keySet(), memb.getVirAttrMap().keySet());
 
                     if (conf.getFeatures().contains(Feature.resources)) {
-                        Membership actualMemb = 
user.getMembership(memb.getRoleId());
+                        Membership actualMemb = 
user.getMembership(memb.getGroupId());
                         if (actualMemb == null) {
-                            LOG.warn("Unexpected: cannot find membership for 
role {} for user {}", memb.getRoleId(),
+                            LOG.warn("Unexpected: cannot find membership for 
group {} for user {}", memb.getGroupId(),
                                     user);
                         } else {
-                            doExtractResources(handler, 
roleDataBinder.getRoleTO(actualMemb.getRole()));
+                            doExtractResources(handler, 
groupDataBinder.getGroupTO(actualMemb.getGroup()));
                         }
                     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/resources/report/groupReportlet2csv.xsl
----------------------------------------------------------------------
diff --git a/core/logic/src/main/resources/report/groupReportlet2csv.xsl 
b/core/logic/src/main/resources/report/groupReportlet2csv.xsl
new file mode 100644
index 0000000..06730dc
--- /dev/null
+++ b/core/logic/src/main/resources/report/groupReportlet2csv.xsl
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+  
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
+                version="1.0">
+
+  <xsl:variable name="delimiter" select="';'"/>
+  
+  <xsl:template 
match="reportlet[@class='org.apache.syncope.core.report.GroupReportlet']">
+    
+    <xsl:call-template name="header">
+      <xsl:with-param name="node" select="configurations/groupAttributes"/>
+    </xsl:call-template>
+    <xsl:for-each select="group">
+      <xsl:call-template name="groupAttributes">
+        <xsl:with-param name="header" 
select="../configurations/groupAttributes"/>
+        <xsl:with-param name="attrs" select="."/>
+      </xsl:call-template>
+      <xsl:text>&#10;</xsl:text>
+    </xsl:for-each>
+  </xsl:template>
+  
+  <xsl:template name="header">
+    <xsl:param name="node"/>  
+    <xsl:for-each select="$node/*">
+      <xsl:value-of select="text()"/>   
+      <xsl:if test="position() != last()">
+        <xsl:value-of select="$delimiter"/>
+      </xsl:if>
+    </xsl:for-each>
+    <xsl:text>&#10;</xsl:text>
+  </xsl:template>
+    
+  <xsl:template name="groupAttributes">
+    <xsl:param name="header"/>
+    <xsl:param name="attrs"/>
+    
+    <xsl:for-each select="$header/*">
+      <xsl:variable name="nameAttr" select="text()"/>
+      
+      <xsl:choose> 
+        <xsl:when test="string-length($attrs/@*[name()=$nameAttr]) &gt; 0">
+          <xsl:variable name="groupAttr" select="$attrs/@*[name()=$nameAttr]"/>
+          <xsl:text>"</xsl:text>
+          <xsl:value-of select="$groupAttr/."/>
+          <xsl:text>"</xsl:text>
+        </xsl:when>
+        <xsl:when 
test="name($attrs/*[name(.)=$nameAttr]/*[name(.)='entitlement']) 
+                        and count($attrs/*[name(.)=$nameAttr]/node()) &gt; 0">
+          <xsl:text>"</xsl:text>       
+          <xsl:for-each select="$attrs/*/entitlement">
+            <xsl:variable name="value" select="@id"/>
+            <xsl:value-of select="$value"/>
+            <xsl:if test="position() != last()">
+              <xsl:value-of select="$delimiter"/>
+            </xsl:if>
+          </xsl:for-each>
+          <xsl:text>"</xsl:text>
+        </xsl:when>
+        <xsl:when 
test="name($attrs/*[name(.)=$nameAttr]/*[name(.)='resource']) 
+                        and count($attrs/*[name(.)=$nameAttr]/node()) &gt; 0">
+          <xsl:text>"</xsl:text>       
+          <xsl:for-each select="$attrs/*/resource">
+            <xsl:variable name="value" select="@name"/>
+            <xsl:value-of select="$value"/>
+            <xsl:if test="position() != last()">
+              <xsl:value-of select="$delimiter"/>
+            </xsl:if>
+          </xsl:for-each>
+          <xsl:text>"</xsl:text>
+        </xsl:when>
+        <xsl:when test="name($attrs/*[name(.)=$nameAttr]/*[name(.)='user']) 
+                        and count($attrs/*[name(.)=$nameAttr]/node()) &gt; 0">
+          <xsl:text>"</xsl:text>       
+          <xsl:for-each select="$attrs/*/user">
+            <xsl:variable name="value" select="@userUsername"/>
+            <xsl:value-of select="$value"/>
+            <xsl:if test="position() != last()">
+              <xsl:value-of select="$delimiter"/>
+            </xsl:if>
+          </xsl:for-each>
+          <xsl:text>"</xsl:text>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:text>"</xsl:text>
+          <xsl:if 
test="string-length($attrs/*/*[@name=$nameAttr]/value/text()) &gt; 0"> 
+            <xsl:variable name="value" 
select="$attrs/*/*[@name=$nameAttr]/value/text()"/>
+            <xsl:value-of select="$value"/>
+          </xsl:if>
+          <xsl:text>"</xsl:text>
+        </xsl:otherwise>
+      </xsl:choose>
+      <xsl:if test="position() != last()">
+        <xsl:value-of select="$delimiter"/>
+      </xsl:if>
+    
+    </xsl:for-each>
+  </xsl:template>
+  
+</xsl:stylesheet>
+

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/resources/report/groupReportlet2fo.xsl
----------------------------------------------------------------------
diff --git a/core/logic/src/main/resources/report/groupReportlet2fo.xsl 
b/core/logic/src/main/resources/report/groupReportlet2fo.xsl
new file mode 100644
index 0000000..c83eb31
--- /dev/null
+++ b/core/logic/src/main/resources/report/groupReportlet2fo.xsl
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
+                xmlns:fo="http://www.w3.org/1999/XSL/Format";
+                version="1.0">
+
+  <xsl:template 
match="reportlet[@class='org.apache.syncope.core.report.GroupReportlet']">
+   
+    <fo:block font-size="16pt" font-weight="bold" space-after="0.5cm" 
space-before="5mm">Reportlet: <xsl:value-of select="@name"/></fo:block>
+        
+    <xsl:for-each select="group">
+      <fo:block font-size="14pt" font-weight="bold" space-before="15mm" 
space-after="5mm" background-color="(#8888ff)">Group <xsl:value-of 
select="@name"/></fo:block>
+      <fo:table table-layout="fixed" space-after="7mm">
+        <fo:table-column/>
+        <fo:table-column/>
+        <fo:table-body>
+          <fo:table-row background-color="(#ccccff)">
+            <fo:table-cell>
+              <fo:block>Id:</fo:block>
+            </fo:table-cell>
+            <fo:table-cell>
+              <fo:block font-style="italic">
+                <xsl:value-of select="@id"/>
+              </fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <xsl:if test="@groupOwner != 'null'">
+            <fo:table-row background-color="(#ccccff)">
+              <fo:table-cell>
+                <fo:block>Group Owner:</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block font-style="italic">
+                  <xsl:value-of select="@groupOwner"/>
+                </fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+          </xsl:if>
+          <xsl:if test="@userOwner != 'null'">
+            <fo:table-row background-color="(#ccccff)">
+              <fo:table-cell>
+                <fo:block>Last Login Date:</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block font-style="italic">
+                  <xsl:value-of select="@userOwner"/>
+                </fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+          </xsl:if>
+        </fo:table-body>
+      </fo:table>
+      <xsl:choose>
+        <xsl:when test="string-length(attributes/attribute) &gt; 0">
+          <xsl:call-template name="attributes">
+            <xsl:with-param name="label">Attributes</xsl:with-param>
+            <xsl:with-param name="node" select="attributes/attribute"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <fo:block color="red" font-size="9pt" space-after="3mm">THIS GROUP 
HASN'T ANY ATTRIBUTE</fo:block>
+        </xsl:otherwise>
+      </xsl:choose>
+      
+      <xsl:choose>
+        <xsl:when test="string-length(derivedAttributes/derivedAttribute) &gt; 
0">
+          <xsl:call-template name="attributes">
+            <xsl:with-param name="label">Derived Attributes</xsl:with-param>
+            <xsl:with-param name="node" 
select="derivedAttributes/derivedAttribute"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <fo:block color="red" font-size="9pt" space-after="3mm">THIS GROUP 
HASN'T ANY DERIVED ATTRIBUTE</fo:block>
+        </xsl:otherwise>
+      </xsl:choose>
+      <xsl:choose>
+        <xsl:when test="string-length(virtualAttributes/virtualAttribute) &gt; 
0">
+          <xsl:call-template name="attributes">
+            <xsl:with-param name="label">Virtual Attributes</xsl:with-param>
+            <xsl:with-param name="node" 
select="virtualAttributes/virtualAttribute"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <fo:block color="red" font-size="9pt" space-after="3mm">THIS GROUP 
HASN'T ANY VIRTUAL ATTRIBUTE</fo:block>
+        </xsl:otherwise>
+      </xsl:choose>
+      
+      <!--entitlements-->
+      <xsl:choose>
+        <xsl:when test="entitlements/entitlement">
+          <xsl:call-template name="entitlements">
+            <xsl:with-param name="label">Entitlements</xsl:with-param>
+            <xsl:with-param name="node" select="entitlements/entitlement"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <fo:block color="red" font-size="9pt" space-after="3mm">THIS GROUP 
HASN'T ANY ENTITLEMENT</fo:block>
+        </xsl:otherwise>
+      </xsl:choose>
+      
+      <xsl:choose>
+        <xsl:when test="users/user">
+          <fo:block font-size="11pt" font-weight="bold">Users</fo:block>
+          <xsl:for-each select="users/user">
+            <fo:block background-color="(#ccccff)" font-size="9pt" 
font-weight="bold" space-before="4mm">User: <xsl:value-of 
select="@userUsername"/> (Id: <xsl:value-of select="@userId"/>)</fo:block>
+                 
+          </xsl:for-each> 
+        </xsl:when>
+        <xsl:otherwise>
+          <fo:block color="red" font-size="9pt" space-after="3mm">THIS GROUP 
HASN'T ANY USER ASSIGNED TO</fo:block>
+        </xsl:otherwise>
+      </xsl:choose>
+      <xsl:call-template name="groupResources">
+        <xsl:with-param name="node" select="resources/resource"/>
+      </xsl:call-template>
+    </xsl:for-each>
+
+  </xsl:template>
+  
+  <xsl:template name="attributes">
+    <xsl:param name="label"/>
+    <xsl:param name="node"/>
+    <fo:block font-size="11pt" font-weight="bold" space-after="2mm">
+      <xsl:value-of select="$label"/>
+    </fo:block>
+    <fo:table table-layout="fixed" space-after="7mm">
+      <fo:table-column/>
+      <fo:table-column/>
+      <fo:table-header>
+        <fo:table-row height="7mm" background-color="(#ccccba)">
+          <fo:table-cell>
+            <fo:block font-weight="bold">Schema name</fo:block>
+          </fo:table-cell>
+          <fo:table-cell>
+            <fo:block font-weight="bold">Value(s)</fo:block>
+          </fo:table-cell>
+        </fo:table-row>
+      </fo:table-header>
+      <fo:table-body>
+        <xsl:for-each select="$node">
+          <xsl:if test="string-length(value/text()) &gt; 0">
+            <fo:table-row height="4mm" background-color="(#ccccff)">
+              <fo:table-cell>
+                <fo:block>
+                  <xsl:value-of select="@name"/>
+                </fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <xsl:for-each select="value">
+                  <fo:block></fo:block><!--                        
<fo:block>&#x2022;</fo:block>-->
+                  <fo:block font-style="italic">
+                    <xsl:value-of select="text()"/>
+                  </fo:block>
+                </xsl:for-each>
+              </fo:table-cell>
+            </fo:table-row>
+          </xsl:if>
+          <fo:table-row>
+            <fo:table-cell>
+              <fo:block></fo:block>
+            </fo:table-cell>
+            <fo:table-cell>
+              <fo:block></fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </xsl:for-each>
+      </fo:table-body>
+    </fo:table>
+  </xsl:template>
+  <!--entitlements template-->
+  <xsl:template name="entitlements">
+    <xsl:param name="label"/>
+    <xsl:param name="node"/>
+    <fo:block font-size="11pt" font-weight="bold" space-after="2mm" 
space-before="5mm">
+      <xsl:value-of select="$label"/>
+    </fo:block>
+    <fo:table table-layout="fixed" space-after="7mm">
+      <fo:table-column/>
+      <!--<fo:table-column/>-->
+      <fo:table-header>
+        <fo:table-row height="7mm" background-color="(#ccccba)">
+          <fo:table-cell>
+            <fo:block font-weight="bold">Name</fo:block>
+          </fo:table-cell>
+        </fo:table-row>
+      </fo:table-header>
+      <fo:table-body>
+        <xsl:for-each select="$node">
+          <fo:table-row height="4mm" background-color="(#ccccff)">
+            <fo:table-cell>
+              <fo:block>
+                <xsl:value-of select="@id"/>
+              </fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </xsl:for-each>
+      </fo:table-body>
+    </fo:table>
+  </xsl:template>
+  
+  <xsl:template name="groupResources">
+    <xsl:param name="node"/>
+    <fo:block font-size="11pt" font-weight="bold" space-after="3mm" 
space-before="5mm">Group Resources</fo:block>
+    <xsl:for-each select="$node">
+      <fo:block></fo:block> <!--            <fo:block>&#x2022;</fo:block>-->
+      <fo:block background-color="(#ccccff)">
+        <xsl:value-of select="@name"/>
+      </fo:block>
+    </xsl:for-each>
+  </xsl:template>
+</xsl:stylesheet>

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/resources/report/groupReportlet2html.xsl
----------------------------------------------------------------------
diff --git a/core/logic/src/main/resources/report/groupReportlet2html.xsl 
b/core/logic/src/main/resources/report/groupReportlet2html.xsl
new file mode 100644
index 0000000..ce36c6b
--- /dev/null
+++ b/core/logic/src/main/resources/report/groupReportlet2html.xsl
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
+                version="1.0">
+
+  <xsl:template 
match="reportlet[@class='org.apache.syncope.core.report.GroupReportlet']">
+    <h2>Reportlet: <xsl:value-of select="@name"/></h2>
+    <xsl:for-each select="group">
+      <h3>Group <xsl:value-of select="@name"/></h3>
+      
+      <table style="border: 1px solid black;">
+        <tr>
+          <td>Id:</td>
+          <td>
+            <xsl:value-of select="@id"/>
+          </td>
+        </tr>
+        <xsl:if test="@groupOwner != 'null'"> <!--!= null 
test="not(USER/FIRSTNAME)" -->
+          <tr>
+            <td>Group Owner:</td>
+            <td>
+              <xsl:value-of select="@groupOwner"/>
+            </td>
+          </tr>
+        </xsl:if>
+        <xsl:if test="@userOwner != 'null'">
+          <tr>
+            <td>User Owner:</td>
+            <td>
+              <xsl:value-of select="@userOwner"/>
+            </td>
+          </tr>
+        </xsl:if>
+        
+      </table>
+
+      <xsl:choose>
+        <xsl:when test="string-length(attributes/attribute) &gt; 0">
+          <xsl:call-template name="attributes">
+            <xsl:with-param name="label">Attributes</xsl:with-param>
+            <xsl:with-param name="node" select="attributes/attribute"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <h5>THIS GROUP HASN'T ANY ATTRIBUTE</h5>
+        </xsl:otherwise>
+      </xsl:choose>
+
+      <xsl:choose>
+        <xsl:when test="string-length(derivedAttributes/derivedAttribute) &gt; 
0">
+          <xsl:call-template name="attributes">
+            <xsl:with-param name="label">Derived Attributes</xsl:with-param>
+            <xsl:with-param name="node" 
select="derivedAttributes/derivedAttribute"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <h5>THIS GROUP HASN'T ANY DERIVED ATTRIBUTE</h5>
+        </xsl:otherwise>
+      </xsl:choose>
+      <!--</xsl:if>-->
+      <xsl:choose>
+        <xsl:when test="string-length(virtualAttributes/virtualAttribute) &gt; 
0">
+          <xsl:call-template name="attributes">
+            <xsl:with-param name="label">Virtual Attributes</xsl:with-param>
+            <xsl:with-param name="node" 
select="virtualAttributes/virtualAttribute"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <h5>THIS GROUP HASN'T ANY VIRTUAL ATTRIBUTE</h5>
+        </xsl:otherwise>
+      </xsl:choose>
+      
+      <xsl:choose>
+        <xsl:when test="entitlements/entitlement">
+          <xsl:call-template name="entitlements">
+            <xsl:with-param name="label">Entitlements: </xsl:with-param>
+            <xsl:with-param name="node" select="entitlements/entitlement"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <h5>THIS GROUP HASN'T ANY ENTITLEMENT</h5>
+        </xsl:otherwise>
+      </xsl:choose>
+      
+      <xsl:choose>
+        <xsl:when test="users/user">
+          <h4>Users</h4>
+          <xsl:for-each select="users/user">
+            <h5>User: <xsl:value-of select="@userUsername"/> (Id: 
<xsl:value-of select="@userId"/>)</h5>
+          </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+          <h5>THIS GROUP HASN'T ANY USER ASSIGNED TO</h5>
+        </xsl:otherwise>
+      </xsl:choose>
+      
+      <xsl:call-template name="groupResources">
+        <xsl:with-param name="node" select="resources/resource"/>
+      </xsl:call-template>
+      <hr/>
+      
+    </xsl:for-each>
+  </xsl:template>
+ 
+  <!--entitlement template-->
+  <xsl:template name="entitlements">
+    <xsl:param name="label"/>
+    <xsl:param name="node"/>
+
+    <h4>
+      <xsl:value-of select="$label"/>
+    </h4>
+    
+    <table>
+      
+      <tbody>
+        <xsl:for-each select="$node">
+          <tr>
+            <td>
+              <xsl:value-of select="@id"/>
+            </td>
+          </tr>
+        </xsl:for-each>
+      </tbody>
+    </table>
+  </xsl:template>
+
+
+  <xsl:template name="attributes">
+    <xsl:param name="label"/>
+    <xsl:param name="node"/>
+
+    <h4>
+      <xsl:value-of select="$label"/>
+    </h4>
+    
+    <table>
+      <thead>
+        <tr>
+          <th>Schema name</th>
+          <th>Value(s)</th>
+        </tr>
+      </thead>
+      <tbody>
+        <xsl:for-each select="$node">
+          <xsl:if test="string-length(value/text()) &gt; 0">
+            <tr>
+              <td>
+                <xsl:value-of select="@name"/>
+              </td>
+              <td>
+                <ul>
+                  <xsl:for-each select="value">
+                    <li>
+                      <xsl:value-of select="text()"/>
+                    </li>
+                  </xsl:for-each>
+                </ul>
+              </td>
+            </tr>
+          </xsl:if>
+        </xsl:for-each>
+      </tbody>
+    </table>
+  </xsl:template>
+
+  <xsl:template name="groupResources">
+    <xsl:param name="node"/>
+    
+    <h4>Group Resources</h4>
+    <ul>
+      <xsl:for-each select="$node">
+        <li>
+          <xsl:value-of select="@name"/>
+        </li>
+      </xsl:for-each>
+    </ul>
+  </xsl:template>
+</xsl:stylesheet>

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/resources/report/report2csv.xsl
----------------------------------------------------------------------
diff --git a/core/logic/src/main/resources/report/report2csv.xsl 
b/core/logic/src/main/resources/report/report2csv.xsl
index b1e2c71..a7a0a42 100644
--- a/core/logic/src/main/resources/report/report2csv.xsl
+++ b/core/logic/src/main/resources/report/report2csv.xsl
@@ -21,7 +21,7 @@ under the License.
                 version="1.0">
 
   <xsl:import href="userReportlet2csv.xsl"/>
-  <xsl:import href="roleReportlet2csv.xsl"/>
+  <xsl:import href="groupReportlet2csv.xsl"/>
   <xsl:import href="staticReportlet2csv.xsl"/>
  
   <xsl:param name="status"/>
@@ -33,4 +33,4 @@ under the License.
     <xsl:apply-templates/>
   </xsl:template>
 
-</xsl:stylesheet>
\ No newline at end of file
+</xsl:stylesheet>

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/resources/report/report2fo.xsl
----------------------------------------------------------------------
diff --git a/core/logic/src/main/resources/report/report2fo.xsl 
b/core/logic/src/main/resources/report/report2fo.xsl
index 7da9cab..e8dcefc 100644
--- a/core/logic/src/main/resources/report/report2fo.xsl
+++ b/core/logic/src/main/resources/report/report2fo.xsl
@@ -22,7 +22,7 @@ under the License.
                 version="1.0">
 
   <xsl:import href="userReportlet2fo.xsl"/>
-  <xsl:import href="roleReportlet2fo.xsl"/>
+  <xsl:import href="groupReportlet2fo.xsl"/>
   <xsl:import href="staticReportlet2fo.xsl"/>
  
   <xsl:param name="status"/>
@@ -94,4 +94,4 @@ under the License.
     </fo:root>
   </xsl:template>
 
-</xsl:stylesheet>
\ No newline at end of file
+</xsl:stylesheet>

http://git-wip-us.apache.org/repos/asf/syncope/blob/4095f1e8/core/logic/src/main/resources/report/report2html.xsl
----------------------------------------------------------------------
diff --git a/core/logic/src/main/resources/report/report2html.xsl 
b/core/logic/src/main/resources/report/report2html.xsl
index c1d6b67..e18f70d 100644
--- a/core/logic/src/main/resources/report/report2html.xsl
+++ b/core/logic/src/main/resources/report/report2html.xsl
@@ -21,7 +21,7 @@ under the License.
                 version="1.0">
 
   <xsl:import href="userReportlet2html.xsl"/>
-  <xsl:import href="roleReportlet2html.xsl"/>
+  <xsl:import href="groupReportlet2html.xsl"/>
   <xsl:import href="staticReportlet2html.xsl"/>
  
   <xsl:param name="status"/>
@@ -74,4 +74,4 @@ under the License.
     </html>
   </xsl:template>
 
-</xsl:stylesheet>
\ No newline at end of file
+</xsl:stylesheet>

Reply via email to