Package org.geoserver.web.data.store

Source Code of org.geoserver.web.data.store.AbstractDataAccessPage

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.web.data.store;

import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Logger;

import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
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.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.validation.IValidator;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.ResourcePool;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.web.ComponentAuthorizer;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.web.GeoServerSecuredPage;
import org.geoserver.web.data.store.panel.CheckBoxParamPanel;
import org.geoserver.web.data.store.panel.NamespacePanel;
import org.geoserver.web.data.store.panel.TextParamPanel;
import org.geoserver.web.data.store.panel.WorkspacePanel;
import org.geotools.data.DataAccessFactory;
import org.geotools.data.DataAccessFactory.Param;
import org.geotools.util.logging.Logging;

/**
* Abstract base class for adding/editing a {@link DataStoreInfo}, provides the UI components and a
* template method {@link #onSaveDataStore(Form)} for the subclasses to perform the insertion or
* update of the object.
*
* @author Gabriel Roldan
* @see DataAccessNewPage
* @see DataAccessEditPage
*/
abstract class AbstractDataAccessPage extends GeoServerSecuredPage {

    protected static final Logger LOGGER = Logging.getLogger("org.geoserver.web.data.store");

    /**
     * Needed as an instance variable so if the DataAccess has a namespace parameter, it is
     * automatically updated to match the workspace's namespace as per GEOS-3149 until the
     * resource/publish split is finalized
     */
    protected WorkspacePanel workspacePanel;

    protected StoreEditPanel storeEditPanel;

    public AbstractDataAccessPage() {

    }

    /**
     *
     * @param storeInfo
     * @throws IllegalArgumentException
     */
    protected void initUI(final DataStoreInfo storeInfo) throws IllegalArgumentException {

        if (storeInfo.getWorkspace() == null) {
            throw new IllegalArgumentException("Workspace not provided");
        }

        final Catalog catalog = getCatalog();
        final ResourcePool resourcePool = catalog.getResourcePool();
        DataAccessFactory dsFactory;
        try {
            dsFactory = resourcePool.getDataStoreFactory(storeInfo);
        } catch (IOException e) {
            String msg = (String) new ResourceModel(
                    "AbstractDataAccessPage.cantGetDataStoreFactory").getObject();
            msg += ": " + e.getMessage();
            throw new IllegalArgumentException(msg);
        }
        if (dsFactory == null) {
            String msg = (String) new ResourceModel(
                    "AbstractDataAccessPage.cantGetDataStoreFactory").getObject();
            throw new IllegalArgumentException(msg);
        }

        final IModel model = new CompoundPropertyModel(storeInfo);

        final Form paramsForm = new Form("dataStoreForm", model);
        add(paramsForm);

        paramsForm.add(new Label("storeType", dsFactory.getDisplayName()));
        paramsForm.add(new Label("storeTypeDescription", dsFactory.getDescription()));

        {
            final IModel wsModel = new PropertyModel(model, "workspace");
            final IModel wsLabelModel = new ResourceModel("workspace", "Workspace");
            workspacePanel = new WorkspacePanel("workspacePanel", wsModel, wsLabelModel, true);
        }
        paramsForm.add(workspacePanel);

        final TextParamPanel dataStoreNamePanel;

        dataStoreNamePanel = new TextParamPanel("dataStoreNamePanel", new PropertyModel(model,
                "name"),
                new ResourceModel("AbstractDataAccessPage.dataSrcName", "Data Source Name"), true);
        paramsForm.add(dataStoreNamePanel);

        paramsForm.add(new TextParamPanel("dataStoreDescriptionPanel", new PropertyModel(model,
                "description"), new ResourceModel("AbstractDataAccessPage.description", "Description"), false,
                (IValidator[]) null));

        paramsForm.add(new CheckBoxParamPanel("dataStoreEnabledPanel", new PropertyModel(model,
                "enabled"), new ResourceModel("enabled", "Enabled")));

        {
            /*
             * Here's where the extension point is applied in order to give extensions a chance to
             * provide custom behavior/components for the coverage form other than the default
             * single "url" input field
             */
            GeoServerApplication app = getGeoServerApplication();
            storeEditPanel = StoreExtensionPoints.getStoreEditPanel("parametersPanel", paramsForm,
                    storeInfo, app);
        }
        paramsForm.add(storeEditPanel);

        paramsForm.add(new FeedbackPanel("feedback"));

        // validate the selected workspace does not already contain a store with the same name
        final String dataStoreInfoId = storeInfo.getId();
        StoreNameValidator storeNameValidator = new StoreNameValidator(workspacePanel
                .getFormComponent(), dataStoreNamePanel.getFormComponent(), dataStoreInfoId);
        paramsForm.add(storeNameValidator);

        paramsForm.add(new BookmarkablePageLink("cancel", StorePage.class));

        paramsForm.add(new AjaxSubmitLink("save", paramsForm) {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onError(AjaxRequestTarget target, Form form) {
                super.onError(target, form);
                target.addComponent(paramsForm);
            }

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form form) {
                try {
                    DataStoreInfo dataStore = (DataStoreInfo) form.getModelObject();
                    onSaveDataStore(dataStore, target);
                } catch (IllegalArgumentException e) {
                    paramsForm.error(e.getMessage());
                    target.addComponent(paramsForm);
                }
            }
        });

