com.evolveum.midpoint.web.page.admin.users.component.OrgMemberPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.web.page.admin.users.component.OrgMemberPanel.java

Source

/**
 * Copyright (c) 2015-2016 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.users.component;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.xml.namespace.QName;

import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.lang.Validate;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.EnumChoiceRenderer;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;

import com.evolveum.midpoint.gui.api.component.MainObjectListPanel;
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.model.api.PolicyViolationException;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismReferenceDefinition;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.AndFilter;
import com.evolveum.midpoint.prism.query.InOidFilter;
import com.evolveum.midpoint.prism.query.NotFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.OrgFilter;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.prism.query.TypeFilter;
import com.evolveum.midpoint.prism.query.OrgFilter.Scope;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.RetrieveOption;
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.task.api.Task;
import com.evolveum.midpoint.task.api.TaskCategory;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
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.exception.SecurityViolationException;
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.component.AjaxButton;
import com.evolveum.midpoint.web.component.FocusSummaryPanel;
import com.evolveum.midpoint.web.component.dialog.ConfirmationPanel;
import com.evolveum.midpoint.web.component.menu.cog.InlineMenu;
import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem;
import com.evolveum.midpoint.web.component.prism.ContainerStatus;
import com.evolveum.midpoint.web.component.prism.ObjectWrapper;
import com.evolveum.midpoint.web.component.util.ObjectWrapperUtil;
import com.evolveum.midpoint.web.page.admin.configuration.component.HeaderMenuAction;
import com.evolveum.midpoint.web.page.admin.roles.component.RoleSummaryPanel;
import com.evolveum.midpoint.web.session.UserProfileStorage.TableId;
import com.evolveum.midpoint.web.util.StringResourceChoiceRenderer;

public class OrgMemberPanel extends AbstractRoleMemberPanel<OrgType> {

    private static final Trace LOGGER = TraceManager.getTrace(OrgMemberPanel.class);

    protected static final String ID_SEARCH_SCOPE = "searchScope";
    protected static final String ID_SEARCH_BY_TYPE = "searchByType";

    protected static final String ID_MANAGER_MENU = "managerMenu";
    protected static final String ID_MANAGER_MENU_BODY = "managerMenuBody";

    protected static final String SEARCH_SCOPE_SUBTREE = "subtree";
    protected static final String SEARCH_SCOPE_ONE = "one";

    protected static final ObjectTypes OBJECT_TYPES_DEFAULT = ObjectTypes.OBJECT;

    protected static final List<String> SEARCH_SCOPE_VALUES = Arrays.asList(SEARCH_SCOPE_SUBTREE, SEARCH_SCOPE_ONE);

    protected static final String DOT_CLASS = OrgMemberPanel.class.getName() + ".";
    protected static final String OPERATION_SEARCH_MANAGERS = DOT_CLASS + "searchManagers";
    private static final String ID_MANAGER_SUMMARY = "managerSummary";
    private static final String ID_REMOVE_MANAGER = "removeManager";
    private static final String ID_DELETE_MANAGER = "deleteManager";
    private static final String ID_EDIT_MANAGER = "editManager";

    private static final long serialVersionUID = 1L;

    public OrgMemberPanel(String id, IModel<OrgType> model, PageBase parentPage) {
        super(id, TableId.ORG_MEMEBER_PANEL, model, parentPage);
        setOutputMarkupId(true);
    }

    @Override
    protected void initSearch(Form form) {

        /// TODO: move to utils class??
        List<ObjectTypes> objectTypes = Arrays.asList(ObjectTypes.values());
        Collections.sort(objectTypes, new Comparator<ObjectTypes>() {

            @Override
            public int compare(ObjectTypes o1, ObjectTypes o2) {
                Validate.notNull(o1);
                Validate.notNull(o2);

                String type1 = o1.getValue();
                String type2 = o2.getValue();

                return String.CASE_INSENSITIVE_ORDER.compare(type1, type2);

            }
        });
        ////////////

        DropDownChoice<ObjectTypes> objectType = new DropDownChoice<ObjectTypes>(ID_SEARCH_BY_TYPE,
                Model.of(OBJECT_TYPES_DEFAULT), objectTypes, new EnumChoiceRenderer<ObjectTypes>());
        objectType.add(new OnChangeAjaxBehavior() {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                refreshTable(target);

            }
        });
        objectType.setOutputMarkupId(true);
        form.add(objectType);

        DropDownChoice<String> seachScrope = new DropDownChoice<String>(ID_SEARCH_SCOPE, Model.of(SEARCH_SCOPE_ONE),
                SEARCH_SCOPE_VALUES, new StringResourceChoiceRenderer("TreeTablePanel.search.scope"));
        seachScrope.add(new OnChangeAjaxBehavior() {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                refreshTable(target);
            }
        });
        seachScrope.setOutputMarkupId(true);
        form.add(seachScrope);

    }

    @Override
    protected void initCustomLayout(Form form) {
        WebMarkupContainer managerContainer = createManagerContainer();
        form.addOrReplace(managerContainer);
    }

    private WebMarkupContainer createManagerContainer() {
        WebMarkupContainer managerContainer = new WebMarkupContainer(ID_CONTAINER_MANAGER);
        managerContainer.setOutputMarkupId(true);
        managerContainer.setOutputMarkupPlaceholderTag(true);

        RepeatingView view = new RepeatingView(ID_MANAGER_TABLE);
        view.setOutputMarkupId(true);
        ObjectQuery managersQuery = createManagerQuery();

        OperationResult searchManagersResult = new OperationResult(OPERATION_SEARCH_MANAGERS);
        Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(
                FocusType.F_JPEG_PHOTO, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE));
        List<PrismObject<FocusType>> managers = WebModelServiceUtils.searchObjects(FocusType.class, managersQuery,
                options, searchManagersResult, getPageBase());
        for (PrismObject<FocusType> manager : managers) {
            ObjectWrapper<FocusType> managerWrapper = ObjectWrapperUtil.createObjectWrapper(
                    WebComponentUtil.getEffectiveName(manager, RoleType.F_DISPLAY_NAME), "", manager,
                    ContainerStatus.MODIFYING, getPageBase());
            WebMarkupContainer managerMarkup = new WebMarkupContainer(view.newChildId());

            AjaxLink<String> link = new AjaxLink<String>(ID_EDIT_MANAGER) {
                private static final long serialVersionUID = 1L;

                @Override
                public void onClick(AjaxRequestTarget target) {
                    FocusSummaryPanel<FocusType> summary = (FocusSummaryPanel<FocusType>) getParent()
                            .get(ID_MANAGER_SUMMARY);
                    detailsPerformed(target, summary.getModelObject());

                }
            };
            if (manager.getCompileTimeClass().equals(UserType.class)) {
                managerMarkup.add(new UserSummaryPanel(ID_MANAGER_SUMMARY,
                        new Model<ObjectWrapper<UserType>>((ObjectWrapper) managerWrapper)));
            } else if (manager.getCompileTimeClass().equals(RoleType.class)) {
                managerMarkup.add(new RoleSummaryPanel(ID_MANAGER_SUMMARY,
                        new Model<ObjectWrapper<RoleType>>((ObjectWrapper) managerWrapper)));
            } else if (manager.getCompileTimeClass().equals(OrgType.class)) {
                managerMarkup.add(new OrgSummaryPanel(ID_MANAGER_SUMMARY,
                        new Model<ObjectWrapper<OrgType>>((ObjectWrapper) managerWrapper)));
            } else if (manager.getCompileTimeClass().equals(ServiceType.class)) {
                managerMarkup.add(new ServiceSummaryPanel(ID_MANAGER_SUMMARY,
                        new Model<ObjectWrapper<ServiceType>>((ObjectWrapper) managerWrapper)));
            }
            link.setOutputMarkupId(true);
            managerMarkup.setOutputMarkupId(true);
            managerMarkup.add(link);
            view.add(managerMarkup);

            AjaxButton removeManager = new AjaxButton(ID_REMOVE_MANAGER) {

                @Override
                public void onClick(AjaxRequestTarget target) {
                    FocusSummaryPanel<FocusType> summary = (FocusSummaryPanel<FocusType>) getParent()
                            .get(ID_MANAGER_SUMMARY);
                    removeManagerPerformed(summary.getModelObject(), target);
                    getParent().setVisible(false);
                    target.add(OrgMemberPanel.this);

                }
            };
            removeManager.setOutputMarkupId(true);
            managerMarkup.add(removeManager);

            AjaxButton deleteManager = new AjaxButton(ID_DELETE_MANAGER) {

                @Override
                public void onClick(AjaxRequestTarget target) {
                    FocusSummaryPanel<FocusType> summary = (FocusSummaryPanel<FocusType>) getParent()
                            .get(ID_MANAGER_SUMMARY);
                    deleteManagerPerformed(summary.getModelObject(), this, target);
                }
            };
            deleteManager.setOutputMarkupId(true);
            managerMarkup.add(deleteManager);
        }

        managerContainer.add(view);

        InlineMenu menupanel = new InlineMenu(ID_MANAGER_MENU,
                new Model<Serializable>((Serializable) createManagersHeaderInlineMenu()));

        add(menupanel);
        menupanel.setOutputMarkupId(true);
        managerContainer.add(menupanel);

        return managerContainer;
    }

    private void removeManagerPerformed(FocusType manager, AjaxRequestTarget target) {
        OperationResult parentResult = new OperationResult("Remove manager");
        Task task = getPageBase().createSimpleTask("Remove manager");
        try {

            ObjectDelta delta = ObjectDelta.createModificationDeleteContainer(
                    manager.asPrismObject().getCompileTimeClass(), manager.getOid(), FocusType.F_ASSIGNMENT,
                    getPageBase().getPrismContext(), createAssignmentToModify(SchemaConstants.ORG_MANAGER));

            getPageBase().getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), null,
                    task, parentResult);
            parentResult.computeStatus();
        } catch (SchemaException | ObjectAlreadyExistsException | ObjectNotFoundException
                | ExpressionEvaluationException | CommunicationException | ConfigurationException
                | PolicyViolationException | SecurityViolationException e) {

            parentResult.recordFatalError("Failed to remove manager " + e.getMessage(), e);
            LoggingUtils.logUnexpectedException(LOGGER, "Failed to remove manager", e);
            getPageBase().showResult(parentResult);
        }
        target.add(getPageBase().getFeedbackPanel());

    }

    private void deleteManagerConfirmPerformed(FocusType manager, AjaxRequestTarget target) {
        getPageBase().hideMainPopup(target);
        OperationResult parentResult = new OperationResult("Remove manager");
        Task task = getPageBase().createSimpleTask("Remove manager");
        try {

            ObjectDelta delta = ObjectDelta.createDeleteDelta(manager.asPrismObject().getCompileTimeClass(),
                    manager.getOid(), getPageBase().getPrismContext());
            getPageBase().getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), null,
                    task, parentResult);
            parentResult.computeStatus();
        } catch (SchemaException | ObjectAlreadyExistsException | ObjectNotFoundException
                | ExpressionEvaluationException | CommunicationException | ConfigurationException
                | PolicyViolationException | SecurityViolationException e) {

            parentResult.recordFatalError("Failed to remove manager " + e.getMessage(), e);
            LoggingUtils.logUnexpectedException(LOGGER, "Failed to remove manager", e);
            getPageBase().showResult(parentResult);
        }
        target.add(getPageBase().getFeedbackPanel());

    }

    private void deleteManagerPerformed(final FocusType manager, final Component summary,
            AjaxRequestTarget target) {
        ConfirmationPanel confirmDelete = new ConfirmationPanel(getPageBase().getMainPopupBodyId(),
                createStringResource("TreeTablePanel.menu.deleteManager.confirm")) {
            @Override
            public void yesPerformed(AjaxRequestTarget target) {
                OrgMemberPanel.this.deleteManagerConfirmPerformed(manager, target);
                summary.getParent().setVisible(false);
                target.add(OrgMemberPanel.this);
            }
        };

        getPageBase().showMainPopup(confirmDelete, target);
    }

    @Override
    protected List<InlineMenuItem> createMembersHeaderInlineMenu() {
        List<InlineMenuItem> headerMenuItems = super.createMembersHeaderInlineMenu();

        headerMenuItems.add(new InlineMenuItem(createStringResource("TreeTablePanel.menu.deleteMember"), false,
                new HeaderMenuAction(this) {

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        deleteMemberPerformed(QueryScope.SELECTED, null, target,
                                "TreeTablePanel.menu.deleteMember.confirm");
                    }
                }));

        headerMenuItems.add(new InlineMenuItem(createStringResource("TreeTablePanel.menu.deleteAllMembers"), false,
                new HeaderMenuAction(this) {

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        deleteMemberPerformed(QueryScope.ALL, null, target,
                                "TreeTablePanel.menu.deleteAllMembers.confirm");
                    }
                }));
        return headerMenuItems;
    }

    private void deleteMemberPerformed(final QueryScope scope, final QName relation, final AjaxRequestTarget target,
            String confirmMessageKey) {
        ConfirmationPanel confirmDelete = new ConfirmationPanel(getPageBase().getMainPopupBodyId(),
                createStringResource(confirmMessageKey)) {
            @Override
            public void yesPerformed(AjaxRequestTarget target) {
                OrgMemberPanel.this.deleteMemberConfirmPerformed(scope, relation, target);
            }
        };

        getPageBase().showMainPopup(confirmDelete, target);
    }

    private void deleteMemberConfirmPerformed(QueryScope scope, QName relation, AjaxRequestTarget target) {
        getPageBase().hideMainPopup(target);
        Task operationalTask = getPageBase().createSimpleTask(getTaskName("Delete", scope, false));
        ObjectDelta delta = ObjectDelta.createDeleteDelta(FocusType.class, "fakeOid",
                getPageBase().getPrismContext());
        if (delta == null) {
            return;
        }
        executeMemberOperation(operationalTask, FocusType.COMPLEX_TYPE,
                createQueryForMemberAction(scope, relation, true), delta, TaskCategory.EXECUTE_CHANGES, target);

    }

    private List<InlineMenuItem> createManagersHeaderInlineMenu() {
        List<InlineMenuItem> headerMenuItems = new ArrayList<>();

        headerMenuItems.add(new InlineMenuItem(createStringResource("TreeTablePanel.menu.createManager"), false,
                new HeaderMenuAction(this) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        OrgMemberPanel.this.createFocusMemberPerformed(SchemaConstants.ORG_MANAGER, target);
                    }
                }));
        headerMenuItems.add(new InlineMenuItem());

        headerMenuItems.add(new InlineMenuItem(createStringResource("TreeTablePanel.menu.addManagers"), false,
                new HeaderMenuAction(this) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        OrgMemberPanel.this.addMembers(SchemaConstants.ORG_MANAGER, target);
                    }
                }));
        headerMenuItems.add(new InlineMenuItem());

        headerMenuItems.add(new InlineMenuItem(createStringResource("TreeTablePanel.menu.removeManagersAll"), false,
                new HeaderMenuAction(this) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        removeManagersPerformed(QueryScope.ALL, target);
                    }
                }));

        headerMenuItems.add(new InlineMenuItem(createStringResource("TreeTablePanel.menu.recomputeManagersAll"),
                false, new HeaderMenuAction(this) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        recomputeManagersPerformed(QueryScope.ALL, target);
                    }
                }));

        headerMenuItems.add(new InlineMenuItem(createStringResource("TreeTablePanel.menu.deleteManagersAll"), false,
                new HeaderMenuAction(this) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        OrgMemberPanel.this.deleteMemberPerformed(QueryScope.ALL, SchemaConstants.ORG_MANAGER,
                                target, "TreeTablePanel.menu.deleteManagersAll.confirm");
                    }
                }));

        return headerMenuItems;
    }

    protected void refreshTable(AjaxRequestTarget target) {
        DropDownChoice<ObjectTypes> typeChoice = (DropDownChoice<ObjectTypes>) get(
                createComponentPath(ID_FORM, ID_SEARCH_BY_TYPE));
        ObjectTypes type = typeChoice.getModelObject();
        target.add(get(createComponentPath(ID_FORM, ID_SEARCH_SCOPE)));
        getMemberTable().clearCache();
        getMemberTable().refreshTable((Class<ObjectType>) WebComponentUtil
                .qnameToClass(getPageBase().getPrismContext(), type.getTypeQName()), target);
    }

    private MainObjectListPanel<ObjectType> getMemberTable() {
        return (MainObjectListPanel<ObjectType>) get(
                createComponentPath(ID_FORM, ID_CONTAINER_MEMBER, ID_MEMBER_TABLE));
    }

    private QName getSearchType() {
        DropDownChoice<ObjectTypes> searchByTypeChoice = (DropDownChoice<ObjectTypes>) get(
                createComponentPath(ID_FORM, ID_SEARCH_BY_TYPE));
        ObjectTypes typeModel = searchByTypeChoice.getModelObject();
        return typeModel.getTypeQName();
    }

    private ObjectQuery createManagerQuery() {

        String oid = getModelObject().getOid();
        PrismReferenceValue referenceFilter = new PrismReferenceValue();
        referenceFilter.setOid(oid);
        referenceFilter.setRelation(SchemaConstants.ORG_MANAGER);
        RefFilter referenceOidFilter;
        try {
            referenceOidFilter = RefFilter.createReferenceEqual(new ItemPath(FocusType.F_PARENT_ORG_REF),
                    UserType.class, getPageBase().getPrismContext(), referenceFilter);
            ObjectQuery query = ObjectQuery.createObjectQuery(referenceOidFilter);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Searching members of org {} with query:\n{}", oid, query.debugDump());
            }
            return query;
        } catch (SchemaException e) {
            LoggingUtils.logUnexpectedException(LOGGER, "Couldn't prepare query for org. managers.", e);
            return null;
        }

    }

    private ObjectDelta prepareDelta(MemberOperation operaton, QName type, QName relation, OperationResult result,
            AjaxRequestTarget target) {
        ObjectDelta delta = null;
        try {
            delta = createMemberDelta(operaton, type, relation);
        } catch (SchemaException e) {
            result.recordFatalError("Failed to prepare delta for add members");
            getPageBase().showResult(result);
            target.add(getPageBase().getFeedbackPanel());
        }
        return delta;
    }

    @Override
    protected void addMembersPerformed(QName type, QName relation, List selected, AjaxRequestTarget target) {
        Task operationalTask = getPageBase().createSimpleTask(getTaskName("Add", null, false));
        ObjectDelta delta = prepareDelta(MemberOperation.ADD, type, relation, operationalTask.getResult(), target);
        if (delta == null) {
            return;
        }
        executeMemberOperation(operationalTask, type, createQueryForAdd(selected), delta,
                TaskCategory.EXECUTE_CHANGES, target);

    }

    protected void addManagersPerformed(QName type, List selected, AjaxRequestTarget target) {
        Task operationalTask = getPageBase().createSimpleTask(getTaskName("Add", null, true));
        ObjectDelta delta = prepareDelta(MemberOperation.ADD, type, SchemaConstants.ORG_MANAGER,
                operationalTask.getResult(), target);
        if (delta == null) {
            return;
        }
        executeMemberOperation(operationalTask, type, createQueryForAdd(selected), delta,
                TaskCategory.EXECUTE_CHANGES, target);

    }

    protected void removeManagersPerformed(QueryScope scope, AjaxRequestTarget target) {

        Task operationalTask = getPageBase().createSimpleTask(getTaskName("Remove", scope, true));
        ObjectDelta delta = prepareDelta(MemberOperation.REMOVE, FocusType.COMPLEX_TYPE,
                SchemaConstants.ORG_MANAGER, operationalTask.getResult(), target);
        if (delta == null) {
            return;
        }
        executeMemberOperation(operationalTask, FocusType.COMPLEX_TYPE,
                createQueryForMemberAction(scope, SchemaConstants.ORG_MANAGER, true), delta,
                TaskCategory.EXECUTE_CHANGES, target);

    }

    @Override
    protected void removeMembersPerformed(QueryScope scope, AjaxRequestTarget target) {

        Task operationalTask = getPageBase().createSimpleTask(getTaskName("Remove", scope, false));

        ObjectDelta delta = prepareDelta(MemberOperation.REMOVE, FocusType.COMPLEX_TYPE, null,
                operationalTask.getResult(), target);
        if (delta != null) {
            executeMemberOperation(operationalTask, FocusType.COMPLEX_TYPE,
                    createQueryForMemberAction(scope, null, true), delta, TaskCategory.EXECUTE_CHANGES, target);
        }

        delta = prepareDelta(MemberOperation.REMOVE, ObjectType.COMPLEX_TYPE, null, operationalTask.getResult(),
                target);
        if (delta == null) {
            return;
        }
        executeMemberOperation(operationalTask, ObjectType.COMPLEX_TYPE,
                createQueryForMemberAction(scope, null, false), delta, TaskCategory.EXECUTE_CHANGES, target);

    }

    @Override
    protected void recomputeMembersPerformed(QueryScope scope, AjaxRequestTarget target) {
        Task operationalTask = getPageBase().createSimpleTask(getTaskName("Recompute", scope, false));
        executeMemberOperation(operationalTask, FocusType.COMPLEX_TYPE,
                createQueryForMemberAction(scope, null, true), null, TaskCategory.RECOMPUTATION, target);
    }

    protected void recomputeManagersPerformed(QueryScope scope, AjaxRequestTarget target) {
        Task operationalTask = getPageBase().createSimpleTask(getTaskName("Recompute", scope, true));
        executeMemberOperation(operationalTask, FocusType.COMPLEX_TYPE,
                createQueryForMemberAction(scope, SchemaConstants.ORG_MANAGER, true), null,
                TaskCategory.RECOMPUTATION, target);
    }

    @Override
    protected ObjectQuery createMemberQuery() {
        ObjectQuery query = null;

        String oid = getModelObject().getOid();

        List<ObjectFilter> filters = new ArrayList<>();

        DropDownChoice<String> searchScopeChoice = (DropDownChoice<String>) get(
                createComponentPath(ID_FORM, ID_SEARCH_SCOPE));
        String scope = searchScopeChoice.getModelObject();

        QName searchType = getSearchType();

        OrgFilter org;
        if (SEARCH_SCOPE_ONE.equals(scope)) {
            filters.add(OrgFilter.createOrg(oid, OrgFilter.Scope.ONE_LEVEL));
        } else {
            filters.add(OrgFilter.createOrg(oid, OrgFilter.Scope.SUBTREE));
        }

        query = ObjectQuery.createObjectQuery(AndFilter.createAnd(filters));

        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Searching members of org {} with query:\n{}", oid, query.debugDump());
        }

        if (searchType.equals(ObjectType.COMPLEX_TYPE)) {
            return query;
        }

        return ObjectQuery.createObjectQuery(TypeFilter.createType(searchType, query.getFilter()));

    }

    private ObjectQuery createQueryForMemberAction(QueryScope scope, QName orgRelation, boolean isFocus) {

        ObjectQuery query = null;
        switch (scope) {
        case SELECTED:
            List<ObjectType> objects = getMemberTable().getSelectedObjects();
            List<String> oids = new ArrayList<>();
            for (ObjectType object : objects) {
                if (satisfyConstraints(isFocus, object.getClass())) {
                    oids.add(object.getOid());
                }
            }

            query = ObjectQuery.createObjectQuery(InOidFilter.createInOid(oids));
            break;
        case ALL_DIRECT:
        case ALL:
            query = createQueryForAll(scope, isFocus, orgRelation);
            break;
        default:
            break;
        }
        return query;

    }

    private boolean satisfyConstraints(boolean isFocus, Class<? extends ObjectType> type) {
        if (isFocus && FocusType.class.isAssignableFrom(type)) {
            return true;
        }

        if (!isFocus && !FocusType.class.isAssignableFrom(type)) {
            return true;
        }

        return false;
    }

    private ObjectQuery createQueryForAll(QueryScope scope, boolean isFocus, QName relation) {
        OrgType org = getModelObject();

        return ObjectQuery.createObjectQuery(OrgFilter.createOrg(org.getOid(), getScope(scope)));

    }

    private Scope getScope(QueryScope queryScope) {
        return QueryScope.ALL == queryScope ? Scope.SUBTREE : Scope.ONE_LEVEL;
    }

    protected ObjectDelta createMemberDelta(MemberOperation operation, QName type, QName relation)
            throws SchemaException {
        Class classType = WebComponentUtil.qnameToClass(getPageBase().getPrismContext(), type);
        ObjectDelta delta = null;
        switch (operation) {
        case ADD:

            if (isFocus(type)) {

                delta = ObjectDelta.createModificationAddContainer(classType, "fakeOid", FocusType.F_ASSIGNMENT,
                        getPageBase().getPrismContext(), createAssignmentToModify(relation));
            } else {
                delta = ObjectDelta.createModificationAddReference(classType, "fakeOid",
                        ObjectType.F_PARENT_ORG_REF, getPageBase().getPrismContext(),
                        createReference(relation).asReferenceValue());
            }
            break;

        case REMOVE:
            if (isFocus(type)) {
                delta = ObjectDelta.createModificationDeleteContainer(classType, "fakeOid", FocusType.F_ASSIGNMENT,
                        getPageBase().getPrismContext(), createAssignmentToModify(relation));
            } else {
                delta = ObjectDelta.createModificationDeleteReference(classType, "fakeOid",
                        ObjectType.F_PARENT_ORG_REF, getPageBase().getPrismContext(),
                        createReference(relation).asReferenceValue());
            }
            break;
        default:
            break;
        }
        return delta;

    }

    private boolean isFocus(QName type) {
        return FocusType.COMPLEX_TYPE.equals(type) || UserType.COMPLEX_TYPE.equals(type)
                || RoleType.COMPLEX_TYPE.equals(type) || OrgType.COMPLEX_TYPE.equals(type)
                || ServiceType.COMPLEX_TYPE.equals(type);
    }

}