com.evolveum.midpoint.web.page.admin.configuration.PageDebugList.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.web.page.admin.configuration.PageDebugList.java

Source

/*
 * Copyright (c) 2010-2013 Evolveum
 *
 * Licensed 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 com.evolveum.midpoint.web.page.admin.configuration;

import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.model.api.ModelPublicConstants;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.match.PolyStringNormMatchingRule;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.polystring.PolyStringNormalizer;
import com.evolveum.midpoint.prism.query.*;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.application.AuthorizationAction;
import com.evolveum.midpoint.web.application.PageDescriptor;
import com.evolveum.midpoint.web.component.BasicSearchPanel;
import com.evolveum.midpoint.web.component.data.BoxedTablePanel;
import com.evolveum.midpoint.web.component.data.RepositoryObjectDataProvider;
import com.evolveum.midpoint.web.component.data.Table;
import com.evolveum.midpoint.web.component.data.column.CheckBoxHeaderColumn;
import com.evolveum.midpoint.web.component.data.column.InlineMenuHeaderColumn;
import com.evolveum.midpoint.web.component.data.column.InlineMenuable;
import com.evolveum.midpoint.web.component.data.column.LinkColumn;
import com.evolveum.midpoint.web.component.data.column.LinkPanel;
import com.evolveum.midpoint.web.component.data.column.TwoValueLinkPanel;
import com.evolveum.midpoint.web.component.dialog.ConfirmationDialog;
import com.evolveum.midpoint.web.component.dialog.DeleteAllDialog;
import com.evolveum.midpoint.web.component.dialog.DeleteAllDto;
import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem;
import com.evolveum.midpoint.web.component.util.LoadableModel;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.web.page.admin.configuration.component.DebugButtonPanel;
import com.evolveum.midpoint.web.page.admin.configuration.component.HeaderMenuAction;
import com.evolveum.midpoint.web.page.admin.configuration.component.PageDebugDownloadBehaviour;
import com.evolveum.midpoint.web.page.admin.configuration.dto.DebugConfDialogDto;
import com.evolveum.midpoint.web.page.admin.configuration.dto.DebugObjectItem;
import com.evolveum.midpoint.web.page.admin.configuration.dto.DebugSearchDto;
import com.evolveum.midpoint.web.page.admin.dto.ObjectViewDto;
import com.evolveum.midpoint.web.session.ConfigurationStorage;
import com.evolveum.midpoint.web.session.UserProfileStorage;
import com.evolveum.midpoint.web.util.ObjectTypeGuiDescriptor;
import com.evolveum.midpoint.web.util.WebMiscUtil;
import com.evolveum.midpoint.web.util.WebModelUtils;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.query_3.QueryType;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
import org.apache.wicket.behavior.Behavior;
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.DataTable;
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.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.form.IChoiceRenderer;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.PropertyListView;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.*;
import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;

import javax.swing.text.html.ListView;
import javax.xml.namespace.QName;
import java.util.*;

/**
 * @author lazyman
 */
@PageDescriptor(url = "/admin/config/debugs", action = {
        @AuthorizationAction(actionUri = PageAdminConfiguration.AUTH_CONFIGURATION_ALL, label = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_LABEL, description = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_DESCRIPTION),
        @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_CONFIGURATION_DEBUGS_URL, label = "PageDebugList.auth.debugs.label", description = "PageDebugList.auth.debugs.description") })
public class PageDebugList extends PageAdminConfiguration {

    private static final Trace LOGGER = TraceManager.getTrace(PageDebugList.class);
    private static final String DOT_CLASS = PageDebugList.class.getName() + ".";
    private static final String OPERATION_DELETE_OBJECTS = DOT_CLASS + "deleteObjects";

    private static final String OPERATION_LAXATIVE_DELETE = DOT_CLASS + "laxativeDelete";

    private static final String OPERATION_LOAD_RESOURCES = DOT_CLASS + "loadResources";
    private static final String OPERATION_DELETE_SHADOWS = DOT_CLASS + "deleteShadows";

