Skip to content

Commit

Permalink
[GEOS-8580] Use appropriate editors for coverage parameters list
Browse files Browse the repository at this point in the history
  • Loading branch information
aaime committed Feb 17, 2018
1 parent 2ece5fd commit 4055b52
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 23 deletions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,40 @@
*/
package org.geoserver.web.data.resource;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import org.apache.wicket.Component;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.link.Link;
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.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.validation.validator.RangeValidator;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.catalog.CoverageView;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.web.data.layer.CoverageViewEditPage;
import org.geoserver.web.data.store.panel.CheckBoxParamPanel;
import org.geoserver.web.data.store.panel.ColorPickerPanel;
import org.geoserver.web.data.store.panel.DropDownChoiceParamPanel;
import org.geoserver.web.data.store.panel.TextParamPanel;
import org.geoserver.web.util.MapModel;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.parameter.DefaultParameterDescriptor;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValueGroup;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.stream.Collectors;

/**
* A configuration panel for CoverageInfo properties that related to WCS publication
Expand All @@ -35,12 +47,15 @@
*/
@SuppressWarnings("serial")
public class CoverageResourceConfigurationPanel extends ResourceConfigurationPanel {

Map<String, DefaultParameterDescriptor> parameterDescriptorMap;

public CoverageResourceConfigurationPanel(final String panelId, final IModel model){
super(panelId, model);
initParameterDescriptors();

final CoverageInfo coverage = (CoverageInfo) getResourceInfo();

final Map<String, Serializable> parameters = coverage.getParameters();
List<String> keys = new ArrayList<String>(parameters.keySet());
Collections.sort(keys);
Expand Down Expand Up @@ -86,14 +101,76 @@ public void onClick() {
if(keys.size() == 0)
setVisible(false);
}


private void initParameterDescriptors() {
try {
final CoverageInfo coverage = (CoverageInfo) getResourceInfo();
AbstractGridFormat format = coverage.getStore().getFormat();
ParameterValueGroup readParameters = format.getReadParameters();
List<GeneralParameterValue> parameterValues = readParameters.values();
parameterDescriptorMap = parameterValues.stream()
.map(p -> p.getDescriptor())
.filter(p -> p instanceof DefaultParameterDescriptor)
.map(p -> (DefaultParameterDescriptor) p)
.collect(Collectors.toMap(p -> p.getName().getCode(), Function.identity()));
} catch (Exception e) {
LOGGER.log(Level.INFO, "Failed to initialize parameter descriptors, the UI will use generic text " +
"editors", e);
}
}

private Component getInputComponent(String id, IModel paramsModel,
String keyName) {
if (keyName.contains("Color"))
return new ColorPickerPanel(id, new MapModel(paramsModel, keyName),
new org.apache.wicket.model.ResourceModel(keyName, keyName), false);
else
return new TextParamPanel(id, new MapModel(paramsModel, keyName),
new org.apache.wicket.model.ResourceModel(keyName, keyName), false);
MapModel valueModel = new MapModel(paramsModel, keyName);
ResourceModel labelModel = new ResourceModel(keyName, keyName);
if (keyName.contains("Color")) {
return new ColorPickerPanel(id, valueModel, labelModel, false);
}

DefaultParameterDescriptor descriptor = parameterDescriptorMap.get(keyName);
if (descriptor != null) {
Class valueClass = descriptor.getValueClass();

// checkbox for booleans
if (valueClass.equals(Boolean.class)) {
return new CheckBoxParamPanel(id, valueModel, labelModel);
}

// dropdown for enumerations
if (descriptor.getValueClass().isEnum()) {
List<? extends Serializable> values = Arrays.stream(descriptor.getValueClass().getEnumConstants())
.map(v -> (Serializable) v)
.collect(Collectors.toList());
return new DropDownChoiceParamPanel(id, valueModel, labelModel, values, false);
}

// dropdown for cases in which there is a set of valid values
Set validValues = descriptor.getValidValues();
if (Serializable.class.isAssignableFrom(descriptor.getValueClass()) && validValues != null && !validValues.isEmpty()) {
List<? extends Serializable> values = new ArrayList<>(validValues);
return new DropDownChoiceParamPanel(id, valueModel, labelModel, values, false);
}

// anything else is a text, with some target type and eventual validation
TextParamPanel panel = new TextParamPanel(id, valueModel, labelModel, false);
if (Number.class.isAssignableFrom(valueClass)) {
panel.getFormComponent().setType(valueClass);

Number minimum = (Number) descriptor.getMinimumValue();
if (minimum != null) {
panel.getFormComponent().add(RangeValidator.minimum(minimum.doubleValue()));
}
Number maximum = (Number) descriptor.getMaximumValue();
if (maximum != null && maximum instanceof Serializable) {
panel.getFormComponent().add(RangeValidator.maximum(maximum.doubleValue()));
}
}

return panel;

}

return new TextParamPanel(id, valueModel,
labelModel, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ public DropDownChoiceParamPanel(final String id, final IModel<Serializable> para
final IModel<String> paramLabelModel, final List<? extends Serializable> options,
final boolean required) {

super(id);
super(id, paramValue);

String requiredMark = required ? " *" : "";
Label label = new Label("paramName", paramLabelModel.getObject() + requiredMark);
add(label);

choice = new DropDownChoice<Serializable>("paramValue", paramValue, options);
choice = new DropDownChoice<>("paramValue", paramValue, options);
choice.setRequired(required);
if (!required) {
choice.setNullValid(true);
}

FormComponentFeedbackBorder feedback = new FormComponentFeedbackBorder("border");
feedback.add(choice);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ public MapModel(IModel<? extends Map<String,? extends Object>> model, String exp
this.model = model;
this.expression = expression;
}


public String getExpression() {
return expression;
}

@SuppressWarnings("unchecked")
public T getObject() {
return (T) model.getObject().get(expression);
Expand Down
16 changes: 16 additions & 0 deletions src/web/core/src/main/resources/GeoServerApplication.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1020,3 +1020,19 @@ PropertyEditorFormComponent.ValueRequired=Property value required
MetadataLinkEditor$UrlValidator = Invalid metadata link URL
DataLinkEditor$UrlValidator = Invalid data link URL

#CoverageStore property names
Accurate\ resolution\ computation=Accurate Resolution Computation
AllowMultithreading=Multithreaded granule loading (disable JAI ImageRead to use it)
BackgroundValues=Background Values
Bands=Bands (comma separated list of numbers)
ExcessGranuleRemoval=Excess Granule Removal
Filter=Filter
FootprintBehavior=Footprint Behavior
InputTransparentColor=Input Transparent Color
MaxAllowedTiles=Maximum number of granules to load
MergeBehavior=Merge Behavior
OVERVIEW_POLICY=Overview Policy
OutputTransparentColor=Output Transparent Color
SORTING=Granule Sorting (WFS like syntax)
SUGGESTED_TILE_SIZE=Suggested Tile Size
USE_JAI_IMAGEREAD=Use JAI ImageRead (deferred loading)
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,48 @@
*/
package org.geoserver.web.data.resource;

import static org.junit.Assert.*;

import java.io.IOException;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.list.ListView;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CatalogBuilder;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.web.GeoServerWicketTestSupport;
import org.geoserver.web.data.store.panel.CheckBoxParamPanel;
import org.geoserver.web.data.store.panel.ColorPickerPanel;
import org.geoserver.web.data.store.panel.DropDownChoiceParamPanel;
import org.geoserver.web.data.store.panel.ParamPanel;
import org.geoserver.web.data.store.panel.TextParamPanel;
import org.geoserver.web.util.MapModel;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.feature.NameImpl;
import org.geotools.gce.imagemosaic.ImageMosaicFormat;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.hamcrest.CoreMatchers;
import org.junit.Test;

import javax.xml.namespace.QName;

import static org.geotools.coverage.grid.io.AbstractGridFormat.*;
import static org.geotools.gce.imagemosaic.ImageMosaicFormat.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

public class ResourceConfigurationPageTest extends GeoServerWicketTestSupport {

protected static QName TIMERANGES = new QName(MockData.SF_URI, "timeranges", MockData.SF_PREFIX);

@Override
protected void onSetUp(SystemTestData testData) throws Exception {
super.onSetUp(testData);
testData.addRasterLayer(TIMERANGES, "timeranges.zip", null, null, SystemTestData.class, getCatalog());
}

@Test
public void testBasic() {
LayerInfo layer = getGeoServerApplication().getCatalog().getLayerByName(getLayerId(MockData.BASIC_POLYGONS));
Expand Down Expand Up @@ -86,4 +107,40 @@ public void testComputeLatLon() throws Exception {
assertEquals(4.5, re.getMaxY(), 0.1);
}

@Test
public void testParametersUI() throws Exception {
LayerInfo layer = getGeoServerApplication().getCatalog().getLayerByName(getLayerId(TIMERANGES));

login();
tester.startPage(new ResourceConfigurationPage(layer, false));
print(tester.getLastRenderedPage(), true, true);

// get the list of parameters in the UI
ListView parametersList = (ListView) tester.getComponentFromLastRenderedPage("publishedinfo:tabs:panel:theList:1:content:parameters");
parametersList.visitChildren(ParamPanel.class, (c, v) -> {
MapModel mapModel = (MapModel) c.getDefaultModel();
String parameterKey = mapModel.getExpression();
if (USE_JAI_IMAGEREAD.getName().getCode().equals(parameterKey) ||
ACCURATE_RESOLUTION.getName().getCode().equals(parameterKey) ||
ALLOW_MULTITHREADING.getName().getCode().equals(parameterKey)) {
assertThat(parameterKey, c, CoreMatchers.instanceOf(CheckBoxParamPanel.class));
} else if (EXCESS_GRANULE_REMOVAL.getName().getCode().equals(parameterKey) ||
FOOTPRINT_BEHAVIOR.getName().getCode().equals(parameterKey) ||
MERGE_BEHAVIOR.getName().getCode().equals(parameterKey) ||
OVERVIEW_POLICY.getName().getCode().equals(parameterKey)) {
assertThat(parameterKey, c, CoreMatchers.instanceOf(DropDownChoiceParamPanel.class));
} else if(BACKGROUND_COLOR.getName().getCode().equals(parameterKey) ||
OUTPUT_TRANSPARENT_COLOR.getName().getCode().equals(parameterKey) ||
INPUT_TRANSPARENT_COLOR.getName().getCode().equals(parameterKey)) {
assertThat(parameterKey, c, CoreMatchers.instanceOf(ColorPickerPanel.class));
} else if (SORT_BY.getName().getCode().equals(parameterKey) ||
BACKGROUND_VALUES.getName().getCode().equals(parameterKey) ||
SUGGESTED_TILE_SIZE.getName().getCode().equals(parameterKey)) {
assertThat(parameterKey, c, CoreMatchers.instanceOf(TextParamPanel.class));
}
});
tester.assertComponent("publishedinfo:tabs:panel:theList:1:content:parameters:0:parameterPanel",
CheckBoxParamPanel.class);
}

}

0 comments on commit 4055b52

Please sign in to comment.