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/07/07 09:38:01 UTC

[7/7] syncope git commit: [SYNCOPE-676] Merge from 1_2_X

[SYNCOPE-676] Merge from 1_2_X


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

Branch: refs/heads/master
Commit: 97607b16e4ed807ff055b3ae55f0c722717c6472
Parents: 3eb0bfb 2612337
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Jul 7 09:37:35 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Jul 7 09:37:35 2015 +0200

----------------------------------------------------------------------
 .../client/console/commons/Constants.java       |  2 -
 .../client/console/rest/GroupRestClient.java    |  4 +-
 .../client/console/rest/UserRestClient.java     |  4 +-
 .../lib/builders/AnyListQueryBuilder.java       |  6 ++
 .../lib/builders/AnySearchQueryBuilder.java     |  6 ++
 .../client/lib/builders/ListQueryBuilder.java   |  6 ++
 .../pages/DisplayAttributesModalPage.java       | 48 +----------
 .../console/panels/UserSearchResultPanel.java   | 11 +--
 .../client/console/rest/UserRestClient.java     |  4 +-
 .../pages/DisplayAttributesModalPage.html       |  2 -
 .../common/rest/api/beans/ListQuery.java        | 12 +++
 .../common/rest/api/service/JAXRSService.java   |  2 +
 .../syncope/core/logic/AbstractAnyLogic.java    | 10 ++-
 .../syncope/core/logic/AnyObjectLogic.java      | 16 ++--
 .../apache/syncope/core/logic/GroupLogic.java   | 13 +--
 .../apache/syncope/core/logic/UserLogic.java    | 13 +--
 .../core/logic/report/GroupReportlet.java       |  2 +-
 .../core/logic/report/UserReportlet.java        |  7 +-
 .../syncope/core/logic/NotificationTest.java    |  7 +-
 .../src/main/resources/indexes.xml              | 31 ++++++++
 .../api/data/AnyObjectDataBinder.java           |  2 +-
 .../provisioning/api/data/GroupDataBinder.java  |  2 +-
 .../provisioning/api/data/UserDataBinder.java   |  2 +-
 .../java/data/AnyObjectDataBinderImpl.java      | 53 +++++++------
 .../java/data/GroupDataBinderImpl.java          | 10 ++-
 .../java/data/UserDataBinderImpl.java           | 83 +++++++++++---------
 .../notification/NotificationManagerImpl.java   |  6 +-
 .../sync/AnyObjectPushResultHandlerImpl.java    |  4 +-
 .../java/sync/GroupPushResultHandlerImpl.java   |  4 +-
 .../rest/cxf/service/AbstractAnyService.java    |  6 +-
 .../rest/cxf/service/AbstractServiceImpl.java   |  3 -
 .../rest/cxf/service/AnyObjectServiceImpl.java  |  3 +-
 .../activiti/ActivitiUserWorkflowAdapter.java   |  4 +-
 .../fit/console/reference/ReportITCase.java     |  4 +-
 34 files changed, 212 insertions(+), 180 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