    private static final String ID_CONFIRM_DELETE_POPUP = "confirmDeletePopup";
    private static final String ID_MAIN_FORM = "mainForm";
    private static final String ID_ZIP_CHECK = "zipCheck";
    private static final String ID_TABLE = "table";
    private static final String ID_CHOICE = "choice";
    private static final String ID_EXPORT = "export";
    private static final String ID_EXPORT_ALL = "exportAll";
    private static final String ID_SEARCH_FORM = "searchForm";
    private static final String ID_BASIC_SEARCH = "basicSearch";
    private static final String ID_DELETE_ALL_DIALOG = "confirmDeleteAll";
    private static final String ID_RESOURCE = "resource";
    private static final String ID_TABLE_HEADER = "tableHeader";

    private static final Integer DELETE_LOG_INTERVAL = 50;

    // search form model;
    private IModel<DebugSearchDto> searchModel;
    // confirmation dialog model
    private IModel<DebugConfDialogDto> confDialogModel;
    private IModel<List<ObjectViewDto>> resourcesModel;

    public PageDebugList() {
        this(true);
    }

    public PageDebugList(boolean clearPagingInSession) {
        searchModel = new LoadableModel<DebugSearchDto>(false) {

            @Override
            protected DebugSearchDto load() {
                ConfigurationStorage storage = getSessionStorage().getConfiguration();
                return storage.getDebugSearchDto();
            }
        };

        confDialogModel = new LoadableModel<DebugConfDialogDto>() {

            @Override
            protected DebugConfDialogDto load() {
                return new DebugConfDialogDto();
            }
        };

        resourcesModel = new LoadableModel<List<ObjectViewDto>>() {

            @Override
            protected List<ObjectViewDto> load() {
                return loadResources();
            }
        };

        getSessionStorage().clearPagingInSession(clearPagingInSession);
        initLayout();
    }

    private List<ObjectViewDto> loadResources() {
        List<ObjectViewDto> objects = new ArrayList<>();

        try {
            OperationResult result = new OperationResult(OPERATION_LOAD_RESOURCES);
            List<PrismObject<ResourceType>> list = WebModelUtils.searchObjects(ResourceType.class, null,
                    SelectorOptions.createCollection(GetOperationOptions.createRaw()), result, this, null);

            for (PrismObject obj : list) {
                ObjectViewDto dto = new ObjectViewDto(obj.getOid(), WebMiscUtil.getName(obj));
                objects.add(dto);
            }
        } catch (Exception ex) {
            // todo implement error handling
        }

        Collections.sort(objects, new Comparator<ObjectViewDto>() {

            @Override
            public int compare(ObjectViewDto o1, ObjectViewDto o2) {
                return String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName());
            }
        });

