Package org.apache.syncope.console.pages

Source Code of org.apache.syncope.console.pages.ConnectorModalPage

/*
* 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.console.pages;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.SyncopeClientException;
import org.apache.syncope.common.to.ConnBundleTO;
import org.apache.syncope.common.to.ConnInstanceTO;
import org.apache.syncope.common.to.ConnPoolConfTO;
import org.apache.syncope.common.types.ConnConfPropSchema;
import org.apache.syncope.common.types.ConnConfProperty;
import org.apache.syncope.common.types.ConnectorCapability;
import org.apache.syncope.console.commons.Constants;
import org.apache.syncope.console.markup.html.list.AltListView;
import org.apache.syncope.console.rest.ConnectorRestClient;
import org.apache.syncope.console.wicket.markup.html.form.AjaxCheckBoxPanel;
import org.apache.syncope.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
import org.apache.syncope.console.wicket.markup.html.form.AjaxPasswordFieldPanel;
import org.apache.syncope.console.wicket.markup.html.form.AjaxTextFieldPanel;
import org.apache.syncope.console.wicket.markup.html.form.FieldPanel;
import org.apache.syncope.console.wicket.markup.html.form.MultiFieldPanel;
import org.apache.syncope.console.wicket.markup.html.form.SpinnerFieldPanel;
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.AjaxLink;
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.IndicatingAjaxLink;
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.CheckBoxMultipleChoice;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.CompoundPropertyModel;
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.spring.injection.annot.SpringBean;
import org.apache.wicket.validation.validator.RangeValidator;
import org.springframework.util.ClassUtils;

/**
* Modal window with Connector form.
*/
public class ConnectorModalPage extends BaseModalPage {

    private static final long serialVersionUID = -2025535531121434050L;

    @SpringBean
    private ConnectorRestClient restClient;

    private final Map<String, Map<String, Map<String, ConnBundleTO>>> mapConnBundleTOs;

    private final List<ConnectorCapability> selectedCapabilities;

    private ConnBundleTO bundleTO;

    private List<ConnConfProperty> properties;

    private final WebMarkupContainer propertiesContainer;

