org.geogig.geoserver.web.repository.RepositoryImportPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.geogig.geoserver.web.repository.RepositoryImportPanel.java

Source

/* (c) 2016 Open Source Geospatial Foundation - all rights reserved
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geogig.geoserver.web.repository;

import static org.geogig.geoserver.config.RepositoryManager.isGeogigDirectory;

import java.io.File;
import java.io.Serializable;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponentPanel;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.validation.FormComponentFeedbackBorder;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;
import org.geogig.geoserver.config.ImportRepositoryFormBean;
import org.geogig.geoserver.config.PostgresConfigBean;
import org.geogig.geoserver.config.RepositoryInfo;
import org.geogig.geoserver.config.RepositoryManager;
import org.geogig.geoserver.model.DropDownModel;
import org.geogig.geoserver.model.ImportRepositoryFormModel;
import org.geogig.geoserver.util.PostgresConnectionErrorHandler;
import org.geoserver.web.data.store.panel.DropDownChoiceParamPanel;
import org.geoserver.web.data.store.panel.TextParamPanel;
import org.locationtech.geogig.repository.RepositoryResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The Wicket panel that holds the components for importing an existing GeoGig repository. This is
 * very similar to {@link RepositoryEditPanel}, however there are some subtle differences. Since
 * this panel is used for importing an existing repo, the validation checks are different. Also, the
 * {@link DirectoryChooser} is configured to allow repository directories to be selected instead of
 * just the parent directory. As such, the repository name is not separately selected. The
 * differences also called for a slightly different way of wrapping the {@link RepositoryInfo} data
 * bean with a different data model, {@link ImportRepositoryFormModel} and
 * {@link ImportRepositoryFormBean}.
 */
public class RepositoryImportPanel extends FormComponentPanel<RepositoryInfo> {

    private static final long serialVersionUID = 1L;
    private static final Logger LOGGER = LoggerFactory.getLogger(RepositoryImportPanel.class);

    private final TextParamPanel repoNamePanel;
    private final DropDownChoiceParamPanel dropdownPanel;
    private final RepoDirectoryComponent repoDirectoryComponent;
    private final PostgresConfigFormPanel pgPanel;
    private final WebMarkupContainer settingsPanel;

    public RepositoryImportPanel(String id, IModel<RepositoryInfo> model) {
        super(id, model);

        setOutputMarkupId(true);

        // build the backing form model
        ImportRepositoryFormModel formModel = new ImportRepositoryFormModel(model);
        // add the dropdown to switch between configurations
        dropdownPanel = new DropDownChoiceParamPanel("configChoicePanel", new DropDownModel(model),
                new ResourceModel("RepositoryImportPanel.repositoryType", "Repository Type"),
                DropDownModel.CONFIG_LIST, true);
        final DropDownChoice<Serializable> dropDownChoice = dropdownPanel.getFormComponent();
        dropDownChoice.add(new AjaxFormComponentUpdatingBehavior("change") {

            private static final long serialVersionUID = 1L;

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                final String value = dropDownChoice.getModelObject().toString();
                repoDirectoryComponent.setVisible(DropDownModel.DIRECTORY_CONFIG.equals(value));
                pgPanel.setVisible(DropDownModel.PG_CONFIG.equals(value));
                repoNamePanel.setVisible(DropDownModel.PG_CONFIG.equals(value));
                target.add(settingsPanel);
            }
        });
        add(dropdownPanel);

        settingsPanel = new WebMarkupContainer("settingsContainer");
        settingsPanel.setOutputMarkupId(true);
        add(settingsPanel);

        repoNamePanel = new TextParamPanel("repositoryNamePanel", new PropertyModel(formModel, "repoName"),
                new ResourceModel("RepositoryImportPanel.repositoryName", "Repository Name"), true);
        repoNamePanel.setOutputMarkupId(true);
        repoNamePanel.getFormComponent().setOutputMarkupId(true);
        repoNamePanel.setVisible(DropDownModel.PG_CONFIG.equals(dropDownChoice.getModelObject().toString()));
        settingsPanel.add(repoNamePanel);

        pgPanel = new PostgresConfigFormPanel("pgPanel", new PropertyModel<>(formModel, "pgBean"));
        pgPanel.setVisible(DropDownModel.PG_CONFIG.equals(dropDownChoice.getModelObject().toString()));
        settingsPanel.add(pgPanel);

        repoDirectoryComponent = new RepoDirectoryComponent("repoDirectoryPanel", formModel);
        repoDirectoryComponent.setOutputMarkupId(true);
        repoDirectoryComponent
                .setVisible(DropDownModel.DIRECTORY_CONFIG.equals(dropDownChoice.getModelObject().toString()));
        settingsPanel.add(repoDirectoryComponent);