        return objects;
    }

    private void initLayout() {
        DeleteAllDialog deleteAllDialog = new DeleteAllDialog(ID_DELETE_ALL_DIALOG,
                createStringResource("pageDebugList.dialog.title.deleteAll")) {

            @Override
            public void yesPerformed(AjaxRequestTarget target) {
                close(target);

                deleteAllIdentitiesConfirmed(target, getModel().getObject());
            }
        };
        add(deleteAllDialog);

        ConfirmationDialog deleteConfirm = new ConfirmationDialog(ID_CONFIRM_DELETE_POPUP,
                createStringResource("pageDebugList.dialog.title.confirmDelete"), createDeleteConfirmString()) {

            @Override
            public void yesPerformed(AjaxRequestTarget target) {
                close(target);

                DebugConfDialogDto dto = confDialogModel.getObject();
                switch (dto.getOperation()) {
                case DELETE_ALL_TYPE:
                    deleteAllTypeConfirmed(target);
                    break;
                case DELETE_SELECTED:
                    deleteSelectedConfirmed(target, dto.getObjects());
                    break;
                case DELETE_RESOURCE_SHADOWS:
                    deleteAllShadowsOnResourceConfirmed(target);
                    break;
                }
            }

            @Override
            public boolean getLabelEscapeModelStrings() {
                return false;
            }
        };
        add(deleteConfirm);

        Form main = new Form(ID_MAIN_FORM);
        add(main);

        DebugSearchDto dto = searchModel.getObject();
        Class type = dto.getType().getClassDefinition();
        addOrReplaceTable(new RepositoryObjectDataProvider(this, type) {

            @Override
            protected void saveProviderPaging(ObjectQuery query, ObjectPaging paging) {
                ConfigurationStorage storage = getSessionStorage().getConfiguration();
                storage.setDebugSearchPaging(paging);
            }
        });

        PageDebugDownloadBehaviour ajaxDownloadBehavior = new PageDebugDownloadBehaviour();
        main.add(ajaxDownloadBehavior);
    }

    private void initDownload(AjaxRequestTarget target, Class<? extends ObjectType> type, ObjectQuery query) {
        List<PageDebugDownloadBehaviour> list = get(ID_MAIN_FORM).getBehaviors(PageDebugDownloadBehaviour.class);
        PageDebugDownloadBehaviour downloadBehaviour = list.get(0);

        downloadBehaviour.setType(type);
        downloadBehaviour.setQuery(query);
        downloadBehaviour.setUseZip(hasToZip());
        downloadBehaviour.initiate(target);
    }

    private void addOrReplaceTable(RepositoryObjectDataProvider provider) {
        provider.setQuery(createQuery());
        Form mainForm = (Form) get(ID_MAIN_FORM);

        BoxedTablePanel table = new BoxedTablePanel(ID_TABLE, provider, initColumns(provider.getType()),
                UserProfileStorage.TableId.CONF_DEBUG_LIST_PANEL,
                (int) getItemsPerPage(UserProfileStorage.TableId.CONF_DEBUG_LIST_PANEL)) {

            @Override
            protected WebMarkupContainer createHeader(String headerId) {
                return new SearchFragment(headerId, ID_TABLE_HEADER, PageDebugList.this, searchModel,
                        resourcesModel);
            }

        };
        table.setOutputMarkupId(true);

        ConfigurationStorage storage = getSessionStorage().getConfiguration();
        table.setCurrentPage(storage.getDebugSearchPaging());

        mainForm.addOrReplace(table);
    }

    private List<IColumn> initColumns(final Class<? extends ObjectType> type) {
        List<IColumn> columns = new ArrayList<>();

        IColumn column = new CheckBoxHeaderColumn<ObjectType>();
        columns.add(column);

        column = new LinkColumn<DebugObjectItem>(createStringResource("pageDebugList.name"), DebugObjectItem.F_NAME,
                DebugObjectItem.F_NAME) {

            @Override
            public void populateItem(Item<ICellPopulator<DebugObjectItem>> cellItem, String componentId,
                    final IModel<DebugObjectItem> rowModel) {

                TwoValueLinkPanel panel = new TwoValueLinkPanel(componentId,
                        new PropertyModel<String>(rowModel, DebugObjectItem.F_NAME),
                        new PropertyModel<String>(rowModel, DebugObjectItem.F_OID)) {

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        DebugObjectItem object = rowModel.getObject();
                        objectEditPerformed(target, object.getOid(), type);
                    }
                };

                cellItem.add(panel);
                cellItem.add(new AttributeModifier("class", "col-md-3"));

            }

        };

        columns.add(column);
        columns.add(new PropertyColumn(createStringResource("pageDebugList.description"),
                DebugObjectItem.F_DESCRIPTION));

        if (ShadowType.class.isAssignableFrom(type)) {
            columns.add(new PropertyColumn(createStringResource("pageDebugList.resourceName"),
                    DebugObjectItem.F_RESOURCE_NAME));
            columns.add(new PropertyColumn(createStringResource("pageDebugList.resourceType"),
                    DebugObjectItem.F_RESOURCE_TYPE));
        }

        column = new AbstractColumn<DebugObjectItem, String>(new Model(), null) {

            @Override
            public String getCssClass() {
                return "debug-list-buttons";
            }

            @Override
            public void populateItem(Item<ICellPopulator<DebugObjectItem>> cellItem, String componentId,
                    IModel<DebugObjectItem> rowModel) {
                cellItem.add(new DebugButtonPanel<DebugObjectItem>(componentId, rowModel) {

                    @Override
                    public void deletePerformed(AjaxRequestTarget target, IModel<DebugObjectItem> model) {
                        deleteSelected(target, model.getObject());
                    }

                    @Override
                    public void exportPerformed(AjaxRequestTarget target, IModel<DebugObjectItem> model) {
                        exportSelected(target, model.getObject());
                    }
                });
            }
        };

        columns.add(column);

        column = new InlineMenuHeaderColumn<InlineMenuable>(initInlineMenu()) {

            @Override
            public void populateItem(Item<ICellPopulator<InlineMenuable>> cellItem, String componentId,
                    IModel<InlineMenuable> rowModel) {
                // we don't need row inline menu
                cellItem.add(new Label(componentId));
            }
        };
        columns.add(column);

        return columns;
    }

    private List<InlineMenuItem> initInlineMenu() {
        List<InlineMenuItem> headerMenuItems = new ArrayList<>();
        headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.exportSelected"), true,
                new HeaderMenuAction(this) {

                    @Override
                    public void onSubmit(AjaxRequestTarget target, Form<?> form) {
                        exportSelected(target, null);
                    }
                }));

        headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.exportAllSelectedType"),
                true, new HeaderMenuAction(this) {

                    @Override
                    public void onSubmit(AjaxRequestTarget target, Form<?> form) {
                        exportAllType(target);
                    }
                }));

        headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.exportAll"), true,
                new HeaderMenuAction(this) {

                    @Override
                    public void onSubmit(AjaxRequestTarget target, Form<?> form) {
                        exportAll(target);
                    }
                }));

        headerMenuItems.add(new InlineMenuItem());

        headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.deleteSelected"), true,
                new HeaderMenuAction(this) {

                    @Override
                    public void onSubmit(AjaxRequestTarget target, Form<?> form) {
                        deleteSelected(target, null);
                    }
                }));

        headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.deleteAllType"), true,
                new HeaderMenuAction(this) {

                    @Override
                    public void onSubmit(AjaxRequestTarget target, Form<?> form) {
                        deleteAllType(target);
                    }
                }));

        headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.deleteShadowsOnResource"),
                new Model(true), new AbstractReadOnlyModel<Boolean>() {

                    @Override
                    public Boolean getObject() {
                        DebugSearchDto dto = searchModel.getObject();
                        return ObjectTypes.SHADOW.equals(dto.getType());
                    }

                }, false, new HeaderMenuAction(this) {

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        deleteAllShadowsOnResource(target);
                    }
                }));

        headerMenuItems.add(new InlineMenuItem());

        headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.deleteAllIdentities"), true,
                new HeaderMenuAction(this) {

                    @Override
                    public void onSubmit(AjaxRequestTarget target, Form<?> form) {
                        deleteAllIdentities(target);
                    }
                }));

        return headerMenuItems;
    }

    private boolean hasToZip() {
        BoxedTablePanel table = (BoxedTablePanel) getListTable();
        SearchFragment header = (SearchFragment) table.getHeader();
        AjaxCheckBox zipCheck = header.getZipCheck();

        return zipCheck.getModelObject();
    }

    private Table getListTable() {
        return (Table) get(createComponentPath(ID_MAIN_FORM, ID_TABLE));
    }

    private void listObjectsPerformed(AjaxRequestTarget target) {
        DebugSearchDto dto = searchModel.getObject();
        ObjectTypes selected = dto.getType();

        RepositoryObjectDataProvider provider = getTableDataProvider();
        provider.setQuery(createQuery());

        if (selected != null) {
            provider.setType(selected.getClassDefinition());
            addOrReplaceTable(provider);
        }

        // save object type category to session storage, used by back button
        ConfigurationStorage storage = getSessionStorage().getConfiguration();
        storage.setDebugSearchDto(dto);

        Table table = getListTable();
        target.add((Component) table);
    }

    private ObjectQuery createQuery() {
        DebugSearchDto dto = searchModel.getObject();

        List<ObjectFilter> filters = new ArrayList<>();
        if (ObjectTypes.SHADOW.equals(dto.getType()) && dto.getResource() != null) {
            String oid = dto.getResource().getOid();
            RefFilter ref = RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class,
                    getPrismContext(), oid);
            filters.add(ref);
        }

        if (StringUtils.isNotEmpty(dto.getText())) {
            String nameText = dto.getText();
            PolyStringNormalizer normalizer = getPrismContext().getDefaultPolyStringNormalizer();
            String normalizedString = normalizer.normalize(nameText);

            ObjectFilter substring = SubstringFilter.createSubstring(ObjectType.F_NAME, ObjectType.class,
                    getPrismContext(), PolyStringNormMatchingRule.NAME, normalizedString);
            filters.add(substring);
        }

        if (filters.isEmpty()) {
            return null;
        }

        ObjectFilter filter = filters.size() > 1 ? AndFilter.createAnd(filters) : filters.get(0);
        ObjectQuery query = new ObjectQuery();
        query.setFilter(filter);

        return query;
    }

    private void objectEditPerformed(AjaxRequestTarget target, String oid, Class<? extends ObjectType> type) {
        PageParameters parameters = new PageParameters();
        parameters.add(PageDebugView.PARAM_OBJECT_ID, oid);
        parameters.add(PageDebugView.PARAM_OBJECT_TYPE, type.getSimpleName());
        setResponsePage(PageDebugView.class, parameters);
    }

    private RepositoryObjectDataProvider getTableDataProvider() {
        Table tablePanel = getListTable();
        DataTable table = tablePanel.getDataTable();
        return (RepositoryObjectDataProvider) table.getDataProvider();
    }

    private IModel<String> createDeleteConfirmString() {
        return new AbstractReadOnlyModel<String>() {

            @Override
            public String getObject() {
                DebugConfDialogDto dto = confDialogModel.getObject();

                switch (dto.getOperation()) {
                case DELETE_ALL_TYPE:
                    String key = ObjectTypeGuiDescriptor.getDescriptor(dto.getType()).getLocalizationKey();
                    String type = createStringResource(key).getString();
                    return createStringResource("pageDebugList.message.deleteAllType", type).getString();
                case DELETE_SELECTED:
                    List<DebugObjectItem> selectedList = dto.getObjects();

                    if (selectedList.size() > 1) {
                        return createStringResource("pageDebugList.message.deleteSelectedConfirm",
                                selectedList.size()).getString();
                    }

                    DebugObjectItem selectedItem = selectedList.get(0);
                    return createStringResource("pageDebugList.message.deleteObjectConfirm", selectedItem.getName())
                            .getString();
                case DELETE_RESOURCE_SHADOWS:
                    DebugSearchDto search = searchModel.getObject();
                    return createStringResource("pageDebugList.messsage.deleteAllResourceShadows",
                            search.getResource().getName()).getString();
                }

                return "";
            }
        };
    }

    private void deleteAllIdentitiesConfirmed(AjaxRequestTarget target, DeleteAllDto dto) {
        Collection<SelectorOptions<GetOperationOptions>> options = new ArrayList<>();
        GetOperationOptions opt = GetOperationOptions.createRaw();
        options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, opt));

        OperationResult result = new OperationResult(OPERATION_LAXATIVE_DELETE);
        try {
            if (dto.getDeleteUsers()) {
                ObjectQuery query = createDeleteAllUsersQuery();
                deleteObjectsAsync(UserType.COMPLEX_TYPE, query, true, "Delete all users", result);
            }
            if (dto.getDeleteOrgs()) {
                deleteObjectsAsync(OrgType.COMPLEX_TYPE, null, true, "Delete all orgs", result);
            }
            if (dto.getDeleteAccountShadow()) {
                deleteAllShadowsConfirmed(result, true);
            }
            if (dto.getDeleteNonAccountShadow()) {
                deleteAllShadowsConfirmed(result, false);
            }
        } catch (Exception ex) {
            result.computeStatus(getString("pageDebugList.message.laxativeProblem"));
            LoggingUtils.logException(LOGGER, getString("pageDebugList.message.laxativeProblem"), ex);
        }

        target.add(getFeedbackPanel());

        result.recomputeStatus();
        showResult(result);
    }

    private ObjectQuery createDeleteAllUsersQuery() {
        InOidFilter inOid = InOidFilter.createInOid(SystemObjectsType.USER_ADMINISTRATOR.value());
        NotFilter not = new NotFilter(inOid);

        return ObjectQuery.createObjectQuery(not);
    }

    private void deleteAllShadowsConfirmed(OperationResult result, boolean deleteAccountShadows)
            throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException {

        ObjectFilter kind = EqualFilter.createEqual(ShadowType.F_KIND, ShadowType.class, getPrismContext(), null,
                ShadowKindType.ACCOUNT);

        String taskName;
        ObjectQuery query;
        if (deleteAccountShadows) {
            taskName = "Delete all account shadows";
            query = ObjectQuery.createObjectQuery(kind);
        } else {
            taskName = "Delete all non-account shadows";
            query = ObjectQuery.createObjectQuery(NotFilter.createNot(kind));
        }

        deleteObjectsAsync(ShadowType.COMPLEX_TYPE, query, true, taskName, result);
    }

    private void exportSelected(AjaxRequestTarget target, DebugObjectItem item) {
        List<DebugObjectItem> selected = getSelectedData(target, item);
        if (selected.isEmpty()) {
            return;
        }

        List<String> oids = new ArrayList<>();
        for (DebugObjectItem dItem : selected) {
            oids.add(dItem.getOid());
        }

        ObjectFilter filter = InOidFilter.createInOid(oids);

        DebugSearchDto searchDto = searchModel.getObject();
        initDownload(target, searchDto.getType().getClassDefinition(), ObjectQuery.createObjectQuery(filter));
    }

    private void exportAllType(AjaxRequestTarget target) {
        DebugSearchDto searchDto = searchModel.getObject();
        initDownload(target, searchDto.getType().getClassDefinition(), null);
    }

    private void exportAll(AjaxRequestTarget target) {
        initDownload(target, ObjectType.class, null);
    }

    private void deleteAllType(AjaxRequestTarget target) {
        DebugSearchDto searchDto = searchModel.getObject();
        DebugConfDialogDto dto = new DebugConfDialogDto(DebugConfDialogDto.Operation.DELETE_ALL_TYPE, null,
                searchDto.getType().getClassDefinition());
        confDialogModel.setObject(dto);

        ModalWindow dialog = (ModalWindow) get(ID_CONFIRM_DELETE_POPUP);
        dialog.show(target);
    }

    private List<DebugObjectItem> getSelectedData(AjaxRequestTarget target, DebugObjectItem item) {
        List<DebugObjectItem> items;
        if (item != null) {
            items = new ArrayList<>();
            items.add(item);
            return items;
        }

        items = WebMiscUtil.getSelectedData(getListTable());
        if (items.isEmpty()) {
            warn(getString("pageDebugList.message.nothingSelected"));
            target.add(getFeedbackPanel());
        }

        return items;
    }

    private void deleteSelected(AjaxRequestTarget target, DebugObjectItem item) {
        List<DebugObjectItem> selected = getSelectedData(target, item);
        if (selected.isEmpty()) {
            return;
        }

        DebugSearchDto searchDto = searchModel.getObject();
        DebugConfDialogDto dto = new DebugConfDialogDto(DebugConfDialogDto.Operation.DELETE_SELECTED, selected,
                searchDto.getType().getClassDefinition());
        confDialogModel.setObject(dto);

        ModalWindow dialog = (ModalWindow) get(ID_CONFIRM_DELETE_POPUP);
        dialog.show(target);
    }

    private void deleteAllIdentities(AjaxRequestTarget target) {
        DeleteAllDialog dialog = (DeleteAllDialog) get(ID_DELETE_ALL_DIALOG);
        dialog.show(target);
    }

    private void deleteAllTypeConfirmed(AjaxRequestTarget target) {
        DebugSearchDto dto = searchModel.getObject();

        LOGGER.debug("Deleting all of type {}", dto.getType());

        OperationResult result = new OperationResult(OPERATION_DELETE_OBJECTS);
        try {
            ObjectQuery query = null;
            if (ObjectTypes.USER.equals(dto.getType())) {
                query = createDeleteAllUsersQuery();
            }

            QName type = dto.getType().getTypeQName();

            deleteObjectsAsync(type, query, true, "Delete all of type " + type.getLocalPart(), result);

            info(getString("pageDebugList.messsage.deleteAllOfType", dto.getType()));
        } catch (Exception ex) {
            result.recomputeStatus();
            result.recordFatalError("Couldn't delete objects of type " + dto.getType(), ex);

            LoggingUtils.logException(LOGGER, "Couldn't delete objects of type " + dto.getType(), ex);
        }

        showResult(result);
        target.add(getFeedbackPanel());
    }

    private void deleteSelectedConfirmed(AjaxRequestTarget target, List<DebugObjectItem> items) {
        DebugConfDialogDto dto = confDialogModel.getObject();

        OperationResult result = new OperationResult(OPERATION_DELETE_OBJECTS);
        for (DebugObjectItem bean : items) {
            WebModelUtils.deleteObject(dto.getType(), bean.getOid(), ModelExecuteOptions.createRaw(), result, this);
        }
        result.computeStatusIfUnknown();

        RepositoryObjectDataProvider provider = getTableDataProvider();
        provider.clearCache();

        showResult(result);
        target.add((Component) getListTable());
        target.add(getFeedbackPanel());
    }

    private void clearSearchPerformed(AjaxRequestTarget target) {
        DebugSearchDto dto = searchModel.getObject();
        dto.setText(null);

        listObjectsPerformed(target);
    }

    private void deleteAllShadowsOnResource(AjaxRequestTarget target) {
        DebugSearchDto dto = searchModel.getObject();
        if (dto.getResource() == null) {
            error(getString("pageDebugList.message.resourceNotSelected"));
            target.add(getFeedbackPanel());
            return;
        }

        LOGGER.debug("Displaying delete all shadows on resource {} confirmation dialog",
                dto.getResource().getName());

        DebugConfDialogDto dialogDto = new DebugConfDialogDto(DebugConfDialogDto.Operation.DELETE_RESOURCE_SHADOWS,
                null, null);
        confDialogModel.setObject(dialogDto);

        ModalWindow dialog = (ModalWindow) get(ID_CONFIRM_DELETE_POPUP);
        dialog.show(target);
    }

    private void deleteAllShadowsOnResourceConfirmed(AjaxRequestTarget target) {
        DebugSearchDto dto = searchModel.getObject();
        String resourceOid = dto.getResource().getOid();

        LOGGER.debug("Deleting shadows on resource {}", resourceOid);

        OperationResult result = new OperationResult(OPERATION_DELETE_SHADOWS);
        try {
            RefFilter ref = RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class,
                    getPrismContext(), dto.getResource().getOid());
            ObjectQuery objectQuery = ObjectQuery.createObjectQuery(ref);

            QName type = ShadowType.COMPLEX_TYPE;

            deleteObjectsAsync(type, objectQuery, true, "Delete shadows on " + dto.getResource().getName(), result);

            info(getString("pageDebugList.messsage.deleteAllShadowsStarted", dto.getResource().getName()));
        } catch (Exception ex) {
            result.recomputeStatus();
            result.recordFatalError("Couldn't delete shadows.", ex);

            LoggingUtils.logException(LOGGER, "Couldn't delete shadows", ex);
        }

        showResult(result);
        target.add(getFeedbackPanel());
    }

    private void deleteObjectsAsync(QName type, ObjectQuery objectQuery, boolean raw, String taskName,
            OperationResult result) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException {

        Task task = createSimpleTask(result.getOperation());
        task.setHandlerUri(ModelPublicConstants.DELETE_TASK_HANDLER_URI);

        if (objectQuery == null) {
            objectQuery = new ObjectQuery();
        }

        QueryType query = QueryJaxbConvertor.createQueryType(objectQuery, getPrismContext());

        PrismPropertyDefinition queryDef = new PrismPropertyDefinition(SchemaConstants.MODEL_EXTENSION_OBJECT_QUERY,
                QueryType.COMPLEX_TYPE, getPrismContext());
        PrismProperty<QueryType> queryProp = queryDef.instantiate();
        queryProp.setRealValue(query);
        task.setExtensionProperty(queryProp);

        PrismPropertyDefinition typeDef = new PrismPropertyDefinition(SchemaConstants.MODEL_EXTENSION_OBJECT_TYPE,
                DOMUtil.XSD_QNAME, getPrismContext());
        PrismProperty<QName> typeProp = typeDef.instantiate();
        typeProp.setRealValue(type);
        task.setExtensionProperty(typeProp);

        PrismPropertyDefinition rawDef = new PrismPropertyDefinition(SchemaConstants.MODEL_EXTENSION_OPTION_RAW,
                DOMUtil.XSD_BOOLEAN, getPrismContext());
        PrismProperty<QName> rawProp = rawDef.instantiate();
        rawProp.setRealValue(raw);
        task.setExtensionProperty(rawProp);

        task.setName(taskName);
        task.savePendingModifications(result);

        TaskManager taskManager = getTaskManager();
        taskManager.switchToBackground(task, result);
    }

    private static class SearchFragment extends Fragment {

        public SearchFragment(String id, String markupId, MarkupContainer markupProvider,
                IModel<DebugSearchDto> model, IModel<List<ObjectViewDto>> resourcesModel) {
            super(id, markupId, markupProvider, model);

            initLayout(resourcesModel);
        }

        private void initLayout(IModel<List<ObjectViewDto>> resourcesModel) {
            final Form searchForm = new Form(ID_SEARCH_FORM);
            add(searchForm);
            searchForm.setOutputMarkupId(true);

            final IModel<DebugSearchDto> model = (IModel) getDefaultModel();

            BasicSearchPanel<DebugSearchDto> basicSearch = new BasicSearchPanel<DebugSearchDto>(ID_BASIC_SEARCH,
                    model) {

                @Override
                protected IModel<String> createSearchTextModel() {
                    return new PropertyModel<>(model, DebugSearchDto.F_TEXT);
                }

                @Override
                protected void searchPerformed(AjaxRequestTarget target) {
                    PageDebugList page = (PageDebugList) getPage();
                    page.listObjectsPerformed(target);
                }

                @Override
                protected void clearSearchPerformed(AjaxRequestTarget target) {
                    PageDebugList page = (PageDebugList) getPage();
                    page.clearSearchPerformed(target);
                }
            };
            searchForm.add(basicSearch);

            IChoiceRenderer<ObjectTypes> renderer = new IChoiceRenderer<ObjectTypes>() {

                @Override
                public Object getDisplayValue(ObjectTypes object) {
                    ObjectTypeGuiDescriptor descr = ObjectTypeGuiDescriptor.getDescriptor(object);
                    String key = descr != null ? descr.getLocalizationKey()
                            : ObjectTypeGuiDescriptor.ERROR_LOCALIZATION_KEY;

                    return new StringResourceModel(key, getPage(), null).getString();
                }

                @Override
                public String getIdValue(ObjectTypes object, int index) {
                    return object.getClassDefinition().getSimpleName();
                }
            };

            DropDownChoice choice = new DropDownChoice(ID_CHOICE, new PropertyModel(model, DebugSearchDto.F_TYPE),
                    createChoiceModel(renderer), renderer);
            searchForm.add(choice);
            choice.add(new OnChangeAjaxBehavior() {

                @Override
                protected void onUpdate(AjaxRequestTarget target) {
                    PageDebugList page = (PageDebugList) getPage();
                    page.listObjectsPerformed(target);
                }
            });

            DropDownChoice resource = new DropDownChoice(ID_RESOURCE,
                    new PropertyModel(model, DebugSearchDto.F_RESOURCE_OID), resourcesModel,
                    createResourceRenderer());
            resource.setNullValid(true);
            resource.add(new AjaxFormComponentUpdatingBehavior("onblur") {

                @Override
                protected void onUpdate(AjaxRequestTarget target) {
                    // nothing to do, it's here just to update model
                }
            });
            resource.add(new VisibleEnableBehaviour() {

                @Override
                public boolean isVisible() {
                    DebugSearchDto dto = model.getObject();
                    return ObjectTypes.SHADOW.equals(dto.getType());
                }
            });
            searchForm.add(resource);

            AjaxCheckBox zipCheck = new AjaxCheckBox(ID_ZIP_CHECK, new Model<>(false)) {

                @Override
                protected void onUpdate(AjaxRequestTarget target) {
                }
            };
            add(zipCheck);
        }

        public AjaxCheckBox getZipCheck() {
            return (AjaxCheckBox) get(ID_ZIP_CHECK);
        }

        private IModel<List<ObjectTypes>> createChoiceModel(final IChoiceRenderer<ObjectTypes> renderer) {
            return new LoadableModel<List<ObjectTypes>>(false) {

                @Override
                protected List<ObjectTypes> load() {
                    List<ObjectTypes> choices = new ArrayList<>();

                    Collections.addAll(choices, ObjectTypes.values());
                    choices.remove(ObjectTypes.OBJECT);

                    Collections.sort(choices, new Comparator<ObjectTypes>() {

                        @Override
                        public int compare(ObjectTypes o1, ObjectTypes o2) {
                            String str1 = (String) renderer.getDisplayValue(o1);
                            String str2 = (String) renderer.getDisplayValue(o2);
                            return String.CASE_INSENSITIVE_ORDER.compare(str1, str2);
                        }
                    });

                    return choices;
                }
            };
        }

        private IChoiceRenderer<ObjectViewDto> createResourceRenderer() {
            return new IChoiceRenderer<ObjectViewDto>() {

                @Override
                public Object getDisplayValue(ObjectViewDto object) {
                    if (object == null) {
                        return getString("pageDebugList.resource");
                    }
                    return object.getName();
                }

                @Override
                public String getIdValue(ObjectViewDto object, int index) {
                    return Integer.toString(index);
                }
            };
        }
    }
}