com.evolveum.midpoint.web.component.wizard.resource.NameStep.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.web.component.wizard.resource.NameStep.java

Source

/*
 * Copyright (c) 2010-2015 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.component.wizard.resource;

import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.model.api.ModelService;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismReference;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.delta.DiffUtil;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
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.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.component.form.DropDownFormGroup;
import com.evolveum.midpoint.web.component.form.TextAreaFormGroup;
import com.evolveum.midpoint.web.component.form.TextFormGroup;
import com.evolveum.midpoint.web.component.util.LoadableModel;
import com.evolveum.midpoint.web.component.util.PrismPropertyModel;
import com.evolveum.midpoint.web.component.wizard.WizardStep;
import com.evolveum.midpoint.web.component.wizard.resource.dto.ConnectorHostTypeComparator;
import com.evolveum.midpoint.web.page.PageBase;
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 org.apache.commons.lang.StringUtils;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.model.IModel;

import java.util.*;

/**
 * @author lazyman
 */
public class NameStep extends WizardStep {

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

    private static final String DOT_CLASS = NameStep.class.getName() + ".";
    private static final String OPERATION_DISCOVER_CONNECTORS = DOT_CLASS + "discoverConnectors";
    private static final String OPERATION_SAVE_RESOURCE = DOT_CLASS + "saveResource";

    private static final String ID_NAME = "name";
    private static final String ID_DESCRIPTION = "description";
    private static final String ID_LOCATION = "location";
    private static final String ID_CONNECTOR_TYPE = "connectorType";

    private static final ConnectorHostType NOT_USED_HOST = new ConnectorHostType();

    private IModel<PrismObject<ResourceType>> resourceModel;

    //all objects
    private LoadableModel<List<PrismObject<ConnectorHostType>>> connectorHostsModel;
    private LoadableModel<List<PrismObject<ConnectorType>>> connectorsModel;

    //filtered, based on selection
    private LoadableModel<List<PrismObject<ConnectorType>>> connectorTypes;

    public NameStep(IModel<PrismObject<ResourceType>> model, PageBase pageBase) {
        super(pageBase);
        this.resourceModel = model;

        connectorsModel = new LoadableModel<List<PrismObject<ConnectorType>>>(false) {

            @Override
            protected List<PrismObject<ConnectorType>> load() {
                return WebModelUtils.searchObjects(ConnectorType.class, null, null, getPageBase());
            }
        };
        connectorHostsModel = new LoadableModel<List<PrismObject<ConnectorHostType>>>(false) {

            @Override
            protected List<PrismObject<ConnectorHostType>> load() {
                return WebModelUtils.searchObjects(ConnectorHostType.class, null, null, getPageBase());
            }
        };

        initLayout();
    }

    private void initLayout() {
        TextFormGroup name = new TextFormGroup(ID_NAME, new PrismPropertyModel(resourceModel, UserType.F_NAME),
                createStringResource("NameStep.name"), "col-md-3", "col-md-3", true);
        add(name);

        TextAreaFormGroup description = new TextAreaFormGroup(ID_DESCRIPTION,
                new PrismPropertyModel(resourceModel, UserType.F_DESCRIPTION),
                createStringResource("NameStep.description"), "col-md-3", "col-md-3");
        description.setRows(3);
        add(description);

        DropDownFormGroup<PrismObject<ConnectorHostType>> location = createLocationDropDown();
        add(location);

        DropDownFormGroup<PrismObject<ConnectorType>> connectorType = createConnectorTypeDropDown(
                location.getModel());
        add(connectorType);
    }

