/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.web.data.importer; import java.io.IOException; import java.util.List; import java.util.logging.Level; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.image.Image; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.repeater.DefaultItemReuseStrategy; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.request.resource.PackageResourceReference; import org.geoserver.catalog.Catalog; import org.geoserver.catalog.CatalogBuilder; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.StoreInfo; import org.geoserver.catalog.WMSLayerInfo; import org.geoserver.catalog.WMSStoreInfo; import org.geoserver.web.CatalogIconFactory; import org.geoserver.web.GeoServerBasePage; import org.geoserver.web.GeoServerSecuredPage; import org.geoserver.web.data.importer.LayerResource.LayerStatus; import org.geoserver.web.data.resource.ResourceConfigurationPage; import org.geoserver.web.wicket.GeoServerDataProvider.Property; import org.geoserver.web.wicket.GeoServerTablePanel; import org.geoserver.web.wicket.ParamResourceModel; import org.geoserver.web.wicket.SimpleAjaxLink; public class WMSLayerImporterPage extends GeoServerSecuredPage { private static final long serialVersionUID = -3413451886777414860L; String storeId; private GeoServerTablePanel<LayerResource> layers; private WMSLayerProvider provider; int importCount; int errorCount; int updateCount; private Form<WMSLayerImporterPage> form; public WMSLayerImporterPage(PageParameters params) { storeId = params.get("storeId").toString(); WMSStoreInfo store = getCatalog().getStore(storeId, WMSStoreInfo.class); // check if we have anything to import provider = new WMSLayerProvider(); provider.setStoreId(storeId); if (provider.size() <= 0) { error(new ParamResourceModel("storeEmpty", this, store.getName(), store.getWorkspace().getName()).getString()); } // build the GUI form = new Form<WMSLayerImporterPage>("form", new CompoundPropertyModel<WMSLayerImporterPage>(this)); form.setOutputMarkupId(true); add(form); layers = new GeoServerTablePanel<LayerResource>("layerChooser", provider, true) { private static final long serialVersionUID = -5817898784100419973L; @Override protected Component getComponentForProperty(String id, IModel<LayerResource> itemModel, Property<LayerResource> property) { if (property == WMSLayerProvider.NAME) { return new Label(id, property.getModel(itemModel)); } else if(property == WMSLayerProvider.STATUS) { Fragment f = new Fragment(id, "labelIcon", WMSLayerImporterPage.this); f.add(new Image("icon", new IconModel(itemModel))); f.add(new Label("label", new StatusModel(itemModel))); return f; } else if(property == WMSLayerProvider.ACTION) { final LayerResource resource = (LayerResource) itemModel.getObject(); final LayerStatus status = resource.getStatus(); if(status == LayerStatus.PUBLISHED || status == LayerStatus.NEWLY_PUBLISHED || status == LayerStatus.UPDATED) { return resourceChooserLink(id, itemModel, new ParamResourceModel("NewLayerPage.publishAgain", this)); } else { return resourceChooserLink(id, itemModel, new ParamResourceModel("NewLayerPage.publish", this)); } } return null; } }; layers.setItemReuseStrategy(DefaultItemReuseStrategy.getInstance()); layers.setFilterable(true); form.add(layers); AjaxSubmitLink submitLink = submitLink(); form.add(submitLink); form.add(importAllLink()); } SimpleAjaxLink<LayerResource> resourceChooserLink(String id, IModel<LayerResource> itemModel, IModel<?> label) { return new SimpleAjaxLink<LayerResource>(id, itemModel, label) { private static final long serialVersionUID = 163167608296661157L; @Override protected void onClick(AjaxRequestTarget target) { LayerResource resource = (LayerResource) getDefaultModelObject(); setResponsePage(new ResourceConfigurationPage( buildLayerInfo(resource), true)); } }; } LayerInfo buildLayerInfo(LayerResource resource) { Catalog catalog = getCatalog(); StoreInfo store = catalog.getStore(storeId, StoreInfo.class); try { CatalogBuilder builder = new CatalogBuilder(catalog); builder.setStore(store); WMSLayerInfo wli = builder.buildWMSLayer(resource.getLocalName()); return builder.buildLayer(wli); } catch (Exception e) { throw new RuntimeException( "Error occurred while building the resources for the configuration page", e); } } AjaxSubmitLink submitLink() { return new AjaxSubmitLink("import") { private static final long serialVersionUID = -7161320029912723242L; @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { try { // grab the selection List<LayerResource> selection = layers.getSelection(); // if nothing was selected we need to go back if (selection.size() == 0) { error(new ParamResourceModel("selectionEmpty", WMSLayerImporterPage.this) .getString()); } else { publishLayers(selection); } } catch (Exception e) { LOGGER.log(Level.SEVERE, "Error while setting up mass import", e); } target.add(form); target.add(feedbackPanel); } }; } void publishLayers(List<LayerResource> selection) { Catalog catalog = getCatalog(); CatalogBuilder builder = new CatalogBuilder(catalog); WMSStoreInfo store = getCatalog().getStore(storeId, WMSStoreInfo.class); builder.setStore(store); importCount = 0; errorCount = 0; updateCount = 0; for (LayerResource resource : selection) { publishLayer(resource, builder, store, catalog); } createImportReport(); layers.reset(); provider.updateLayerOrder(); } AjaxSubmitLink importAllLink() { return new AjaxSubmitLink("importAll") { private static final long serialVersionUID = 7089389540839181808L; @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { try { publishLayers(provider.getItems()); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Error while setting up mass import", e); } target.add(form); target.add(feedbackPanel); } }; } private void publishLayer(LayerResource layer, CatalogBuilder builder, WMSStoreInfo store, Catalog catalog) { WMSLayerInfo wli; LayerInfo li; try { wli = builder.buildWMSLayer(layer.getLocalName()); li = builder.buildLayer(wli); } catch (IOException e) { LOGGER.log(Level.WARNING, "Error building WMS cascading layer " + layer.getLocalName(), e); layer.setStatus(LayerStatus.ERROR); layer.setError(e.getMessage()); errorCount++; return; } WMSLayerInfo exists = catalog.getResourceByStore(store, li.getName(), WMSLayerInfo.class); if (exists != null) { // TODO what to do if layer already exists? builder.updateWMSLayer(exists, wli); layer.setStatus(LayerStatus.UPDATED); updateCount++; } else { try { catalog.add(wli); catalog.add(li); layer.setStatus(LayerStatus.NEWLY_PUBLISHED); importCount++; } catch (Exception e) { catalog.remove(wli); LOGGER.log(Level.WARNING, "Error auto configuring WMS cascading layer " + li.getName(), e); layer.setStatus(LayerStatus.ERROR); layer.setError(e.getMessage()); errorCount++; } } } private void createImportReport(){ if (importCount > 0) { info("Succesfully imported " + importCount + " layers"); } else { info("No new layers were imported"); } if (updateCount > 0) { info("Updated " + updateCount + " layers"); } if (errorCount > 0) { error("Unable to import " + errorCount + " layers, you may want to import them manually"); } } final class StatusModel implements IModel<String> { private static final long serialVersionUID = 7754149365712750847L; IModel<LayerResource> layerResource; public StatusModel(IModel<LayerResource> layerResource) { super(); this.layerResource = layerResource; } public String getObject() { LayerResource resource = (LayerResource) layerResource.getObject(); return new ParamResourceModel("WMSLayerImporterPage.status." + resource.getStatus(), WMSLayerImporterPage.this, resource.getError()).getString(); } public void setObject(String object) { throw new UnsupportedOperationException(); } public void detach() { // nothing to do } } final class IconModel implements IModel<PackageResourceReference> { private static final long serialVersionUID = 5762710251083186192L; IModel<LayerResource> layerResource; public IconModel(IModel<LayerResource> layerResource) { this.layerResource = layerResource; } public PackageResourceReference getObject() { LayerResource resource = (LayerResource) layerResource.getObject(); if(resource.getStatus() == LayerStatus.ERROR) { return new PackageResourceReference( GeoServerBasePage.class, "img/icons/silk/error.png"); } else if(resource.getStatus() == LayerStatus.NEW) { return new PackageResourceReference( GeoServerBasePage.class, "img/icons/silk/add.png"); } else if(resource.getStatus() == LayerStatus.NEWLY_PUBLISHED) { return CatalogIconFactory.ENABLED_ICON; } else if(resource.getStatus() == LayerStatus.UPDATED) { return new PackageResourceReference( GeoServerBasePage.class, "img/icons/silk/pencil.png"); } else if(resource.getStatus() == LayerStatus.PUBLISHED) { return CatalogIconFactory.MAP_ICON; } else { return null; } } public void setObject(PackageResourceReference object) { throw new UnsupportedOperationException(); } public void detach() { // nothing to do } } }