        add(new IValidator<RepositoryInfo>() {

            private static final long serialVersionUID = 1L;

            @Override
            public void validate(IValidatable<RepositoryInfo> validatable) {
                ValidationError error = new ValidationError();
                RepositoryInfo repo = validatable.getValue();
                final URI location = repo.getLocation();
                // look for already configured repos
                List<RepositoryInfo> existingRepos = RepositoryManager.get().getAll();
                for (RepositoryInfo configuredRepo : existingRepos) {
                    if (configuredRepo.getLocation().equals(location)) {
                        error.addKey("errRepositoryAlreadyConfigured");
                        // quit looking
                        break;
                    }
                }
                if (error.getKeys().isEmpty()) {
                    final RepositoryResolver resolver = RepositoryResolver.lookup(location);
                    final String scheme = location.getScheme();
                    if ("file".equals(scheme)) {
                        File repoDir = new File(location);
                        if (!repoDir.exists() || !repoDir.isDirectory()) {
                            error.addKey("errRepositoryDirectoryDoesntExist");
                        }
                        if (!isGeogigDirectory(repoDir)) {
                            error.addKey("notAGeogigRepository");
                        }
                    } else if ("postgresql".equals(scheme)) {
                        try {
                            if (!resolver.repoExists(location)) {
                                error.addKey("errRepositoryDoesntExist");
                            }
                        } catch (Exception ex) {
                            // likely failed to connect
                            LOGGER.error("Failed to connect to PostgreSQL database", ex);
                            error.addKey("errCannotConnectToDatabase");
                            // find root cause
                            error.setVariable("message", PostgresConnectionErrorHandler.getMessage(ex));
                        }
                    }
                }
                if (!error.getKeys().isEmpty()) {
                    validatable.error(error);
                }
            }
        });
    }

    @Override
    public void convertInput() {
        RepositoryInfo repoInfo = getModelObject();
        final String repoTypeChoice = dropdownPanel.getFormComponent().getConvertedInput().toString();
        if (null != repoTypeChoice) {
            switch (repoTypeChoice) {
            case DropDownModel.PG_CONFIG:
                // PG config used
                PostgresConfigBean bean = pgPanel.getConvertedInput();
                // build a URI out of the config
                URI uri = bean
                        .buildUriForRepo(repoNamePanel.getFormComponent().getConvertedInput().toString().trim());
                repoInfo.setLocation(uri);
                break;
            case DropDownModel.DIRECTORY_CONFIG:
                // local directory used
                ImportRepositoryFormBean formBean = repoDirectoryComponent.getConvertedInput();
                Path uriPath = Paths.get(formBean.getRepoDirectory());
                repoInfo.setLocation(uriPath.toUri());
                break;
            default:
                throw new IllegalStateException(String.format("Unknown repositry type '%s', expected one of %s, %s",
                        repoTypeChoice, DropDownModel.PG_CONFIG, DropDownModel.DIRECTORY_CONFIG));
            }
        }
        setConvertedInput(repoInfo);
    }

    static class RepoDirectoryComponent extends FormComponentPanel<ImportRepositoryFormBean> {

        private static final long serialVersionUID = 1L;

        private final TextField<String> repoDirectoryField;
        private final ModalWindow dialog;

        RepoDirectoryComponent(String id, IModel<ImportRepositoryFormBean> model) {
            super(id, model);

            dialog = new ModalWindow("dialog");
            add(dialog);

            repoDirectoryField = new TextField<>("repoDirectory",
                    new PropertyModel<String>(model, "repoDirectory"));
            repoDirectoryField.setRequired(true);
            repoDirectoryField.setOutputMarkupId(true);

            IModel<String> labelModel = new ResourceModel("RepositoryImportPanel.directoryLabel",
                    "Repository Directory") {

                private static final long serialVersionUID = 1L;

                @Override
                public String getObject() {
                    String value = super.getObject();
                    return value + " *";
                }
            };

            Label directoryLabel = new Label("repoLabel", labelModel.getObject());
            add(directoryLabel);
            repoDirectoryField.setLabel(labelModel);

            FormComponentFeedbackBorder feedback = new FormComponentFeedbackBorder("wrapper");
            feedback.add(repoDirectoryField);
            feedback.add(createChooserButton());
            add(feedback);
        }

        @Override
        public void convertInput() {
            ImportRepositoryFormBean bean = new ImportRepositoryFormBean();
            String repoDir = repoDirectoryField.getConvertedInput();
            bean.setRepoDirectory(repoDir);
            setConvertedInput(bean);
        }

        private Component createChooserButton() {
            return new AjaxSubmitLink("chooser") {

                private static final long serialVersionUID = 1L;

                @Override
                public boolean getDefaultFormProcessing() {
                    return false;
                }

                @Override
                protected void onSubmit(AjaxRequestTarget target, Form form) {
                    File repoDirFile = null;
                    repoDirectoryField.processInput();
                    String repoDir = repoDirectoryField.getConvertedInput();
                    if (repoDir != null && !repoDir.trim().isEmpty()) {
                        repoDirFile = new File(repoDir);
                    }
                    DirectoryChooser chooser = new DirectoryChooser(dialog.getContentId(), new Model<>(repoDirFile),
                            true) {

                        private static final long serialVersionUID = 1L;

                        @Override
                        protected void geogigDirectoryClicked(File file, AjaxRequestTarget target) {
                            repoDirectoryField.clearInput();
                            repoDirectoryField.setModelObject(file.getAbsolutePath());
                            target.add(repoDirectoryField);
                            dialog.close(target);
                        }

                        @Override
                        protected void directorySelected(File file, AjaxRequestTarget target) {
                            repoDirectoryField.clearInput();
                            repoDirectoryField.setModelObject(file.getAbsolutePath());
                            target.add(repoDirectoryField);
                            dialog.close(target);
                        }

                    };
                    chooser.setFileTableHeight(null);
                    dialog.setContent(chooser);
                    dialog.setTitle(new ResourceModel("GeoGigDirectoryFormComponent.chooser.chooseParentTile"));
                    dialog.show(target);
                }

            };
        }
    }
}