/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2014 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wms.web;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
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.form.CheckBox;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.model.util.CollectionModel;
import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.validation.validator.MinimumValidator;
import org.apache.wicket.validation.validator.RangeValidator;
import org.geoserver.catalog.impl.ModificationProxy;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.web.services.BaseServiceAdminPage;
import org.geoserver.web.util.MapModel;
import org.geoserver.web.wicket.FileExistsValidator;
import org.geoserver.web.wicket.LiveCollectionModel;
import org.geoserver.web.wicket.ParamResourceModel;
import org.geoserver.web.wicket.SRSListTextArea;
import org.geoserver.web.wicket.browser.GeoServerFileChooser;
import org.geoserver.wms.GetMapOutputFormat;
import org.geoserver.wms.WMS;
import org.geoserver.wms.WMSInfo;
import org.geoserver.wms.WMSInfo.WMSInterpolation;
import org.geoserver.wms.WatermarkInfo.Position;
import org.geoserver.wms.featureinfo.GetFeatureInfoOutputFormat;
import org.geoserver.wms.web.publish.LayerAuthoritiesAndIdentifiersPanel;
import org.geoserver.web.data.store.panel.FileModel;
/**
* Edits the WMS service details
*/
@SuppressWarnings("serial")
public class WMSAdminPage extends BaseServiceAdminPage<WMSInfo> {
static final List<String> SVG_RENDERERS = Arrays.asList(new String[] {WMS.SVG_BATIK, WMS.SVG_SIMPLE});
static final List<String> KML_REFLECTOR_MODES = Arrays.asList(new String[] {WMS.KML_REFLECTOR_MODE_REFRESH,
WMS.KML_REFLECTOR_MODE_SUPEROVERLAY, WMS.KML_REFLECTOR_MODE_DOWNLOAD});
static final List<String> KML_SUPEROVERLAY_MODES = Arrays.asList(new String[] {WMS.KML_SUPEROVERLAY_MODE_AUTO,
WMS.KML_SUPEROVERLAY_MODE_RASTER, WMS.KML_SUPEROVERLAY_MODE_OVERVIEW, WMS.KML_SUPEROVERLAY_MODE_HYBRID, WMS.KML_SUPEROVERLAY_MODE_CACHED});
ModalWindow modal;
MimeTypesFormComponent getMapMimeTypesComponent,getFeatureInfoMimeTypesComponent;
TreeSet<String> getMapAvailable;
TreeSet<String> getFeatureInfoAvailable;
public WMSAdminPage() {
super();
}
public WMSAdminPage(PageParameters pageParams) {
super(pageParams);
}
public WMSAdminPage(WMSInfo service) {
super(service);
}
protected Class<WMSInfo> getServiceClass() {
return WMSInfo.class;
}
@SuppressWarnings("unchecked")
protected void build(IModel info, Form form) {
// popups support
form.add(modal = new ModalWindow("modal"));
// authority URLs and Identifiers for the root layer
LayerAuthoritiesAndIdentifiersPanel authAndIds;
authAndIds = new LayerAuthoritiesAndIdentifiersPanel("authoritiesAndIds", true, info);
form.add(authAndIds);
// limited srs list
TextArea srsList = new SRSListTextArea("srs", LiveCollectionModel.list(new PropertyModel(info, "sRS")));
form.add(srsList);
form.add(new CheckBox("bBOXForEachCRS"));
form.add(new AjaxLink("bBOXForEachCRSHelp") {
@Override
public void onClick(AjaxRequestTarget target) {
dialog.showInfo(target,
new StringResourceModel("bboxForEachCRSHelp.title",WMSAdminPage.this, null),
new StringResourceModel("bboxForEachCRSHelp.message",WMSAdminPage.this, null));
}
});
// general
form.add(new DropDownChoice("interpolation", Arrays.asList(WMSInfo.WMSInterpolation.values()), new InterpolationRenderer()));
// resource limits
TextField<Integer> maxMemory = new TextField<Integer>("maxRequestMemory");
maxMemory.add(new MinimumValidator<Integer>(0));
form.add(maxMemory);
TextField<Integer> maxTime = new TextField<Integer>("maxRenderingTime");
maxTime.add(new MinimumValidator<Integer>(0));
form.add(maxTime);
TextField<Integer> maxErrors = new TextField<Integer>("maxRenderingErrors");
maxErrors.add(new MinimumValidator<Integer>(0));
form.add(maxErrors);
// watermark
form.add(new CheckBox("watermark.enabled"));
TextField watermarkUrlField = new TextField("watermark.uRL", new FileModel(new PropertyModel<String>(form.getModel(), "watermark.URL")));
watermarkUrlField.add(new FileExistsValidator(true));
watermarkUrlField.setOutputMarkupId(true);
form.add(watermarkUrlField);
form.add(chooserButton("chooser", new ParamResourceModel("chooseWatermark", this).getString(), watermarkUrlField));
TextField<Integer> transparency = new TextField<Integer>("watermark.transparency");
transparency.add(new RangeValidator<Integer>(0,100));
form.add(transparency);
form.add(new DropDownChoice("watermark.position", Arrays.asList(Position.values()), new WatermarkPositionRenderer()));
// svg
PropertyModel metadataModel = new PropertyModel(info, "metadata");
form.add(new CheckBox("svg.antialias", new MapModel(metadataModel, "svgAntiAlias")));
form.add(new DropDownChoice("svg.producer", new MapModel(metadataModel, "svgRenderer"), SVG_RENDERERS, new SVGMethodRenderer()));
// png compression levels
MapModel pngCompression = defaultedModel(metadataModel, WMS.PNG_COMPRESSION, WMS.PNG_COMPRESSION_DEFAULT);
TextField<Integer> pngCompressionField = new TextField<Integer>("png.compression", pngCompression, Integer.class);
pngCompressionField.add(new RangeValidator<Integer>(0, 100));
form.add(pngCompressionField);
// jpeg compression levels
MapModel jpegCompression = defaultedModel(metadataModel, WMS.JPEG_COMPRESSION, WMS.JPEG_COMPRESSION_DEFAULT);
TextField<Integer> jpegCompressionField = new TextField<Integer>("jpeg.compression", jpegCompression, Integer.class);
jpegCompressionField.add(new RangeValidator<Integer>(0,100));
form.add(jpegCompressionField);
// GIF animated
// MAX_ALLOWED_FRAMES
MapModel maxAllowedFrames = defaultedModel(metadataModel, WMS.MAX_ALLOWED_FRAMES, WMS.MAX_ALLOWED_FRAMES_DEFAULT);
TextField<Integer> maxAllowedFramesField = new TextField<Integer>("anim.maxallowedframes", maxAllowedFrames, Integer.class);
maxAllowedFramesField.add(new RangeValidator<Integer>(0, Integer.MAX_VALUE));
form.add(maxAllowedFramesField);
// MAX_RENDERING_TIME
MapModel maxRenderingTime = defaultedModel(metadataModel, WMS.MAX_RENDERING_TIME, null);
TextField<Integer> maxRenderingTimeField = new TextField<Integer>("anim.maxrenderingtime", maxRenderingTime, Integer.class);
form.add(maxRenderingTimeField);
// MAX_RENDERING_SIZE
MapModel maxRenderingSize = defaultedModel(metadataModel, WMS.MAX_RENDERING_SIZE, null);
TextField<Integer> maxRenderingSizeField = new TextField<Integer>("anim.maxrenderingsize", maxRenderingSize, Integer.class);
form.add(maxRenderingSizeField);
// FRAMES_DELAY
MapModel framesDelay = defaultedModel(metadataModel, WMS.FRAMES_DELAY, WMS.FRAMES_DELAY_DEFAULT);
TextField<Integer> framesDelayField = new TextField<Integer>("anim.framesdelay", framesDelay, Integer.class);
framesDelayField.add(new RangeValidator<Integer>(0, Integer.MAX_VALUE));
form.add(framesDelayField);
// LOOP_CONTINUOUSLY
MapModel loopContinuously = defaultedModel(metadataModel, WMS.LOOP_CONTINUOUSLY, WMS.LOOP_CONTINUOUSLY_DEFAULT);
CheckBox loopContinuouslyField = new CheckBox("anim.loopcontinuously", loopContinuously);
form.add(loopContinuouslyField);
// kml handling
MapModel kmlReflectorMode = defaultedModel(metadataModel, WMS.KML_REFLECTOR_MODE, WMS.KML_REFLECTOR_MODE_DEFAULT);
form.add(new DropDownChoice("kml.defaultReflectorMode", kmlReflectorMode, KML_REFLECTOR_MODES));
MapModel kmlSuperoverlayMode = defaultedModel(metadataModel, WMS.KML_SUPEROVERLAY_MODE, WMS.KML_SUPEROVERLAY_MODE_DEFAULT);
form.add(new DropDownChoice("kml.superoverlayMode", kmlSuperoverlayMode, KML_SUPEROVERLAY_MODES));
form.add(new CheckBox("kml.kmattr", defaultedModel(metadataModel, WMS.KML_KMLATTR, WMS.KML_KMLATTR_DEFAULT)));
form.add(new CheckBox("kml.kmlplacemark", defaultedModel(metadataModel, WMS.KML_KMLPLACEMARK, WMS.KML_KMLPLACEMARK_DEFAULT)));
MapModel kmScore = defaultedModel(metadataModel, WMS.KML_KMSCORE, WMS.KML_KMSCORE_DEFAULT);
TextField<Integer> kmScoreField = new TextField<Integer>("kml.kmscore", kmScore, Integer.class);
kmScoreField.add(new RangeValidator<Integer>(0, 100));
form.add(kmScoreField);
//scalehint
form.add(new CheckBox("scalehint.mapunitsPixel",defaultedModel(metadataModel, WMS.SCALEHINT_MAPUNITS_PIXEL, WMS.SCALEHINT_MAPUNITS_PIXEL_DEFAULT)));
// mime types for GetMap
getMapAvailable = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (GetMapOutputFormat format : GeoServerExtensions.extensions(GetMapOutputFormat.class)) {
getMapAvailable.add(format.getMimeType());
}
List<String> getMapSelected = new ArrayList<String>();
getMapSelected.addAll(new PropertyModel<Set<String>>(info, "getMapMimeTypes").getObject());
List<String> getMapChoices = new ArrayList<String>();
getMapChoices.addAll(getMapAvailable);
form.add(getMapMimeTypesComponent= new MimeTypesFormComponent("getMapMimeTypes",
new ListModel<String>(getMapSelected),new CollectionModel<String>(getMapChoices),
new PropertyModel<Boolean>(info, "getMapMimeTypeCheckingEnabled").getObject()));
// mime types for GetFeatueInfo
getFeatureInfoAvailable = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (GetFeatureInfoOutputFormat format : GeoServerExtensions.extensions(GetFeatureInfoOutputFormat.class)) {
getFeatureInfoAvailable.add(format.getContentType());
}
List<String> getFeatureInfoSelected = new ArrayList<String>();
getFeatureInfoSelected.addAll(new PropertyModel<Set<String>>(info, "getFeatureInfoMimeTypes").getObject());
List<String> getFeatureInfoChoices = new ArrayList<String>();
getFeatureInfoChoices.addAll(getFeatureInfoAvailable);
form.add(getFeatureInfoMimeTypesComponent =new MimeTypesFormComponent("getFeatureInfoMimeTypes",
new ListModel<String>(getFeatureInfoSelected),new CollectionModel<String>(getFeatureInfoChoices),
new PropertyModel<Boolean>(info, "getFeatureInfoMimeTypeCheckingEnabled").getObject()));
}
@Override
protected void handleSubmit(WMSInfo info) {
info.setGetMapMimeTypeCheckingEnabled(getMapMimeTypesComponent.isMimeTypeCheckingEnabled());
if (info.isGetMapMimeTypeCheckingEnabled())
info.getGetMapMimeTypes().addAll(getMapMimeTypesComponent.getPalette().getModelCollection());
else
info.getGetMapMimeTypes().clear();
info.setGetFeatureInfoMimeTypeCheckingEnabled(getFeatureInfoMimeTypesComponent.isMimeTypeCheckingEnabled());
if (info.isGetFeatureInfoMimeTypeCheckingEnabled())
info.getGetFeatureInfoMimeTypes().addAll(getFeatureInfoMimeTypesComponent.getPalette().getModelCollection());
else
info.getGetFeatureInfoMimeTypes().clear();
super.handleSubmit(info);
}
protected Component chooserButton(String linkId, final String windowTitle, final TextField<String> textField) {
AjaxSubmitLink link = new AjaxSubmitLink(linkId) {
@Override
public boolean getDefaultFormProcessing() {
return false;
}
@Override
public void onSubmit(AjaxRequestTarget target, Form form) {
File file = null;
textField.processInput();
String input = (String) textField.getConvertedInput();
if (input != null && !input.equals("")) {
file = new File(input);
}
GeoServerFileChooser chooser = new GeoServerFileChooser(modal.getContentId(), new Model(file)) {
protected void fileClicked(File file, AjaxRequestTarget target) {
// clear the raw input of the field won't show the new model value
textField.clearInput();
textField.setModelObject(file.getAbsolutePath());
target.addComponent(textField);
dialog.close(target);
};
};
chooser.setFileTableHeight(null);
modal.setContent(chooser);
modal.setTitle(windowTitle);
modal.show(target);
}
};
return link;
}
MapModel defaultedModel(IModel baseModel, String key, Object defaultValue) {
MapModel model = new MapModel(baseModel, key);
if(model.getObject() == null)
model.setObject(defaultValue);
return model;
}
protected String getServiceName(){
return "WMS";
}
private class WatermarkPositionRenderer implements IChoiceRenderer {
public Object getDisplayValue(Object object) {
return new StringResourceModel(((Position) object).name(), WMSAdminPage.this, null).getString();
}
public String getIdValue(Object object, int index) {
return ((Position) object).name();
}
}
private class InterpolationRenderer implements IChoiceRenderer {
public Object getDisplayValue(Object object) {
return new StringResourceModel(((WMSInterpolation) object).name(), WMSAdminPage.this, null).getString();
}
public String getIdValue(Object object, int index) {
return ((WMSInterpolation) object).name();
}
}
private class SVGMethodRenderer implements IChoiceRenderer {
public Object getDisplayValue(Object object) {
return new StringResourceModel("svg." + object, WMSAdminPage.this, null).getString();
}
public String getIdValue(Object object, int index) {
return (String) object;
}
}
}