/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.web.data.resource; import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.FormComponent; import org.apache.wicket.markup.html.form.FormComponentPanel; import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.model.IModel; import org.apache.wicket.model.PropertyModel; import org.geoserver.catalog.CoverageInfo; import org.geoserver.catalog.DimensionInfo; import org.geoserver.catalog.DimensionPresentation; import org.geoserver.catalog.FeatureTypeInfo; import org.geoserver.catalog.ResourceInfo; import org.geoserver.catalog.impl.DimensionInfoImpl; import org.geoserver.web.wicket.ParamResourceModel; import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader; import org.opengis.coverage.grid.GridCoverageReader; import org.opengis.feature.type.PropertyDescriptor; /** * Edits a {@link DimensionInfo} object for the specified resource * * @author Andrea Aime - GeoSolutions */ @SuppressWarnings("serial") public class DimensionEditor extends FormComponentPanel<DimensionInfo> { List<DimensionPresentation> PRESENTATION_MODES = Arrays.asList(DimensionPresentation.values()); private CheckBox enabled; private DropDownChoice<String> attribute; private DropDownChoice<DimensionPresentation> presentation; private PeriodEditor resTime; private TextField<BigDecimal> resElevation; boolean time; public DimensionEditor(String id, IModel<DimensionInfo> model, ResourceInfo resource, Class type) { super(id, model); // double container dance to get stuff to show up and hide on demand (grrr) final WebMarkupContainer configsContainer = new WebMarkupContainer("configContainer"); configsContainer.setOutputMarkupId(true); add(configsContainer); final WebMarkupContainer configs = new WebMarkupContainer("configs"); configs.setOutputMarkupId(true); configs.setVisible(getModelObject().isEnabled()); configsContainer.add(configs); // enabled flag, and show the rest only if enabled is true final PropertyModel<Boolean> enabledModel = new PropertyModel<Boolean>(model, "enabled"); enabled = new CheckBox("enabled", enabledModel); add(enabled); enabled.add(new AjaxFormComponentUpdatingBehavior("onclick") { @Override protected void onUpdate(AjaxRequestTarget target) { Boolean visile = enabled.getModelObject(); configs.setVisible(visile); target.addComponent(configsContainer); } }); // error message label Label noAttributeMessage = new Label("noAttributeMsg", ""); add(noAttributeMessage); // the attribute label and dropdown container WebMarkupContainer attContainer = new WebMarkupContainer("attributeContainer"); configs.add(attContainer); // check the attributes and show a dropdown List<String> attributes = getAttributesOfType(resource, type); attribute = new DropDownChoice<String>("attribute", new PropertyModel<String>(model, "attribute"), attributes); attribute.setOutputMarkupId(true); attribute.setRequired(true); attContainer.add(attribute); // do we show it? if(resource instanceof FeatureTypeInfo) { if (attributes.isEmpty()) { disableDimension(type, configs, noAttributeMessage); } else { noAttributeMessage.setVisible(false); } } else if(resource instanceof CoverageInfo) { attContainer.setVisible(false); attribute.setRequired(false); try { GridCoverageReader reader = ((CoverageInfo) resource).getGridCoverageReader(null, null); if(Number.class.isAssignableFrom(type)) { String elev = reader.getMetadataValue(AbstractGridCoverage2DReader.HAS_ELEVATION_DOMAIN); if(!Boolean.parseBoolean(elev)) { disableDimension(type, configs, noAttributeMessage); } } else if(Date.class.isAssignableFrom(type)) { String time = reader.getMetadataValue(AbstractGridCoverage2DReader.HAS_TIME_DOMAIN); if(!Boolean.parseBoolean(time)) { disableDimension(type, configs, noAttributeMessage); } } } catch(IOException e) { throw new WicketRuntimeException(e); } } // presentation/resolution block final WebMarkupContainer resContainer = new WebMarkupContainer("resolutionContainer"); resContainer.setOutputMarkupId(true); configs.add(resContainer); final WebMarkupContainer resolutions = new WebMarkupContainer("resolutions"); resolutions .setVisible(model.getObject().getPresentation() == DimensionPresentation.DISCRETE_INTERVAL); resolutions.setOutputMarkupId(true); resContainer.add(resolutions); presentation = new DropDownChoice<DimensionPresentation>("presentation", new PropertyModel<DimensionPresentation>(model, "presentation"), PRESENTATION_MODES, new PresentationModeRenderer()); configs.add(presentation); presentation.setRequired(true); presentation.add(new AjaxFormComponentUpdatingBehavior("onchange") { @Override protected void onUpdate(AjaxRequestTarget target) { boolean visible = presentation.getModelObject() == DimensionPresentation.DISCRETE_INTERVAL; resolutions.setVisible(visible); target.addComponent(resContainer); } }); IModel<BigDecimal> rmodel = new PropertyModel<BigDecimal>(model, "resolution"); resTime = new PeriodEditor("resTime", rmodel); resolutions.add(resTime); resElevation = new TextField<BigDecimal>("resElevation", rmodel); resolutions.add(resElevation); time = Date.class.isAssignableFrom(type); if(time) { resElevation.setVisible(false); resTime.setRequired(true); } else { resTime.setVisible(false); resElevation.setRequired(true); } } private void disableDimension(Class type, final WebMarkupContainer configs, Label noAttributeMessage) { // no attributes of the required type, no party enabled.setEnabled(false); enabled.setModelObject(false); configs.setVisible(false); ParamResourceModel typeName = new ParamResourceModel("AttributeType." + type.getSimpleName(), null); ParamResourceModel error = new ParamResourceModel("missingAttribute", this, typeName .getString()); noAttributeMessage.setDefaultModelObject(error.getString()); } @Override public boolean processChildren() { return true; } protected void convertInput() { if (!enabled.getModelObject()) { setConvertedInput(new DimensionInfoImpl()); } else { DimensionInfoImpl info = new DimensionInfoImpl(); info.setEnabled(true); attribute.processInput(); info.setAttribute(attribute.getModelObject()); info.setPresentation(presentation.getModelObject()); if (info.getPresentation() == DimensionPresentation.DISCRETE_INTERVAL) { if(time) { resTime.processInput(); info.setResolution(resTime.getModelObject()); } else { resElevation.processInput(); info.setResolution(resElevation.getModelObject()); } } setConvertedInput(info); } }; /** * Returns all attributes conforming to the specified type * * @param resource * @param type * @return */ List<String> getAttributesOfType(ResourceInfo resource, Class<?> type) { List<String> result = new ArrayList<String>(); if (resource instanceof FeatureTypeInfo) { try { FeatureTypeInfo ft = (FeatureTypeInfo) resource; for (PropertyDescriptor pd : ft.getFeatureType() .getDescriptors()) { if (type.isAssignableFrom(pd.getType().getBinding())) { result.add(pd.getName().getLocalPart()); } } } catch (IOException e) { throw new WicketRuntimeException(e); } } return result; } /** * Renders a presentation mode into a human readable form * * @author Alessio */ public class PresentationModeRenderer implements IChoiceRenderer<DimensionPresentation> { public PresentationModeRenderer() { super(); } public Object getDisplayValue(DimensionPresentation object) { return new ParamResourceModel(object.name(), DimensionEditor.this).getString(); } public String getIdValue(DimensionPresentation object, int index) { return String.valueOf(object.ordinal()); } } }