    private IModel<PrismObject<ConnectorHostType>> createConnectorHostModel() {
        return new IModel<PrismObject<ConnectorHostType>>() {

            private PrismObject<ConnectorHostType> connectorHost;

            @Override
            public PrismObject<ConnectorHostType> getObject() {
                if (connectorHost != null) {
                    return connectorHost;
                }

                PrismObject<ResourceType> resource = resourceModel.getObject();
                PrismReference ref = resource.findReference(ResourceType.F_CONNECTOR_REF);
                if (ref == null || ref.getOid() == null) {
                    connectorHost = null;
                    return connectorHost;
                }

                PrismObject<ConnectorType> connector = null;
                List<PrismObject<ConnectorType>> connectors = connectorsModel.getObject();
                for (PrismObject<ConnectorType> conn : connectors) {
                    if (ref.getOid().equals(conn.getOid())) {
                        connector = conn;
                        break;
                    }
                }

                if (connector == null || connector.findReference(ConnectorType.F_CONNECTOR_HOST_REF) == null) {
                    connectorHost = null;
                    return connectorHost;
                }

                PrismReference hostRef = connector.findReference(ConnectorType.F_CONNECTOR_HOST_REF);
                if (hostRef.getOid() == null) {
                    connectorHost = null;
                    return connectorHost;
                }

                for (PrismObject<ConnectorHostType> host : connectorHostsModel.getObject()) {
                    if (hostRef.getOid().equals(host.getOid())) {
                        connectorHost = host;
                        return connectorHost;
                    }
                }

                connectorHost = null;
                return connectorHost;
            }

            @Override
            public void setObject(PrismObject<ConnectorHostType> object) {
                connectorHost = object;
            }

            @Override
            public void detach() {
            }
        };
    }

    private PrismObject<ConnectorType> getConnectorFromResource(List<PrismObject<ConnectorType>> connectors) {
        PrismReference ref = resourceModel.getObject().findReference(ResourceType.F_CONNECTOR_REF);
        if (ref == null || ref.getOid() == null) {
            return null;
        }

        for (PrismObject<ConnectorType> connector : connectors) {
            if (ref.getOid().equals(connector.getOid())) {
                return connector;
            }
        }

        return null;
    }

    private IModel<PrismObject<ConnectorType>> createReadonlyUsedConnectorModel() {
        return new IModel<PrismObject<ConnectorType>>() {

            private PrismObject<ConnectorType> selected;

            @Override
            public PrismObject<ConnectorType> getObject() {
                if (selected != null) {
                    return selected;
                }

                List<PrismObject<ConnectorType>> connectors = connectorsModel.getObject();
                selected = getConnectorFromResource(connectors);

                return selected;
            }

            @Override
            public void setObject(PrismObject<ConnectorType> object) {
                selected = object;
            }

            @Override
            public void detach() {
            }
        };
    }

    private DropDownFormGroup<PrismObject<ConnectorType>> createConnectorTypeDropDown(
            final IModel<PrismObject<ConnectorHostType>> hostModel) {
        connectorTypes = new LoadableModel<List<PrismObject<ConnectorType>>>(false) {

            @Override
            protected List<PrismObject<ConnectorType>> load() {
                return loadConnectorTypes(hostModel.getObject());
            }
        };

        return new DropDownFormGroup<PrismObject<ConnectorType>>(ID_CONNECTOR_TYPE,
                createReadonlyUsedConnectorModel(), connectorTypes,
                new IChoiceRenderer<PrismObject<ConnectorType>>() {

                    @Override
                    public Object getDisplayValue(PrismObject<ConnectorType> object) {
                        return WebMiscUtil.getName(object);
                    }

                    @Override
                    public String getIdValue(PrismObject<ConnectorType> object, int index) {
                        return Integer.toString(index);
                    }
                }, createStringResource("NameStep.connectorType"), "col-md-3", "col-md-3", true) {

            @Override
            protected DropDownChoice createDropDown(String id, IModel<List<PrismObject<ConnectorType>>> choices,
                    IChoiceRenderer<PrismObject<ConnectorType>> renderer, boolean required) {
                DropDownChoice choice = super.createDropDown(id, choices, renderer, required);
                choice.setOutputMarkupId(true);

                return choice;
            }
        };
    }

