syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject [38/52] syncope git commit: [SYNCOPE-620] Console (JAR) in, now time for console-reference
Date Thu, 05 Feb 2015 16:01:09 GMT
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportletConfModalPage.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportletConfModalPage.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportletConfModalPage.java
new file mode 100644
index 0000000..9c625e1
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportletConfModalPage.java
@@ -0,0 +1,362 @@
+/*
+ * 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.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.RoleSearchPanel;
+import org.apache.syncope.client.console.panels.UserSearchPanel;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.CheckBoxMultipleChoiceFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.DateTimeFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.SpinnerFieldPanel;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.annotation.FormAttributeField;
+import org.apache.syncope.common.lib.report.AbstractReportletConf;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.wicket.Component;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+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.form.DropDownChoice;
+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.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.util.ListModel;
+import org.apache.wicket.util.visit.IVisit;
+import org.apache.wicket.util.visit.IVisitor;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.PropertyAccessorFactory;
+import org.springframework.util.ClassUtils;
+
+public class ReportletConfModalPage extends BaseModalPage {
+
+    private static final long serialVersionUID = 3910027601200382958L;
+
+    private static final String[] EXCLUDE_PROPERTIES = new String[] { "serialVersionUID", "class", "name",
+        "reportletClassName" };
+
+    private AbstractReportletConf reportletConf;
+
+    private final AjaxTextFieldPanel name;
+
+    private WebMarkupContainer propertiesContainer;
+
+    private ListView<String> propView;
+
+    public ReportletConfModalPage(final AbstractReportletConf reportletConf, final ModalWindow window,
+            final PageReference pageRef) {
+
+        this.reportletConf = reportletConf;
+
+        final Form form = new Form(FORM);
+        add(form);
+
+        propertiesContainer = new WebMarkupContainer("container");
+        propertiesContainer.setOutputMarkupId(true);
+        form.add(propertiesContainer);
+
+        name = new AjaxTextFieldPanel("name", "name", this.reportletConf == null
+                ? new Model<String>()
+                : new PropertyModel<String>(this.reportletConf, "name"));
+        name.setOutputMarkupId(true);
+        name.addRequiredLabel();
+        form.add(name);
+
+        final AjaxDropDownChoicePanel<String> reportletClass = new AjaxDropDownChoicePanel<String>("reportletClass",
+                "reportletClass", new IModel<String>() {
+
+                    private static final long serialVersionUID = -2316468110411802130L;
+
+                    @Override
+                    public String getObject() {
+                        return ReportletConfModalPage.this.reportletConf == null
+                                ? null
+                                : ReportletConfModalPage.this.reportletConf.getClass().getName();
+                    }
+
+                    @Override
+                    public void setObject(final String object) {
+                        try {
+                            Class<?> reportletClass = Class.forName(object);
+                            ReportletConfModalPage.this.reportletConf = (AbstractReportletConf) reportletClass.
+                            newInstance();
+                            propertiesContainer.replace(buildPropView());
+                        } catch (Exception e) {
+                            LOG.error("Cannot find or initialize {}", object, e);
+                        }
+                    }
+
+                    @Override
+                    public void detach() {
+                    }
+                });
+        reportletClass.setStyleSheet("long_dynamicsize");
+        reportletClass.setChoices(reportRestClient.getReportletConfClasses());
+        ((DropDownChoice) reportletClass.getField()).setNullValid(true);
+        reportletClass.addRequiredLabel();
+        reportletClass.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = 5538299138211283825L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                ((DropDownChoice) reportletClass.getField()).setNullValid(false);
+                target.add(reportletClass.getField());
+                target.add(propertiesContainer);
+            }
+        });
+        form.add(reportletClass);
+
+        propertiesContainer.add(buildPropView());
+
+        final AjaxButton submit = new AjaxButton(APPLY, new ResourceModel(APPLY)) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                final BeanWrapper wrapper = PropertyAccessorFactory.
+                        forBeanPropertyAccess(ReportletConfModalPage.this.reportletConf);
+                wrapper.setPropertyValue("name", name.getField().getInput());
+
+                // Iterate over properties in order to find UserSearchPanel instances and manually update
+                // this.reportletConf with select search criteria - this is needed because UserSearchPanel
+                // does not comply with usual Wicket model paradigm.
+                ReportletConfModalPage.this.propView.visitChildren(new IVisitor<Component, Void>() {
+
+                    @Override
+                    public void component(final Component component, final IVisit<Void> ivisit) {
+                        if (component instanceof UserSearchPanel) {
+                            // using component.getDefaultModelObjectAsString() to fetch field name (set above)
+                            wrapper.setPropertyValue(component.getDefaultModelObjectAsString(),
+                                    ((UserSearchPanel) component).buildFIQL());
+                        }
+                    }
+                });
+
+                ((ReportModalPage) pageRef.getPage()).setModalReportletConf(ReportletConfModalPage.this.reportletConf);
+                window.close(target);
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+                feedbackPanel.refresh(target);
+            }
+        };
+        form.add(submit);
+
+        final AjaxButton cancel = new ClearIndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL), pageRef) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+                window.close(target);
+            }
+        };
+
+        cancel.setDefaultFormProcessing(false);
+        form.add(cancel);
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private FieldPanel buildSinglePanel(final Class<?> type, final String fieldName, final String id) {
+        FieldPanel result = null;
+        PropertyModel model = new PropertyModel(ReportletConfModalPage.this.reportletConf, fieldName);
+        if (ClassUtils.isAssignable(Boolean.class, type)) {
+            result = new AjaxCheckBoxPanel(id, fieldName, model);
+        } else if (ClassUtils.isAssignable(Number.class, type)) {
+            result = new SpinnerFieldPanel<Number>(id, fieldName,
+                    (Class<Number>) ClassUtils.resolvePrimitiveIfNecessary(type), model, null, null);
+        } else if (Date.class.equals(type)) {
+            result = new DateTimeFieldPanel(id, fieldName, model, SyncopeConstants.DEFAULT_DATE_PATTERN);
+        } else if (type.isEnum()) {
+            result = new AjaxDropDownChoicePanel(id, fieldName, model).setChoices(
+                    Arrays.asList(type.getEnumConstants()));
+        }
+
+        // treat as String if nothing matched above
+        if (result == null) {
+            result = new AjaxTextFieldPanel(id, fieldName, model);
+        }
+
+        return result;
+    }
+
+    private ListView<String> buildPropView() {
+        LoadableDetachableModel<List<String>> propViewModel = new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                List<String> result = new ArrayList<String>();
+                if (ReportletConfModalPage.this.reportletConf != null) {
+                    for (Field field : ReportletConfModalPage.this.reportletConf.getClass().getDeclaredFields()) {
+                        if (!ArrayUtils.contains(EXCLUDE_PROPERTIES, field.getName())) {
+                            result.add(field.getName());
+                        }
+                    }
+                }
+
+                return result;
+            }
+        };
+
+        propView = new ListView<String>("propView", propViewModel) {
+
+            private static final long serialVersionUID = 9101744072914090143L;
+
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            @Override
+            protected void populateItem(final ListItem<String> item) {
+                final String fieldName = item.getModelObject();
+
+                Label label = new Label("key", fieldName);
+                item.add(label);
+
+                Field field = null;
+                try {
+                    field = ReportletConfModalPage.this.reportletConf.getClass().getDeclaredField(fieldName);
+                } catch (Exception e) {
+                    LOG.error("Could not find field {} in class {}",
+                            fieldName, ReportletConfModalPage.this.reportletConf.getClass(), e);
+                }
+                if (field == null) {
+                    return;
+                }
+
+                FormAttributeField annotation = field.getAnnotation(FormAttributeField.class);
+
+                BeanWrapper wrapper = PropertyAccessorFactory.
+                        forBeanPropertyAccess(ReportletConfModalPage.this.reportletConf);
+
+                Panel panel;
+
+                if (String.class.equals(field.getType()) && annotation != null && annotation.userSearch()) {
+                    panel = new UserSearchPanel.Builder("value").
+                            fiql((String) wrapper.getPropertyValue(fieldName)).required(false).build();
+                    // This is needed in order to manually update this.reportletConf with search panel selections
+                    panel.setDefaultModel(new Model<String>(fieldName));
+                } else if (String.class.equals(field.getType()) && annotation != null && annotation.roleSearch()) {
+                    panel = new RoleSearchPanel.Builder("value").
+                            fiql((String) wrapper.getPropertyValue(fieldName)).required(false).build();
+                    // This is needed in order to manually update this.reportletConf with search panel selections
+                    panel.setDefaultModel(new Model<String>(fieldName));
+                } else if (List.class.equals(field.getType())) {
+                    Class<?> listItemType = String.class;
+                    if (field.getGenericType() instanceof ParameterizedType) {
+                        listItemType =
+                                (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
+                    }
+
+                    if (listItemType.equals(String.class) && annotation != null) {
+                        List<String> choices;
+                        switch (annotation.schema()) {
+                            case UserPlainSchema:
+                                choices = schemaRestClient.getSchemaNames(AttributableType.USER);
+                                break;
+
+                            case UserDerivedSchema:
+                                choices = schemaRestClient.getDerSchemaNames(AttributableType.USER);
+                                break;
+
+                            case UserVirtualSchema:
+                                choices = schemaRestClient.getVirSchemaNames(AttributableType.USER);
+                                break;
+
+                            case RolePlainSchema:
+                                choices = schemaRestClient.getSchemaNames(AttributableType.ROLE);
+                                break;
+
+                            case RoleDerivedSchema:
+                                choices = schemaRestClient.getDerSchemaNames(AttributableType.ROLE);
+                                break;
+
+                            case RoleVirtualSchema:
+                                choices = schemaRestClient.getVirSchemaNames(AttributableType.ROLE);
+                                break;
+
+                            case MembershipPlainSchema:
+                                choices = schemaRestClient.getSchemaNames(AttributableType.MEMBERSHIP);
+                                break;
+
+                            case MembershipDerivedSchema:
+                                choices = schemaRestClient.getDerSchemaNames(AttributableType.MEMBERSHIP);
+                                break;
+
+                            case MembershipVirtualSchema:
+                                choices = schemaRestClient.getVirSchemaNames(AttributableType.MEMBERSHIP);
+                                break;
+
+                            default:
+                                choices = Collections.emptyList();
+                        }
+
+                        panel = new AjaxPalettePanel("value", new PropertyModel<List<String>>(
+                                ReportletConfModalPage.this.reportletConf, fieldName), new ListModel<String>(choices),
+                                true);
+                    } else if (listItemType.isEnum()) {
+                        panel = new CheckBoxMultipleChoiceFieldPanel("value", new PropertyModel(
+                                ReportletConfModalPage.this.reportletConf, fieldName),
+                                new ListModel(Arrays.asList(listItemType.getEnumConstants())));
+                    } else {
+                        if (((List) wrapper.getPropertyValue(fieldName)).isEmpty()) {
+                            ((List) wrapper.getPropertyValue(fieldName)).add(null);
+                        }
+
+                        panel = new MultiFieldPanel("value", new PropertyModel<List>(
+                                ReportletConfModalPage.this.reportletConf, fieldName),
+                                buildSinglePanel(field.getType(), fieldName, "panel"));
+                    }
+                } else {
+                    panel = buildSinglePanel(field.getType(), fieldName, "value");
+                }
+
+                item.add(panel);
+            }
+        };
+
+        return propView;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Reports.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
new file mode 100644
index 0000000..6c53dee
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
@@ -0,0 +1,413 @@
+/*
+ * 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.Collections;
+import java.util.Iterator;
+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.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.panels.LoggerCategoryPanel;
+import org.apache.syncope.client.console.panels.SelectedEventsPanel;
+import org.apache.syncope.client.console.rest.LoggerRestClient;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+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.DatePropertyColumn;
+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.EventCategoryTO;
+import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.types.AuditElements.Result;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+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.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.util.ListModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * Auditing and Reporting.
+ */
+public class Reports extends BasePage {
+
+    private static final long serialVersionUID = -2071214196989178694L;
+
+    private static final int WIN_HEIGHT = 500;
+
+    private static final int WIN_WIDTH = 700;
+
+    @SpringBean
+    private LoggerRestClient loggerRestClient;
+
+    @SpringBean
+    private PreferenceManager prefMan;
+
+    private WebMarkupContainer reportContainer;
+
+    private WebMarkupContainer auditContainer;
+
+    private int paginatorRows;
+
+    private final ModalWindow window;
+
+    public Reports(final PageParameters parameters) {
+        super(parameters);
+
+        window = new ModalWindow("reportWin");
+        window.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        window.setInitialHeight(WIN_HEIGHT);
+        window.setInitialWidth(WIN_WIDTH);
+        window.setCookieName("view-report-win");
+        add(window);
+
+        setupReport();
+        setupAudit();
+    }
+
+    private void setupReport() {
+        reportContainer = new WebMarkupContainer("reportContainer");
+        setWindowClosedCallback(window, reportContainer);
+
+        MetaDataRoleAuthorizationStrategy.authorize(reportContainer, RENDER,
+                xmlRolesReader.getEntitlement("Reports", "list"));
+
+        paginatorRows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_REPORT_PAGINATOR_ROWS);
+
+        List<IColumn<ReportTO, String>> columns = new ArrayList<IColumn<ReportTO, String>>();
+        columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("id"), "id", "id"));
+        columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("name"), "name", "name"));
+        columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("lastExec"), "lastExec", "lastExec"));
+        columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("nextExec"), "nextExec", "nextExec"));
+        columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("startDate"), "startDate", "startDate"));
+        columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("endDate"), "endDate", "endDate"));
+        columns.add(new PropertyColumn<ReportTO, String>(
+                new ResourceModel("latestExecStatus"), "latestExecStatus", "latestExecStatus"));
+        columns.add(new ActionColumn<ReportTO, String>(new ResourceModel("actions", "")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public ActionLinksPanel getActions(final String componentId, final IModel<ReportTO> model) {
+
+                final ReportTO reportTO = model.getObject();
+
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference());
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+
+                        window.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new ReportModalPage(window, reportTO, Reports.this.getPageReference());
+                            }
+                        });
+
+                        window.show(target);
+                    }
+                }, ActionLink.ActionType.EDIT, "Reports");
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            reportRestClient.startExecution(reportTO.getKey());
+                            getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException scce) {
+                            error(scce.getMessage());
+                        }
+
+                        feedbackPanel.refresh(target);
+                        target.add(reportContainer);
+                    }
+                }, ActionLink.ActionType.EXECUTE, "Reports");
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            reportRestClient.delete(reportTO.getKey());
+                            info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException scce) {
+                            error(scce.getMessage());
+                        }
+                        target.add(reportContainer);
+                        feedbackPanel.refresh(target);
+                    }
+                }, ActionLink.ActionType.DELETE, "Reports");
+
+                return panel;
+            }
+
+            @Override
+            public Component getHeader(final String componentId) {
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), getPageReference());
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        if (target != null) {
+                            target.add(reportContainer);
+                        }
+                    }
+                }, ActionLink.ActionType.RELOAD, TASKS, "list");
+
+                return panel;
+            }
+        });
+
+        final AjaxFallbackDefaultDataTable<ReportTO, String> reportTable =
+                new AjaxFallbackDefaultDataTable<ReportTO, String>(
+                        "reportTable", columns, new ReportProvider(), paginatorRows);
+
+        reportContainer.add(reportTable);
+        reportContainer.setOutputMarkupId(true);
+
+        add(reportContainer);
+
+        @SuppressWarnings("rawtypes")
+        Form paginatorForm = new Form("paginatorForm");
+
+        MetaDataRoleAuthorizationStrategy.authorize(paginatorForm, RENDER,
+                xmlRolesReader.getEntitlement("Reports", "list"));
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this, "paginatorRows"),
+                prefMan.getPaginatorChoices());
+
+        rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                prefMan.set(getRequest(), getResponse(), Constants.PREF_REPORT_PAGINATOR_ROWS,
+                        String.valueOf(paginatorRows));
+                reportTable.setItemsPerPage(paginatorRows);
+
+                target.add(reportContainer);
+            }
+        });
+
+        paginatorForm.add(rowsChooser);
+        add(paginatorForm);
+
+        AjaxLink createLink = new ClearIndicatingAjaxLink("createLink", getPageReference()) {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            protected void onClickInternal(final AjaxRequestTarget target) {
+                window.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = -7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        return new ReportModalPage(window, new ReportTO(), Reports.this.getPageReference());
+                    }
+                });
+
+                window.show(target);
+            }
+        };
+
+        MetaDataRoleAuthorizationStrategy.authorize(createLink, RENDER, xmlRolesReader.getEntitlement("Reports",
+                "create"));
+
+        add(createLink);
+    }
+
+    @SuppressWarnings("rawtypes")
+    private void setupAudit() {
+        auditContainer = new WebMarkupContainer("auditContainer");
+        auditContainer.setOutputMarkupId(true);
+        add(auditContainer);
+
+        MetaDataRoleAuthorizationStrategy.authorize(
+                auditContainer, RENDER, xmlRolesReader.getEntitlement("Audit", "list"));
+
+        final Form form = new Form("auditForm");
+        auditContainer.add(form);
+
+        final List<String> events = new ArrayList<>();
+
+        final List<AuditLoggerName> audits = loggerRestClient.listAudits();
+        for (AuditLoggerName audit : audits) {
+            events.add(AuditLoggerName.buildEvent(
+                    audit.getType(),
+                    audit.getCategory(),
+                    audit.getSubcategory(),
+                    audit.getEvent(),
+                    audit.getResult()));
+        }
+
+        final ListModel<String> model = new ListModel<String>(new ArrayList<String>(events));
+
+        form.add(new LoggerCategoryPanel(
+                "events", loggerRestClient.listEvents(), model, getPageReference(), "Reports") {
+
+                    private static final long serialVersionUID = 6113164334533550277L;
+
+                    @Override
+                    protected String[] getListRoles() {
+                        return new String[] {
+                            xmlRolesReader.getEntitlement("Audit", "list")
+                        };
+                    }
+
+                    @Override
+                    protected String[] getChangeRoles() {
+                        return new String[] {
+                            xmlRolesReader.getEntitlement("Audit", "enable"),
+                            xmlRolesReader.getEntitlement("Audit", "disable")
+                        };
+                    }
+
+                    @Override
+                    public void onEventAction(final IEvent<?> event) {
+                        if (event.getPayload() instanceof SelectedEventsPanel.EventSelectionChanged) {
+
+                            final SelectedEventsPanel.EventSelectionChanged eventSelectionChanged =
+                            (SelectedEventsPanel.EventSelectionChanged) event.getPayload();
+
+                            for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) {
+                                if (events.contains(toBeRemoved)) {
+                                    final Map.Entry<EventCategoryTO, Result> eventCategory =
+                                    AuditLoggerName.parseEventCategory(toBeRemoved);
+
+                                    final AuditLoggerName auditLoggerName = new AuditLoggerName(
+                                            eventCategory.getKey().getType(),
+                                            eventCategory.getKey().getCategory(),
+                                            eventCategory.getKey().getSubcategory(),
+                                            CollectionUtils.isEmpty(eventCategory.getKey().getEvents())
+                                                    ? null : eventCategory.getKey().getEvents().iterator().next(),
+                                            eventCategory.getValue());
+
+                                    loggerRestClient.disableAudit(auditLoggerName);
+                                    events.remove(toBeRemoved);
+                                }
+                            }
+
+                            for (String toBeAdded : eventSelectionChanged.getToBeAdded()) {
+                                if (!events.contains(toBeAdded)) {
+                                    final Map.Entry<EventCategoryTO, Result> eventCategory =
+                                    AuditLoggerName.parseEventCategory(toBeAdded);
+
+                                    final AuditLoggerName auditLoggerName = new AuditLoggerName(
+                                            eventCategory.getKey().getType(),
+                                            eventCategory.getKey().getCategory(),
+                                            eventCategory.getKey().getSubcategory(),
+                                            CollectionUtils.isEmpty(eventCategory.getKey().getEvents())
+                                                    ? null : eventCategory.getKey().getEvents().iterator().next(),
+                                            eventCategory.getValue());
+
+                                    loggerRestClient.enableAudit(auditLoggerName);
+                                    events.add(toBeAdded);
+                                }
+                            }
+                        }
+                    }
+                });
+    }
+
+    private class ReportProvider extends SortableDataProvider<ReportTO, String> {
+
+        private static final long serialVersionUID = -2311716167583335852L;
+
+        private final SortableDataProviderComparator<ReportTO> comparator;
+
+        public ReportProvider() {
+            super();
+
+            //Default sorting
+            setSort("id", SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<ReportTO>(this);
+        }
+
+        @Override
+        public Iterator<ReportTO> iterator(final long first, final long count) {
+            final int page = ((int) first / paginatorRows);
+
+            final List<ReportTO> list =
+                    reportRestClient.list((page < 0 ? 0 : page) + 1, paginatorRows, getSort());
+            Collections.sort(list, comparator);
+            return list.iterator();
+        }
+
+        @Override
+        public long size() {
+            return reportRestClient.count();
+        }
+
+        @Override
+        public IModel<ReportTO> model(final ReportTO configuration) {
+
+            return new AbstractReadOnlyModel<ReportTO>() {
+
+                private static final long serialVersionUID = 4921104837546595602L;
+
+                @Override
+                public ReportTO getObject() {
+                    return configuration;
+                }
+            };
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/RequestPasswordResetModalPage.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/RequestPasswordResetModalPage.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/RequestPasswordResetModalPage.java
new file mode 100644
index 0000000..d8b762f
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/RequestPasswordResetModalPage.java
@@ -0,0 +1,153 @@
+/*
+ * 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.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.Mode;
+import org.apache.syncope.client.console.rest.SecurityQuestionRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+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.Form;
+import org.apache.wicket.markup.html.form.StatelessForm;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class RequestPasswordResetModalPage extends BaseModalPage {
+
+    private static final long serialVersionUID = -8419445804421211904L;
+
+    @SpringBean
+    private SecurityQuestionRestClient securityQuestionRestClient;
+
+    public RequestPasswordResetModalPage(final ModalWindow window) {
+        super();
+        setOutputMarkupId(true);
+
+        final boolean handleSecurityQuestion = userSelfRestClient.isPwdResetRequiringSecurityQuestions();
+
+        final StatelessForm<?> form = new StatelessForm<Object>(FORM);
+        form.setOutputMarkupId(true);
+
+        final Label securityQuestionLabel = new Label("securityQuestionLabel", getString("securityQuestion"));
+        securityQuestionLabel.setOutputMarkupPlaceholderTag(true);
+        securityQuestionLabel.setVisible(handleSecurityQuestion);
+        form.add(securityQuestionLabel);
+        final AjaxTextFieldPanel securityQuestion =
+                new AjaxTextFieldPanel("securityQuestion", "securityQuestion", new Model<String>());
+        securityQuestion.setReadOnly(true);
+        securityQuestion.setRequired(true);
+        securityQuestion.getField().setOutputMarkupId(true);
+        securityQuestion.setOutputMarkupPlaceholderTag(true);
+        securityQuestion.setVisible(handleSecurityQuestion);
+        form.add(securityQuestion);
+
+        final AjaxTextFieldPanel username =
+                new AjaxTextFieldPanel("username", "username", new Model<String>());
+        username.setRequired(true);
+        username.getField().setOutputMarkupId(true);
+        if (handleSecurityQuestion) {
+            username.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_BLUR) {
+
+                private static final long serialVersionUID = -1107858522700306810L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget target) {
+                    getFeedbackMessages().clear();
+                    target.add(feedbackPanel);
+                    try {
+                        SecurityQuestionTO read = securityQuestionRestClient.readByUser(username.getModelObject());
+                        securityQuestion.setModelObject(read.getContent());
+                    } catch (Exception e) {
+                        LOG.error("While fetching security question for {}", username.getModelObject(), e);
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        feedbackPanel.refresh(target);
+                        securityQuestion.setModelObject(null);
+                    } finally {
+                        target.add(securityQuestion);
+                    }
+                }
+            });
+        }
+        form.add(username);
+
+        final Label securityAnswerLabel = new Label("securityAnswerLabel", getString("securityAnswer"));
+        securityAnswerLabel.setOutputMarkupPlaceholderTag(true);
+        securityAnswerLabel.setVisible(handleSecurityQuestion);
+        form.add(securityAnswerLabel);
+        final AjaxTextFieldPanel securityAnswer =
+                new AjaxTextFieldPanel("securityAnswer", "securityAnswer", new Model<String>());
+        securityAnswer.setRequired(handleSecurityQuestion);
+        securityAnswer.setOutputMarkupPlaceholderTag(true);
+        securityAnswer.setVisible(handleSecurityQuestion);
+        form.add(securityAnswer);
+
+        final AjaxButton submit = new IndicatingAjaxButton(APPLY, new ResourceModel(SUBMIT, SUBMIT)) {
+
+            private static final long serialVersionUID = -4804368561204623354L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                try {
+                    userSelfRestClient.requestPasswordReset(username.getModelObject(), securityAnswer.getModelObject());
+
+                    setResponsePage(new ResultStatusModalPage.Builder(window, new UserTO()).
+                            mode(Mode.SELF).build());
+                } catch (Exception e) {
+                    LOG.error("While requesting password reset for {}", username.getModelObject(), e);
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                    feedbackPanel.refresh(target);
+                }
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+                feedbackPanel.refresh(target);
+            }
+        };
+        form.add(submit);
+        form.setDefaultButton(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);
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+                // do nothing
+            }
+        };
+        cancel.setDefaultFormProcessing(false);
+        form.add(cancel);
+
+        add(form);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ResourceModalPage.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ResourceModalPage.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ResourceModalPage.java
new file mode 100644
index 0000000..824c39c
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ResourceModalPage.java
@@ -0,0 +1,217 @@
+/*
+ * 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.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.AnnotatedBeanPanel;
+import org.apache.syncope.client.console.panels.ResourceConnConfPanel;
+import org.apache.syncope.client.console.panels.ResourceDetailsPanel;
+import org.apache.syncope.client.console.panels.ResourceMappingPanel;
+import org.apache.syncope.client.console.panels.ResourceSecurityPanel;
+import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+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.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+
+/**
+ * Modal window with Resource form.
+ */
+public class ResourceModalPage extends BaseModalPage {
+
+    private static final long serialVersionUID = 1734415311027284221L;
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public ResourceModalPage(final PageReference pageRef, final ModalWindow window, final ResourceTO resourceTO,
+            final boolean createFlag) {
+
+        super();
+
+        this.add(new Label("new", StringUtils.isBlank(resourceTO.getKey())
+                ? new ResourceModel("new")
+                : new Model("")));
+
+        this.add(new Label("name", StringUtils.isBlank(resourceTO.getKey())
+                ? ""
+                : resourceTO.getKey()));
+
+        final Form<ResourceTO> form = new Form<ResourceTO>(FORM);
+        form.setModel(new CompoundPropertyModel<ResourceTO>(resourceTO));
+
+        //--------------------------------
+        // Resource details panel
+        //--------------------------------
+        form.add(new ResourceDetailsPanel("details", resourceTO,
+                resourceRestClient.getPropagationActionsClasses(), createFlag));
+
+        form.add(new AnnotatedBeanPanel("systeminformation", resourceTO));
+        //--------------------------------
+
+        //--------------------------------
+        // Resource mapping panels
+        //--------------------------------
+        form.add(new ResourceMappingPanel("umapping", resourceTO, AttributableType.USER));
+        form.add(new ResourceMappingPanel("rmapping", resourceTO, AttributableType.ROLE));
+        //--------------------------------
+
+        //--------------------------------
+        // Resource connector configuration panel
+        //--------------------------------
+        ResourceConnConfPanel resourceConnConfPanel = new ResourceConnConfPanel("connconf", resourceTO, createFlag);
+        MetaDataRoleAuthorizationStrategy.authorize(
+                resourceConnConfPanel, ENABLE, xmlRolesReader.getEntitlement("Connectors", "read"));
+        form.add(resourceConnConfPanel);
+        //--------------------------------
+
+        //--------------------------------
+        // Resource security panel
+        //--------------------------------
+        form.add(new ResourceSecurityPanel("security", resourceTO));
+        //--------------------------------
+
+        final AjaxButton submit = new IndicatingAjaxButton(APPLY, new ResourceModel(SUBMIT, SUBMIT)) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                final ResourceTO resourceTO = (ResourceTO) form.getDefaultModelObject();
+
+                boolean accountIdError = false;
+
+                if (resourceTO.getUmapping() == null || resourceTO.getUmapping().getItems().isEmpty()) {
+                    resourceTO.setUmapping(null);
+                } else {
+                    int uAccountIdCount = 0;
+                    for (MappingItemTO item : resourceTO.getUmapping().getItems()) {
+                        if (item.isAccountid()) {
+                            uAccountIdCount++;
+                        }
+                    }
+                    accountIdError = uAccountIdCount != 1;
+                }
+
+                if (resourceTO.getRmapping() == null || resourceTO.getRmapping().getItems().isEmpty()) {
+                    resourceTO.setRmapping(null);
+                } else {
+                    int rAccountIdCount = 0;
+                    for (MappingItemTO item : resourceTO.getRmapping().getItems()) {
+                        if (item.isAccountid()) {
+                            rAccountIdCount++;
+                        }
+                    }
+                    accountIdError |= rAccountIdCount != 1;
+                }
+
+                if (accountIdError) {
+                    error(getString("accountIdValidation"));
+                    feedbackPanel.refresh(target);
+                } else {
+                    try {
+                        if (createFlag) {
+                            resourceRestClient.create(resourceTO);
+                        } else {
+                            resourceRestClient.update(resourceTO);
+                        }
+
+                        if (pageRef != null && pageRef.getPage() instanceof AbstractBasePage) {
+                            ((AbstractBasePage) pageRef.getPage()).setModalResult(true);
+                        }
+                        window.close(target);
+                    } catch (Exception e) {
+                        LOG.error("Failure managing resource {}", resourceTO, e);
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        feedbackPanel.refresh(target);
+                    }
+                }
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+                feedbackPanel.refresh(target);
+            }
+        };
+
+        form.add(submit);
+        form.setDefaultButton(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);
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+            }
+        };
+
+        cancel.setDefaultFormProcessing(false);
+        form.add(cancel);
+
+        add(form);
+
+        MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE, xmlRolesReader.getEntitlement("Resources",
+                createFlag
+                        ? "create"
+                        : "update"));
+    }
+
+    /**
+     * Generic resource event.
+     */
+    public static class ResourceEvent {
+
+        /**
+         * Request target.
+         */
+        private AjaxRequestTarget target;
+
+        /**
+         * Constructor.
+         *
+         * @param target request target.
+         */
+        public ResourceEvent(final AjaxRequestTarget target) {
+            this.target = target;
+        }
+
+        /**
+         * Target getter.
+         *
+         * @return request target.
+         */
+        public AjaxRequestTarget getTarget() {
+            return target;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Resources.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Resources.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Resources.java
new file mode 100644
index 0000000..c0ebfa0
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Resources.java
@@ -0,0 +1,732 @@
+/*
+ * 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.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.PreferenceManager;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.panels.AbstractSearchResultPanel;
+import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
+import org.apache.syncope.client.console.rest.ConnectorRestClient;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+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.client.console.wicket.markup.html.form.LinkPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.IEvent;
+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.sort.SortOrder;
+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.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.StringResourceModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+/**
+ * Resources WebPage.
+ */
+public class Resources extends BasePage {
+
+    private static final long serialVersionUID = -3789252860990261728L;
+
+    private static final int WIN_HEIGHT = 600;
+
+    private static final int WIN_WIDTH = 1100;
+
+    @SpringBean
+    private ConnectorRestClient connectorRestClient;
+
+    @SpringBean
+    private PreferenceManager prefMan;
+
+    private final ModalWindow createResourceWin;
+
+    private final ModalWindow editResourceWin;
+
+    private final ModalWindow createConnectorWin;
+
+    private final ModalWindow editConnectorWin;
+
+    private final int resourcePaginatorRows;
+
+    private final int connectorPaginatorRows;
+
+    private WebMarkupContainer resourceContainer;
+
+    private WebMarkupContainer connectorContainer;
+
+    /**
+     * Modal window to be used for user status management.
+     */
+    protected final ModalWindow statusmodal = new ModalWindow("statusModal");
+
+    /**
+     * Schemas to be shown modal window height.
+     */
+    private final static int STATUS_MODAL_WIN_HEIGHT = 500;
+
+    /**
+     * Schemas to be shown modal window width.
+     */
+    private final static int STATUS_MODAL_WIN_WIDTH = 700;
+
+    public Resources(final PageParameters parameters) {
+        super(parameters);
+
+        add(createResourceWin = new ModalWindow("createResourceWin"));
+        add(editResourceWin = new ModalWindow("editResourceWin"));
+        add(createConnectorWin = new ModalWindow("createConnectorWin"));
+        add(editConnectorWin = new ModalWindow("editConnectorWin"));
+
+        statusmodal.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        statusmodal.setInitialHeight(STATUS_MODAL_WIN_HEIGHT);
+        statusmodal.setInitialWidth(STATUS_MODAL_WIN_WIDTH);
+        statusmodal.setCookieName("status-modal");
+        add(statusmodal);
+
+        AjaxLink<Void> reloadLink = new ClearIndicatingAjaxLink<Void>("reloadLink", getPageReference()) {
+
+            private static final long serialVersionUID = 3109256773218160485L;
+
+            @Override
+            protected void onClickInternal(final AjaxRequestTarget target) {
+                try {
+                    connectorRestClient.reload();
+                    info(getString(Constants.OPERATION_SUCCEEDED));
+                } catch (Exception e) {
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                }
+                feedbackPanel.refresh(target);
+                target.add(connectorContainer);
+            }
+
+            @Override
+            protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) {
+                super.updateAjaxAttributes(attributes);
+
+                final AjaxCallListener ajaxCallListener = new AjaxCallListener() {
+
+                    private static final long serialVersionUID = 7160235486520935153L;
+
+                    @Override
+                    public CharSequence getPrecondition(final Component component) {
+                        return "if (!confirm('" + getString("confirmReloadConnectors") + "')) "
+                                + "{return false;} else {return true;}";
+                    }
+                };
+                attributes.getAjaxCallListeners().add(ajaxCallListener);
+            }
+        };
+        MetaDataRoleAuthorizationStrategy.authorize(reloadLink, ENABLE, xmlRolesReader.getEntitlement(
+                "Connectors", "reload"));
+        add(reloadLink);
+
+        resourcePaginatorRows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_RESOURCES_PAGINATOR_ROWS);
+        connectorPaginatorRows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_CONNECTORS_PAGINATOR_ROWS);
+
+        setupResources();
+        setupConnectors();
+    }
+
+    private void setupResources() {
+        List<IColumn<ResourceTO, String>> columns = new ArrayList<IColumn<ResourceTO, String>>();
+
+        columns.add(
+                new PropertyColumn<ResourceTO, String>(new StringResourceModel("name", this, null), "name", "name"));
+
+        columns.add(new AbstractColumn<ResourceTO, String>(
+                new StringResourceModel("connector", this, null, "connector")) {
+
+                    private static final long serialVersionUID = 8263694778917279290L;
+
+                    @Override
+                    public void populateItem(final Item<ICellPopulator<ResourceTO>> cellItem, final String componentId,
+                            final IModel<ResourceTO> rowModel) {
+
+                        final AjaxLink<String> editLink =
+                        new ClearIndicatingAjaxLink<String>("link", getPageReference()) {
+
+                            private static final long serialVersionUID = -7978723352517770644L;
+
+                            @Override
+                            protected void onClickInternal(final AjaxRequestTarget target) {
+
+                                editConnectorWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                                    private static final long serialVersionUID = -7834632442532690940L;
+
+                                    @Override
+                                    public Page createPage() {
+                                        return new ConnectorModalPage(Resources.this.getPageReference(),
+                                                editConnectorWin,
+                                                connectorRestClient.read(rowModel.getObject().getConnectorId()));
+                                    }
+                                });
+
+                                editConnectorWin.show(target);
+                            }
+                        };
+                        editLink.add(new Label("linkTitle", rowModel.getObject().getConnectorDisplayName()));
+
+                        LinkPanel editConnPanel = new LinkPanel(componentId);
+                        editConnPanel.add(editLink);
+
+                        cellItem.add(editConnPanel);
+
+                        MetaDataRoleAuthorizationStrategy.authorize(editConnPanel, ENABLE, xmlRolesReader.
+                                getEntitlement(
+                                        "Connectors", "read"));
+                    }
+                });
+
+        columns.add(new AbstractColumn<ResourceTO, String>(
+                new StringResourceModel("propagationPrimary", this, null)) {
+
+                    private static final long serialVersionUID = -3503023501954863131L;
+
+                    @Override
+                    public void populateItem(final Item<ICellPopulator<ResourceTO>> item,
+                            final String componentId, final IModel<ResourceTO> model) {
+
+                        item.add(new Label(componentId, ""));
+                        item.add(new AttributeModifier("class", new Model<String>(
+                                                Boolean.toString(model.getObject().isPropagationPrimary()))));
+                    }
+
+                    @Override
+                    public String getCssClass() {
+                        return "narrowcolumn";
+                    }
+                });
+
+        columns.add(new PropertyColumn<ResourceTO, String>(new StringResourceModel(
+                "propagationPriority", this, null), "propagationPriority", "propagationPriority") {
+
+                    @Override
+                    public String getCssClass() {
+                        return "narrowcolumn";
+                    }
+                });
+
+        columns.add(new AbstractColumn<ResourceTO, String>(new StringResourceModel("actions", this, null, "")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public String getCssClass() {
+                return "action";
+            }
+
+            @Override
+            public void populateItem(final Item<ICellPopulator<ResourceTO>> cellItem, final String componentId,
+                    final IModel<ResourceTO> model) {
+
+                final ResourceTO resourceTO = model.getObject();
+
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference());
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        statusmodal.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new ProvisioningModalPage<>(
+                                        getPageReference(), statusmodal, model.getObject(), UserTO.class);
+                            }
+                        });
+
+                        statusmodal.show(target);
+                    }
+                }, ActionLink.ActionType.MANAGE_USERS, "Resources");
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+
+                        statusmodal.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new ProvisioningModalPage<RoleTO>(
+                                        getPageReference(), statusmodal, model.getObject(), RoleTO.class);
+                            }
+                        });
+
+                        statusmodal.show(target);
+                    }
+                }, ActionLink.ActionType.MANAGE_ROLES, "Resources");
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        resourceTO.setUsyncToken(null);
+                        resourceTO.setRsyncToken(null);
+                        try {
+                            resourceRestClient.update(resourceTO);
+                            info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException e) {
+                            error(getString(Constants.ERROR) + ":" + e.getMessage());
+
+                            LOG.error("While resetting sync token from " + resourceTO.getKey(), e);
+                        }
+
+                        feedbackPanel.refresh(target);
+                        target.add(resourceContainer);
+                    }
+                }, ActionLink.ActionType.RESET, "Resources");
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        editResourceWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new ResourceModalPage(Resources.this.getPageReference(),
+                                        editResourceWin, resourceTO, false);
+                            }
+                        });
+
+                        editResourceWin.show(target);
+                    }
+                }, ActionLink.ActionType.EDIT, "Resources");
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            resourceRestClient.delete(resourceTO.getKey());
+                            info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException e) {
+                            error(getString(Constants.ERROR) + ": " + e.getMessage());
+
+                            LOG.error("While deleting resource " + resourceTO.getKey(), e);
+                        }
+
+                        feedbackPanel.refresh(target);
+                        target.add(resourceContainer);
+                    }
+                }, ActionLink.ActionType.DELETE, "Resources");
+
+                cellItem.add(panel);
+            }
+        });
+
+        final AjaxDataTablePanel<ResourceTO, String> table = new AjaxDataTablePanel<ResourceTO, String>(
+                "resourceDatatable",
+                columns,
+                (ISortableDataProvider<ResourceTO, String>) new ResourcesProvider(),
+                resourcePaginatorRows,
+                Arrays.asList(new ActionLink.ActionType[] { ActionLink.ActionType.DELETE }),
+                resourceRestClient,
+                "name",
+                "Resources",
+                getPageReference());
+
+        resourceContainer = new WebMarkupContainer("resourceContainer");
+        resourceContainer.add(table);
+        resourceContainer.setOutputMarkupId(true);
+
+        add(resourceContainer);
+
+        setWindowClosedCallback(createResourceWin, resourceContainer);
+        setWindowClosedCallback(editResourceWin, resourceContainer);
+
+        createResourceWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        createResourceWin.setInitialHeight(WIN_HEIGHT);
+        createResourceWin.setInitialWidth(WIN_WIDTH);
+        createResourceWin.setCookieName("create-res-modal");
+
+        editResourceWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        editResourceWin.setInitialHeight(WIN_HEIGHT);
+        editResourceWin.setInitialWidth(WIN_WIDTH);
+        editResourceWin.setCookieName("edit-res-modal");
+
+        AjaxLink<Void> createResourceLink =
+                new ClearIndicatingAjaxLink<Void>("createResourceLink", getPageReference()) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        createResourceWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                final ResourceModalPage windows = new ResourceModalPage(Resources.this.
+                                        getPageReference(),
+                                        editResourceWin, new ResourceTO(), true);
+                                return windows;
+                            }
+                        });
+
+                        createResourceWin.show(target);
+                    }
+                };
+
+        MetaDataRoleAuthorizationStrategy.authorize(createResourceLink, ENABLE, xmlRolesReader.getEntitlement(
+                "Resources", "create"));
+
+        add(createResourceLink);
+
+        @SuppressWarnings("rawtypes")
+        final Form paginatorForm = new Form("resourcePaginatorForm");
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this,
+                "resourcePaginatorRows"), prefMan.getPaginatorChoices());
+
+        rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                prefMan.set(getRequest(), getResponse(), Constants.PREF_RESOURCES_PAGINATOR_ROWS,
+                        String.valueOf(resourcePaginatorRows));
+
+                table.setItemsPerPage(resourcePaginatorRows);
+                target.add(resourceContainer);
+            }
+        });
+
+        paginatorForm.add(rowsChooser);
+        add(paginatorForm);
+    }
+
+    private void setupConnectors() {
+        List<IColumn<ConnInstanceTO, String>> columns = new ArrayList<IColumn<ConnInstanceTO, String>>();
+
+        columns.add(new PropertyColumn<ConnInstanceTO, String>(
+                new StringResourceModel("id", this, null), "id", "id"));
+        columns.add(new PropertyColumn<ConnInstanceTO, String>(
+                new StringResourceModel("name", this, null), "connectorName", "connectorName"));
+        columns.add(new PropertyColumn<ConnInstanceTO, String>(
+                new StringResourceModel("displayName", this, null), "displayName", "displayName"));
+        columns.add(new PropertyColumn<ConnInstanceTO, String>(
+                new StringResourceModel("bundleName", this, null), "bundleName", "bundleName"));
+        columns.add(new PropertyColumn<ConnInstanceTO, String>(
+                new StringResourceModel("version", this, null), "version", "version"));
+        columns.add(new AbstractColumn<ConnInstanceTO, String>(new StringResourceModel("actions", this, null, "")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public String getCssClass() {
+                return "action";
+            }
+
+            @Override
+            public void populateItem(final Item<ICellPopulator<ConnInstanceTO>> cellItem, final String componentId,
+                    final IModel<ConnInstanceTO> model) {
+
+                final ConnInstanceTO connectorTO = model.getObject();
+
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference());
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        editConnectorWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new ConnectorModalPage(Resources.this.getPageReference(), editConnectorWin,
+                                        connectorTO);
+                            }
+                        });
+
+                        editConnectorWin.show(target);
+                    }
+                }, ActionLink.ActionType.EDIT, "Connectors");
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            connectorRestClient.delete(connectorTO.getKey());
+                            info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException e) {
+                            error(getString(Constants.ERROR) + ": " + e.getMessage());
+
+                            LOG.error("While deleting connector " + connectorTO.getKey(), e);
+                        }
+
+                        target.add(connectorContainer);
+                        feedbackPanel.refresh(target);
+                    }
+                }, ActionLink.ActionType.DELETE, "Connectors");
+
+                cellItem.add(panel);
+            }
+        });
+
+        final AjaxDataTablePanel<ConnInstanceTO, String> table = new AjaxDataTablePanel<ConnInstanceTO, String>(
+                "connectorDatatable",
+                columns,
+                (ISortableDataProvider<ConnInstanceTO, String>) new ConnectorsProvider(),
+                connectorPaginatorRows,
+                Arrays.asList(new ActionLink.ActionType[] { ActionLink.ActionType.DELETE }),
+                connectorRestClient,
+                "id",
+                "Connectors",
+                getPageReference());
+
+        connectorContainer = new WebMarkupContainer("connectorContainer");
+        connectorContainer.add(table);
+        connectorContainer.setOutputMarkupId(true);
+
+        MetaDataRoleAuthorizationStrategy.authorize(connectorContainer, RENDER, xmlRolesReader.getEntitlement(
+                "Connectors", "list"));
+
+        add(connectorContainer);
+
+        setWindowClosedCallback(createConnectorWin, connectorContainer);
+        setWindowClosedCallback(editConnectorWin, connectorContainer);
+
+        createConnectorWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        createConnectorWin.setInitialHeight(WIN_HEIGHT);
+        createConnectorWin.setInitialWidth(WIN_WIDTH);
+        createConnectorWin.setCookieName("create-conn-modal");
+
+        editConnectorWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        editConnectorWin.setInitialHeight(WIN_HEIGHT);
+        editConnectorWin.setInitialWidth(WIN_WIDTH);
+        editConnectorWin.setCookieName("edit-conn-modal");
+
+        AjaxLink<Void> createConnectorLink =
+                new ClearIndicatingAjaxLink<Void>("createConnectorLink", getPageReference()) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        createConnectorWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                ConnectorModalPage form = new ConnectorModalPage(Resources.this.getPageReference(),
+                                        editConnectorWin, new ConnInstanceTO());
+                                return form;
+                            }
+                        });
+
+                        createConnectorWin.show(target);
+                    }
+                };
+
+        MetaDataRoleAuthorizationStrategy.authorize(createConnectorLink, ENABLE, xmlRolesReader.getEntitlement(
+                "Connectors", "create"));
+
+        add(createConnectorLink);
+
+        @SuppressWarnings("rawtypes")
+        Form paginatorForm = new Form("connectorPaginatorForm");
+
+        MetaDataRoleAuthorizationStrategy.authorize(paginatorForm, RENDER, xmlRolesReader.getEntitlement(
+                "Connectors", "list"));
+
+        final DropDownChoice<Integer> rowsChooser = new DropDownChoice<Integer>(
+                "rowsChooser",
+                new PropertyModel<Integer>(this,
+                        "connectorPaginatorRows"),
+                prefMan.getPaginatorChoices());
+
+        rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(AjaxRequestTarget target) {
+                prefMan.set(getRequest(), getResponse(), Constants.PREF_CONNECTORS_PAGINATOR_ROWS,
+                        String.valueOf(connectorPaginatorRows));
+                table.setItemsPerPage(connectorPaginatorRows);
+
+                target.add(connectorContainer);
+            }
+        });
+
+        paginatorForm.add(rowsChooser);
+        add(paginatorForm);
+    }
+
+    class ResourcesProvider extends SortableDataProvider<ResourceTO, String> {
+
+        private static final long serialVersionUID = -9055916672926643975L;
+
+        private final SortableDataProviderComparator<ResourceTO> comparator;
+
+        public ResourcesProvider() {
+            super();
+            //Default sorting
+            setSort("name", SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<ResourceTO>(this);
+        }
+
+        @Override
+        public Iterator<ResourceTO> iterator(final long first, final long count) {
+            List<ResourceTO> list = getResourcesListDB();
+
+            Collections.sort(list, comparator);
+
+            return list.subList((int) first, (int) first + (int) count).iterator();
+        }
+
+        @Override
+        public long size() {
+            return getResourcesListDB().size();
+        }
+
+        @Override
+        public IModel<ResourceTO> model(final ResourceTO resource) {
+            return new AbstractReadOnlyModel<ResourceTO>() {
+
+                private static final long serialVersionUID = 8952474152465381634L;
+
+                @Override
+                public ResourceTO getObject() {
+                    return resource;
+                }
+            };
+        }
+
+        public List<ResourceTO> getResourcesListDB() {
+            return resourceRestClient.getAll();
+        }
+    }
+
+    private class ConnectorsProvider extends SortableDataProvider<ConnInstanceTO, String> {
+
+        private static final long serialVersionUID = 4445909568349448518L;
+
+        private final SortableDataProviderComparator<ConnInstanceTO> comparator;
+
+        public ConnectorsProvider() {
+            super();
+            //Default sorting
+            setSort("id", SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<ConnInstanceTO>(this);
+        }
+
+        @Override
+        public Iterator<ConnInstanceTO> iterator(long first, long count) {
+            List<ConnInstanceTO> list = getConnectorsListDB();
+
+            Collections.sort(list, comparator);
+
+            return list.subList((int) first, (int) first + (int) count).iterator();
+        }
+
+        @Override
+        public long size() {
+            return getConnectorsListDB().size();
+        }
+
+        @Override
+        public IModel<ConnInstanceTO> model(final ConnInstanceTO connector) {
+
+            return new AbstractReadOnlyModel<ConnInstanceTO>() {
+
+                private static final long serialVersionUID = -6033068018293569398L;
+
+                @Override
+                public ConnInstanceTO getObject() {
+                    return connector;
+                }
+            };
+        }
+
+        public List<ConnInstanceTO> getConnectorsListDB() {
+            return connectorRestClient.getAllConnectors();
+        }
+    }
+
+    @Override
+    public void onEvent(final IEvent<?> event) {
+        if (event.getPayload() instanceof AbstractSearchResultPanel.EventDataWrapper) {
+            ((AbstractSearchResultPanel.EventDataWrapper) event.getPayload()).getTarget().add(resourceContainer);
+            ((AbstractSearchResultPanel.EventDataWrapper) event.getPayload()).getTarget().add(connectorContainer);
+        }
+    }
+}


Mime
View raw message