----------------------------------------------------------------------
diff --cc client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
index 0b8391a,0000000..98339ec
mode 100644,000000..100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
@@@ -1,110 -1,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.client.console.commons;
 +
 +public final class Constants {
 +
 +    public static final String ON_CLICK = "onclick";
 +
 +    public static final String ON_CHANGE = "onchange";
 +
 +    public static final String ON_BLUR = "onblur";
 +
 +    public static final String PNG_EXT = ".png";
 +
 +    public static final String FEEDBACK = "feedback";
 +
 +    public static final String OPERATION_SUCCEEDED = "operation_succeeded";
 +
 +    public static final String OPERATION_ERROR = "operation_error";
 +
 +    public static final String SEARCH_ERROR = "search_error";
 +
 +    public static final String ERROR = "error";
 +
 +    public static final String PARAM_PASSWORD_RESET_TOKEN = "pwdResetToken";
 +
 +    public static final String PREF_USERS_DETAILS_VIEW = "users.details.view";
 +
 +    public static final String PREF_USERS_ATTRIBUTES_VIEW = "users.attributes.view";
 +
 +    public static final String PREF_USERS_DERIVED_ATTRIBUTES_VIEW = "users.derived.attributes.view";
 +
-     public static final String PREF_USERS_VIRTUAL_ATTRIBUTES_VIEW = "users.virtual.attributes.view";
- 
 +    public static final String PREF_CONF_SCHEMA_PAGINATOR_ROWS = "conf.schema.paginator.rows";
 +
 +    public static final String PREF_USER_PLAIN_SCHEMA_PAGINATOR_ROWS = "user.schema.paginator.rows";
 +
 +    public static final String PREF_USER_DER_SCHEMA_PAGINATOR_ROWS = "user.derived.schema.paginator.rows";
 +
 +    public static final String PREF_USER_VIR_SCHEMA_PAGINATOR_ROWS = "user.virtual.schema.paginator.rows";
 +
 +    public static final String PREF_GROUP_PLAIN_SCHEMA_PAGINATOR_ROWS = "group.schema.paginator.rows";
 +
 +    public static final String PREF_GROUP_DER_SCHEMA_PAGINATOR_ROWS = "group.derived.schema.paginator.rows";
 +
 +    public static final String PREF_GROUP_VIR_SCHEMA_PAGINATOR_ROWS = "group.virtual.schema.paginator.rows";
 +
 +    public static final String PREF_MEMBERSHIP_PLAIN_SCHEMA_PAGINATOR_ROWS = "membership.schema.paginator.rows";
 +
 +    public static final String PREF_MEMBERSHIP_DER_SCHEMA_PAGINATOR_ROWS = "membership.derived.aschema.paginator.rows";
 +
 +    public static final String PREF_MEMBERSHIP_VIR_SCHEMA_PAGINATOR_ROWS = "membership.virtual.aschema.paginator.rows";
 +
 +    public static final String PREF_USERS_PAGINATOR_ROWS = "users.paginator.rows";
 +
 +    public static final String PREF_RESOURCES_PAGINATOR_ROWS = "resources.paginator.rows";
 +
 +    public static final String PREF_CONNECTORS_PAGINATOR_ROWS = "connectors.paginator.rows";
 +
 +    public static final String PREF_NOTIFICATION_PAGINATOR_ROWS = "notification.paginator.rows";
 +
 +    public static final String PREF_PROPAGATION_TASKS_PAGINATOR_ROWS = "proagationtasks.paginator.rows";
 +
 +    public static final String PREF_NOTIFICATION_TASKS_PAGINATOR_ROWS = "notificationtasks.paginator.rows";
 +
 +    public static final String PREF_SCHED_TASKS_PAGINATOR_ROWS = "schedtasks.paginator.rows";
 +
 +    public static final String PREF_SYNC_TASKS_PAGINATOR_ROWS = "synctasks.paginator.rows";
 +
 +    public static final String PREF_TODO_PAGINATOR_ROWS = "todo.paginator.rows";
 +
 +    public static final String PREF_REPORT_PAGINATOR_ROWS = "report.paginator.rows";
 +
 +    public static final String PAGEPARAM_CREATE = "CREATE";
 +
 +    public static final String PAGEPARAM_CURRENT_PAGE = "_current_page";
 +
 +    public static final String PREF_POLICY_PAGINATOR_ROWS = "policy.paginator.rows";
 +
 +    /**
 +     * ConnId's GuardedString is not in the classpath.
 +     */
 +    public static final String GUARDED_STRING = "org.identityconnectors.common.security.GuardedString";
 +
 +    /**
 +     * ConnId's GuardedByteArray is not in the classpath.
 +     */
 +    public static final String GUARDED_BYTE_ARRAY = "org.identityconnectors.common.security.GuardedByteArray";
 +
 +    private Constants() {
 +        // private constructor for static utility class
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/console/src/main/java/org/apache/syncope/client/console/rest/GroupRestClient.java
----------------------------------------------------------------------
diff --cc client/console/src/main/java/org/apache/syncope/client/console/rest/GroupRestClient.java
index b4b848c,0000000..512e08f
mode 100644,000000..100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/GroupRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/GroupRestClient.java
@@@ -1,204 -1,0 +1,204 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.client.console.rest;
 +
 +import java.util.List;
 +
 +import javax.ws.rs.core.Response;
 +import org.apache.syncope.client.console.commons.status.StatusBean;
 +import org.apache.syncope.client.console.commons.status.StatusUtils;
 +import org.apache.syncope.client.lib.SyncopeClient;
 +import org.apache.syncope.common.lib.mod.GroupMod;
 +import org.apache.syncope.common.lib.mod.ResourceAssociationMod;
 +import org.apache.syncope.common.lib.to.BulkAction;
 +import org.apache.syncope.common.lib.to.BulkActionResult;
 +import org.apache.syncope.common.lib.to.ConnObjectTO;
 +import org.apache.syncope.common.lib.to.GroupTO;
 +import org.apache.syncope.common.lib.types.AnyTypeKind;
 +import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
 +import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
 +import org.apache.syncope.common.lib.wrap.ResourceKey;
 +import org.apache.syncope.common.rest.api.CollectionWrapper;
 +import org.apache.syncope.common.rest.api.service.ResourceService;
 +import org.apache.syncope.common.rest.api.service.GroupService;
 +import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 +import org.springframework.stereotype.Component;
 +
 +/**
 + * Console client for invoking Rest Group's services.
 + */
 +@Component
 +public class GroupRestClient extends AbstractAnyRestClient {
 +
 +    private static final long serialVersionUID = -8549081557283519638L;
 +
 +    @Override
 +    public int count(final String realm) {
 +        return getService(GroupService.class).
 +                list(SyncopeClient.getAnyListQueryBuilder().realm(realm).page(1).size(1).build()).
 +                getTotalCount();
 +    }
 +
 +    @Override
 +    public List<GroupTO> list(final String realm, final int page, final int size, final SortParam<String> sort) {
 +        return getService(GroupService.class).
 +                list(SyncopeClient.getAnyListQueryBuilder().realm(realm).page(page).size(size).
-                         orderBy(toOrderBy(sort)).build()).
++                        orderBy(toOrderBy(sort)).details(false).build()).
 +                getResult();
 +    }
 +
 +    @Override
 +    public int searchCount(final String realm, final String fiql) {
 +        return getService(GroupService.class).
 +                search(SyncopeClient.getAnySearchQueryBuilder().realm(realm).fiql(fiql).page(1).size(1).build()).
 +                getTotalCount();
 +    }
 +
 +    @Override
 +    public List<GroupTO> search(
 +            final String realm, final String fiql, final int page, final int size, final SortParam<String> sort) {
 +
 +        return getService(GroupService.class).
 +                search(SyncopeClient.getAnySearchQueryBuilder().realm(realm).fiql(fiql).page(page).size(size).
-                         orderBy(toOrderBy(sort)).build()).
++                        orderBy(toOrderBy(sort)).details(false).build()).
 +                getResult();
 +    }
 +
 +    @Override
 +    public ConnObjectTO readConnObject(final String resourceName, final Long id) {
 +        return getService(ResourceService.class).readConnObject(resourceName, AnyTypeKind.GROUP.name(), id);
 +    }
 +
 +    public GroupTO create(final GroupTO groupTO) {
 +        Response response = getService(GroupService.class).create(groupTO);
 +        return response.readEntity(GroupTO.class);
 +    }
 +
 +    public GroupTO read(final Long key) {
 +        return getService(GroupService.class).read(key);
 +    }
 +
 +    public GroupTO update(final String etag, final GroupMod groupMod) {
 +        GroupTO result;
 +        synchronized (this) {
 +            GroupService service = getService(etag, GroupService.class);
 +            result = service.update(groupMod).readEntity(GroupTO.class);
 +            resetClient(GroupService.class);
 +        }
 +        return result;
 +    }
 +
 +    @Override
 +    public GroupTO delete(final String etag, final Long key) {
 +        GroupTO result;
 +        synchronized (this) {
 +            GroupService service = getService(etag, GroupService.class);
 +            result = service.delete(key).readEntity(GroupTO.class);
 +            resetClient(GroupService.class);
 +        }
 +        return result;
 +    }
 +
 +    @Override
 +    public BulkActionResult bulkAction(final BulkAction action) {
 +        return getService(GroupService.class).bulk(action);
 +    }
 +
 +    public void unlink(final String etag, final long groupKey, final List<StatusBean> statuses) {
 +        synchronized (this) {
 +            GroupService service = getService(etag, GroupService.class);
 +            service.bulkDeassociation(groupKey, ResourceDeassociationActionType.UNLINK,
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceKey.class));
 +            resetClient(GroupService.class);
 +        }
 +    }
 +
 +    public void link(final String etag, final long groupKey, final List<StatusBean> statuses) {
 +        synchronized (this) {
 +            GroupService service = getService(etag, GroupService.class);
 +
 +            ResourceAssociationMod associationMod = new ResourceAssociationMod();
 +            associationMod.getTargetResources().addAll(
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceKey.class));
 +            service.bulkAssociation(groupKey, ResourceAssociationActionType.LINK, associationMod);
 +
 +            resetClient(GroupService.class);
 +        }
 +    }
 +
 +    public BulkActionResult deprovision(final String etag, final long groupKey, final List<StatusBean> statuses) {
 +        BulkActionResult result;
 +        synchronized (this) {
 +            GroupService service = getService(etag, GroupService.class);
 +            result = service.bulkDeassociation(groupKey, ResourceDeassociationActionType.DEPROVISION,
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceKey.class)).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(GroupService.class);
 +        }
 +        return result;
 +    }
 +
 +    public BulkActionResult provision(final String etag, final long groupKey, final List<StatusBean> statuses) {
 +        BulkActionResult result;
 +        synchronized (this) {
 +            GroupService service = getService(etag, GroupService.class);
 +
 +            ResourceAssociationMod associationMod = new ResourceAssociationMod();
 +            associationMod.getTargetResources().addAll(
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceKey.class));
 +
 +            result = service.bulkAssociation(groupKey, ResourceAssociationActionType.PROVISION, associationMod).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(GroupService.class);
 +        }
 +        return result;
 +    }
 +
 +    public BulkActionResult unassign(final String etag, final long groupKey, final List<StatusBean> statuses) {
 +        BulkActionResult result;
 +        synchronized (this) {
 +            GroupService service = getService(etag, GroupService.class);
 +            result = service.bulkDeassociation(groupKey, ResourceDeassociationActionType.UNASSIGN,
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceKey.class)).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(GroupService.class);
 +        }
 +        return result;
 +    }
 +
 +    public BulkActionResult assign(final String etag, final long groupKey, final List<StatusBean> statuses) {
 +        BulkActionResult result;
 +        synchronized (this) {
 +            GroupService service = getService(etag, GroupService.class);
 +
 +            ResourceAssociationMod associationMod = new ResourceAssociationMod();
 +            associationMod.getTargetResources().addAll(
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceKey.class));
 +
 +            result = service.bulkAssociation(groupKey, ResourceAssociationActionType.ASSIGN, associationMod).
 +                    readEntity(BulkActionResult.class);
 +
 +            resetClient(GroupService.class);
 +        }
 +        return result;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