    private DropDownFormGroup<PrismObject<ConnectorHostType>> createLocationDropDown() {
        return new DropDownFormGroup<PrismObject<ConnectorHostType>>(ID_LOCATION, createConnectorHostModel(),
                connectorHostsModel, new IChoiceRenderer<PrismObject<ConnectorHostType>>() {

                    @Override
                    public Object getDisplayValue(PrismObject<ConnectorHostType> object) {
                        if (object == null) {
                            return NameStep.this.getString("NameStep.hostNotUsed");
                        }
                        return ConnectorHostTypeComparator.getUserFriendlyName(object);
                    }

                    @Override
                    public String getIdValue(PrismObject<ConnectorHostType> object, int index) {
                        return Integer.toString(index);
                    }
                }, createStringResource("NameStep.connectorHost"), "col-md-3", "col-md-3", false) {

            @Override
            protected DropDownChoice createDropDown(String id, IModel<List<PrismObject<ConnectorHostType>>> choices,
                    IChoiceRenderer<PrismObject<ConnectorHostType>> renderer, boolean required) {
                DropDownChoice choice = super.createDropDown(id, choices, renderer, required);
                choice.add(new AjaxFormComponentUpdatingBehavior("onchange") {

                    @Override
                    protected void onUpdate(AjaxRequestTarget target) {
                        discoverConnectorsPerformed(target);
                    }
                });
                return choice;
            }
        };
    }

    private List<PrismObject<ConnectorType>> loadConnectorTypes(PrismObject<ConnectorHostType> host) {
        List<PrismObject<ConnectorType>> filtered = filterConnectorTypes(host, null);

        Collections.sort(filtered, new Comparator<PrismObject<ConnectorType>>() {

            @Override
            public int compare(PrismObject<ConnectorType> c1, PrismObject<ConnectorType> c2) {
                String name1 = c1.getPropertyRealValue(ConnectorType.F_CONNECTOR_TYPE, String.class);
                String name2 = c2.getPropertyRealValue(ConnectorType.F_CONNECTOR_TYPE, String.class);

                return String.CASE_INSENSITIVE_ORDER.compare(name1, name2);
            }
        });

        return filtered;
    }

    private List<PrismObject<ConnectorType>> filterConnectorTypes(PrismObject<ConnectorHostType> host,
            PrismObject<ConnectorType> type) {
        List<PrismObject<ConnectorType>> connectors = connectorsModel.getObject();
        final String connectorType = type == null ? null
                : type.getPropertyRealValue(ConnectorType.F_CONNECTOR_TYPE, String.class);

        Set<String> alreadyAddedTypes = new HashSet<>();
        List<PrismObject<ConnectorType>> filtered = new ArrayList<>();
        for (PrismObject<ConnectorType> connector : connectors) {
            if (host != null && !isConnectorOnHost(connector, host)) {
                continue;
            }

            String cType = connector.getPropertyRealValue(ConnectorType.F_CONNECTOR_TYPE, String.class);
            if (connectorType != null
                    && (!StringUtils.equals(connectorType, cType) || alreadyAddedTypes.contains(cType))) {
                //filter out connector if connectorType is not equal to parameter type.connectorType
                //and we remove same connector types if we filtering connector based on types...
                continue;
            }

            alreadyAddedTypes.add(cType);
            filtered.add(connector);
        }

        return filtered;
    }

    private boolean isConnectorOnHost(PrismObject<ConnectorType> connector, PrismObject<ConnectorHostType> host) {
        PrismReference hostRef = connector.findReference(ConnectorType.F_CONNECTOR_HOST_REF);
        if (hostRef == null && host == null) {
            return true;
        }

        if (hostRef != null && host == null) {
            return false;
        }

        if (hostRef != null && hostRef.getOid() != null && hostRef.getOid().equals(host.getOid())) {
            return true;
        }

        return false;
    }

