/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.web.data.layer;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import net.opengis.wfs20.ParameterExpressionType;
import net.opengis.wfs20.StoredQueryDescriptionType;
import net.opengis.wfs20.StoredQueryListItemType;
import net.opengis.wfs20.TitleType;
import org.apache.wicket.Component;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.SubmitLink;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.web.GeoServerSecuredPage;
import org.geoserver.web.wicket.GeoServerDataProvider;
import org.geoserver.web.wicket.GeoServerDataProvider.BeanProperty;
import org.geoserver.web.wicket.GeoServerDataProvider.Property;
import org.geoserver.web.wicket.GeoServerTablePanel;
import org.geotools.data.DataAccess;
import org.geotools.data.wfs.WFSDataStore;
import org.geotools.data.wfs.internal.v2_0.storedquery.ParameterMapping;
import org.geotools.data.wfs.internal.v2_0.storedquery.ParameterMappingBlockValue;
import org.geotools.data.wfs.internal.v2_0.storedquery.ParameterMappingDefaultValue;
import org.geotools.data.wfs.internal.v2_0.storedquery.ParameterMappingExpressionValue;
import org.geotools.data.wfs.internal.v2_0.storedquery.StoredQueryConfiguration;
import org.geotools.util.logging.Logging;
/**
* Page that controls the configuration for a single feature type based on a cascaded WFS Stored Query.
*/
public abstract class CascadedWFSStoredQueryAbstractPage extends GeoServerSecuredPage {
/** serialVersionUID */
private static final long serialVersionUID = 3805287974674434336L;
static final Logger LOGGER = Logging.getLogger(CascadedWFSStoredQueryAbstractPage.class);
public static final String DATASTORE = "storeName";
public static final String WORKSPACE = "wsName";
String storeId;
GeoServerTablePanel<StoredQueryParameterAttribute> parameters;
StoredQueryParameterAttributeProvider parameterProvider;
public CascadedWFSStoredQueryAbstractPage(PageParameters params) throws IOException {
this(params.get(WORKSPACE).toOptionalString(), params.get(DATASTORE).toString(), null);
}
public CascadedWFSStoredQueryAbstractPage(String workspaceName, String storeName, String typeName)
throws IOException {
storeId = getCatalog().getStoreByName(workspaceName, storeName, DataStoreInfo.class)
.getId();
Form<CascadedWFSStoredQueryAbstractPage> form = new Form<>("form", new CompoundPropertyModel<>(this));
form.add(getStoredQueryNameComponent());
parameterProvider = new StoredQueryParameterAttributeProvider();
parameters = new GeoServerTablePanel<StoredQueryParameterAttribute>("parameters", parameterProvider) {
/** serialVersionUID */
private static final long serialVersionUID = 8282438267732625198L;
@Override
protected Component getComponentForProperty(String id,
final IModel<StoredQueryParameterAttribute> itemModel,
Property<StoredQueryParameterAttribute> property) {
if (property == ATTR_MAPTYPE) {
Fragment f = new Fragment(id, "parameterMappingType", CascadedWFSStoredQueryAbstractPage.this);
ArrayList<ParameterMappingType> choices = new ArrayList<ParameterMappingType>();
for (ParameterMappingType pmt : ParameterMappingType.values()) {
choices.add(pmt);
}
DropDownChoice<ParameterMappingType> choice =
new DropDownChoice<>("dropdown",
new PropertyModel<>(itemModel, "mappingType"),
choices,
new ParameterMappingTypeRenderer());
f.add(choice);
return f;
} else
if (property == ATTR_VALUE) {
Fragment f = new Fragment(id, "parameterMappingValue", CascadedWFSStoredQueryAbstractPage.this);
TextField<String> textField = new TextField<>("text", new PropertyModel<>(itemModel, "value"));
f.add(textField);
return f;
}
return null;
}
};
// just a plain table, no filters, no paging
parameters.setFilterVisible(false);
parameters.setSortable(false);
parameters.setPageable(false);
parameters.setOutputMarkupId(true);
form.add(parameters);
add(form);
// save and cancel at the bottom of the page
form.add(new SubmitLink("save") {
/** serialVersionUID */
private static final long serialVersionUID = 2540349398885832870L;
@Override
public void onSubmit() {
onSave();
}
});
form.add(new Link<Void>("cancel") {
/** serialVersionUID */
private static final long serialVersionUID = 451678049485016709L;
@Override
public void onClick() {
onCancel();
}
});
}
static StoredQueryConfiguration createStoredQueryConfiguration(
List<StoredQueryParameterAttribute> items, String storedQueryId) {
StoredQueryConfiguration ret = new StoredQueryConfiguration();
ret.setStoredQueryId(storedQueryId);
for (StoredQueryParameterAttribute i : items) {
ParameterMapping mapping;
String name = i.getParameterName();
switch (i.getMappingType()) {
case BLOCKED:
mapping = new ParameterMappingBlockValue(name);
break;
case DEFAULT:
mapping = new ParameterMappingDefaultValue(name, false, i.getValue());
break;
case STATIC:
mapping = new ParameterMappingDefaultValue(name, true, i.getValue());
break;
case EXPRESSION_CQL:
mapping = new ParameterMappingExpressionValue(name, "CQL", i.getValue());
break;
case NONE:
default:
mapping = null;
}
if (mapping != null) {
ret.getStoredQueryParameterMappings().add(mapping);
}
}
return ret;
}
protected List<StoredQueryListItemType> listStoredQueries() {
try {
WFSDataStore contentStore = getContentDataStore();
return contentStore.getStoredQueryListResponse().getStoredQuery();
} catch(IOException ie) {
throw new RuntimeException("Uanble to list stored queries", ie);
}
}
protected WFSDataStore getContentDataStore() throws IOException {
DataStoreInfo store = getCatalog().getStore(storeId, DataStoreInfo.class);
DataAccess<?,?> da = store.getDataStore(null);
return (WFSDataStore)da;
}
public static String createStoredQueryTitle(StoredQueryListItemType object) {
StringBuilder ret = new StringBuilder();
TitleType title = null;
for (TitleType t : object.getTitle()) {
if (title == null) {
title = t;
} else if (title.getValue() == null || title.getValue().length() == 0) {
title = t;
}
}
if (title != null) {
ret.append(title.getValue()).append(" (").append(object.getId()).append(")");
} else {
ret.append(object.getId());
}
return ret.toString();
}
/**
* Attribute model for how a single stored query parameter is supposed to be handled.
*/
public class StoredQueryParameterAttribute implements Serializable {
/** serialVersionUID */
private static final long serialVersionUID = -9213562985695412130L;
private String parameterName;
private String title;
private QName type;
private ParameterMappingType mappingType;
private String value;
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setType(QName type) {
this.type = type;
}
public QName getType() {
return type;
}
public void setMappingType(ParameterMappingType mappingType)
{
this.mappingType = mappingType;
}
public ParameterMappingType getMappingType()
{
return mappingType;
}
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setParameterName(String parameterName) {
this.parameterName = parameterName;
}
public String getParameterName() {
return parameterName;
}
@Override
public int hashCode() {
final int prime = 37;
int result = 1;
result = prime * result + ((parameterName == null) ? 0 : parameterName.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((mappingType == null) ? 0 : mappingType.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
private boolean nullSafeCompare(Object a, Object b) {
if (a == null && b == null) {
return true;
}
if (a == null && b != null) {
return false;
}
return a.equals(b);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StoredQueryParameterAttribute other = (StoredQueryParameterAttribute) obj;
if (!nullSafeCompare(this.parameterName, other.parameterName)) {
return false;
}
if (!nullSafeCompare(this.title, other.title)) {
return false;
}
if (!nullSafeCompare(this.type, other.type)) {
return false;
}
if (!nullSafeCompare(this.mappingType, other.mappingType)) {
return false;
}
if (!nullSafeCompare(this.value, other.value)) {
return false;
}
return true;
}
@Override
public String toString() {
StringBuilder ret = new StringBuilder();
ret.append(getParameterName()).append(": ")
.append("title=").append(title).append(", ")
.append("type=").append(type).append(", ")
.append("mappingType=").append(mappingType).append(", ")
.append("value=").append(value);
return ret.toString();
}
}
public StoredQueryParameterAttribute createStoredQueryParameterAttribute(
String storedQueryId, ParameterExpressionType pet) {
StoredQueryParameterAttribute ret = new StoredQueryParameterAttribute();
ret.setParameterName(pet.getName());
ret.setType(pet.getType());
StringBuilder title = new StringBuilder();
for (TitleType t : pet.getTitle()) {
if (t.getValue() != null && t.getValue().length() > 0) {
title.append(t.getValue());
break;
}
}
ret.setTitle(title.toString());
populateStoredQueryParameterAttribute(storedQueryId, pet, ret);
return ret;
}
public abstract void populateStoredQueryParameterAttribute(String storedQueryId,
ParameterExpressionType pet, StoredQueryParameterAttribute attr);
public static Property<StoredQueryParameterAttribute> ATTR_NAME = new BeanProperty<StoredQueryParameterAttribute>("parameterName", "parameterName");
public static Property<StoredQueryParameterAttribute> ATTR_TITLE = new BeanProperty<StoredQueryParameterAttribute>("title", "title");
public static Property<StoredQueryParameterAttribute> ATTR_TYPE = new BeanProperty<StoredQueryParameterAttribute>("type", "type");
public static Property<StoredQueryParameterAttribute> ATTR_MAPTYPE = new BeanProperty<StoredQueryParameterAttribute>("mappingType", "mappingType");
public static Property<StoredQueryParameterAttribute> ATTR_VALUE = new BeanProperty<StoredQueryParameterAttribute>("value", "value");
public enum ParameterMappingType {
NONE,
STATIC,
DEFAULT,
EXPRESSION_CQL,
BLOCKED
}
public class ParameterMappingTypeRenderer extends ChoiceRenderer<ParameterMappingType> {
/** serialVersionUID */
private static final long serialVersionUID = 1875427995762137069L;
@Override
public Object getDisplayValue(ParameterMappingType object) {
return new StringResourceModel("ParameterMappingType."+object.toString(), CascadedWFSStoredQueryAbstractPage.this, null).getString();
}
@Override
public String getIdValue(ParameterMappingType object, int index) {
return object.toString();
}
}
public class StoredQueryParameterAttributeProvider extends GeoServerDataProvider<StoredQueryParameterAttribute> {
/** serialVersionUID */
private static final long serialVersionUID = 5295091510256421604L;
private List<StoredQueryParameterAttribute> items = new ArrayList<StoredQueryParameterAttribute>();
public void refreshItems(String storedQueryId) {
items.clear();
if (storedQueryId != null) {
StoredQueryDescriptionType desc;
try {
WFSDataStore contentStore = getContentDataStore();
desc = contentStore.getStoredQueryDescriptionType(storedQueryId);
} catch(IOException ie) {
throw new RuntimeException("Unable to describe stored query", ie);
}
for (ParameterExpressionType pet : desc.getParameter()) {
items.add(createStoredQueryParameterAttribute(storedQueryId, pet));
}
}
}
@Override
protected List<StoredQueryParameterAttribute> getItems() {
return items;
}
@Override
protected List<Property<StoredQueryParameterAttribute>> getProperties() {
return Arrays.asList(ATTR_NAME, ATTR_TITLE, ATTR_TYPE, ATTR_MAPTYPE, ATTR_VALUE);
}
}
protected abstract Component getStoredQueryNameComponent();
protected abstract void onSave();
protected abstract void onCancel();
}