----------------------------------------------------------------------
diff --cc client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
index f517c4c,0000000..338851d
mode 100644,000000..100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
@@@ -1,238 -1,0 +1,238 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.client.console.rest;
 +
 +import java.util.List;
 +import javax.ws.rs.core.Response;
 +import org.apache.syncope.client.console.commons.status.StatusBean;
 +import org.apache.syncope.client.console.commons.status.StatusUtils;
 +import org.apache.syncope.client.lib.SyncopeClient;
 +import org.apache.syncope.common.lib.SyncopeClientException;
 +import org.apache.syncope.common.lib.mod.ResourceAssociationMod;
 +import org.apache.syncope.common.lib.mod.StatusMod;
 +import org.apache.syncope.common.lib.mod.UserMod;
 +import org.apache.syncope.common.lib.to.BulkAction;
 +import org.apache.syncope.common.lib.to.BulkActionResult;
 +import org.apache.syncope.common.lib.to.ConnObjectTO;
 +import org.apache.syncope.common.lib.to.UserTO;
 +import org.apache.syncope.common.lib.types.AnyTypeKind;
 +import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
 +import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
 +import org.apache.syncope.common.lib.wrap.ResourceKey;
 +import org.apache.syncope.common.rest.api.CollectionWrapper;
 +import org.apache.syncope.common.rest.api.service.ResourceService;
 +import org.apache.syncope.common.rest.api.service.UserService;
 +import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 +import org.springframework.stereotype.Component;
 +
 +/**
 + * Console client for invoking rest users services.
 + */
 +@Component
 +public class UserRestClient extends AbstractAnyRestClient {
 +
 +    private static final long serialVersionUID = -1575748964398293968L;
 +
 +    @Override
 +    public int count(final String realm) {
 +        return getService(UserService.class).
 +                list(SyncopeClient.getAnyListQueryBuilder().realm(realm).page(1).size(1).build()).
 +                getTotalCount();
 +    }
 +
 +    @Override
 +    public List<UserTO> list(final String realm, final int page, final int size, final SortParam<String> sort) {
 +        return getService(UserService.class).
 +                list(SyncopeClient.getAnyListQueryBuilder().realm(realm).page(page).size(size).
-                         orderBy(toOrderBy(sort)).build()).
++                        orderBy(toOrderBy(sort)).details(false).build()).
 +                getResult();
 +    }
 +
 +    public UserTO create(final UserTO userTO, final boolean storePassword) {
 +        Response response = getService(UserService.class).create(userTO, storePassword);
 +        return response.readEntity(UserTO.class);
 +    }
 +
 +    public UserTO update(final String etag, final UserMod userMod) {
 +        UserTO result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            result = service.update(userMod).readEntity(UserTO.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    @Override
 +    public UserTO delete(final String etag, final Long id) {
 +        UserTO result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            result = service.delete(id).readEntity(UserTO.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    public UserTO read(final Long id) {
 +        UserTO userTO = null;
 +        try {
 +            userTO = getService(UserService.class).read(id);
 +        } catch (SyncopeClientException e) {
 +            LOG.error("While reading a user", e);
 +        }
 +        return userTO;
 +    }
 +
 +    @Override
 +    public int searchCount(final String realm, final String fiql) {
 +        return getService(UserService.class).
 +                search(SyncopeClient.getAnySearchQueryBuilder().realm(realm).fiql(fiql).page(1).size(1).build()).
 +                getTotalCount();
 +    }
 +
 +    @Override
 +    public List<UserTO> search(
 +            final String realm, final String fiql, final int page, final int size, final SortParam<String> sort) {
 +
 +        return getService(UserService.class).
 +                search(SyncopeClient.getAnySearchQueryBuilder().realm(realm).fiql(fiql).page(page).size(size).
-                         orderBy(toOrderBy(sort)).build()).
++                        orderBy(toOrderBy(sort)).details(false).build()).
 +                getResult();
 +    }
 +
 +    @Override
 +    public ConnObjectTO readConnObject(final String resourceName, final Long id) {
 +        return getService(ResourceService.class).readConnObject(resourceName, AnyTypeKind.USER.name(), id);
 +    }
 +
 +    public void suspend(final String etag, final long userKey, final List<StatusBean> statuses) {
 +        StatusMod statusMod = StatusUtils.buildStatusMod(statuses, false);
 +        statusMod.setType(StatusMod.ModType.SUSPEND);
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            service.status(userKey, statusMod);
 +            resetClient(UserService.class);
 +        }
 +    }
 +
 +    public void reactivate(final String etag, final long userKey, final List<StatusBean> statuses) {
 +        StatusMod statusMod = StatusUtils.buildStatusMod(statuses, true);
 +        statusMod.setType(StatusMod.ModType.REACTIVATE);
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            service.status(userKey, statusMod);
 +            resetClient(UserService.class);
 +        }
 +    }
 +
 +    @Override
 +    public BulkActionResult bulkAction(final BulkAction action) {
 +        return getService(UserService.class).bulk(action);
 +    }
 +
 +    public void unlink(final String etag, final long userKey, final List<StatusBean> statuses) {
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            service.bulkDeassociation(userKey, ResourceDeassociationActionType.UNLINK,
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceKey.class));
 +            resetClient(UserService.class);
 +        }
 +    }
 +
 +    public void link(final String etag, final long userKey, final List<StatusBean> statuses) {
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +
 +            ResourceAssociationMod associationMod = new ResourceAssociationMod();
 +            associationMod.getTargetResources().addAll(
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceKey.class));
 +            service.bulkAssociation(userKey, ResourceAssociationActionType.LINK, associationMod);
 +
 +            resetClient(UserService.class);
 +        }
 +    }
 +
 +    public BulkActionResult deprovision(final String etag, final long userKey, final List<StatusBean> statuses) {
 +        BulkActionResult result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            result = service.bulkDeassociation(userKey, ResourceDeassociationActionType.DEPROVISION,
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceKey.class)).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    public BulkActionResult provision(final String etag, final long userKey,
 +            final List<StatusBean> statuses, final boolean changepwd, final String password) {
 +
 +        BulkActionResult result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +
 +            ResourceAssociationMod associationMod = new ResourceAssociationMod();
 +            associationMod.getTargetResources().addAll(
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceKey.class));
 +            associationMod.setChangePwd(changepwd);
 +            associationMod.setPassword(password);
 +
 +            result = service.bulkAssociation(userKey, ResourceAssociationActionType.PROVISION, associationMod).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    public BulkActionResult unassign(final String etag, final long userKey, final List<StatusBean> statuses) {
 +        BulkActionResult result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            result = service.bulkDeassociation(userKey, ResourceDeassociationActionType.UNASSIGN,
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceKey.class)).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    public BulkActionResult assign(final String etag, final long userKey,
 +            final List<StatusBean> statuses, final boolean changepwd, final String password) {
 +
 +        BulkActionResult result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +
 +            ResourceAssociationMod associationMod = new ResourceAssociationMod();
 +            associationMod.getTargetResources().addAll(
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceKey.class));
 +            associationMod.setChangePwd(changepwd);
 +            associationMod.setPassword(password);
 +
 +            result = service.bulkAssociation(userKey, ResourceAssociationActionType.ASSIGN, associationMod).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/lib/src/main/java/org/apache/syncope/client/lib/builders/AnyListQueryBuilder.java
