/* (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.layer;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.geoserver.catalog.CatalogBuilder;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StoreInfo;
import org.geoserver.catalog.WMSStoreInfo;
import org.geoserver.platform.GeoServerEnvironment;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.web.wicket.GeoServerDataProvider;
import org.geotools.data.ows.Layer;
import org.geotools.feature.NameImpl;
import org.opengis.coverage.grid.GridCoverageReader;
import org.opengis.feature.type.Name;
/**
* Provides a list of resources for a specific data store
* @author Andrea Aime - OpenGeo
*
*/
@SuppressWarnings("serial")
public class NewLayerPageProvider extends GeoServerDataProvider<Resource> {
public static final Property<Resource> PUBLISHED = new BeanProperty<Resource>("published", "published");
public static final Property<Resource> NAME = new BeanProperty<Resource>("name", "localName");
public static final Property<Resource> ACTION = new PropertyPlaceholder<Resource>("action");
public static final List<Property<Resource>> PROPERTIES = Arrays.asList(PUBLISHED, NAME, ACTION);
boolean showPublished;
String storeId;
transient List<Resource> cachedItems;
@Override
protected List<Resource> getItems() {
// return an empty list in case we still don't know about the store
if(storeId == null) {
return new ArrayList<Resource>();
} else if(cachedItems == null) {
cachedItems = getItemsInternal();
}
return cachedItems;
}
private List<Resource> getItemsInternal() {
// else, grab the resource list
try {
List<Resource> result;
StoreInfo store = getCatalog().getStore(storeId, StoreInfo.class);
Map<String, Resource> resources = new HashMap<String, Resource>();
if(store instanceof DataStoreInfo) {
DataStoreInfo dstore = (DataStoreInfo) store;
DataStoreInfo expandedStore = getCatalog().getResourcePool().clone(dstore, true);
// collect all the type names and turn them into resources
// for the moment we use local names as datastores are not returning
// namespace qualified NameImpl
List<Name> names = expandedStore.getDataStore(null).getNames();
for (Name name : names) {
FeatureTypeInfo fti = getCatalog().getFeatureTypeByDataStore(expandedStore, name.getLocalPart());
// skip views, we cannot have two layers use the same feature type info, as the
// underlying definition is attached to the feature type info itself
if(fti == null || fti.getMetadata().get(FeatureTypeInfo.JDBC_VIRTUAL_TABLE) == null) {
resources.put(name.getLocalPart(), new Resource(name));
}
}
} else if(store instanceof CoverageStoreInfo) {
CoverageStoreInfo cstore = (CoverageStoreInfo) store;
CoverageStoreInfo expandedStore = getCatalog().getResourcePool().clone(cstore, true);
NamespaceInfo ns = getCatalog().getNamespaceByPrefix(expandedStore.getWorkspace().getName());
GridCoverageReader reader = expandedStore.getGridCoverageReader(null, null);
try {
String[] names = reader.getGridCoverageNames();
for (String name : names) {
Name qualified = new NameImpl(ns.getURI(), name);
Resource resource = new Resource(qualified);
resource.setMultiCoverageReader(true);
resources.put(name, resource);
}
} catch(UnsupportedOperationException e) {
// old code, pre multi-coverage
// getting to the coverage name without reading the whole coverage seems to
// be hard stuff, let's have the catalog builder to the heavy lifting
CatalogBuilder builder = new CatalogBuilder(getCatalog());
builder.setStore(store);
CoverageInfo ci = builder.buildCoverage();
Name name = ci.getQualifiedName();
resources.put(name.getLocalPart(), new Resource(name));
}
} else if(store instanceof WMSStoreInfo) {
WMSStoreInfo wmsInfo = (WMSStoreInfo) store;
WMSStoreInfo expandedStore = getCatalog().getResourcePool().clone(wmsInfo, true);
CatalogBuilder builder = new CatalogBuilder(getCatalog());
builder.setStore(store);
List<Layer> layers = expandedStore.getWebMapServer(null).getCapabilities().getLayerList();
for(Layer l : layers) {
if(l.getName() == null) {
continue;
}
resources.put(l.getName(), new Resource(new NameImpl(l.getName())));
}
}
// lookup all configured layers, mark them as published in the resources
List<ResourceInfo> configuredTypes = getCatalog().getResourcesByStore(store, ResourceInfo.class);
for (ResourceInfo type : configuredTypes) {
// compare with native name, which is what the DataStore provides through getNames()
// above
Resource resource;
if(type instanceof CoverageInfo) {
CoverageInfo ci = (CoverageInfo) type;
if(ci.getNativeCoverageName() != null) {
resource = resources.get(ci.getNativeCoverageName());
} else {
resource = resources.get(type.getNativeName());
}
} else {
resource = resources.get(type.getNativeName());
}
if(resource != null) {
resource.setPublished(true);
}
}
result = new ArrayList<Resource>(resources.values());
// return by natural order
Collections.sort(result);
return result;
} catch(Exception e) {
throw new RuntimeException("Could not list layers for this store, "
+ "an error occurred retrieving them: " + e.getMessage(), e);
}
}
public String getStoreId() {
return storeId;
}
public void setStoreId(String storeId) {
this.cachedItems = null;
this.storeId = storeId;
}
@Override
protected List<Resource> getFilteredItems() {
List<Resource> resources = super.getFilteredItems();
if(showPublished)
return resources;
List<Resource> unconfigured = new ArrayList<Resource>();
for (Resource resource : resources) {
if(!resource.isPublished())
unconfigured.add(resource);
}
return unconfigured;
}
@Override
protected List<Property<Resource>> getProperties() {
return PROPERTIES;
}
public void setShowPublished(boolean showPublished) {
this.showPublished = showPublished;
}
}