    private void discoverConnectorsPerformed(AjaxRequestTarget target) {
        DropDownFormGroup<PrismObject<ConnectorHostType>> group = (DropDownFormGroup) get(ID_LOCATION);
        DropDownChoice<PrismObject<ConnectorHostType>> location = group.getInput();
        PrismObject<ConnectorHostType> prism = location.getModelObject();
        ConnectorHostType host = prism.asObjectable();

        if (!NOT_USED_HOST.equals(host)) {
            discoverConnectors(host);
            connectorsModel.reset();
        }

        connectorTypes.reset();

        PageBase page = (PageBase) getPage();

        DropDownFormGroup type = (DropDownFormGroup) get(ID_CONNECTOR_TYPE);

        target.add(type.getInput(), page.getFeedbackPanel());
    }

    private void discoverConnectors(ConnectorHostType host) {
        PageBase page = (PageBase) getPage();
        Task task = page.createSimpleTask(OPERATION_DISCOVER_CONNECTORS);
        OperationResult result = task.getResult();
        try {
            ModelService model = page.getModelService();
            model.discoverConnectors(host, task, result);
        } catch (Exception ex) {
            LoggingUtils.logException(LOGGER, "Couldn't discover connectors", ex);
        } finally {
            result.recomputeStatus();
        }

        if (WebMiscUtil.showResultInPage(result)) {
            page.showResult(result);
        }
    }

    @Override
    public void applyState() {
        PageBase page = (PageBase) getPage();
        Task task = page.createSimpleTask(OPERATION_SAVE_RESOURCE);
        OperationResult result = task.getResult();
        boolean newResource;

        try {
            PrismObject<ResourceType> resource = resourceModel.getObject();

            if (StringUtils.isNotEmpty(resource.getOid())) {
                newResource = false;
            } else {
                newResource = true;
            }

            page.getPrismContext().adopt(resource);

            if (newResource) {
                resource.findOrCreateContainer(ResourceType.F_CONNECTOR_CONFIGURATION)
                        .findOrCreateContainer(SchemaConstants.ICF_CONFIGURATION_PROPERTIES).createNewValue();
            }

            DropDownFormGroup connectorTypeDropDown = ((DropDownFormGroup) get(ID_CONNECTOR_TYPE));
            if (connectorTypeDropDown != null && connectorTypeDropDown.getInput() != null) {

                if (connectorTypeDropDown.getInput().getModelObject() != null) {
                    PrismObject<ConnectorType> connectorTypeReference = (PrismObject<ConnectorType>) connectorTypeDropDown
                            .getInput().getModel().getObject();
                    PrismReference ref = resource.findOrCreateReference(ResourceType.F_CONNECTOR_REF);

                    if (connectorTypeReference == null) {
                        resource.removeReference(ResourceType.F_CONNECTOR_REF);
                    } else {
                        PrismReferenceValue val = new PrismReferenceValue();
                        val.setObject(connectorTypeReference);
                        ref.replace(val);
                    }
                }
            }

            ObjectDelta delta;
            if (!newResource) {
                PrismObject<ResourceType> oldResource = WebModelUtils.loadObject(ResourceType.class,
                        resource.getOid(), page, task, result);

                delta = DiffUtil.diff(oldResource, resource);
            } else {
                delta = ObjectDelta.createAddDelta(resource);
            }

            WebModelUtils.save(delta, ModelExecuteOptions.createRaw(), result, page);

            if (!newResource) {
                resource = WebModelUtils.loadObject(ResourceType.class, delta.getOid(), page, task, result);
            } else {
                Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions
                        .createCollection(GetOperationOptions.createRaw());
                resource = WebModelUtils.loadObject(ResourceType.class, delta.getOid(), options, page, task,
                        result);
            }

            resourceModel.setObject(resource);

        } catch (Exception ex) {
            LoggingUtils.logException(LOGGER, "Couldn't save resource", ex);
            result.recordFatalError("Couldn't save resource, reason: " + ex.getMessage(), ex);
        } finally {
            result.computeStatus();
            setResult(result);
        }

        if (WebMiscUtil.showResultInPage(result)) {
            page.showResult(result);
        }
    }
}