----------------------------------------------------------------------
diff --cc client/lib/src/main/java/org/apache/syncope/client/lib/builders/AnyListQueryBuilder.java
index afd29e9,0000000..e25daef
mode 100644,000000..100644
--- a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/AnyListQueryBuilder.java
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/AnyListQueryBuilder.java
@@@ -1,62 -1,0 +1,68 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.client.lib.builders;
 +
 +import java.util.ArrayList;
 +import org.apache.syncope.common.rest.api.beans.ListQuery;
 +import org.apache.syncope.common.rest.api.beans.AnyListQuery;
 +
 +public class AnyListQueryBuilder extends ListQueryBuilder {
 +
 +    private final AnyListQuery instance = new AnyListQuery();
 +
 +    @Override
 +    public AnyListQueryBuilder page(final Integer page) {
 +        return AnyListQueryBuilder.class.cast(super.page(page));
 +    }
 +
 +    @Override
 +    public AnyListQueryBuilder size(final Integer size) {
 +        return AnyListQueryBuilder.class.cast(super.size(size));
 +    }
 +
 +    @Override
 +    public AnyListQueryBuilder orderBy(final String orderBy) {
 +        return AnyListQueryBuilder.class.cast(super.orderBy(orderBy));
 +    }
 +
++    @Override
++    public AnyListQueryBuilder details(final boolean details) {
++        return AnyListQueryBuilder.class.cast(super.details(details));
++    }
++
 +    public AnyListQueryBuilder realm(final String realm) {
 +        if (instance.getRealms() == null) {
 +            instance.setRealms(new ArrayList<String>());
 +        }
 +        instance.getRealms().add(realm);
 +
 +        return this;
 +    }
 +
 +    @Override
 +    public AnyListQuery build() {
 +        ListQuery lq = super.build();
 +        instance.setPage(lq.getPage());
 +        instance.setSize(lq.getSize());
 +        instance.setOrderBy(lq.getOrderBy());
++        instance.setDetails(lq.isDetails());
 +
 +        return instance;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/lib/src/main/java/org/apache/syncope/client/lib/builders/AnySearchQueryBuilder.java
----------------------------------------------------------------------
diff --cc client/lib/src/main/java/org/apache/syncope/client/lib/builders/AnySearchQueryBuilder.java
index c3fce47,0000000..5bffdcc
mode 100644,000000..100644
--- a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/AnySearchQueryBuilder.java
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/AnySearchQueryBuilder.java
@@@ -1,64 -1,0 +1,70 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.client.lib.builders;
 +
 +import org.apache.syncope.common.rest.api.beans.AnyListQuery;
 +import org.apache.syncope.common.rest.api.beans.AnySearchQuery;
 +
 +public class AnySearchQueryBuilder extends AnyListQueryBuilder {
 +
 +    private final AnySearchQuery instance = new AnySearchQuery();
 +
 +    @Override
 +    public AnySearchQueryBuilder realm(final String realm) {
 +        return AnySearchQueryBuilder.class.cast(super.realm(realm));
 +    }
 +
 +    @Override
 +    public AnySearchQueryBuilder page(final Integer page) {
 +        return AnySearchQueryBuilder.class.cast(super.page(page));
 +    }
 +
 +    @Override
 +    public AnySearchQueryBuilder size(final Integer size) {
 +        return AnySearchQueryBuilder.class.cast(super.size(size));
 +    }
 +
 +    @Override
 +    public AnySearchQueryBuilder orderBy(final String orderBy) {
 +        return AnySearchQueryBuilder.class.cast(super.orderBy(orderBy));
 +    }
 +
++    @Override
++    public AnySearchQueryBuilder details(final boolean details) {
++        return AnySearchQueryBuilder.class.cast(super.details(details));
++    }
++
 +    public AnySearchQueryBuilder fiql(final String fiql) {
 +        instance.setFiql(fiql);
 +
 +        return this;
 +    }
 +
 +    @Override
 +    public AnySearchQuery build() {
 +        AnyListQuery slq = super.build();
 +        instance.setRealms(slq.getRealms());
 +        instance.setPage(slq.getPage());
 +        instance.setSize(slq.getSize());
 +        instance.setOrderBy(slq.getOrderBy());
++        instance.setDetails(slq.isDetails());
 +
 +        return instance;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ListQueryBuilder.java
----------------------------------------------------------------------
diff --cc client/lib/src/main/java/org/apache/syncope/client/lib/builders/ListQueryBuilder.java
index 5d6202a,0000000..bce0e73
mode 100644,000000..100644
--- a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ListQueryBuilder.java
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ListQueryBuilder.java
@@@ -1,48 -1,0 +1,54 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.client.lib.builders;
 +
 +import org.apache.syncope.common.rest.api.beans.ListQuery;
 +
 +public class ListQueryBuilder {
 +
 +    private final ListQuery instance = new ListQuery();
 +
 +    public ListQueryBuilder page(final Integer page) {
 +        instance.setPage(page);
 +
 +        return this;
 +    }
 +
 +    public ListQueryBuilder size(final Integer size) {
 +        instance.setSize(size);
 +
 +        return this;
 +    }
 +
 +    public ListQueryBuilder orderBy(final String orderBy) {
 +        instance.setOrderBy(orderBy);
 +
 +        return this;
 +    }
 +
++    public ListQueryBuilder details(final boolean details) {
++        instance.setDetails(details);
++
++        return this;
++    }
++
 +    public ListQuery build() {
 +        return instance;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/old_console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java
index 6f89ec3,0000000..d588a01
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java
@@@ -1,273 -1,0 +1,231 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.client.console.pages;
 +
 +import java.util.HashMap;
 +import java.util.List;
 +import java.util.Map;
 +import org.apache.syncope.client.console.commons.Constants;
 +import org.apache.syncope.client.console.commons.PreferenceManager;
 +import org.apache.syncope.common.lib.search.SearchableFields;
 +import org.apache.syncope.common.lib.to.UserTO;
 +import org.apache.wicket.PageReference;
 +import org.apache.wicket.ajax.AjaxRequestTarget;
 +import org.apache.wicket.ajax.markup.html.form.AjaxButton;
 +import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
 +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 +import org.apache.wicket.markup.html.basic.Label;
 +import org.apache.wicket.markup.html.form.Check;
 +import org.apache.wicket.markup.html.form.CheckGroup;
 +import org.apache.wicket.markup.html.form.Form;
 +import org.apache.wicket.markup.html.list.ListItem;
 +import org.apache.wicket.markup.html.list.ListView;
 +import org.apache.wicket.markup.html.panel.Fragment;
 +import org.apache.wicket.model.CompoundPropertyModel;
 +import org.apache.wicket.model.IModel;
 +import org.apache.wicket.model.LoadableDetachableModel;
 +import org.apache.wicket.model.PropertyModel;
 +import org.apache.wicket.model.ResourceModel;
 +import org.apache.wicket.spring.injection.annot.SpringBean;
 +
 +/**
 + * Modal window with Display attributes form.
 + */
 +@SuppressWarnings({ "unchecked", "rawtypes" })
 +public class DisplayAttributesModalPage extends BaseModalPage {
 +
 +    private static final long serialVersionUID = -4274117450918385110L;
 +
 +    /**
 +     * Max allowed selections.
 +     */
 +    private static final int MAX_SELECTIONS = 9;
 +
 +    public static final String[] DEFAULT_SELECTION = { "key", "username", "status" };
 +
 +    @SpringBean
 +    private PreferenceManager prefMan;
 +
 +    private final List<String> selectedDetails;
 +
 +    private final List<String> selectedPlainSchemas;
 +
 +    private final List<String> selectedDerSchemas;
 +
-     private final List<String> selectedVirSchemas;
- 
 +    public DisplayAttributesModalPage(final PageReference pageRef, final ModalWindow window,
-             final List<String> schemaNames, final List<String> dSchemaNames, final List<String> vSchemaNames) {
++            final List<String> schemaNames, final List<String> dSchemaNames) {
 +
 +        super();
 +
 +        final IModel<List<String>> fnames = new LoadableDetachableModel<List<String>>() {
 +
 +            private static final long serialVersionUID = 5275935387613157437L;
 +
 +            @Override
 +            protected List<String> load() {
 +                return SearchableFields.get(UserTO.class);
 +            }
 +        };
 +
 +        final IModel<List<String>> names = new LoadableDetachableModel<List<String>>() {
 +
 +            private static final long serialVersionUID = 5275935387613157437L;
 +
 +            @Override
 +            protected List<String> load() {
 +                return schemaNames;
 +            }
 +        };
 +
 +        final IModel<List<String>> dsnames = new LoadableDetachableModel<List<String>>() {
 +
 +            private static final long serialVersionUID = 5275935387613157437L;
 +
 +            @Override
 +            protected List<String> load() {
 +                return dSchemaNames;
 +            }
 +        };
 +
-         final IModel<List<String>> vsnames = new LoadableDetachableModel<List<String>>() {
- 
-             private static final long serialVersionUID = 5275935387613157437L;
- 
-             @Override
-             protected List<String> load() {
-                 return vSchemaNames;
-             }
-         };
- 
 +        final Form form = new Form(FORM);
 +        form.setModel(new CompoundPropertyModel(this));
 +
 +        selectedDetails = prefMan.getList(getRequest(), Constants.PREF_USERS_DETAILS_VIEW);
 +
 +        selectedPlainSchemas = prefMan.getList(getRequest(), Constants.PREF_USERS_ATTRIBUTES_VIEW);
 +
 +        selectedDerSchemas = prefMan.getList(getRequest(), Constants.PREF_USERS_DERIVED_ATTRIBUTES_VIEW);
 +
-         selectedVirSchemas = prefMan.getList(getRequest(), Constants.PREF_USERS_VIRTUAL_ATTRIBUTES_VIEW);
- 
 +        final CheckGroup dgroup = new CheckGroup("dCheckGroup", new PropertyModel(this, "selectedDetails"));
 +        form.add(dgroup);
 +
 +        final ListView<String> details = new ListView<String>("details", fnames) {
 +
 +            private static final long serialVersionUID = 9101744072914090143L;
 +
 +            @Override
 +            protected void populateItem(final ListItem<String> item) {
 +                item.add(new Check("dcheck", item.getModel()));
 +                item.add(new Label("dname", new ResourceModel(item.getModelObject(), item.getModelObject())));
 +            }
 +        };
 +        dgroup.add(details);
 +
 +        if (names.getObject() == null || names.getObject().isEmpty()) {
 +            final Fragment fragment = new Fragment("plainSchemas", "emptyFragment", form);
 +            form.add(fragment);
 +
 +            selectedPlainSchemas.clear();
 +        } else {
 +            final Fragment fragment = new Fragment("plainSchemas", "sfragment", form);
 +            form.add(fragment);
 +
 +            final CheckGroup sgroup = new CheckGroup("psCheckGroup", new PropertyModel(this, "selectedPlainSchemas"));
 +            fragment.add(sgroup);
 +
 +            final ListView<String> schemas = new ListView<String>("plainSchemas", names) {
 +
 +                private static final long serialVersionUID = 9101744072914090143L;
 +
 +                @Override
 +                protected void populateItem(final ListItem<String> item) {
 +                    item.add(new Check("scheck", item.getModel()));
 +                    item.add(new Label("sname", new ResourceModel(item.getModelObject(), item.getModelObject())));
 +                }
 +            };
 +            sgroup.add(schemas);
 +        }
 +
 +        if (dsnames.getObject() == null || dsnames.getObject().isEmpty()) {
 +            final Fragment fragment = new Fragment("dschemas", "emptyFragment", form);
 +            form.add(fragment);
 +
 +            selectedDerSchemas.clear();
 +        } else {
 +            final Fragment fragment = new Fragment("dschemas", "dsfragment", form);
 +            form.add(fragment);
 +
 +            final CheckGroup dsgroup = new CheckGroup("dsCheckGroup", new PropertyModel(this, "selectedDerSchemas"));
 +            fragment.add(dsgroup);
 +
 +            final ListView<String> derSchemas = new ListView<String>("derSchemas", dsnames) {
 +
 +                private static final long serialVersionUID = 9101744072914090143L;
 +
 +                @Override
 +                protected void populateItem(ListItem<String> item) {
 +                    item.add(new Check("dscheck", item.getModel()));
 +                    item.add(new Label("dsname", new ResourceModel(item.getModelObject(), item.getModelObject())));
 +                }
 +            };
 +            dsgroup.add(derSchemas);
 +        }
 +
-         if (vsnames.getObject() == null || vsnames.getObject().isEmpty()) {
-             final Fragment fragment = new Fragment("vschemas", "emptyFragment", form);
-             form.add(fragment);
- 
-             selectedVirSchemas.clear();
-         } else {
-             final Fragment fragment = new Fragment("vschemas", "vsfragment", form);
-             form.add(fragment);
- 
-             final CheckGroup vsgroup = new CheckGroup("vsCheckGroup", new PropertyModel(this, "selectedVirSchemas"));
-             fragment.add(vsgroup);
- 
-             final ListView<String> virSchemas = new ListView<String>("virSchemas", vsnames) {
- 
-                 private static final long serialVersionUID = 9101744072914090143L;
- 
-                 @Override
-                 protected void populateItem(ListItem<String> item) {
-                     item.add(new Check("vscheck", item.getModel()));
-                     item.add(new Label("vsname", new ResourceModel(item.getModelObject(), item.getModelObject())));
-                 }
-             };
-             vsgroup.add(virSchemas);
-         }
- 
 +        final AjaxButton submit = new IndicatingAjaxButton(SUBMIT, new ResourceModel(SUBMIT)) {
 +
 +            private static final long serialVersionUID = -4804368561204623354L;
 +
 +            @Override
 +            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-                 if (selectedDetails.size() + selectedPlainSchemas.size() + selectedVirSchemas.size() + selectedDerSchemas.
-                         size()
++                if (selectedDetails.size() + selectedPlainSchemas.size() + selectedDerSchemas.size()
 +                        > MAX_SELECTIONS) {
 +
 +                    error(getString("tooManySelections"));
 +                    onError(target, form);
 +                } else {
-                     final Map<String, List<String>> prefs = new HashMap<String, List<String>>();
++                    final Map<String, List<String>> prefs = new HashMap<>();
 +
 +                    prefs.put(Constants.PREF_USERS_DETAILS_VIEW, selectedDetails);
 +
 +                    prefs.put(Constants.PREF_USERS_ATTRIBUTES_VIEW, selectedPlainSchemas);
 +
 +                    prefs.put(Constants.PREF_USERS_DERIVED_ATTRIBUTES_VIEW, selectedDerSchemas);
 +
-                     prefs.put(Constants.PREF_USERS_VIRTUAL_ATTRIBUTES_VIEW, selectedVirSchemas);
- 
 +                    prefMan.setList(getRequest(), getResponse(), prefs);
 +
 +                    ((BasePage) pageRef.getPage()).setModalResult(true);
 +
 +                    window.close(target);
 +                }
 +            }
 +
 +            @Override
 +            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
 +                feedbackPanel.refresh(target);
 +            }
 +        };
 +
 +        form.add(submit);
 +
 +        final AjaxButton cancel = new IndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL)) {
 +
 +            private static final long serialVersionUID = -958724007591692537L;
 +
 +            @Override
 +            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
 +                window.close(target);
 +            }
 +        };
 +
 +        cancel.setDefaultFormProcessing(false);
 +        form.add(cancel);
 +
 +        add(form);
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/old_console/src/main/java/org/apache/syncope/client/console/panels/UserSearchResultPanel.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/panels/UserSearchResultPanel.java
index 132bb66,0000000..16f7a22
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/UserSearchResultPanel.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/UserSearchResultPanel.java
@@@ -1,297 -1,0 +1,288 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.client.console.panels;
 +
 +import java.lang.reflect.Field;
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.Collection;
 +import java.util.Date;
 +import java.util.List;
 +import org.apache.syncope.client.console.commons.Constants;
 +import org.apache.syncope.client.console.pages.DisplayAttributesModalPage;
 +import org.apache.syncope.client.console.pages.EditUserModalPage;
 +import org.apache.syncope.client.console.pages.ResultStatusModalPage;
 +import org.apache.syncope.client.console.pages.StatusModalPage;
 +import org.apache.syncope.client.console.rest.AbstractSubjectRestClient;
 +import org.apache.syncope.client.console.rest.SchemaRestClient;
 +import org.apache.syncope.client.console.rest.UserRestClient;
 +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
 +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.AttrColumn;
 +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
 +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.TokenColumn;
 +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
 +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
 +import org.apache.syncope.common.lib.SyncopeClientException;
 +import org.apache.syncope.common.lib.to.AbstractAttributableTO;
 +import org.apache.syncope.common.lib.to.UserTO;
 +import org.apache.syncope.common.lib.types.AttributableType;
 +import org.apache.syncope.common.lib.types.SchemaType;
 +import org.apache.wicket.Page;
 +import org.apache.wicket.PageReference;
 +import org.apache.wicket.ajax.AjaxRequestTarget;
 +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
 +import org.apache.wicket.model.IModel;
 +import org.apache.wicket.model.Model;
 +import org.apache.wicket.model.ResourceModel;
 +import org.apache.wicket.spring.injection.annot.SpringBean;
 +import org.springframework.util.ReflectionUtils;
 +
 +public class UserSearchResultPanel extends AbstractSearchResultPanel {
 +
 +    private static final long serialVersionUID = -905187144506842332L;
 +
 +    private final static String PAGEID = "Users";
 +
 +    @SpringBean
 +    private SchemaRestClient schemaRestClient;
 +
 +    private final List<String> pSchemaNames;
 +
 +    private final List<String> dSchemaNames;
 +
-     private final List<String> vSchemaNames;
- 
 +    public <T extends AbstractAttributableTO> UserSearchResultPanel(final String id, final boolean filtered,
 +            final String fiql, final PageReference callerRef, final AbstractSubjectRestClient restClient) {
 +
 +        super(id, filtered, fiql, callerRef, restClient);
 +
 +        this.pSchemaNames = schemaRestClient.getPlainSchemaNames(AttributableType.USER);
 +        this.dSchemaNames = schemaRestClient.getDerSchemaNames(AttributableType.USER);
-         this.vSchemaNames = schemaRestClient.getVirSchemaNames(AttributableType.USER);
 +
 +        initResultTable();
 +    }
 +
 +    @Override
 +    protected List<IColumn<AbstractAttributableTO, String>> getColumns() {
 +        final List<IColumn<AbstractAttributableTO, String>> columns = new ArrayList<>();
 +
 +        for (String name : prefMan.getList(getRequest(), Constants.PREF_USERS_DETAILS_VIEW)) {
 +            final Field field = ReflectionUtils.findField(UserTO.class, name);
 +
 +            if ("token".equalsIgnoreCase(name)) {
 +                columns.add(new TokenColumn("token"));
 +            } else if (field != null && field.getType().equals(Date.class)) {
 +                columns.add(new DatePropertyColumn<AbstractAttributableTO>(new ResourceModel(name, name), name, name));
 +            } else {
 +                columns.add(
 +                        new PropertyColumn<AbstractAttributableTO, String>(new ResourceModel(name, name), name, name));
 +            }
 +        }
 +
 +        for (String name : prefMan.getList(getRequest(), Constants.PREF_USERS_ATTRIBUTES_VIEW)) {
 +            if (pSchemaNames.contains(name)) {
 +                columns.add(new AttrColumn(name, SchemaType.PLAIN));
 +            }
 +        }
 +
 +        for (String name : prefMan.getList(getRequest(), Constants.PREF_USERS_DERIVED_ATTRIBUTES_VIEW)) {
 +            if (dSchemaNames.contains(name)) {
 +                columns.add(new AttrColumn(name, SchemaType.DERIVED));
 +            }
 +        }
 +
-         for (String name : prefMan.getList(getRequest(), Constants.PREF_USERS_VIRTUAL_ATTRIBUTES_VIEW)) {
-             if (vSchemaNames.contains(name)) {
-                 columns.add(new AttrColumn(name, SchemaType.VIRTUAL));
-             }
-         }
- 
 +        // Add defaults in case of no selection
 +        if (columns.isEmpty()) {
 +            for (String name : DisplayAttributesModalPage.DEFAULT_SELECTION) {
 +                columns.add(
 +                        new PropertyColumn<AbstractAttributableTO, String>(new ResourceModel(name, name), name, name));
 +            }
 +
 +            prefMan.setList(getRequest(), getResponse(), Constants.PREF_USERS_DETAILS_VIEW,
 +                    Arrays.asList(DisplayAttributesModalPage.DEFAULT_SELECTION));
 +        }
 +
 +        columns.add(new ActionColumn<AbstractAttributableTO, String>(new ResourceModel("actions", "")) {
 +
 +            private static final long serialVersionUID = -3503023501954863131L;
 +
 +            @Override
 +            public ActionLinksPanel getActions(final String componentId, final IModel<AbstractAttributableTO> model) {
 +
 +                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, page.getPageReference());
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -7978723352517770644L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        statusmodal.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                            private static final long serialVersionUID = -7834632442532690940L;
 +
 +                            @Override
 +                            public Page createPage() {
 +                                return new StatusModalPage<UserTO>(
 +                                        page.getPageReference(), statusmodal, (UserTO) model.getObject());
 +                            }
 +                        });
 +
 +                        statusmodal.show(target);
 +                    }
 +                }, ActionLink.ActionType.MANAGE_RESOURCES, PAGEID);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -7978723352517770644L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        statusmodal.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                            private static final long serialVersionUID = -7834632442532690940L;
 +
 +                            @Override
 +                            public Page createPage() {
 +                                return new StatusModalPage<UserTO>(
 +                                        page.getPageReference(), statusmodal, (UserTO) model.getObject(), true);
 +                            }
 +                        });
 +
 +                        statusmodal.show(target);
 +                    }
 +                }, ActionLink.ActionType.ENABLE, PAGEID);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -7978723352517770644L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        editmodal.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                            private static final long serialVersionUID = -7834632442532690940L;
 +
 +                            @Override
 +                            public Page createPage() {
 +                                // SYNCOPE-294: re-read userTO before edit
 +                                UserTO userTO = ((UserRestClient) restClient).read(model.getObject().getKey());
 +                                return new EditUserModalPage(page.getPageReference(), editmodal, userTO);
 +                            }
 +                        });
 +
 +                        editmodal.show(target);
 +                    }
 +                }, ActionLink.ActionType.EDIT, PAGEID);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -7978723352517770644L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        try {
 +                            final UserTO userTO = (UserTO) restClient.
 +                                    delete(model.getObject().getETagValue(), model.getObject().getKey());
 +
 +                            page.setModalResult(true);
 +
 +                            editmodal.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                                private static final long serialVersionUID = -7834632442532690940L;
 +
 +                                @Override
 +                                public Page createPage() {
 +                                    return new ResultStatusModalPage.Builder(editmodal, userTO).build();
 +                                }
 +                            });
 +
 +                            editmodal.show(target);
 +                        } catch (SyncopeClientException scce) {
 +                            error(getString(Constants.OPERATION_ERROR) + ": " + scce.getMessage());
 +                            feedbackPanel.refresh(target);
 +                        }
 +                    }
 +                }, ActionLink.ActionType.DELETE, PAGEID);
 +
 +                return panel;
 +            }
 +
 +            @Override
 +            public ActionLinksPanel getHeader(final String componentId) {
 +                final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), page.getPageReference());
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -7978723352517770644L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        displaymodal.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                            private static final long serialVersionUID = -7834632442532690940L;
 +
 +                            @Override
 +                            public Page createPage() {
 +                                return new DisplayAttributesModalPage(page.getPageReference(), displaymodal,
-                                         pSchemaNames, dSchemaNames, vSchemaNames);
++                                        pSchemaNames, dSchemaNames);
 +                            }
 +                        });
 +
 +                        displaymodal.show(target);
 +                    }
 +                }, ActionLink.ActionType.CHANGE_VIEW, PAGEID);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -7978723352517770644L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        if (target != null) {
 +                            target.add(container);
 +                        }
 +                    }
 +                }, ActionLink.ActionType.RELOAD, PAGEID, "list");
 +
 +                return panel;
 +            }
 +        });
 +
 +        return columns;
 +    }
 +
 +    @Override
 +    protected <T extends AbstractAttributableTO> Collection<ActionType> getBulkActions() {
 +        final List<ActionType> bulkActions = new ArrayList<ActionType>();
 +
 +        bulkActions.add(ActionType.DELETE);
 +        bulkActions.add(ActionType.SUSPEND);
 +        bulkActions.add(ActionType.REACTIVATE);
 +
 +        return bulkActions;
 +    }
 +
 +    @Override
 +    protected String getPageId() {
 +        return PAGEID;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/old_console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
index bca0e28,0000000..fff02bb
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
@@@ -1,228 -1,0 +1,228 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.client.console.rest;
 +
 +import java.util.List;
 +import javax.ws.rs.core.Response;
 +import org.apache.syncope.client.console.commons.status.StatusBean;
 +import org.apache.syncope.client.console.commons.status.StatusUtils;
 +import org.apache.syncope.common.lib.SyncopeClientException;
 +import org.apache.syncope.common.lib.mod.ResourceAssociationMod;
 +import org.apache.syncope.common.lib.mod.StatusMod;
 +import org.apache.syncope.common.lib.mod.UserMod;
 +import org.apache.syncope.common.lib.to.BulkAction;
 +import org.apache.syncope.common.lib.to.BulkActionResult;
 +import org.apache.syncope.common.lib.to.ConnObjectTO;
 +import org.apache.syncope.common.lib.to.UserTO;
 +import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
 +import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
 +import org.apache.syncope.common.lib.types.SubjectType;
 +import org.apache.syncope.common.lib.wrap.ResourceName;
 +import org.apache.syncope.common.rest.api.CollectionWrapper;
 +import org.apache.syncope.common.rest.api.service.ResourceService;
 +import org.apache.syncope.common.rest.api.service.UserService;
 +import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 +import org.springframework.stereotype.Component;
 +
 +/**
 + * Console client for invoking rest users services.
 + */
 +@Component
 +public class UserRestClient extends AbstractSubjectRestClient {
 +
 +    private static final long serialVersionUID = -1575748964398293968L;
 +
 +    @Override
 +    public int count() {
 +        return getService(UserService.class).list(1, 1).getTotalCount();
 +    }
 +
 +    @Override
 +    public List<UserTO> list(final int page, final int size, final SortParam<String> sort) {
-         return getService(UserService.class).list(page, size, toOrderBy(sort)).getResult();
++        return getService(UserService.class).list(page, size, toOrderBy(sort), false).getResult();
 +    }
 +
 +    public UserTO create(final UserTO userTO, final boolean storePassword) {
 +        Response response = getService(UserService.class).create(userTO, storePassword);
 +        return response.readEntity(UserTO.class);
 +    }
 +
 +    public UserTO update(final String etag, final UserMod userMod) {
 +        UserTO result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            result = service.update(userMod.getKey(), userMod).readEntity(UserTO.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    @Override
 +    public UserTO delete(final String etag, final Long id) {
 +        UserTO result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            result = service.delete(id).readEntity(UserTO.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    public UserTO read(final Long id) {
 +        UserTO userTO = null;
 +        try {
 +            userTO = getService(UserService.class).read(id);
 +        } catch (SyncopeClientException e) {
 +            LOG.error("While reading a user", e);
 +        }
 +        return userTO;
 +    }
 +
 +    @Override
 +    public int searchCount(final String fiql) {
 +        return getService(UserService.class).search(fiql, 1, 1).getTotalCount();
 +    }
 +
 +    @Override
 +    public List<UserTO> search(final String fiql, final int page, final int size, final SortParam<String> sort) {
-         return getService(UserService.class).search(fiql, page, size, toOrderBy(sort)).getResult();
++        return getService(UserService.class).search(fiql, page, size, toOrderBy(sort), false).getResult();
 +    }
 +
 +    @Override
 +    public ConnObjectTO getConnectorObject(final String resourceName, final Long id) {
 +        return getService(ResourceService.class).getConnectorObject(resourceName, SubjectType.USER, id);
 +    }
 +
 +    public void suspend(final String etag, final long userId, final List<StatusBean> statuses) {
 +        StatusMod statusMod = StatusUtils.buildStatusMod(statuses, false);
 +        statusMod.setType(StatusMod.ModType.SUSPEND);
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            service.status(userId, statusMod);
 +            resetClient(UserService.class);
 +        }
 +    }
 +
 +    public void reactivate(final String etag, final long userId, final List<StatusBean> statuses) {
 +        StatusMod statusMod = StatusUtils.buildStatusMod(statuses, true);
 +        statusMod.setType(StatusMod.ModType.REACTIVATE);
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            service.status(userId, statusMod);
 +            resetClient(UserService.class);
 +        }
 +    }
 +
 +    @Override
 +    public BulkActionResult bulkAction(final BulkAction action) {
 +        return getService(UserService.class).bulk(action);
 +    }
 +
 +    public void unlink(final String etag, final long userId, final List<StatusBean> statuses) {
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            service.bulkDeassociation(userId, ResourceDeassociationActionType.UNLINK,
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceName.class));
 +            resetClient(UserService.class);
 +        }
 +    }
 +
 +    public void link(final String etag, final long userId, final List<StatusBean> statuses) {
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +
 +            final ResourceAssociationMod associationMod = new ResourceAssociationMod();
 +            associationMod.getTargetResources().addAll(
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceName.class));
 +            service.bulkAssociation(userId, ResourceAssociationActionType.LINK, associationMod);
 +
 +            resetClient(UserService.class);
 +        }
 +    }
 +
 +    public BulkActionResult deprovision(final String etag, final long userId, final List<StatusBean> statuses) {
 +        BulkActionResult result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            result = service.bulkDeassociation(userId, ResourceDeassociationActionType.DEPROVISION,
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceName.class)).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    public BulkActionResult provision(final String etag, final long userId,
 +            final List<StatusBean> statuses, final boolean changepwd, final String password) {
 +
 +        BulkActionResult result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +
 +            final ResourceAssociationMod associationMod = new ResourceAssociationMod();
 +            associationMod.getTargetResources().addAll(
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceName.class));
 +            associationMod.setChangePwd(changepwd);
 +            associationMod.setPassword(password);
 +
 +            result = service.bulkAssociation(userId, ResourceAssociationActionType.PROVISION, associationMod).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    public BulkActionResult unassign(final String etag, final long userId, final List<StatusBean> statuses) {
 +        BulkActionResult result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +            result = service.bulkDeassociation(userId, ResourceDeassociationActionType.UNASSIGN,
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceName.class)).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +
 +    public BulkActionResult assign(final String etag, final long userId,
 +            final List<StatusBean> statuses, final boolean changepwd, final String password) {
 +
 +        BulkActionResult result;
 +        synchronized (this) {
 +            UserService service = getService(etag, UserService.class);
 +
 +            final ResourceAssociationMod associationMod = new ResourceAssociationMod();
 +            associationMod.getTargetResources().addAll(
 +                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
 +                            ResourceName.class));
 +            associationMod.setChangePwd(changepwd);
 +            associationMod.setPassword(password);
 +
 +            result = service.bulkAssociation(userId, ResourceAssociationActionType.ASSIGN, associationMod).
 +                    readEntity(BulkActionResult.class);
 +            resetClient(UserService.class);
 +        }
 +        return result;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/client/old_console/src/main/resources/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.html
