/* (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.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import net.opengis.wfs20.ParameterExpressionType; import net.opengis.wfs20.StoredQueryListItemType; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.markup.html.form.ChoiceRenderer; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.validation.IValidatable; import org.apache.wicket.validation.IValidationError; import org.apache.wicket.validation.IValidator; import org.apache.wicket.validation.ValidationError; import org.geoserver.catalog.CatalogBuilder; import org.geoserver.catalog.DataStoreInfo; import org.geoserver.catalog.FeatureTypeInfo; import org.geoserver.catalog.LayerInfo; import org.geoserver.web.data.resource.ResourceConfigurationPage; import org.geoserver.web.wicket.ParamResourceModel; import org.geotools.data.DataAccess; import org.geotools.data.wfs.WFSDataStore; import org.geotools.data.wfs.internal.v2_0.storedquery.StoredQueryConfiguration; import org.geotools.util.logging.Logging; import org.opengis.feature.type.Name; public class CascadedWFSStoredQueryNewPage extends CascadedWFSStoredQueryAbstractPage { /** serialVersionUID */ private static final long serialVersionUID = 5430480206314316146L; static final Logger LOGGER = Logging.getLogger(CascadedWFSStoredQueryNewPage.class); DropDownChoice<StoredQuery> storedQueriesDropDown; private String nativeName; public CascadedWFSStoredQueryNewPage(PageParameters params) throws IOException { super(params); } @Override protected Component getStoredQueryNameComponent() { Fragment f = new Fragment("storedQueryName", "newPage", this); storedQueriesDropDown = storedQueriesDropDown(); f.add(storedQueriesDropDown); TextField<String> textField = new TextField<>("nativeName", new PropertyModel<>(this, "nativeName")); textField.setRequired(true); textField.add(new ViewNameValidator()); f.add(textField); return f; } public void setNativeName(String nativeName) { this.nativeName = nativeName; } public String getNativeName() { return nativeName; } @Override public void populateStoredQueryParameterAttribute(String storedQueryId, ParameterExpressionType pet, StoredQueryParameterAttribute attr) { // We're creating a new layer, all parameters are empty by default attr.setMappingType(ParameterMappingType.NONE); attr.setValue(null); } @Override protected void onSave() { // TODO: check stuff before saving StoredQuery selection = (StoredQuery)storedQueriesDropDown.getDefaultModelObject(); StoredQueryConfiguration config = createStoredQueryConfiguration(parameterProvider.getItems(), selection.storedQueryId); try { DataStoreInfo dsInfo = getCatalog().getStore(storeId, DataStoreInfo.class); WFSDataStore directDs = getContentDataStore(); DataAccess<?,?> da = dsInfo.getDataStore(null); Name typeName = directDs.addStoredQuery(getNativeName(), config.getStoredQueryId()); CatalogBuilder builder = new CatalogBuilder(getCatalog()); builder.setStore(dsInfo); FeatureTypeInfo fti = builder.buildFeatureType(da.getFeatureSource(typeName)); fti.getMetadata().put(FeatureTypeInfo.STORED_QUERY_CONFIGURATION, config); LayerInfo layerInfo = builder.buildLayer(fti); setResponsePage(new ResourceConfigurationPage(layerInfo, true)); } catch(Exception e) { LOGGER.log(Level.SEVERE, "Failed to create feature type", e); error(new ParamResourceModel("creationFailure", this, e.getMessage()) .getString()); } } @Override protected void onCancel() { doReturn(LayerPage.class); } private DropDownChoice<StoredQuery> storedQueriesDropDown() { final DropDownChoice<StoredQuery> dropdown = new DropDownChoice<>("storedQueriesDropDown", new Model<>(), new StoredQueryListModel(), new StoredQueryListRenderer()); dropdown.setRequired(true); dropdown.add(new AjaxFormComponentUpdatingBehavior("change") { /** serialVersionUID */ private static final long serialVersionUID = -7195159596309736905L; @Override protected void onUpdate(AjaxRequestTarget target) { StoredQuery selection = (StoredQuery)dropdown.getDefaultModelObject(); parameterProvider.refreshItems(selection.storedQueryId); target.add(parameters); } }); return dropdown; } private class StoredQueryListModel extends LoadableDetachableModel<List<StoredQuery>> { /** serialVersionUID */ private static final long serialVersionUID = 2434460260811775002L; @Override protected List<StoredQuery> load() { List<StoredQuery> ret = new ArrayList<StoredQuery>(); for (StoredQueryListItemType sqlit : listStoredQueries()) { StoredQuery item = new StoredQuery(); item.setStoredQueryId(sqlit.getId()); item.setTitle(createStoredQueryTitle(sqlit)); ret.add(item); } return ret; } } private class StoredQueryListRenderer extends ChoiceRenderer<StoredQuery> { /** serialVersionUID */ private static final long serialVersionUID = 7539702994237874704L; @Override public Object getDisplayValue(StoredQuery object) { return object.getTitle(); } @Override public String getIdValue(StoredQuery object, int index) { return object.getStoredQueryId(); } } public static class StoredQuery implements Serializable { private static final long serialVersionUID = 1L; private String title; private String storedQueryId; public void setStoredQueryId(String storedQueryId) { this.storedQueryId = storedQueryId; } public String getStoredQueryId() { return storedQueryId; } public void setTitle(String title) { this.title = title; } public String getTitle() { return title; } } class ViewNameValidator implements IValidator<String> { /** serialVersionUID */ private static final long serialVersionUID = 8023559657640603820L; @Override public void validate(IValidatable<String> validatable) { String csqName = (String) validatable.getValue(); final DataStoreInfo store = getCatalog().getStore(storeId, DataStoreInfo.class); List<FeatureTypeInfo> ftis = getCatalog().getResourcesByStore(store, FeatureTypeInfo.class); for (FeatureTypeInfo curr : ftis) { StoredQueryConfiguration config = curr.getMetadata().get(FeatureTypeInfo.STORED_QUERY_CONFIGURATION, StoredQueryConfiguration.class); if(config != null) { if(curr.getNativeName().equals(csqName)) { Map<String, Object> map = new HashMap<>(); map.put("name", csqName); map.put("dataStore", store.getName()); IValidationError err = new ValidationError("duplicateSqlViewName") .addKey("duplicateSqlViewName").setVariables(map); validatable.error(err); return; } } } } } }