You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by gi...@apache.org on 2015/07/30 10:01:43 UTC

[2/2] syncope git commit: [SYNCOPE-156] Realm page now displays user groups and any object

[SYNCOPE-156] Realm page now displays user groups and any object


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

Branch: refs/heads/SYNCOPE-156
Commit: 518f7bef2c019191b8a20a0ace8862f7b4573d48
Parents: 7eca0ab
Author: giacomolm <gi...@hotmail.it>
Authored: Thu Jul 30 10:01:17 2015 +0200
Committer: giacomolm <gi...@hotmail.it>
Committed: Thu Jul 30 10:01:17 2015 +0200

----------------------------------------------------------------------
 .../client/console/commons/AnyDataProvider.java |  16 +-
 .../client/console/commons/Constants.java       |  12 +
 .../pages/AnyDisplayAttributesModalPage.java    |  61 ++
 .../pages/DisplayAttributesModalPage.java       | 236 +++++++
 .../console/pages/EditRealmModalPage.java       |  41 ++
 .../pages/GroupDisplayAttributesModalPage.java  |  61 ++
 .../console/pages/ProvisioningModalPage.java    |   4 +-
 .../client/console/pages/RealmModalPage.java    | 142 ++++
 .../syncope/client/console/pages/Realms.java    |  84 ++-
 .../client/console/pages/StatusModalPage.java   | 641 +++++++++++++++++++
 .../pages/UserDisplayAttributesModalPage.java   |  62 ++
 .../panels/AbstractSearchResultPanel.java       |  18 +-
 .../console/panels/AjaxDataTablePanel.java      |   4 +
 .../syncope/client/console/panels/Any.java      |  35 -
 .../console/panels/AnySearchResultPanel.java    | 264 ++++++++
 .../client/console/panels/AnyTypeMenuItem.java  |  43 ++
 .../console/panels/GroupSearchResultPanel.java  | 234 +++++++
 .../syncope/client/console/panels/Realm.java    | 100 ++-
 .../client/console/panels/RealmDetails.java     |   7 +-
 .../console/panels/UserSearchResultPanel.java   | 277 ++++++++
 .../console/rest/AbstractAnyRestClient.java     |   6 +-
 .../console/rest/AnyObjectRestClient.java       |  96 +++
 .../client/console/rest/AnyTypeRestClient.java  |  49 ++
 .../client/console/rest/GroupRestClient.java    |   8 +-
 .../client/console/rest/RealmRestClient.java    |   5 +-
 .../client/console/rest/UserRestClient.java     |   8 +-
 .../html/repeater/data/table/ActionColumn.java  |  59 ++
 .../html/repeater/data/table/AttrColumn.java    |  84 +++
 .../META-INF/resources/css/AdminLTE.css         |   4 +
 .../META-INF/resources/css/syncopeConsole.css   | 134 ++--
 .../pages/DisplayAttributesModalPage.html       | 118 ++++
 .../pages/DisplayAttributesModalPage.properties |  32 +
 .../client/console/pages/RealmModalPage.html    |  70 ++
 .../syncope/client/console/pages/Realms.html    |  13 +-
 .../console/panels/AjaxDataTablePanel.html      |   2 +-
 .../syncope/client/console/panels/Any.html      |  29 -
 .../client/console/panels/AnyTypeMenuItem.html  |  29 +
 .../syncope/client/console/panels/Realm.html    |  64 +-
 .../client/console/panels/RealmDetails.html     |  36 +-
 .../markup/html/form/ActionLinksPanel.html      |  12 +-
 .../pages/DisplayAttributesModalPage.java       |   2 +-
 .../client/console/pages/EditUserModalPage.java |   2 +-
 42 files changed, 2954 insertions(+), 250 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java