----------------------------------------------------------------------
diff --cc client/old_console/src/main/resources/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.html
index 998483d,0000000..4e4064c
mode 100644,000000..100644
--- a/client/old_console/src/main/resources/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.html
+++ b/client/old_console/src/main/resources/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.html
@@@ -1,132 -1,0 +1,130 @@@
 +<!--
 +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.
 +-->
 +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
 +  <wicket:head>
 +    <style>
 +      div.group{
 +        width:450px;
 +      }
 +
 +      div.group div{
 +        width:150;
 +        height: 25px;
 +        float:left;
 +      }
 +
 +      div.group div input {
 +        width: 30px;
 +      }
 +
 +      div#attributes-view {
 +        display:  block;
 +        clear:  both;
 +        float: none;
 +        overflow: auto;
 +        margin-top: 0px;
 +        margin-bottom: 20px;
 +        margin-left: 10px;
 +        margin-right: 10px;
 +      }
 +
 +      .submit{
 +        display:  block;
 +        clear:  both;
 +        float: none;
 +        margin-left: 10px;
 +      }
 +
 +      span.grouplabel{
 +        display:block;
 +        clear: both;
 +        margin-left: 10px;
 +        margin-bottom: 10px;
 +        font-weight: bold;
 +      }
 +    </style>
 +  </wicket:head>
 +  <wicket:extend>
 +    <form wicket:id="form">
 +      <div id="attributes-view">
 +        <p class="ui-widget ui-corner-all ui-widget-header">
 +          <wicket:message key="title"/>
 +        </p>
 +
 +        <span class="grouplabel"><wicket:message key="plainSchemas"/></span>
 +        <span wicket:id="dCheckGroup">
 +          <div class="group">
 +            <div wicket:id="details">
 +              <input type="checkbox" wicket:id="dcheck"/>
 +              <span wicket:id="dname">[schema name]</span>
 +            </div>
 +          </div>
 +        </span>
 +
 +        <span wicket:id="plainSchemas">[schemas]</span>
 +
 +        <span wicket:id="dschemas">[derived schemas]</span>
 +