        // save the namespace panel as an instance variable. Needed as per GEOS-3149
        makeNamespaceSyncUpWithWorkspace(paramsForm);
    }

    /**
     * Call back method called when the save button is hit. Subclasses shall override in order to
     * perform the action over the catalog, whether it is adding a new {@link DataStoreInfo} or
     * saving the edits to an existing onefinal StoreEditPanel
     *
     * @param info
     *            the object to save
     * @param requestTarget
     * @throws IllegalArgumentException
     *             with an appropriate message for the user if the operation failed
     */
    protected abstract void onSaveDataStore(final DataStoreInfo info,
            AjaxRequestTarget requestTarget) throws IllegalArgumentException;

    /**
     * Make the {@link #namespacePanel} model to synch up with the workspace whenever the
     * {@link #workspacePanel} option changes.
     * <p>
     * This is so to maintain namespaces in synch with workspace while the resource/publish split is
     * not finalized, as per GEOS-3149.
     * </p>
     * <p>
     * Removing this method and the call to it on
     * {@link #getInputComponent(String, IModel, ParamInfo)} is all that's needed to let the
     * namespace be selectable independently of the workspace once the resource/publish split is
     * done.
     * </p>
     */
    private void makeNamespaceSyncUpWithWorkspace(final Form paramsForm) {

        // do not allow the namespace choice to be manually changed
        final DropDownChoice wsDropDown = (DropDownChoice) workspacePanel.getFormComponent();
        // add an ajax onchange behaviour that keeps ws and ns in synch
        wsDropDown.add(new OnChangeAjaxBehavior() {
            private static final long serialVersionUID = 1L;
            private NamespaceParamModel namespaceModel;
            private NamespacePanel namespacePanel;
            private boolean namespaceLookupOccurred;

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                // see if the namespace param is tied to a NamespacePanel and save it
                if (!namespaceLookupOccurred) {
                    // search for the panel
                    Component paramsPanel = AbstractDataAccessPage.this
                            .get("dataStoreForm:parametersPanel");
                    namespacePanel = findNamespacePanel((MarkupContainer) paramsPanel);
                   
                    // if the panel is not there search for the parameter and build a model around it
                    if(namespacePanel == null) {
                        final IModel model = paramsForm.getModel();
                        final DataStoreInfo info = (DataStoreInfo) model.getObject();
                        final Catalog catalog = getCatalog();
                        final ResourcePool resourcePool = catalog.getResourcePool();
                        DataAccessFactory dsFactory;
                        try {
                            dsFactory = resourcePool.getDataStoreFactory(info);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }

                        final Param[] dsParams = dsFactory.getParametersInfo();
                        for (Param p : dsParams) {
                            if("namespace".equals(p.getName())) {
                                final IModel paramsModel = new PropertyModel(model, "connectionParameters");
                                namespaceModel = new NamespaceParamModel(paramsModel, "namespace");
                                break;
                            }
                        }
                       
                    }
                    namespaceLookupOccurred = true;
                }

                // get the namespace
                WorkspaceInfo ws = (WorkspaceInfo) wsDropDown.getModelObject();
                String prefix = ws.getName();
                NamespaceInfo namespaceInfo = getCatalog().getNamespaceByPrefix(prefix);
                if (namespacePanel != null) {
                    // update the GUI
                    namespacePanel.setDefaultModelObject(namespaceInfo);
                    target.addComponent(namespacePanel.getFormComponent());
                } else if(namespaceModel != null) {
                    // update the model directly
                    namespaceModel.setObject(namespaceInfo);
                    // target.addComponent(AbstractDataAccessPage.this);
                }
            }
        });
    }

    @SuppressWarnings("unchecked")
    private NamespacePanel findNamespacePanel(MarkupContainer c) {
        Component child;
        for (Iterator<? extends Component> it = ((MarkupContainer) c).iterator(); it.hasNext();) {
            child = it.next();
            if (child instanceof NamespacePanel) {
                return (NamespacePanel) child;
            } else if (child instanceof MarkupContainer) {
                NamespacePanel panel = findNamespacePanel((MarkupContainer) child);
                if (panel != null) {
                    return panel;
                }
            }
        }
        return null;
    }

    protected void clone(final DataStoreInfo source, DataStoreInfo target) {
        target.setDescription(source.getDescription());
        target.setEnabled(source.isEnabled());
        target.setName(source.getName());
        target.setWorkspace(source.getWorkspace());
        target.setType(source.getType());

        target.getConnectionParameters().clear();
        target.getConnectionParameters().putAll(source.getConnectionParameters());
    }

    @Override
    protected ComponentAuthorizer getPageAuthorizer() {
        return ComponentAuthorizer.WORKSPACE_ADMIN;
    }
}
TOP

Related Classes of org.geoserver.web.data.store.AbstractDataAccessPage

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.