    public ConnectorModalPage(final PageReference pageRef, final ModalWindow window,
            final ConnInstanceTO connInstanceTO) {

        super();

        // general data setup
        selectedCapabilities = new ArrayList<ConnectorCapability>(connInstanceTO.getId() == 0
                ? EnumSet.noneOf(ConnectorCapability.class)
                : connInstanceTO.getCapabilities());

        mapConnBundleTOs = new HashMap<String, Map<String, Map<String, ConnBundleTO>>>();
        for (ConnBundleTO connBundleTO : restClient.getAllBundles()) {
            // by location
            if (!mapConnBundleTOs.containsKey(connBundleTO.getLocation())) {
                mapConnBundleTOs.put(connBundleTO.getLocation(), new HashMap<String, Map<String, ConnBundleTO>>());
            }
            final Map<String, Map<String, ConnBundleTO>> byLocation = mapConnBundleTOs.get(connBundleTO.getLocation());

            // by name
            if (!byLocation.containsKey(connBundleTO.getBundleName())) {
                byLocation.put(connBundleTO.getBundleName(), new HashMap<String, ConnBundleTO>());
            }
            final Map<String, ConnBundleTO> byName = byLocation.get(connBundleTO.getBundleName());

            // by version
            if (!byName.containsKey(connBundleTO.getVersion())) {
                byName.put(connBundleTO.getVersion(), connBundleTO);
            }
        }

        bundleTO = getSelectedBundleTO(connInstanceTO);
        properties = fillProperties(bundleTO, connInstanceTO);

        // form - first tab
        final Form<ConnInstanceTO> connectorForm = new Form<ConnInstanceTO>(FORM);
        connectorForm.setModel(new CompoundPropertyModel<ConnInstanceTO>(connInstanceTO));
        connectorForm.setOutputMarkupId(true);
        add(connectorForm);

        propertiesContainer = new WebMarkupContainer("container");
        propertiesContainer.setOutputMarkupId(true);
        connectorForm.add(propertiesContainer);

        final Form<ConnInstanceTO> connectorPropForm = new Form<ConnInstanceTO>("connectorPropForm");
        connectorPropForm.setModel(new CompoundPropertyModel<ConnInstanceTO>(connInstanceTO));
        connectorPropForm.setOutputMarkupId(true);
        propertiesContainer.add(connectorPropForm);

        final AjaxTextFieldPanel displayName = new AjaxTextFieldPanel(
                "displayName", "display name", new PropertyModel<String>(connInstanceTO, "displayName"));
        displayName.setOutputMarkupId(true);
        displayName.addRequiredLabel();
        connectorForm.add(displayName);

        final AjaxDropDownChoicePanel<String> location =
                new AjaxDropDownChoicePanel<String>("location", "location",
                        new Model<String>(bundleTO == null ? null : bundleTO.getLocation()));
        ((DropDownChoice<String>) location.getField()).setNullValid(true);
        location.setStyleSheet("long_dynamicsize");
        location.setChoices(new ArrayList<String>(mapConnBundleTOs.keySet()));
        location.setRequired(true);
        location.addRequiredLabel();
        location.setOutputMarkupId(true);
        location.setEnabled(connInstanceTO.getId() == 0);
        location.getField().setOutputMarkupId(true);
        connectorForm.add(location);

        final AjaxDropDownChoicePanel<String> connectorName =
                new AjaxDropDownChoicePanel<String>("connectorName", "connectorName",
                        new Model<String>(bundleTO == null ? null : bundleTO.getBundleName()));
        ((DropDownChoice<String>) connectorName.getField()).setNullValid(true);
        connectorName.setStyleSheet("long_dynamicsize");
        connectorName.setChoices(bundleTO == null
                ? new ArrayList<String>()
                : new ArrayList<String>(mapConnBundleTOs.get(connInstanceTO.getLocation()).keySet()));
        connectorName.setRequired(true);
        connectorName.addRequiredLabel();
        connectorName.setEnabled(connInstanceTO.getLocation() != null);
        connectorName.setOutputMarkupId(true);
        connectorName.setEnabled(connInstanceTO.getId() == 0);
        connectorName.getField().setOutputMarkupId(true);
        connectorForm.add(connectorName);

        final AjaxDropDownChoicePanel<String> version =
                new AjaxDropDownChoicePanel<String>("version", "version",
                        new Model<String>(bundleTO == null ? null : bundleTO.getVersion()));
        version.setStyleSheet("long_dynamicsize");
        version.setChoices(bundleTO == null
                ? new ArrayList<String>()
                : new ArrayList<String>(mapConnBundleTOs.get(connInstanceTO.getLocation()).
                        get(connInstanceTO.getBundleName()).keySet()));
        version.setRequired(true);
        version.addRequiredLabel();
        version.setEnabled(connInstanceTO.getBundleName() != null);
        version.setOutputMarkupId(true);
        version.addRequiredLabel();
        version.getField().setOutputMarkupId(true);
        connectorForm.add(version);

        final SpinnerFieldPanel<Integer> connRequestTimeout =
                new SpinnerFieldPanel<Integer>("connRequestTimeout", "connRequestTimeout", Integer.class,
                        new PropertyModel<Integer>(connInstanceTO, "connRequestTimeout"), 0, null);
        connRequestTimeout.getField().add(new RangeValidator<Integer>(0, Integer.MAX_VALUE));
        connectorForm.add(connRequestTimeout);

        if (connInstanceTO.getPoolConf() == null) {
            connInstanceTO.setPoolConf(new ConnPoolConfTO());
        }
        final SpinnerFieldPanel<Integer> poolMaxObjects =
                new SpinnerFieldPanel<Integer>("poolMaxObjects", "poolMaxObjects", Integer.class,
                        new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "maxObjects"), 0, null);
        poolMaxObjects.getField().add(new RangeValidator<Integer>(0, Integer.MAX_VALUE));
        connectorForm.add(poolMaxObjects);
        final SpinnerFieldPanel<Integer> poolMinIdle =
                new SpinnerFieldPanel<Integer>("poolMinIdle", "poolMinIdle", Integer.class,
                        new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "minIdle"), 0, null);
        poolMinIdle.getField().add(new RangeValidator<Integer>(0, Integer.MAX_VALUE));
        connectorForm.add(poolMinIdle);
        final SpinnerFieldPanel<Integer> poolMaxIdle =
                new SpinnerFieldPanel<Integer>("poolMaxIdle", "poolMaxIdle", Integer.class,
                        new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "maxIdle"), 0, null);
        poolMaxIdle.getField().add(new RangeValidator<Integer>(0, Integer.MAX_VALUE));
        connectorForm.add(poolMaxIdle);
        final SpinnerFieldPanel<Long> poolMaxWait =
                new SpinnerFieldPanel<Long>("poolMaxWait", "poolMaxWait", Long.class,
                        new PropertyModel<Long>(connInstanceTO.getPoolConf(), "maxWait"), 0L, null);
        poolMaxWait.getField().add(new RangeValidator<Long>(0L, Long.MAX_VALUE));
        connectorForm.add(poolMaxWait);
        final SpinnerFieldPanel<Long> poolMinEvictableIdleTime =
                new SpinnerFieldPanel<Long>("poolMinEvictableIdleTime", "poolMinEvictableIdleTime", Long.class,
                        new PropertyModel<Long>(connInstanceTO.getPoolConf(), "minEvictableIdleTimeMillis"),
                        0L, null);
        poolMinEvictableIdleTime.getField().add(new RangeValidator<Long>(0L, Long.MAX_VALUE));
        connectorForm.add(poolMinEvictableIdleTime);

        // form - first tab - onchange()
        location.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {

            private static final long serialVersionUID = -1107858522700306810L;

            @Override
            protected void onUpdate(final AjaxRequestTarget target) {
                ((DropDownChoice<String>) location.getField()).setNullValid(false);
                connInstanceTO.setLocation(location.getModelObject());
                target.add(location);

                connectorName.setChoices(new ArrayList<String>(
                        mapConnBundleTOs.get(location.getModelObject()).keySet()));
                connectorName.setEnabled(true);
                connectorName.getField().setModelValue(null);
                target.add(connectorName);

                version.setChoices(new ArrayList<String>());
                version.getField().setModelValue(null);
                version.setEnabled(false);
                target.add(version);

                properties.clear();
                target.add(propertiesContainer);
            }
        });
        connectorName.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {

            private static final long serialVersionUID = -1107858522700306810L;

            @Override
            protected void onUpdate(final AjaxRequestTarget target) {
                ((DropDownChoice<String>) connectorName.getField()).setNullValid(false);
                connInstanceTO.setBundleName(connectorName.getModelObject());
                target.add(connectorName);

                List<String> versions = new ArrayList<String>(
                        mapConnBundleTOs.get(location.getModelObject()).get(connectorName.getModelObject()).keySet());
                version.setChoices(versions);
                version.setEnabled(true);
                if (versions.size() == 1) {
                    selectVersion(target, connInstanceTO, version, versions.get(0));
                    version.getField().setModelObject(versions.get(0));
                } else {
                    version.getField().setModelValue(null);
                    properties.clear();
                    target.add(propertiesContainer);
                }
                target.add(version);
            }
        });
        version.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {

            private static final long serialVersionUID = -1107858522700306810L;

            @Override
            protected void onUpdate(final AjaxRequestTarget target) {
                selectVersion(target, connInstanceTO, version, version.getModelObject());
            }
        });

        // form - second tab (properties)
        final ListView<ConnConfProperty> connPropView = new AltListView<ConnConfProperty>(
                "connectorProperties", new PropertyModel<List<ConnConfProperty>>(this, "properties")) {

                    private static final long serialVersionUID = 9101744072914090143L;

                    @Override
                    protected void populateItem(final ListItem<ConnConfProperty> item) {
                        final ConnConfProperty property = item.getModelObject();

                        final Label label = new Label("connPropAttrSchema",
                                StringUtils.isBlank(property.getSchema().getDisplayName())
                                ? property.getSchema().getName()
                                : property.getSchema().getDisplayName());
                        item.add(label);

                        @SuppressWarnings("rawtypes")
                        final FieldPanel field;
                        boolean required = false;
                        boolean isArray = false;
                        if (property.getSchema().isConfidential()
                        || Constants.GUARDED_STRING.equalsIgnoreCase(property.getSchema().getType())
                        || Constants.GUARDED_BYTE_ARRAY.equalsIgnoreCase(property.getSchema().getType())) {

                            field = new AjaxPasswordFieldPanel("panel",
                                    label.getDefaultModelObjectAsString(), new Model<String>());

                            ((PasswordTextField) field.getField()).setResetPassword(false);

                            required = property.getSchema().isRequired();
                        } else {
                            Class<?> propertySchemaClass;

                            try {
                                propertySchemaClass =
                                ClassUtils.forName(property.getSchema().getType(), ClassUtils.getDefaultClassLoader());
                                if (ClassUtils.isPrimitiveOrWrapper(propertySchemaClass)) {
                                    propertySchemaClass =
                                    org.apache.commons.lang3.ClassUtils.primitiveToWrapper(propertySchemaClass);
                                }
                            } catch (Exception e) {
                                LOG.error("Error parsing attribute type", e);
                                propertySchemaClass = String.class;
                            }
                            if (ClassUtils.isAssignable(Number.class, propertySchemaClass)) {
                                @SuppressWarnings("unchecked")
                                final Class<Number> numberClass = (Class<Number>) propertySchemaClass;
                                field = new SpinnerFieldPanel<Number>("panel", label.getDefaultModelObjectAsString(),
                                        numberClass, new Model<Number>(), null, null);

                                required = property.getSchema().isRequired();
                            } else if (ClassUtils.isAssignable(Boolean.class, propertySchemaClass)) {
                                field = new AjaxCheckBoxPanel("panel",
                                        label.getDefaultModelObjectAsString(), new Model<Boolean>());
                            } else {
                                field = new AjaxTextFieldPanel("panel",
                                        label.getDefaultModelObjectAsString(), new Model<String>());

                                required = property.getSchema().isRequired();
                            }

                            if (propertySchemaClass.isArray()) {
                                isArray = true;
                            }
                        }

                        field.setTitle(property.getSchema().getHelpMessage());

                        if (required) {
                            field.addRequiredLabel();
                        }

                        if (isArray) {
                            if (property.getValues().isEmpty()) {
                                property.getValues().add(null);
                            }

                            @SuppressWarnings("unchecked")
                            final MultiFieldPanel<String> multiFieldPanel = new MultiFieldPanel<String>(
                                    "panel", new PropertyModel<List<String>>(property, "values"), field);
                            item.add(multiFieldPanel);
                        } else {
                            setNewFieldModel(field, property.getValues());
                            item.add(field);
                        }

                        final AjaxCheckBoxPanel overridable = new AjaxCheckBoxPanel("connPropAttrOverridable",
                                "connPropAttrOverridable", new PropertyModel<Boolean>(property, "overridable"));

                        item.add(overridable);
                        connInstanceTO.getConfiguration().add(property);
                    }
                };
        connPropView.setOutputMarkupId(true);
        connectorPropForm.add(connPropView);

        final AjaxLink<String> check = new IndicatingAjaxLink<String>("check", new ResourceModel("check")) {

            private static final long serialVersionUID = -7978723352517770644L;

            @Override
            public void onClick(final AjaxRequestTarget target) {
                connInstanceTO.setBundleName(bundleTO.getBundleName());
                connInstanceTO.setVersion(bundleTO.getVersion());
                connInstanceTO.setConnectorName(bundleTO.getConnectorName());

                if (restClient.check(connInstanceTO)) {
                    info(getString("success_connection"));
                } else {
                    error(getString("error_connection"));
                }

                feedbackPanel.refresh(target);
            }
        };
        connectorPropForm.add(check);

        // form - third tab (capabilities)
        final IModel<List<ConnectorCapability>> capabilities =
                new LoadableDetachableModel<List<ConnectorCapability>>() {

                    private static final long serialVersionUID = 5275935387613157437L;

                    @Override
                    protected List<ConnectorCapability> load() {
                        return Arrays.asList(ConnectorCapability.values());
                    }
                };
        CheckBoxMultipleChoice<ConnectorCapability> capabilitiesPalette =
                new CheckBoxMultipleChoice<ConnectorCapability>("capabilitiesPalette",
                        new PropertyModel<List<ConnectorCapability>>(this, "selectedCapabilities"), capabilities);
        connectorForm.add(capabilitiesPalette);

        // form - submit / cancel buttons
        final AjaxButton submit = new IndicatingAjaxButton(APPLY, new Model<String>(getString(SUBMIT))) {

            private static final long serialVersionUID = -958724007591692537L;

            @Override
            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
                final ConnInstanceTO conn = (ConnInstanceTO) form.getModelObject();

                conn.setConnectorName(bundleTO.getConnectorName());
                conn.setBundleName(bundleTO.getBundleName());
                conn.setVersion(bundleTO.getVersion());
                conn.getConfiguration().clear();
                conn.getConfiguration().addAll(connPropView.getModelObject());

                // Set the model object's capabilities to capabilitiesPalette's converted Set
                conn.getCapabilities().addAll(selectedCapabilities.isEmpty()
                        ? EnumSet.noneOf(ConnectorCapability.class)
                        : EnumSet.copyOf(selectedCapabilities));

                // Reset pool configuration if all fields are null
                if (conn.getPoolConf() != null
                        && conn.getPoolConf().getMaxIdle() == null
                        && conn.getPoolConf().getMaxObjects() == null
                        && conn.getPoolConf().getMaxWait() == null
                        && conn.getPoolConf().getMinEvictableIdleTimeMillis() == null
                        && conn.getPoolConf().getMinIdle() == null) {

                    conn.setPoolConf(null);
                }

                try {
                    if (connInstanceTO.getId() == 0) {
                        restClient.create(conn);
                    } else {
                        restClient.update(conn);
                    }

                    ((Resources) pageRef.getPage()).setModalResult(true);
                    window.close(target);
                } catch (SyncopeClientException e) {
                    error(getString(Constants.ERROR) + ": " + e.getMessage());
                    feedbackPanel.refresh(target);
                    ((Resources) pageRef.getPage()).setModalResult(false);
                    LOG.error("While creating or updating connector {}", conn, e);
                }
            }

            @Override
            protected void onError(final AjaxRequestTarget target, final Form<?> form) {

                feedbackPanel.refresh(target);
            }
        };
        String roles = connInstanceTO.getId() == 0
                ? xmlRolesReader.getAllAllowedRoles("Connectors", "create")
                : xmlRolesReader.getAllAllowedRoles("Connectors", "update");
        MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE, roles);
        connectorForm.add(submit);

        final IndicatingAjaxButton cancel = new IndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL)) {

            private static final long serialVersionUID = -958724007591692537L;

            @Override
            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
                window.close(target);
            }
        };
        cancel.setDefaultFormProcessing(false);
        connectorForm.add(cancel);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void setNewFieldModel(final FieldPanel field, final List<Object> values) {
        field.setNewModel(values);
    }

    private ConnBundleTO getSelectedBundleTO(final ConnInstanceTO connInstanceTO) {
        ConnBundleTO result = null;
        if (connInstanceTO != null
                && StringUtils.isNotBlank(connInstanceTO.getLocation())
                && StringUtils.isNotBlank(connInstanceTO.getBundleName())
                && StringUtils.isNotBlank(connInstanceTO.getVersion())
                && mapConnBundleTOs.containsKey(connInstanceTO.getLocation())) {

            Map<String, Map<String, ConnBundleTO>> byLocation = mapConnBundleTOs.get(connInstanceTO.getLocation());
            if (byLocation.containsKey(connInstanceTO.getBundleName())) {
                Map<String, ConnBundleTO> byName = byLocation.get(connInstanceTO.getBundleName());
                if (byName.containsKey(connInstanceTO.getVersion())) {
                    result = byName.get(connInstanceTO.getVersion());
                }
            }
        }
        return result;
    }

    private List<ConnConfProperty> fillProperties(final ConnBundleTO bundleTO, final ConnInstanceTO connInstanceTO) {
        final List<ConnConfProperty> props = new ArrayList<ConnConfProperty>();

        if (bundleTO != null) {
            for (ConnConfPropSchema key : bundleTO.getProperties()) {
                final ConnConfProperty property = new ConnConfProperty();
                property.setSchema(key);
                if (connInstanceTO.getId() != 0
                        && connInstanceTO.getConfigurationMap().containsKey(key.getName())
                        && connInstanceTO.getConfigurationMap().get(key.getName()).getValues() != null) {

                    property.getValues().addAll(connInstanceTO.getConfigurationMap().get(key.getName()).getValues());
                    property.setOverridable(connInstanceTO.getConfigurationMap().get(key.getName()).isOverridable());
                }

                if (property.getValues().isEmpty() && !key.getDefaultValues().isEmpty()) {
                    property.getValues().addAll(key.getDefaultValues());
                }

                props.add(property);
            }
        }

        // re-order properties (implements Comparable)
        Collections.sort(props);
        return props;
    }

    private void selectVersion(final AjaxRequestTarget target, final ConnInstanceTO connInstanceTO,
            final AjaxDropDownChoicePanel<String> version, final String versionValue) {

        connInstanceTO.setVersion(versionValue);
        target.add(version);

        bundleTO = getSelectedBundleTO(connInstanceTO);
        properties = fillProperties(bundleTO, connInstanceTO);
        target.add(propertiesContainer);
    }

    public List<ConnConfProperty> getProperties() {
        return properties;
    }
}
TOP

Related Classes of org.apache.syncope.console.pages.ConnectorModalPage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.