-         <span wicket:id="vschemas">[virtual schemas]</span>
- 
 +      </div>
 +
 +      <wicket:fragment wicket:id="sfragment">
 +        <span wicket:id="psCheckGroup">
 +          <div class="group">
 +            <div wicket:id="plainSchemas">
 +              <input type="checkbox" wicket:id="scheck"/>
 +              <span wicket:id="sname">[schema name]</span>
 +            </div>
 +          </div>
 +        </span>
 +      </wicket:fragment>
 +
 +      <wicket:fragment wicket:id="dsfragment">
 +        <span class="grouplabel"><wicket:message key="derSchemas"/></span>
 +        <span wicket:id="dsCheckGroup">
 +          <div class="group">
 +            <div wicket:id="derSchemas">
 +              <input type="checkbox" wicket:id="dscheck"/>
 +              <span wicket:id="dsname">[schema name]</span>
 +            </div>
 +          </div>
 +        </span>
 +      </wicket:fragment>
 +
 +      <wicket:fragment wicket:id="vsfragment">
 +        <span class="grouplabel"><wicket:message key="virSchemas"/></span>
 +        <span wicket:id="vsCheckGroup">
 +          <div class="group">
 +            <div wicket:id="virSchemas">
 +              <input type="checkbox" wicket:id="vscheck"/>
 +              <span wicket:id="vsname">[schema name]</span>
 +            </div>
 +          </div>
 +        </span>
 +      </wicket:fragment>
 +
 +      <wicket:fragment wicket:id="emptyFragment">
 +      </wicket:fragment>
 +
 +      <div class="submit">
 +        <input type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" wicket:id="submit"/>
 +        <input type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" wicket:id="cancel"/>
 +      </div>
 +    </form>
 +  </wicket:extend>
 +</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ListQuery.java
