Package org.geoserver.gwc.web.layer

Source Code of org.geoserver.gwc.web.layer.GridSubsetsEditor

/* (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.gwc.web.layer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.behavior.SimpleAttributeModifier;
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.FormComponent;
import org.apache.wicket.markup.html.form.FormComponentPanel;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
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.geoserver.gwc.GWC;
import org.geoserver.gwc.web.GWCIconFactory;
import org.geoserver.web.wicket.GeoServerAjaxFormLink;
import org.geoserver.web.wicket.Icon;
import org.geoserver.web.wicket.ImageAjaxLink;
import org.geoserver.web.wicket.ParamResourceModel;
import org.geowebcache.config.XMLGridSubset;
import org.geowebcache.grid.BoundingBox;
import org.geowebcache.grid.GridSet;
import org.geowebcache.grid.GridSetBroker;

class GridSubsetsEditor extends FormComponentPanel<Set<XMLGridSubset>> {

    private static final long serialVersionUID = 5098470663723800345L;

    private final WebMarkupContainer table;

    private final ListView<XMLGridSubset> grids;

    private final DropDownChoice<String> availableGridSets;

    private final GridSubsetListValidator validator;

    private class GridSubsetListValidator implements IValidator<Set<XMLGridSubset>> {

        private static final long serialVersionUID = 1L;

        private boolean validate;

        public GridSubsetListValidator() {
            this.setEnabled(true);
        }

        @Override
        public void validate(IValidatable<Set<XMLGridSubset>> validatable) {
            if (!validate) {
                return;
            }
            Set<XMLGridSubset> gridSubsets = validatable.getValue();
            if (gridSubsets == null || gridSubsets.size() == 0) {
                error(validatable, "GridSubsetsEditor.validation.empty");
                return;
            }

            final GWC gwc = GWC.get();
            for (XMLGridSubset subset : gridSubsets) {
                final String gridSetName = subset.getGridSetName();
                final Integer zoomStart = subset.getZoomStart();
                final Integer zoomStop = subset.getZoomStop();
                final BoundingBox extent = subset.getExtent();

                if (gridSetName == null) {
                    throw new IllegalStateException("GridSet name is null");
                }

                if (zoomStart != null && zoomStop != null) {
                    if (zoomStart.intValue() > zoomStop.intValue()) {
                        error(validatable, "GridSubsetsEditor.validation.zoomLevelsError");
                        return;
                    }
                }

                final GridSetBroker gridSetBroker = gwc.getGridSetBroker();
                final GridSet gridSet = gridSetBroker.get(gridSetName);

                if (null == gridSet) {
                    error(validatable, "GridSubsetsEditor.validation.gridSetNotFound", gridSetName);
                    return;
                }

                if (extent != null) {
                    if (extent.isNull() || !extent.isSane()) {
                        error(validatable, "GridSubsetsEditor.validation.invalidBounds");
                    }
                    final BoundingBox fullBounds = gridSet.getOriginalExtent();
                    final boolean intersects = fullBounds.intersects(extent);
                    if (!intersects) {
                        error(validatable, "GridSubsetsEditor.validation.boundsOutsideCoverage");
                    }
                }
            }
        }

        private void error(IValidatable<Set<XMLGridSubset>> validatable, final String resourceKey,
                final String... params) {

            ValidationError error = new ValidationError();
            String message;
            if (params == null) {
                message = new ResourceModel(resourceKey).getObject();
            } else {
                message = new ParamResourceModel(resourceKey, GridSubsetsEditor.this,
                        (Object[]) params).getObject();
            }
            error.setMessage(message);
            validatable.error(error);
        }

        public void setEnabled(boolean validate) {
            this.validate = validate;
        }
    }

    public GridSubsetsEditor(final String id, final IModel<Set<XMLGridSubset>> model) {
        super(id, model);
        add(validator = new GridSubsetListValidator());

        // container for ajax updates
        final WebMarkupContainer container = new WebMarkupContainer("container");
        container.setOutputMarkupId(true);
        add(container);

        // the link list
        table = new WebMarkupContainer("table");
        table.setOutputMarkupId(true);

        container.add(table);

        grids = new ListView<XMLGridSubset>("gridSubsets", new ArrayList<XMLGridSubset>(
                model.getObject())) {

            private static final long serialVersionUID = 1L;

            @Override
            protected void onBeforeRender() {
                super.onBeforeRender();
            }

            @Override
            protected void populateItem(final ListItem<XMLGridSubset> item) {
                // odd/even style
                final int index = item.getIndex();
                item.add(new SimpleAttributeModifier("class", index % 2 == 0 ? "even" : "odd"));

                final XMLGridSubset gridSubset = item.getModelObject();
                GridSetBroker gridSetBroker = GWC.get().getGridSetBroker();

                String gridsetDescription = null;
                int gridsetLevels;
                boolean gridsetExists;
                {
                    final GridSet gridSet = gridSetBroker.get(gridSubset.getGridSetName());
                    gridsetExists = gridSet != null;
                    if (gridsetExists) {
                        gridsetLevels = gridSet.getNumLevels();
                        gridsetDescription = gridSet.getDescription();
                    } else {
                        gridsetLevels = gridSubset.getZoomStop() == null ? 1 : gridSubset
                                .getZoomStop().intValue();
                    }
                }
                final Label gridSetLabel;
                final Component gridSetBounds;

                gridSetLabel = new Label("gridSet", new PropertyModel<String>(item.getModel(),
                        "gridSetName"));
                if(!gridsetExists){
                    gridSetLabel.add(new AttributeModifier("style", true, new Model<String>("color:red;text-decoration:line-through;")));
                    getPage().warn("GridSet " + gridSubset.getGridSetName() + " does not exist");
                }
                item.add(gridSetLabel);
                if (null != gridsetDescription) {
                    gridSetLabel.add(new AttributeModifier("title", true, new Model<String>(
                            gridsetDescription)));
                }

                final Component removeLink;

                final int maxZoomLevel = gridsetLevels - 1;
                final ArrayList<Integer> zoomLevels = new ArrayList<Integer>(maxZoomLevel + 1);
                for (int z = 0; z <= maxZoomLevel; z++) {
                    zoomLevels.add(Integer.valueOf(z));
                }

                // zoomStart has all zoom levels as choices
                // zoomStop choices start at zoomStart's selection
                // minCachedLevel start at zoomStart's selection and ends at zoomStop's selection
                // maxCachedLevel start at minCachedLevels' and ends at zoomStop's selection

                final IModel<Integer> zoomStartModel;
                final IModel<Integer> zoomStopModel;
                final IModel<Integer> minCachedLevelModel;
                final IModel<Integer> maxCachedLevelModel;

                final ZoomLevelDropDownChoice zoomStart;
                final ZoomLevelDropDownChoice zoomStop;
                final ZoomLevelDropDownChoice minCachedLevel;
                final ZoomLevelDropDownChoice maxCachedLevel;

                zoomStartModel = new PropertyModel<Integer>(item.getModel(), "zoomStart");
                zoomStopModel = new PropertyModel<Integer>(item.getModel(), "zoomStop");
                minCachedLevelModel = new PropertyModel<Integer>(item.getModel(), "minCachedLevel");
                maxCachedLevelModel = new PropertyModel<Integer>(item.getModel(), "maxCachedLevel");

                @SuppressWarnings({ "rawtypes", "unchecked" })
                final IModel<List<Integer>> allLevels = new Model(zoomLevels);

                zoomStart = new ZoomLevelDropDownChoice("zoomStart", zoomStartModel, allLevels);
                zoomStart.setEnabled(gridsetExists);
                item.add(zoomStart);

                zoomStop = new ZoomLevelDropDownChoice("zoomStop", zoomStopModel, allLevels);
                zoomStop.setEnabled(gridsetExists);
                item.add(zoomStop);

                minCachedLevel = new ZoomLevelDropDownChoice("minCachedLevel", minCachedLevelModel,
                        allLevels);
                minCachedLevel.setEnabled(gridsetExists);
                item.add(minCachedLevel);

                maxCachedLevel = new ZoomLevelDropDownChoice("maxCachedLevel", maxCachedLevelModel,
                        allLevels);
                maxCachedLevel.setEnabled(gridsetExists);
                item.add(maxCachedLevel);

                for (ZoomLevelDropDownChoice dropDown : Arrays.asList(zoomStart, zoomStop,
                        minCachedLevel, maxCachedLevel)) {
                    dropDown.add(new OnChangeAjaxBehavior() {
                        private static final long serialVersionUID = 1L;

                        // cascades to zoomStop, min and max cached levels
                        @Override
                        protected void onUpdate(AjaxRequestTarget target) {
                            updateValidZoomRanges(zoomStart, zoomStop, minCachedLevel,
                                    maxCachedLevel, target);
                        }
                    });
                }

                updateValidZoomRanges(zoomStart, zoomStop, minCachedLevel, maxCachedLevel, null);

                // gridSetBounds = new EnvelopePanel("bounds");
                // gridSetBounds.setCRSFieldVisible(false);
                // gridSetBounds.setCrsRequired(false);
                // gridSetBounds.setLabelsVisibility(false);
                // gridSetBounds.setModel(new Model<ReferencedEnvelope>(new ReferencedEnvelope()));
                gridSetBounds = new Label("bounds", new ResourceModel(
                        "GridSubsetsEditor.bounds.dynamic"));
                item.add(gridSetBounds);

                removeLink = new ImageAjaxLink("removeLink", GWCIconFactory.DELETE_ICON) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    protected void onClick(AjaxRequestTarget target) {
                        List<XMLGridSubset> list;
                        list = new ArrayList<XMLGridSubset>(grids.getModelObject());
                        final XMLGridSubset subset = (XMLGridSubset) getDefaultModelObject();

                        list.remove(subset);

                        grids.setModelObject(list);

                        List<String> choices = new ArrayList<String>(availableGridSets.getChoices());
                        choices.add(subset.getGridSetName());
                        Collections.sort(choices);
                        availableGridSets.setChoices(choices);

                        target.addComponent(container);
                        target.addComponent(availableGridSets);
                    }
                };
                removeLink.setDefaultModel(item.getModel());
                removeLink.add(new AttributeModifier("title", true, new ResourceModel(
                        "GridSubsetsEditor.removeLink")));
                item.add(removeLink);
            }
        };

        grids.setOutputMarkupId(true);
        // this is necessary to avoid loosing item contents on edit/validation checks
        grids.setReuseItems(true);
        table.add(grids);

        List<String> gridSetNames = new ArrayList<String>(GWC.get().getGridSetBroker().getNames());
        for (XMLGridSubset gs : model.getObject()) {
            gridSetNames.remove(gs.getGridSetName());
        }
        Collections.sort(gridSetNames);

        GeoServerAjaxFormLink addGridsubsetLink = new GeoServerAjaxFormLink("addGridSubset") {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onClick(AjaxRequestTarget target, Form form) {
                availableGridSets.processInput();

                final String selectedGridset = availableGridSets.getModelObject();
                if (null == selectedGridset) {
                    return;
                }

                List<String> choices = new ArrayList<String>(availableGridSets.getChoices());
                choices.remove(selectedGridset);
                availableGridSets.setChoices(choices);
                availableGridSets.setEnabled(!choices.isEmpty());

                XMLGridSubset newSubset = new XMLGridSubset();
                newSubset.setGridSetName(selectedGridset);
                grids.getModelObject().add(newSubset);

                target.addComponent(table);
                target.addComponent(availableGridSets);
            }
        };
        addGridsubsetLink.add(new Icon("addIcon", GWCIconFactory.ADD_ICON));
        add(addGridsubsetLink);

        availableGridSets = new DropDownChoice<String>("availableGridsets", new Model<String>(),
                gridSetNames);
        availableGridSets.setOutputMarkupId(true);
        add(availableGridSets);

    }

    @Override
    protected void convertInput() {
        grids.visitChildren(new Component.IVisitor<Component>() {

            @Override
            public Object component(Component component) {
                if (component instanceof FormComponent) {
                    FormComponent<?> formComponent = (FormComponent<?>) component;
                    formComponent.processInput();
                }
                return Component.IVisitor.CONTINUE_TRAVERSAL;
            }
        });
        List<XMLGridSubset> info = grids.getModelObject();
        HashSet<XMLGridSubset> convertedInput = new HashSet<XMLGridSubset>(info);
        setConvertedInput(convertedInput);
    }

    /**
     */
    @Override
    protected void onBeforeRender() {
        super.onBeforeRender();
    }

    public void setValidating(final boolean validate) {
        validator.setEnabled(validate);
    }

    private static class ZoomLevelDropDownChoice extends DropDownChoice<Integer> {
        private static final long serialVersionUID = -1312406093015271637L;

        public ZoomLevelDropDownChoice(final String id, IModel<Integer> model,
                IModel<List<Integer>> allChoices) {
            super(id, model, allChoices);
            setNullValid(true);// show null option even if model value isn't null
            setOutputMarkupId(true);
        }

        @Override
        protected String getNullValidKey() {
            String nullValidKey = "GridSubsetsEditor." + getId() + ".nullValid";
            return nullValidKey;
        }

        public void setAllowedMin(int newMin) {
            List<? extends Integer> choices = getChoices();
            final int max = choices.get(choices.size() - 1).intValue();
            setChoices(newMin, Math.max(newMin, max));
        }

        public void setAllowedMax(int max) {
            List<? extends Integer> choices = getChoices();
            final int min = choices.get(0).intValue();
            setChoices(Math.min(min, max), max);
        }

        private void setChoices(int min, int max) {
            List<Integer> choices = new ArrayList<Integer>();
            for (int i = min; i <= max; i++) {
                choices.add(Integer.valueOf(i));
            }
            Integer modelObject = getModelObject();
            setChoices(choices);
            if (modelObject != null && modelObject >= min && modelObject <= max) {
                setModelObject(modelObject);
            } else {
                setModelObject(null);
            }
        }
    }

    private void updateValidZoomRanges(final ZoomLevelDropDownChoice zoomStart,
            final ZoomLevelDropDownChoice zoomStop, final ZoomLevelDropDownChoice minCachedLevel,
            final ZoomLevelDropDownChoice maxCachedLevel, AjaxRequestTarget target) {

        // zoomStart.processInput();
        Integer min = zoomStart.getModelObject();
        if (min != null) {
            zoomStop.setAllowedMin(min.intValue());
            minCachedLevel.setAllowedMin(min.intValue());
            maxCachedLevel.setAllowedMin(min.intValue());
        }

        Integer max = zoomStop.getModelObject();
        if (max != null) {
            minCachedLevel.setAllowedMax(max.intValue());
            maxCachedLevel.setAllowedMax(max.intValue());
        }

        Integer minCached = minCachedLevel.getModelObject();
        if (minCached != null) {
            maxCachedLevel.setAllowedMin(minCached.intValue());
        }

        if (null != target) {
            target.addComponent(zoomStop);
            target.addComponent(minCachedLevel);
            target.addComponent(maxCachedLevel);
        }
    }
}
TOP

Related Classes of org.geoserver.gwc.web.layer.GridSubsetsEditor

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.