index bd4183b..e13840c 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java
@@ -42,9 +42,12 @@ public class AnyDataProvider extends SortableDataProvider<AnyTO, String> {
 
     private final AbstractAnyRestClient restClient;
 
-    private final String realm = "/";
+    private final String realm;
 
-    public AnyDataProvider(final AbstractAnyRestClient restClient, final int paginatorRows, final boolean filtered) {
+    private final String type;
+
+    public AnyDataProvider(final AbstractAnyRestClient restClient, final int paginatorRows, final boolean filtered,
+            final String realm, final String type) {
         super();
 
         this.restClient = restClient;
@@ -55,6 +58,9 @@ public class AnyDataProvider extends SortableDataProvider<AnyTO, String> {
         setSort("key", SortOrder.ASCENDING);
 
         this.comparator = new SortableAnyProviderComparator(this);
+        
+        this.realm = realm;
+        this.type = type;
     }
 
     public void setFIQL(final String fiql) {
@@ -70,9 +76,9 @@ public class AnyDataProvider extends SortableDataProvider<AnyTO, String> {
         if (filtered) {
             result = fiql == null
                     ? Collections.<AnyTO>emptyList()
-                    : restClient.search(realm, fiql, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
+                    : restClient.search(realm, fiql, (page < 0 ? 0 : page) + 1, paginatorRows, getSort(), type);
         } else {
-            result = restClient.list(realm, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
+            result = restClient.list(realm, (page < 0 ? 0 : page) + 1, paginatorRows, getSort(), type);
         }
 
         Collections.sort(result, comparator);
@@ -86,7 +92,7 @@ public class AnyDataProvider extends SortableDataProvider<AnyTO, String> {
         if (filtered) {
             result = fiql == null
                     ? 0
-                    : restClient.searchCount(realm, fiql);
+                    : restClient.searchCount(realm, fiql, type);
         } else {
             result = restClient.count(realm);
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
----------------------------------------------------------------------
diff --git 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
index 98339ec..804f9fe 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
@@ -54,6 +54,12 @@ public final class Constants {
 
     public static final String PREF_USER_VIR_SCHEMA_PAGINATOR_ROWS = "user.virtual.schema.paginator.rows";
 
+    public static final String PREF_GROUP_DETAILS_VIEW = "group.details.view";
+
+    public static final String PREF_GROUP_ATTRIBUTES_VIEW = "group.attributes.view";
+
+    public static final String PREF_GROUP_DERIVED_ATTRIBUTES_VIEW = "group.derived.attributes.view";
+
     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";
@@ -91,6 +97,12 @@ public final class Constants {
     public static final String PAGEPARAM_CURRENT_PAGE = "_current_page";
 
     public static final String PREF_POLICY_PAGINATOR_ROWS = "policy.paginator.rows";
+    
+    public static final String PREF_ANY_DETAILS_VIEW = "any.details.view";
+    
+    public static final String PREF_ANY_ATTRIBUTES_VIEW = "any.attributes.view";
+
+    public static final String PREF_ANY_DERIVED_ATTRIBUTES_VIEW = "any.derived.attributes.view";
 
     /**
      * ConnId's GuardedString is not in the classpath.

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/AnyDisplayAttributesModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/AnyDisplayAttributesModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/AnyDisplayAttributesModalPage.java
new file mode 100644
index 0000000..63223a0
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/AnyDisplayAttributesModalPage.java
@@ -0,0 +1,61 @@
+/*
+ * 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.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+
+/**
+ * Modal window with Display user attributes form.
+ */
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public class AnyDisplayAttributesModalPage extends DisplayAttributesModalPage {
+
+    private static final long serialVersionUID = 5194630813773543054L;
+
+    public static final String[] ANY_DEFAULT_SELECTION = { "key" };
+
+    public AnyDisplayAttributesModalPage(final PageReference pageRef, final ModalWindow window,
+            final List<String> schemaNames, final List<String> dSchemaNames) {
+        super(pageRef, window, schemaNames, dSchemaNames);
+    }
+
+    @Override
+    public String getPrefDetailView() {
+        return Constants.PREF_ANY_DETAILS_VIEW;
+    }
+
+    @Override
+    public String getPrefAttributeView() {
+        return Constants.PREF_ANY_ATTRIBUTES_VIEW;
+    }
+
+    @Override
+    public String getPrefDerivedAttributeView() {
+        return Constants.PREF_ANY_DERIVED_ATTRIBUTES_VIEW;
+    }
+
+    @Override
+    public Class getTOClass() {
+        return AnyObjectTO.class;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java
new file mode 100644
index 0000000..769cb45
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java
@@ -0,0 +1,236 @@
+/*
+ * 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.PreferenceManager;
+import org.apache.syncope.common.lib.search.SearchableFields;
+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 abstract class DisplayAttributesModalPage extends BaseModalPage {
+
+    private static final long serialVersionUID = -4274117450918385110L;
+
+    /**
+     * Max allowed selections.
+     */
+    private static final int MAX_SELECTIONS = 9;
+
+    @SpringBean
+    private PreferenceManager prefMan;
+
+    private final List<String> selectedDetails;
+
+    private final List<String> selectedPlainSchemas;
+
+    private final List<String> selectedDerSchemas;
+
+    public DisplayAttributesModalPage(final PageReference pageRef, final ModalWindow window,
+            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(getTOClass());
+            }
+        };
+
+        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 Form form = new Form(FORM);
+        form.setModel(new CompoundPropertyModel(this));
+
+        selectedDetails = prefMan.getList(getRequest(), getPrefDetailView());
+
+        selectedPlainSchemas = prefMan.getList(getRequest(), getPrefAttributeView());
+
+        selectedDerSchemas = prefMan.getList(getRequest(), getPrefDerivedAttributeView());
+
+        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(final ListItem<String> item) {
+                    item.add(new Check("dscheck", item.getModel()));
+                    item.add(new Label("dsname", new ResourceModel(item.getModelObject(), item.getModelObject())));
+                }
+            };
+            dsgroup.add(derSchemas);
+        }
+
+        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() + selectedDerSchemas.size()
+                        > MAX_SELECTIONS) {
+
+                    error(getString("tooManySelections"));
+                    onError(target, form);
+                } else {
+                    final Map<String, List<String>> prefs = new HashMap<>();
+
+                    prefs.put(getPrefDetailView(), selectedDetails);
+
+                    prefs.put(getPrefAttributeView(), selectedPlainSchemas);
+
+                    prefs.put(getPrefDerivedAttributeView(), selectedDerSchemas);
+
+                    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);
+    }
+
+    public abstract String getPrefDetailView();
+
+    public abstract String getPrefAttributeView();
+
+    public abstract String getPrefDerivedAttributeView();
+    
+    public abstract Class getTOClass();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/EditRealmModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/EditRealmModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/EditRealmModalPage.java
new file mode 100644
index 0000000..248162e
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/EditRealmModalPage.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+
+public class EditRealmModalPage<T extends AnyTO> extends RealmModalPage {
+
+    private static final long serialVersionUID = -4285220460543213901L;
+
+    public EditRealmModalPage(
+            final PageReference pageRef,
+            final ModalWindow window,
+            final RealmTO realmTO,
+            final String parentPath,
+            final String entitlement) {
+
+        super(pageRef, window, realmTO, parentPath, entitlement);
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/GroupDisplayAttributesModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/GroupDisplayAttributesModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/GroupDisplayAttributesModalPage.java
new file mode 100644
index 0000000..0e5e10f
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/GroupDisplayAttributesModalPage.java
@@ -0,0 +1,61 @@
+/*
+ * 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.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+
+/**
+ * Modal window with Display group attributes form.
+ */
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public class GroupDisplayAttributesModalPage extends DisplayAttributesModalPage {
+
+    private static final long serialVersionUID = 5194630813773543054L;
+
+    public static final String[] GROUP_DEFAULT_SELECTION = { "key", "name" };
+
+    public GroupDisplayAttributesModalPage(final PageReference pageRef, final ModalWindow window,
+            final List<String> schemaNames, final List<String> dSchemaNames) {
+        super(pageRef, window, schemaNames, dSchemaNames);
+    }
+
+    @Override
+    public String getPrefDetailView() {
+        return Constants.PREF_GROUP_DETAILS_VIEW;
+    }
+
+    @Override
+    public String getPrefAttributeView() {
+        return Constants.PREF_GROUP_ATTRIBUTES_VIEW;
+    }
+
+    @Override
+    public String getPrefDerivedAttributeView() {
+        return Constants.PREF_GROUP_DERIVED_ATTRIBUTES_VIEW;
+    }
+
+    @Override
+    public Class getTOClass() {
+        return GroupTO.class;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java
index 9937e36..6e44d62 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java
@@ -198,10 +198,10 @@ public class ProvisioningModalPage<T extends AnyTO> extends AbstractStatusModalP
             final List<T> subjects = new ArrayList<>();
             if (anyTypeKind == AnyTypeKind.USER) {
                 subjects.addAll((List<T>) userRestClient.search(
-                        realm, fiql, 1, ROWS_PER_PAGE, new SortParam<>("key", true)));
+                        realm, fiql, 1, ROWS_PER_PAGE, new SortParam<>("key", true), AnyTypeKind.USER.toString()));
             } else {
                 subjects.addAll((List<T>) groupRestClient.search(
-                        realm, fiql, 1, ROWS_PER_PAGE, new SortParam<>("key", true)));
+                        realm, fiql, 1, ROWS_PER_PAGE, new SortParam<>("key", true), AnyTypeKind.GROUP.toString()));
             }
 
             final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/RealmModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/RealmModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/RealmModalPage.java
new file mode 100644
index 0000000..5b8526d
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/RealmModalPage.java
@@ -0,0 +1,142 @@
+/*
+ * 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 static org.apache.syncope.client.console.pages.AbstractBasePage.CANCEL;
+import static org.apache.wicket.Component.ENABLE;
+
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.RealmDetails;
+import org.apache.syncope.client.console.rest.RealmRestClient;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+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.form.Form;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class RealmModalPage<T extends AnyTO> extends BaseModalPage {
+
+    private static final long serialVersionUID = -4285220460543213901L;
+
+    private static final int ROWS_PER_PAGE = 10;
+
+    protected RealmTO realmTO;
+
+    private final PageReference pageRef;
+
+    private final ModalWindow window;
+
+    @SpringBean
+    private RealmRestClient realmRestClient;
+    
+    private final String parentPath;
+
+    public RealmModalPage(
+            final PageReference pageRef,
+            final ModalWindow window,
+            final RealmTO realmTO,
+            final String parentPath,
+            final String entitlement) {
+
+        super();
+
+        this.pageRef = pageRef;
+        this.window = window;
+        this.realmTO = realmTO;
+        this.parentPath = parentPath;
+
+        final Form<RealmTO> form = new Form<RealmTO>("RealmForm");
+        form.setModel(new CompoundPropertyModel<RealmTO>(realmTO));
+
+        RealmDetails realmDetail = new RealmDetails("details", realmTO);
+        if (SyncopeConsoleSession.get().owns(entitlement)) {
+            MetaDataRoleAuthorizationStrategy.authorize(realmDetail, ENABLE, entitlement);
+        }
+        form.add(realmDetail);
+
+        final AjaxButton submit = getOnSubmit();
+        form.add(submit);
+        form.setDefaultButton(submit);
+
+        final AjaxButton cancel = new AjaxButton(CANCEL, new ResourceModel(CANCEL)) {
+
+            private static final long serialVersionUID = 530608535790823587L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                window.close(target);
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+            }
+        };
+
+        cancel.setDefaultFormProcessing(false);
+        form.add(cancel);
+
+        add(form);
+    }
+
+    protected AjaxButton getOnSubmit() {
+        return new IndicatingAjaxButton(APPLY, new ResourceModel(SUBMIT)) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                try {
+                    submitAction(target, form);
+
+                    if (pageRef.getPage() instanceof BasePage) {
+                        ((BasePage) pageRef.getPage()).setModalResult(true);
+                    }
+
+                    closeAction(target, form);
+                } catch (Exception e) {
+                    LOG.error("While creating or updating user", e);
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                    feedbackPanel.refresh(target);
+                }
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+                feedbackPanel.refresh(target);
+            }
+        };
+    }
+
+    protected void submitAction(final AjaxRequestTarget target, final Form<?> form) {
+        final RealmTO updatedRealmTO = (RealmTO) form.getModelObject();
+        realmRestClient.create(this.parentPath, updatedRealmTO);
+    }
+
+    protected void closeAction(final AjaxRequestTarget target, final Form<?> form) {
+        this.window.close(target);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
index daee99c..50378ed 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.client.console.pages;
 
+import static org.apache.wicket.Component.ENABLE;
+
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -25,14 +27,20 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.Realm;
 import org.apache.syncope.client.console.rest.RealmRestClient;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
 import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.types.Entitlement;
 import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.Page;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.event.IEvent;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.Fragment;
@@ -54,9 +62,13 @@ public class Realms extends BasePage {
 
     private final WebMarkupContainer content;
 
+    private final ModalWindow editModalWin;
+
+    protected RealmTO currentRealm;
+
     public Realms(final PageParameters parameters) {
         super(parameters);
-
+        
         final List<RealmTO> realms = realmRestClient.list();
         Collections.sort(realms, new RealmNameComparator());
 
@@ -68,6 +80,40 @@ public class Realms extends BasePage {
 
         content.add(new Label("header", "Root realm"));
         content.add(new Label("body", "Root realm"));
+
+        //create new realms                
+        final AjaxLink<Void> createLink = new ClearIndicatingAjaxLink<Void>("createLink", getPageReference()) {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            protected void onClickInternal(final AjaxRequestTarget target) {
+                editModalWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = -7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        return new RealmModalPage(Realms.this.getPageReference(), editModalWin, new RealmTO(),
+                                Realms.this.getCurrentRealm().getFullPath(), Entitlement.REALM_CREATE);
+                    }
+                });
+
+                editModalWin.show(target);
+            }
+        };
+        if (SyncopeConsoleSession.get().owns(Entitlement.REALM_CREATE)) {
+            MetaDataRoleAuthorizationStrategy.authorize(createLink, ENABLE, Entitlement.REALM_CREATE);
+        }
+        content.add(createLink);
+
+        // Modal window for editing realms
+        editModalWin = new ModalWindow("editModal");
+        editModalWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        editModalWin.setCookieName("edit-modal");
+
+        content.add(editModalWin);
+        setCurrentRealm(realms.get(0));
     }
 
     private void add(final Map<Long, List<RealmTO>> parentMap, final Long key, final MarkupContainer container) {
@@ -83,6 +129,7 @@ public class Realms extends BasePage {
 
                 @Override
                 public void onClick(final AjaxRequestTarget target) {
+                    Realms.this.setCurrentRealm(realm);
                     send(Realms.this, Broadcast.EXACT, new ControlSidebarClick<>(realm, target));
                 }
             };
@@ -148,11 +195,44 @@ public class Realms extends BasePage {
             @SuppressWarnings("unchecked")
             final ControlSidebarClick<RealmTO> controlSidebarClick = ControlSidebarClick.class.cast(event.getPayload());
             content.addOrReplace(new Label("header", controlSidebarClick.getObj().getName()));
-            content.addOrReplace(new Realm("body", controlSidebarClick.getObj()));
+            content.addOrReplace(new Realm("body", controlSidebarClick.getObj(), getPageReference()));
             controlSidebarClick.getTarget().add(content);
         }
     }
 
+    public void setCurrentRealm(final RealmTO realmTO) {
+        this.currentRealm = realmTO;
+        setupEditModalPage(currentRealm);
+    }
+
+    public RealmTO getCurrentRealm() {
+        return this.currentRealm;
+    }
+
+    public void setupEditModalPage(final RealmTO realmTO) {
+        final AjaxLink<Void> edit = new ClearIndicatingAjaxLink<Void>("edit", getPageReference()) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void onClickInternal(final AjaxRequestTarget target) {
+                editModalWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = -7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        return new EditRealmModalPage(Realms.this.getPageReference(), editModalWin, realmTO,
+                                Realms.this.getCurrentRealm().getFullPath(), Entitlement.REALM_UPDATE);
+                    }
+                });
+
+                editModalWin.show(target);
+            }
+        };
+        content.addOrReplace(edit);
+    }
+
     private static class ControlSidebarClick<T> {
 
         private final AjaxRequestTarget target;

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java
new file mode 100644
index 0000000..6ebb7be
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java
@@ -0,0 +1,641 @@
+/*
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider;
+import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.console.commons.status.Status;
+import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.console.panels.ActionDataTablePanel;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.PasswordTextField;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.StringResourceModel;
+
+public class StatusModalPage<T extends AnyTO> extends AbstractStatusModalPage {
+
+    private static final long serialVersionUID = -9148734710505211261L;
+
+    private final AnyTO anyTO;
+
+    private int rowsPerPage = 10;
+
+    private final StatusUtils statusUtils;
+
+    private final boolean statusOnly;
+
+    // --------------------------------
+    // password management fields ..
+    // --------------------------------
+    private final ClearIndicatingAjaxButton cancel;
+
+    private final WebMarkupContainer pwdMgt;
+
+    private final Form<?> pwdMgtForm;
+
+    private final AjaxCheckBoxPanel changepwd;
+
+    private final PasswordTextField password;
+
+    private final PasswordTextField confirm;
+    // --------------------------------
+
+    private final PageReference pageRef;
+
+    private final ModalWindow window;
+
+    private final ActionDataTablePanel<StatusBean, String> table;
+
+    private final List<IColumn<StatusBean, String>> columns;
+
+    public StatusModalPage(
+            final PageReference pageRef,
+            final ModalWindow window,
+            final AnyTO attributableTO) {
+
+        this(pageRef, window, attributableTO, false);
+    }
+
+    public StatusModalPage(
+            final PageReference pageRef,
+            final ModalWindow window,
+            final AnyTO anyTO,
+            final boolean statusOnly) {
+
+        super();
+
+        this.pageRef = pageRef;
+        this.window = window;
+        this.statusOnly = statusOnly;
+        this.anyTO = anyTO;
+
+        statusUtils = new StatusUtils(anyTO instanceof UserTO ? userRestClient : groupRestClient);
+
+        add(new Label("displayName", anyTO.getKey() + " "
+                + (anyTO instanceof UserTO ? ((UserTO) anyTO).getUsername() : ((GroupTO) anyTO).getName())));
+
+        columns = new ArrayList<>();
+        columns.add(new AbstractColumn<StatusBean, String>(
+                new StringResourceModel("resourceName", this, null), "resourceName") {
+
+                    private static final long serialVersionUID = 2054811145491901166L;
+
+                    @Override
+                    public void populateItem(
+                            final Item<ICellPopulator<StatusBean>> cellItem,
+                            final String componentId,
+                            final IModel<StatusBean> model) {
+
+                                cellItem.add(new Label(componentId, model.getObject().getResourceName()) {
+
+                                    private static final long serialVersionUID = 8432079838783825801L;
+
+                                    @Override
+                                    protected void onComponentTag(final ComponentTag tag) {
+                                        if (model.getObject().isLinked()) {
+                                            super.onComponentTag(tag);
+                                        } else {
+                                            tag.put("style", "color: #DDDDDD");
+                                        }
+                                    }
+                                });
+                            }
+                });
+
+        columns.add(new PropertyColumn<StatusBean, String>(
+                new StringResourceModel("accountLink", this, null), "accountLink", "accountLink"));
+
+        columns.add(new AbstractColumn<StatusBean, String>(
+                new StringResourceModel("status", this, null)) {
+
+                    private static final long serialVersionUID = -3503023501954863131L;
+
+                    @Override
+                    public String getCssClass() {
+                        return "action";
+                    }
+
+                    @Override
+                    public void populateItem(
+                            final Item<ICellPopulator<StatusBean>> cellItem,
+                            final String componentId,
+                            final IModel<StatusBean> model) {
+
+                                if (model.getObject().isLinked()) {
+                                    cellItem.add(statusUtils.getStatusImagePanel(componentId, model.getObject().
+                                                    getStatus()));
+                                } else {
+                                    cellItem.add(new Label(componentId, ""));
+                                }
+                            }
+                });
+
+        table = new ActionDataTablePanel<StatusBean, String>(
+                "resourceDatatable",
+                columns,
+                (ISortableDataProvider<StatusBean, String>) new AttributableStatusProvider(),
+                rowsPerPage,
+                pageRef) {
+
+                    private static final long serialVersionUID = 6510391461033818316L;
+
+                    @Override
+                    public boolean isElementEnabled(final StatusBean element) {
+                        return !statusOnly || element.getStatus() != Status.OBJECT_NOT_FOUND;
+                    }
+                };
+        table.setOutputMarkupId(true);
+
+        final String pageId = anyTO instanceof GroupTO ? "Groups" : "Users";
+
+        final Fragment pwdMgtFragment = new Fragment("pwdMgtFields", "pwdMgtFragment", this);
+        addOrReplace(pwdMgtFragment);
+
+        pwdMgt = new WebMarkupContainer("pwdMgt");
+        pwdMgtFragment.add(pwdMgt.setOutputMarkupId(true));
+
+        pwdMgtForm = new Form("pwdMgtForm");
+        pwdMgtForm.setVisible(false).setEnabled(false);
+        pwdMgt.add(pwdMgtForm);
+
+        password = new PasswordTextField("password", new Model<String>());
+        pwdMgtForm.add(password.setRequired(false).setEnabled(false));
+
+        confirm = new PasswordTextField("confirm", new Model<String>());
+        pwdMgtForm.add(confirm.setRequired(false).setEnabled(false));
+
+        changepwd = new AjaxCheckBoxPanel("changepwd", "changepwd", new Model<Boolean>(false));
+        pwdMgtForm.add(changepwd.setModelObject(false));
+        pwdMgtForm.add(new Label("changePwdLabel", new ResourceModel("changePwdLabel", "Password propagation")));
+
+        changepwd.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                password.setEnabled(changepwd.getModelObject());
+                confirm.setEnabled(changepwd.getModelObject());
+                target.add(pwdMgt);
+            }
+        });
+
+        cancel = new ClearIndicatingAjaxButton("cancel", new ResourceModel("cancel"), pageRef) {
+
+            private static final long serialVersionUID = -2341391430136818026L;
+
+            @Override
+            protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+                // ignore
+                window.close(target);
+            }
+        }.feedbackPanelAutomaticReload(false);
+
+        pwdMgtForm.add(cancel);
+
+        final ClearIndicatingAjaxButton goon =
+                new ClearIndicatingAjaxButton("continue", new ResourceModel("continue"), pageRef) {
+
+                    private static final long serialVersionUID = -2341391430136818027L;
+
+                    @Override
+                    protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+                        // none
+                    }
+                };
+
+        pwdMgtForm.add(goon);
+
+        if (statusOnly) {
+            table.addAction(new ActionLink() {
+
+                private static final long serialVersionUID = -3722207913631435501L;
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    try {
+                        userRestClient.reactivate(
+                                anyTO.getETagValue(),
+                                anyTO.getKey(),
+                                new ArrayList<>(table.getModelObject()));
+
+                        ((BasePage) pageRef.getPage()).setModalResult(true);
+
+                        window.close(target);
+                    } catch (Exception e) {
+                        LOG.error("Error enabling resources", e);
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        feedbackPanel.refresh(target);
+                    }
+                }
+            }, ActionLink.ActionType.REACTIVATE, pageId);
+
+            table.addAction(new ActionLink() {
+
+                private static final long serialVersionUID = -3722207913631435501L;
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    try {
+                        userRestClient.suspend(
+                                anyTO.getETagValue(),
+                                anyTO.getKey(),
+                                new ArrayList<>(table.getModelObject()));
+
+                        if (pageRef.getPage() instanceof BasePage) {
+                            ((BasePage) pageRef.getPage()).setModalResult(true);
+                        }
+
+                        window.close(target);
+                    } catch (Exception e) {
+                        LOG.error("Error disabling resources", e);
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        feedbackPanel.refresh(target);
+                    }
+                }
+            }, ActionLink.ActionType.SUSPEND, pageId);
+        } else {
+            table.addAction(new ActionLink() {
+
+                private static final long serialVersionUID = -3722207913631435501L;
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    try {
+                        if (anyTO instanceof UserTO) {
+                            userRestClient.unlink(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+                        } else {
+                            groupRestClient.unlink(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+                        }
+
+                        ((BasePage) pageRef.getPage()).setModalResult(true);
+                        window.close(target);
+                    } catch (Exception e) {
+                        LOG.error("Error unlinking resources", e);
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        feedbackPanel.refresh(target);
+                    }
+                }
+            }, ActionLink.ActionType.UNLINK, pageId);
+
+            table.addAction(new ActionLink() {
+
+                private static final long serialVersionUID = -3722207913631435501L;
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    try {
+                        if (anyTO instanceof UserTO) {
+                            userRestClient.link(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+                        } else {
+                            groupRestClient.link(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+                        }
+
+                        ((BasePage) pageRef.getPage()).setModalResult(true);
+                        window.close(target);
+                    } catch (Exception e) {
+                        LOG.error("Error linking resources", e);
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        feedbackPanel.refresh(target);
+                    }
+                }
+            }, ActionLink.ActionType.LINK, pageId);
+
+            table.addAction(new ActionLink() {
+
+                private static final long serialVersionUID = -3722207913631435501L;
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    try {
+                        BulkActionResult bulkActionResult;
+                        if (anyTO instanceof UserTO) {
+                            bulkActionResult = userRestClient.deprovision(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+                        } else {
+                            bulkActionResult = groupRestClient.deprovision(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+                        }
+
+                        ((BasePage) pageRef.getPage()).setModalResult(true);
+                        loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
+                    } catch (Exception e) {
+                        LOG.error("Error de-provisioning user", e);
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        feedbackPanel.refresh(target);
+                    }
+                }
+            }, ActionLink.ActionType.DEPROVISION, pageId);
+
+            table.addAction(new ActionLink() {
+
+                private static final long serialVersionUID = -3722207913631435501L;
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+
+                    if (anyTO instanceof UserTO) {
+                        StatusModalPage.this.passwordManagement(
+                                target, ResourceAssociationActionType.PROVISION, table.getModelObject());
+                    } else {
+                        try {
+                            final BulkActionResult bulkActionResult = groupRestClient.provision(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+
+                            ((BasePage) pageRef.getPage()).setModalResult(true);
+                            loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
+                        } catch (Exception e) {
+                            LOG.error("Error provisioning user", e);
+                            error(getString(Constants.ERROR) + ": " + e.getMessage());
+                            feedbackPanel.refresh(target);
+                        }
+                    }
+                }
+            }.feedbackPanelAutomaticReload(!(anyTO instanceof UserTO)), ActionLink.ActionType.PROVISION, pageId);
+
+            table.addAction(new ActionLink() {
+
+                private static final long serialVersionUID = -3722207913631435501L;
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    try {
+                        final BulkActionResult bulkActionResult;
+                        if (anyTO instanceof UserTO) {
+                            bulkActionResult = userRestClient.unassign(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+                        } else {
+                            bulkActionResult = groupRestClient.unassign(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+                        }
+
+                        ((BasePage) pageRef.getPage()).setModalResult(true);
+                        loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
+                    } catch (Exception e) {
+                        LOG.error("Error unassigning resources", e);
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        feedbackPanel.refresh(target);
+                    }
+                }
+            }, ActionLink.ActionType.UNASSIGN, pageId);
+
+            table.addAction(new ActionLink() {
+
+                private static final long serialVersionUID = -3722207913631435501L;
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    if (anyTO instanceof UserTO) {
+                        StatusModalPage.this.passwordManagement(
+                                target, ResourceAssociationActionType.ASSIGN, table.getModelObject());
+                    } else {
+                        try {
+                            final BulkActionResult bulkActionResult = groupRestClient.assign(
+                                    anyTO.getETagValue(),
+                                    anyTO.getKey(),
+                                    new ArrayList<>(table.getModelObject()));
+
+                            ((BasePage) pageRef.getPage()).setModalResult(true);
+                            loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
+                        } catch (Exception e) {
+                            LOG.error("Error assigning resources", e);
+                            error(getString(Constants.ERROR) + ": " + e.getMessage());
+                            feedbackPanel.refresh(target);
+                        }
+                    }
+                }
+            }.feedbackPanelAutomaticReload(!(anyTO instanceof UserTO)), ActionLink.ActionType.ASSIGN, pageId);
+        }
+
+        table.addCancelButton(window);
+        add(table);
+    }
+
+    private class AttributableStatusProvider extends AbstractStatusBeanProvider {
+
+        private static final long serialVersionUID = 4586969457669796621L;
+
+        public AttributableStatusProvider() {
+            super(statusOnly ? "resourceName" : "accountLink");
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public List<StatusBean> getStatusBeans() {
+            final List<String> resources = new ArrayList<>();
+            for (ResourceTO resourceTO : resourceRestClient.getAll()) {
+                resources.add(resourceTO.getKey());
+            }
+
+            final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(anyTO);
+
+            final List<StatusBean> statusBeans = new ArrayList<StatusBean>(connObjects.size() + 1);
+
+            for (ConnObjectWrapper entry : connObjects) {
+                final StatusBean statusBean = statusUtils.getStatusBean(anyTO,
+                        entry.getResourceName(),
+                        entry.getConnObjectTO(),
+                        anyTO instanceof GroupTO);
+
+                statusBeans.add(statusBean);
+                resources.remove(entry.getResourceName());
+            }
+
+            if (statusOnly) {
+                final StatusBean syncope = new StatusBean(anyTO, "Syncope");
+
+                syncope.setConnObjectLink(((UserTO) anyTO).getUsername());
+
+                Status syncopeStatus = Status.UNDEFINED;
+                if (((UserTO) anyTO).getStatus() != null) {
+                    try {
+                        syncopeStatus = Status.valueOf(((UserTO) anyTO).getStatus().toUpperCase());
+                    } catch (IllegalArgumentException e) {
+                        LOG.warn("Unexpected status found: {}", ((UserTO) anyTO).getStatus(), e);
+                    }
+                }
+                syncope.setStatus(syncopeStatus);
+
+                statusBeans.add(syncope);
+            } else {
+                for (String resource : resources) {
+                    final StatusBean statusBean = statusUtils.getStatusBean(anyTO,
+                            resource,
+                            null,
+                            anyTO instanceof GroupTO);
+
+                    statusBean.setLinked(false);
+                    statusBeans.add(statusBean);
+                }
+            }
+
+            return statusBeans;
+        }
+    }
+
+    private void passwordManagement(
+            final AjaxRequestTarget target,
+            final ResourceAssociationActionType type,
+            final Collection<StatusBean> selection) {
+
+        final ClearIndicatingAjaxButton goon =
+                new ClearIndicatingAjaxButton("continue", new ResourceModel("continue", "Continue"), pageRef) {
+
+                    private static final long serialVersionUID = -2341391430136818027L;
+
+                    @Override
+                    protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+                        try {
+                            if (StringUtils.isNotBlank(password.getModelObject())
+                            && !password.getModelObject().equals(confirm.getModelObject())) {
+                                throw new Exception(getString("passwordMismatch"));
+                            }
+
+                            final BulkActionResult bulkActionResult;
+                            switch (type) {
+                                case ASSIGN:
+                                    bulkActionResult = userRestClient.assign(
+                                            anyTO.getETagValue(),
+                                            anyTO.getKey(),
+                                            new ArrayList<>(selection),
+                                            changepwd.getModelObject(),
+                                            password.getModelObject());
+                                    break;
+                                case PROVISION:
+                                    bulkActionResult = userRestClient.provision(
+                                            anyTO.getETagValue(),
+                                            anyTO.getKey(),
+                                            new ArrayList<>(selection),
+                                            changepwd.getModelObject(),
+                                            password.getModelObject());
+                                    break;
+                                default:
+                                    bulkActionResult = null;
+                                // ignore
+                            }
+
+                            ((BasePage) pageRef.getPage()).setModalResult(true);
+
+                            if (bulkActionResult != null) {
+                                loadBulkActionResultPage(selection, bulkActionResult);
+                            } else {
+
+                                target.add(((BasePage) pageRef.getPage()).getFeedbackPanel());
+                                window.close(target);
+                            }
+                        } catch (Exception e) {
+                            LOG.error("Error provisioning resources", e);
+                            error(getString(Constants.ERROR) + ": " + e.getMessage());
+                            feedbackPanel.refresh(target);
+                        }
+                    }
+                }.feedbackPanelAutomaticReload(false);
+
+        pwdMgtForm.addOrReplace(goon);
+
+        table.setVisible(false);
+        pwdMgtForm.setVisible(true).setEnabled(true);
+
+        target.add(table);
+        target.add(pwdMgt);
+    }
+
+    private void loadBulkActionResultPage(
+            final Collection<StatusBean> selection, final BulkActionResult bulkActionResult) {
+        final List<String> resources = new ArrayList<String>(selection.size());
+        for (StatusBean statusBean : selection) {
+            resources.add(statusBean.getResourceName());
+        }
+
+        final List<ConnObjectWrapper> connObjects =
+                statusUtils.getConnectorObjects(Collections.singletonList(anyTO), resources);
+
+        final List<StatusBean> statusBeans = new ArrayList<StatusBean>(connObjects.size());
+
+        for (ConnObjectWrapper entry : connObjects) {
+            final StatusBean statusBean = statusUtils.getStatusBean(anyTO,
+                    entry.getResourceName(),
+                    entry.getConnObjectTO(),
+                    anyTO instanceof GroupTO);
+
+            statusBeans.add(statusBean);
+        }
+
+        setResponsePage(new BulkActionResultModalPage<StatusBean, String>(
+                window,
+                statusBeans,
+                columns,
+                bulkActionResult,
+                "resourceName"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/UserDisplayAttributesModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/UserDisplayAttributesModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/UserDisplayAttributesModalPage.java
new file mode 100644
index 0000000..0eeaa42
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/UserDisplayAttributesModalPage.java
@@ -0,0 +1,62 @@
+/*
+ * 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.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+
+/**
+ * Modal window with Display user attributes form.
+ */
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public class UserDisplayAttributesModalPage extends DisplayAttributesModalPage {
+
+    private static final long serialVersionUID = 5194630813773543054L;
+
+    public static final String[] USER_DEFAULT_SELECTION = { "key", "username", "status" };
+    
+    public UserDisplayAttributesModalPage(final PageReference pageRef, final ModalWindow window,
+            final List<String> schemaNames, final List<String> dSchemaNames) {
+        super(pageRef, window, schemaNames, dSchemaNames);
+    }
+
+    @Override
+    public String getPrefDetailView() {
+        return Constants.PREF_USERS_DETAILS_VIEW;
+    }
+
+    @Override
+    public String getPrefAttributeView() {
+        return Constants.PREF_USERS_ATTRIBUTES_VIEW;
+    }
+
+    @Override
+    public String getPrefDerivedAttributeView() {
+        return Constants.PREF_USERS_DERIVED_ATTRIBUTES_VIEW;
+    }
+
+    @Override
+    public Class getTOClass() {
+        return UserTO.class;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
index 20f62d5..d91c083 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
@@ -147,8 +147,19 @@ public abstract class AbstractSearchResultPanel extends Panel implements IEventS
      */
     protected final AbstractBasePage page;
 
+    /**
+     * Realm related to current panel.
+     */
+    private final String realm;
+
+    /**
+     * Any type related to current panel.
+     */
+    private final String type;
+
     protected <T extends AnyTO> AbstractSearchResultPanel(final String id, final boolean filtered,
-            final String fiql, final PageReference pageRef, final AbstractAnyRestClient restClient) {
+            final String fiql, final PageReference pageRef, final AbstractAnyRestClient restClient,
+            final String realm, final String type) {
 
         super(id);
 
@@ -186,6 +197,9 @@ public abstract class AbstractSearchResultPanel extends Panel implements IEventS
         add(container);
 
         rows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_USERS_PAGINATOR_ROWS);
+
+        this.realm = realm;
+        this.type = type;
     }
 
     protected void initResultTable() {
@@ -238,7 +252,7 @@ public abstract class AbstractSearchResultPanel extends Panel implements IEventS
     }
 
     private void updateResultTable(final boolean create, final int rows) {
-        dataProvider = new AnyDataProvider(restClient, rows, filtered);
+        dataProvider = new AnyDataProvider(restClient, rows, filtered, realm, type);
         dataProvider.setFIQL(fiql);
 
         final int currentPage = resultTable != null

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
index daaaa23..7c77228 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
@@ -28,6 +28,7 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CheckGroupColumn;
 import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
 import org.apache.syncope.client.console.pages.BulkActionModalPage;
+import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.Page;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -110,6 +111,9 @@ public class AjaxDataTablePanel<T, S> extends DataTablePanel<T, S> {
 
         columns.add(0, new CheckGroupColumn<T, S>(group));
         dataTable = new AjaxFallbackDefaultDataTable<>("dataTable", columns, dataProvider, rowsPerPage);
+        dataTable.add(new AttributeModifier("class",
+                "ui-widget ui-widget-content table-hover table table-striped table-bordered"));
+
         group.add(dataTable);
 
         fragment.add(new ClearIndicatingAjaxButton("bulkActionLink", bulkActionForm, pageRef) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/panels/Any.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/Any.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/Any.java
deleted file mode 100644
index 8d99606..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/Any.java
+++ /dev/null
@@ -1,35 +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.client.console.panels;
-
-import org.apache.wicket.markup.html.panel.Panel;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class Any extends Panel {
-
-    private static final long serialVersionUID = -1100228004207271270L;
-
-    protected static final Logger LOG = LoggerFactory.getLogger(Any.class);
-
-    public Any(final String id) {
-        super(id);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java
new file mode 100644
index 0000000..21f7609
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java
@@ -0,0 +1,264 @@
+/*
+ * 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.Collection;
+import java.util.Date;
+import java.util.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.AnyDisplayAttributesModalPage;
+import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
+import org.apache.syncope.client.console.rest.AnyObjectRestClient;
+import org.apache.syncope.client.console.rest.SchemaRestClient;
+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.markup.html.form.ActionLink;
+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.AnyTO;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+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.markup.html.basic.Label;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.ReflectionUtils;
+
+public class AnySearchResultPanel extends AbstractSearchResultPanel {
+
+    private static final long serialVersionUID = -1100228004207271270L;
+
+    protected static final Logger LOG = LoggerFactory.getLogger(AnySearchResultPanel.class);
+
+    private String customMarkupId;
+
+    @SpringBean
+    protected SchemaRestClient schemaRestClient;
+
+    protected final List<String> schemaNames;
+
+    protected final List<String> dSchemaNames;
+
+    protected final String pageID = "Any";
+
+    private final String entitlement = "USER_LIST";
+
+    public AnySearchResultPanel(final String type, final String parentId, final String markupId, final boolean filtered,
+            final String fiql, final PageReference callerRef, final AbstractAnyRestClient restClient,
+            final List<AnyTypeClassTO> anyTypeClassTOs, final String realm) {
+        super(parentId, filtered, fiql, callerRef, restClient, realm, type);
+        setCustomMarkupId(markupId);
+        add(new Label("name", type));
+
+        this.schemaNames = new ArrayList<String>();
+        for (AnyTypeClassTO anyTypeClassTO : anyTypeClassTOs) {
+            this.schemaNames.addAll(anyTypeClassTO.getPlainSchemas());
+        }
+        this.dSchemaNames = new ArrayList<String>();
+        for (AnyTypeClassTO anyTypeClassTO : anyTypeClassTOs) {
+            this.dSchemaNames.addAll(anyTypeClassTO.getDerSchemas());
+        }
+
+        initResultTable();
+    }
+
+    public String getCustomMarkupId() {
+        return customMarkupId;
+    }
+
+    public void setCustomMarkupId(final String markupId) {
+        this.customMarkupId = markupId;
+    }
+
+    @Override
+    protected List<IColumn<AnyTO, String>> getColumns() {
+
+        final List<IColumn<AnyTO, String>> columns =
+                new ArrayList<IColumn<AnyTO, String>>();
+
+        for (String name : prefMan.getList(getRequest(), Constants.PREF_ANY_DETAILS_VIEW)) {
+            final Field field = ReflectionUtils.findField(AnyObjectTO.class, name);
+
+            if ("token".equalsIgnoreCase(name)) {
+                columns.add(new PropertyColumn<AnyTO, String>(new ResourceModel(name, name), name, name));
+            } else if (field != null && field.getType().equals(Date.class)) {
+                columns.add(new PropertyColumn<AnyTO, String>(new ResourceModel(name, name), name, name));
+            } else {
+                columns.add(
+                        new PropertyColumn<AnyTO, String>(new ResourceModel(name, name), name, name));
+            }
+        }
+
+        for (String name : prefMan.getList(getRequest(), Constants.PREF_ANY_ATTRIBUTES_VIEW)) {
+            if (schemaNames.contains(name)) {
+                columns.add(new AttrColumn(name, SchemaType.PLAIN));
+            }
+        }
+
+        for (String name : prefMan.getList(getRequest(), Constants.PREF_ANY_DERIVED_ATTRIBUTES_VIEW)) {
+            if (dSchemaNames.contains(name)) {
+                columns.add(new AttrColumn(name, SchemaType.DERIVED));
+            }
+        }
+
+        // Add defaults in case of no selection
+        if (columns.isEmpty()) {
+            for (String name : AnyDisplayAttributesModalPage.ANY_DEFAULT_SELECTION) {
+                columns.add(
+                        new PropertyColumn<AnyTO, String>(new ResourceModel(name, name), name, name));
+            }
+
+        }
+
+        columns.add(new ActionColumn<AnyTO, String>(new ResourceModel("actions", "")) {
+
+            private static final long serialVersionUID = -3503023501954863131L;
+
+            @Override
+            public ActionLinksPanel getActions(final String componentId, final IModel<AnyTO> 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) {
+                        editmodal.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                // SYNCOPE-294: re-read anyTO before edit
+                                AnyObjectTO anyTO = ((AnyObjectRestClient) restClient).read(model.getObject().getKey());
+                                return null;
+                            }
+                        });
+
+                        editmodal.show(target);
+                    }
+                }, ActionLink.ActionType.EDIT, entitlement);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            final AnyObjectTO anyTO = (AnyObjectTO) 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 null;
+                                }
+                            });
+
+                            editmodal.show(target);
+                        } catch (SyncopeClientException scce) {
+                            error(getString(Constants.OPERATION_ERROR) + ": " + scce.getMessage());
+                            feedbackPanel.refresh(target);
+                        }
+                    }
+                }, ActionLink.ActionType.DELETE, entitlement);
+
+                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 AnyDisplayAttributesModalPage(
+                                        page.getPageReference(), displaymodal, schemaNames, dSchemaNames);
+                            }
+                        });
+
+                        displaymodal.show(target);
+                    }
+                }, ActionLink.ActionType.CHANGE_VIEW, entitlement);
+
+                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, entitlement);
+
+                return panel;
+            }
+        });
+
+        return columns;
+    }
+
+    @Override
+    protected <T extends AnyTO> Collection<ActionLink.ActionType> getBulkActions() {
+        final List<ActionLink.ActionType> bulkActions = new ArrayList<ActionLink.ActionType>();
+
+        bulkActions.add(ActionLink.ActionType.DELETE);
+        bulkActions.add(ActionLink.ActionType.SUSPEND);
+        bulkActions.add(ActionLink.ActionType.REACTIVATE);
+
+        return bulkActions;
+    }
+
+    @Override
+    protected String getPageId() {
+        return pageID;
+    }
+}