----------------------------------------------------------------------
diff --cc common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ListQuery.java
index 1a85fe4,0000000..96fe514
mode 100644,000000..100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ListQuery.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ListQuery.java
@@@ -1,86 -1,0 +1,98 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.common.rest.api.beans;
 +
 +import java.io.Serializable;
 +import javax.validation.constraints.Min;
 +import javax.ws.rs.DefaultValue;
 +import javax.ws.rs.QueryParam;
 +import org.apache.commons.lang3.builder.EqualsBuilder;
 +import org.apache.commons.lang3.builder.HashCodeBuilder;
 +import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
 +import org.apache.commons.lang3.builder.ToStringStyle;
 +import org.apache.syncope.common.rest.api.service.JAXRSService;
 +
 +public class ListQuery implements Serializable {
 +
 +    private static final long serialVersionUID = -371488230250055359L;
 +
 +    private Integer page;
 +
 +    private Integer size;
 +
 +    private String orderBy;
 +
++    private Boolean details;
++
 +    public Integer getPage() {
 +        return page;
 +    }
 +
 +    @Min(1)
 +    @QueryParam(JAXRSService.PARAM_PAGE)
 +    @DefaultValue("1")
 +    public void setPage(final Integer page) {
 +        this.page = page;
 +    }
 +
 +    public Integer getSize() {
 +        return size;
 +    }
 +
 +    @Min(1)
 +    @QueryParam(JAXRSService.PARAM_SIZE)
 +    @DefaultValue("25")
 +    public void setSize(final Integer size) {
 +        this.size = size;
 +    }
 +
 +    @QueryParam(JAXRSService.PARAM_ORDERBY)
 +    public String getOrderBy() {
 +        return orderBy;
 +    }
 +
 +    public void setOrderBy(final String orderBy) {
 +        this.orderBy = orderBy;
 +    }
 +
++    @QueryParam(JAXRSService.PARAM_DETAILS)
++    @DefaultValue("true")
++    public boolean isDetails() {
++        return details == null ? true : details;
++    }
++
++    public void setDetails(final boolean details) {
++        this.details = details;
++    }
++
 +    @Override
 +    public boolean equals(final Object obj) {
 +        return EqualsBuilder.reflectionEquals(this, obj);
 +    }
 +
 +    @Override
 +    public int hashCode() {
 +        return HashCodeBuilder.reflectionHashCode(this);
 +    }
 +
 +    @Override
 +    public String toString() {
 +        return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
----------------------------------------------------------------------
diff --cc common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
index bfd166a,0000000..c6c73d5
mode 100644,000000..100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
@@@ -1,31 -1,0 +1,33 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.common.rest.api.service;
 +
 +public interface JAXRSService {
 +
 +    String PARAM_FIQL = "fiql";
 +
 +    String PARAM_PAGE = "page";
 +
 +    String PARAM_SIZE = "size";
 +
 +    String PARAM_ORDERBY = "orderby";
 +
++    String PARAM_DETAILS = "details";
++
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/97607b16/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
----------------------------------------------------------------------
diff --cc core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
index d24b08e,0000000..6f66113
mode 100644,000000..100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
@@@ -1,86 -1,0 +1,92 @@@
 +/*
 + * 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.util.Collection;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Set;
 +import org.apache.commons.collections4.CollectionUtils;
 +import org.apache.commons.collections4.Predicate;
 +import org.apache.syncope.common.lib.mod.AnyMod;
 +import org.apache.syncope.common.lib.to.AnyTO;
 +import org.apache.syncope.core.misc.RealmUtils;
 +import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 +import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 +
 +public abstract class AbstractAnyLogic<TO extends AnyTO, MOD extends AnyMod>
 +        extends AbstractResourceAssociator<TO> {
 +
 +    private static class StartsWithPredicate implements Predicate<String> {
 +
 +        private final Collection<String> targets;
 +
 +        public StartsWithPredicate(final Collection<String> targets) {
 +            this.targets = targets;
 +        }
 +
 +        @Override
 +        public boolean evaluate(final String realm) {
 +            return CollectionUtils.exists(targets, new Predicate<String>() {
 +
 +                @Override
 +                public boolean evaluate(final String target) {
 +                    return realm.startsWith(target);
 +                }
 +            });
 +        }
 +
 +    }
 +
 +    protected Set<String> getEffectiveRealms(
 +            final Set<String> allowedRealms, final Collection<String> requestedRealms) {
 +
 +        final Set<String> allowed = RealmUtils.normalize(allowedRealms);
 +        final Set<String> requested = RealmUtils.normalize(requestedRealms);
 +
 +        Set<String> effective = new HashSet<>();
 +        CollectionUtils.select(requested, new StartsWithPredicate(allowed), effective);
 +        CollectionUtils.select(allowed, new StartsWithPredicate(requested), effective);
 +
 +        return effective;
 +    }
 +
 +    public abstract TO read(Long key);
 +
 +    public abstract int count(List<String> realms);
 +
 +    public abstract TO create(TO anyTO);
 +
 +    public abstract TO update(MOD anyMod);
 +
 +    public abstract TO delete(Long key);
 +
-     public abstract List<TO> list(int page, int size, List<OrderByClause> orderBy, List<String> realms);
++    public abstract List<TO> list(
++            int page, int size, List<OrderByClause> orderBy,
++            List<String> realms,
++            boolean details);
 +
 +    public abstract List<TO> search(
-             SearchCond searchCondition, int page, int size, List<OrderByClause> orderBy, List<String> realms);
++            SearchCond searchCondition,
++            int page, int size, List<OrderByClause> orderBy,
++            List<String> realms,
++            boolean details);
 +
 +    public abstract int searchCount(SearchCond searchCondition, List<String> realms);
 +}