/* (c) 2014 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.catalog.impl;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CatalogBuilder;
import org.geoserver.catalog.CatalogException;
import org.geoserver.catalog.CatalogFacade;
import org.geoserver.catalog.CatalogFactory;
import org.geoserver.catalog.CatalogInfo;
import org.geoserver.catalog.CatalogValidator;
import org.geoserver.catalog.CatalogVisitor;
import org.geoserver.catalog.CoverageDimensionInfo;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.KeywordInfo;
import org.geoserver.catalog.LayerGroupHelper;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.MapInfo;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.PublishedInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.ResourcePool;
import org.geoserver.catalog.StoreInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.ValidationResult;
import org.geoserver.catalog.WMSLayerInfo;
import org.geoserver.catalog.WMSStoreInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.catalog.event.CatalogAddEvent;
import org.geoserver.catalog.event.CatalogEvent;
import org.geoserver.catalog.event.CatalogListener;
import org.geoserver.catalog.event.CatalogModifyEvent;
import org.geoserver.catalog.event.CatalogPostModifyEvent;
import org.geoserver.catalog.event.CatalogRemoveEvent;
import org.geoserver.catalog.event.impl.CatalogAddEventImpl;
import org.geoserver.catalog.event.impl.CatalogModifyEventImpl;
import org.geoserver.catalog.event.impl.CatalogPostModifyEventImpl;
import org.geoserver.catalog.event.impl.CatalogRemoveEventImpl;
import org.geoserver.catalog.util.CloseableIterator;
import org.geoserver.ows.util.OwsUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geotools.util.logging.Logging;
import org.opengis.feature.type.Name;
import org.opengis.filter.Filter;
import org.opengis.filter.sort.SortBy;
/**
* A default catalog implementation that is memory based.
*
* @author Justin Deoliveira, The Open Planning Project
*
* TODO: remove synchronized blocks, make setting of default workspace/namespace part
* of dao contract
* TODO: move resolve() to dao
*
*/
public class CatalogImpl implements Catalog {
/**
* logger
*/
private static final Logger LOGGER = Logging.getLogger(CatalogImpl.class);
/**
* data access facade
*/
protected CatalogFacade facade;
/**
* listeners
*/
protected List listeners = new ArrayList();
/**
* resources
*/
protected ResourcePool resourcePool;
protected GeoServerResourceLoader resourceLoader;
/**
* extended validation switch
*/
protected boolean extendedValidation = true;
public CatalogImpl() {
facade = new DefaultCatalogFacade(this);
resourcePool = ResourcePool.create(this);
}
public CatalogFacade getFacade() {
return facade;
}
/**
* Turn on/off extended validation switch.
* <p>
* This is not part of the public api, it is used for testing purposes where we have to
* bootstrap catalog contents.
* </p>
*/
public void setExtendedValidation(boolean extendedValidation) {
this.extendedValidation = extendedValidation;
}
public boolean isExtendedValidation() {
return extendedValidation;
}
public Iterable<CatalogValidator> getValidators() {
return GeoServerExtensions.extensions(CatalogValidator.class);
}
public void setFacade(CatalogFacade facade) {
this.facade = facade;
facade.setCatalog(this);
}
public String getId() {
return "catalog";
}
public CatalogFactory getFactory() {
return new CatalogFactoryImpl( this );
}
// Store methods
public void add(StoreInfo store) {
if ( store.getWorkspace() == null ) {
store.setWorkspace( getDefaultWorkspace() );
}
validate(store, true);
//TODO: remove synchronized block, need transactions
StoreInfo added;
synchronized (facade) {
added = facade.add(resolve(store));
// if there is no default store use this one as the default
if(getDefaultDataStore(store.getWorkspace()) == null && store instanceof DataStoreInfo) {
setDefaultDataStore(store.getWorkspace(), (DataStoreInfo) store);
}
}
added(added);
}
public ValidationResult validate(StoreInfo store, boolean isNew) {
if ( isNull(store.getName()) ) {
throw new IllegalArgumentException( "Store name must not be null");
}
if ( store.getWorkspace() == null ) {
throw new IllegalArgumentException( "Store must be part of a workspace");
}
WorkspaceInfo workspace = store.getWorkspace();
StoreInfo existing = getStoreByName( workspace, store.getName(), StoreInfo.class );
if ( existing != null && (isNew || !existing.getId().equals( store.getId() )) ) {
String msg = "Store '"+ store.getName() +"' already exists in workspace '"+workspace.getName()+"'";
throw new IllegalArgumentException( msg );
}
return postValidate(store, isNew);
}
public void remove(StoreInfo store) {
if ( !getResourcesByStore(store, ResourceInfo.class).isEmpty() ) {
throw new IllegalArgumentException( "Unable to delete non-empty store.");
}
//TODO: remove synchronized block, need transactions
synchronized(facade) {
facade.remove(store);
WorkspaceInfo workspace = store.getWorkspace();
DataStoreInfo defaultStore = getDefaultDataStore(workspace);
if (store.equals(defaultStore) || defaultStore == null) {
//TODO: this will fire multiple events, we want to fire only one
setDefaultDataStore(workspace, null);
// default removed, choose another store to become default if possible
List dstores = getStoresByWorkspace(workspace, DataStoreInfo.class);
if (!dstores.isEmpty()) {
setDefaultDataStore(workspace, (DataStoreInfo) dstores.get(0));
}
}
}
removed(store);
}
public void save(StoreInfo store) {
if ( store.getId() == null ) {
//add it instead of saving
add( store );
return;
}
validate(store, false);
facade.save(store);
}
public <T extends StoreInfo> T detach(T store) {
return detached(store, facade.detach(store));
}
public <T extends StoreInfo> T getStore(String id, Class<T> clazz) {
return facade.getStore(id, clazz);
}
public <T extends StoreInfo> T getStoreByName(String name, Class<T> clazz) {
return getStoreByName((WorkspaceInfo) null, name, clazz);
}
public <T extends StoreInfo> T getStoreByName(WorkspaceInfo workspace,
String name, Class<T> clazz) {
WorkspaceInfo ws = workspace;
if (ws == null) {
ws = getDefaultWorkspace();
}
if(DataStoreInfo.class == clazz && (name == null || name.equals(Catalog.DEFAULT))) {
return (T) getDefaultDataStore(workspace);
}
T store = facade.getStoreByName(ws, name, clazz);
if (store == null && workspace == null) {
store = facade.getStoreByName(CatalogFacade.ANY_WORKSPACE, name, clazz);
}
return store;
}
public <T extends StoreInfo> T getStoreByName(String workspaceName,
String name, Class<T> clazz) {
if (workspaceName == null) {
return getStoreByName((WorkspaceInfo)null, name, clazz);
}
WorkspaceInfo workspace = getWorkspaceByName(workspaceName);
if (workspace != null) {
return getStoreByName(workspace, name, clazz);
}
return null;
}
public <T extends StoreInfo> List<T> getStoresByWorkspace(
String workspaceName, Class<T> clazz) {
WorkspaceInfo workspace = null;
if ( workspaceName != null ) {
workspace = getWorkspaceByName(workspaceName);
if ( workspace == null ) {
return Collections.EMPTY_LIST;
}
}
return getStoresByWorkspace(workspace, clazz);
}
public <T extends StoreInfo> List<T> getStoresByWorkspace(
WorkspaceInfo workspace, Class<T> clazz) {
return facade.getStoresByWorkspace(workspace, clazz);
}
public List getStores(Class clazz) {
return facade.getStores(clazz);
}
public DataStoreInfo getDataStore(String id) {
return (DataStoreInfo) getStore(id, DataStoreInfo.class);
}
public DataStoreInfo getDataStoreByName(String name) {
return (DataStoreInfo) getStoreByName(name,DataStoreInfo.class);
}
public DataStoreInfo getDataStoreByName(String workspaceName, String name) {
return (DataStoreInfo) getStoreByName(workspaceName, name, DataStoreInfo.class);
}
public DataStoreInfo getDataStoreByName(WorkspaceInfo workspace, String name) {
return (DataStoreInfo) getStoreByName(workspace, name, DataStoreInfo.class);
}
public List<DataStoreInfo> getDataStoresByWorkspace(String workspaceName) {
return getStoresByWorkspace( workspaceName, DataStoreInfo.class );
}
public List<DataStoreInfo> getDataStoresByWorkspace(WorkspaceInfo workspace) {
return getStoresByWorkspace( workspace, DataStoreInfo.class );
}
public List getDataStores() {
return getStores(DataStoreInfo.class);
}
public DataStoreInfo getDefaultDataStore(WorkspaceInfo workspace) {
return facade.getDefaultDataStore(workspace);
}
public void setDefaultDataStore(WorkspaceInfo workspace, DataStoreInfo store) {
if (store != null) {
// basic sanity check
if (store.getWorkspace() == null) {
throw new IllegalArgumentException("The store has not been assigned a workspace");
}
if (!store.getWorkspace().equals(workspace)) {
throw new IllegalArgumentException("Trying to mark as default " + "for workspace "
+ workspace.getName() + " a store that " + "is contained in "
+ store.getWorkspace().getName());
}
}
facade.setDefaultDataStore(workspace, store);
}
public CoverageStoreInfo getCoverageStore(String id) {
return (CoverageStoreInfo) getStore(id, CoverageStoreInfo.class);
}
public CoverageStoreInfo getCoverageStoreByName(String name) {
return (CoverageStoreInfo) getStoreByName(name, CoverageStoreInfo.class);
}
public CoverageStoreInfo getCoverageStoreByName(String workspaceName,
String name) {
return getStoreByName(workspaceName,name,CoverageStoreInfo.class);
}
public CoverageStoreInfo getCoverageStoreByName(WorkspaceInfo workspace,
String name) {
return getStoreByName(workspace, name,CoverageStoreInfo.class);
}
public List<CoverageStoreInfo> getCoverageStoresByWorkspace(
String workspaceName) {
return getStoresByWorkspace( workspaceName, CoverageStoreInfo.class );
}
public List<CoverageStoreInfo> getCoverageStoresByWorkspace(
WorkspaceInfo workspace) {
return getStoresByWorkspace( workspace, CoverageStoreInfo.class );
}
public List getCoverageStores() {
return getStores(CoverageStoreInfo.class);
}
// Resource methods
public void add(ResourceInfo resource) {
if ( resource.getNamespace() == null ) {
//default to default namespace
resource.setNamespace( getDefaultNamespace() );
}
if ( resource.getNativeName() == null ) {
resource.setNativeName(resource.getName());
}
ResourceInfo resolved = resolve(resource);
validate(resolved,true);
ResourceInfo added = facade.add(resolved);
added(added);
}
public ValidationResult validate(ResourceInfo resource, boolean isNew) {
if ( isNull(resource.getName()) ) {
throw new NullPointerException( "Resource name must not be null");
}
if ( isNull(resource.getNativeName()) && !(resource instanceof CoverageInfo && ((CoverageInfo)resource).getNativeCoverageName() != null)) {
throw new NullPointerException( "Resource native name must not be null");
}
if ( resource.getStore() == null ) {
throw new IllegalArgumentException( "Resource must be part of a store");
}
if ( resource.getNamespace() == null ) {
throw new IllegalArgumentException( "Resource must be part of a namespace");
}
StoreInfo store = resource.getStore();
ResourceInfo existing = getResourceByStore( store, resource.getName(), ResourceInfo.class);
if ( existing != null && !existing.getId().equals( resource.getId() ) ) {
String msg = "Resource named '"+resource.getName()+"' already exists in store: '"+ store.getName()+"'";
throw new IllegalArgumentException( msg );
}
NamespaceInfo namespace = resource.getNamespace();
existing = getResourceByName( namespace, resource.getName(), ResourceInfo.class);
if ( existing != null && !existing.getId().equals( resource.getId() ) ) {
String msg = "Resource named '"+resource.getName()+"' already exists in namespace: '"+ namespace.getPrefix()+"'";
throw new IllegalArgumentException( msg );
}
validateKeywords(resource.getKeywords());
return postValidate(resource, isNew);
}
public void remove(ResourceInfo resource) {
//ensure no references to the resource
if ( !getLayers( resource ).isEmpty() ) {
throw new IllegalArgumentException( "Unable to delete resource referenced by layer");
}
facade.remove(resource);
removed(resource);
}
public void save(ResourceInfo resource) {
validate(resource,false);
facade.save(resource);
}
public <T extends ResourceInfo> T detach(T resource) {
return detached(resource, facade.detach(resource));
}
public <T extends ResourceInfo> T getResource(String id, Class<T> clazz) {
return facade.getResource(id, clazz);
}
public <T extends ResourceInfo> T getResourceByName(String ns, String name, Class<T> clazz) {
if ("".equals( ns ) ) {
ns = null;
}
if (ns != null) {
NamespaceInfo namespace = getNamespaceByPrefix(ns);
if (namespace == null) {
namespace = getNamespaceByURI(ns);
}
if (namespace != null) {
return getResourceByName(namespace, name, clazz);
}
return null;
}
return getResourceByName((NamespaceInfo) null, name, clazz);
}
public <T extends ResourceInfo> T getResourceByName(NamespaceInfo ns,
String name, Class<T> clazz) {
NamespaceInfo namespace = ns;
if (namespace == null) {
namespace = getDefaultNamespace();
}
T resource = facade.getResourceByName(namespace, name, clazz);
if (resource == null && ns == null) {
resource = facade.getResourceByName(CatalogFacade.ANY_NAMESPACE, name, clazz);
}
return resource;
}
public <T extends ResourceInfo> T getResourceByName(Name name, Class<T> clazz) {
return getResourceByName( name.getNamespaceURI(), name.getLocalPart(), clazz );
}
public <T extends ResourceInfo> T getResourceByName( String name, Class<T> clazz ) {
ResourceInfo resource;
// check is the name is a fully qualified one
int colon = name.indexOf( ':' );
if ( colon != -1 ) {
String ns = name.substring(0, colon);
String localName = name.substring(colon + 1);
return getResourceByName(ns, localName, clazz);
}
else {
return getResourceByName((String)null,name,clazz);
}
}
public List getResources(Class clazz) {
return facade.getResources(clazz);
}
public List getResourcesByNamespace(NamespaceInfo namespace, Class clazz) {
return facade.getResourcesByNamespace(namespace, clazz);
}
public <T extends ResourceInfo> List<T> getResourcesByNamespace(
String namespace, Class<T> clazz) {
if ( namespace == null ) {
return getResourcesByNamespace((NamespaceInfo)null,clazz);
}
NamespaceInfo ns = getNamespaceByPrefix(namespace);
if ( ns == null ) {
ns = getNamespaceByURI(namespace);
}
if ( ns == null ) {
return Collections.EMPTY_LIST;
}
return getResourcesByNamespace(ns, clazz);
}
public <T extends ResourceInfo> T getResourceByStore(StoreInfo store,
String name, Class<T> clazz) {
return facade.getResourceByStore(store, name, clazz);
}
public <T extends ResourceInfo> List<T> getResourcesByStore(
StoreInfo store, Class<T> clazz) {
return facade.getResourcesByStore(store, clazz);
}
public FeatureTypeInfo getFeatureType(String id) {
return (FeatureTypeInfo) getResource(id, FeatureTypeInfo.class);
}
public FeatureTypeInfo getFeatureTypeByName(String ns, String name) {
return (FeatureTypeInfo) getResourceByName(ns, name,
FeatureTypeInfo.class);
}
public FeatureTypeInfo getFeatureTypeByName(NamespaceInfo ns, String name) {
return getResourceByName(ns, name, FeatureTypeInfo.class );
}
public FeatureTypeInfo getFeatureTypeByName(Name name) {
return getResourceByName(name, FeatureTypeInfo.class);
}
public FeatureTypeInfo getFeatureTypeByName(String name) {
return (FeatureTypeInfo) getResourceByName(name, FeatureTypeInfo.class);
}
public List getFeatureTypes() {
return getResources(FeatureTypeInfo.class);
}
public List getFeatureTypesByNamespace(NamespaceInfo namespace) {
return getResourcesByNamespace(namespace, FeatureTypeInfo.class);
}
public FeatureTypeInfo getFeatureTypeByStore(DataStoreInfo dataStore,
String name) {
return getFeatureTypeByDataStore(dataStore, name);
}
public FeatureTypeInfo getFeatureTypeByDataStore(DataStoreInfo dataStore,
String name) {
return getResourceByStore( dataStore, name, FeatureTypeInfo.class );
}
public List<FeatureTypeInfo> getFeatureTypesByStore(DataStoreInfo store) {
return getFeatureTypesByDataStore(store);
}
public List<FeatureTypeInfo> getFeatureTypesByDataStore(DataStoreInfo store) {
return getResourcesByStore(store, FeatureTypeInfo.class);
}
public CoverageInfo getCoverage(String id) {
return (CoverageInfo) getResource(id, CoverageInfo.class);
}
public CoverageInfo getCoverageByName(String ns, String name) {
return (CoverageInfo) getResourceByName(ns, name, CoverageInfo.class);
}
public CoverageInfo getCoverageByName(NamespaceInfo ns, String name) {
return (CoverageInfo) getResourceByName(ns, name, CoverageInfo.class);
}
public CoverageInfo getCoverageByName(Name name) {
return getResourceByName(name, CoverageInfo.class);
}
public CoverageInfo getCoverageByName(String name) {
return (CoverageInfo) getResourceByName( name, CoverageInfo.class );
}
public List getCoverages() {
return getResources(CoverageInfo.class);
}
public List getCoveragesByNamespace(NamespaceInfo namespace) {
return getResourcesByNamespace(namespace, CoverageInfo.class);
}
public List<CoverageInfo> getCoveragesByStore(CoverageStoreInfo store) {
return getResourcesByStore(store,CoverageInfo.class);
}
public CoverageInfo getCoverageByCoverageStore(
CoverageStoreInfo coverageStore, String name) {
return getResourceByStore( coverageStore, name, CoverageInfo.class );
}
public List<CoverageInfo> getCoveragesByCoverageStore(
CoverageStoreInfo store) {
return getResourcesByStore( store, CoverageInfo.class );
}
// Layer methods
public void add(LayerInfo layer) {
layer = resolve(layer);
validate(layer,true);
if ( layer.getType() == null ) {
if ( layer.getResource() instanceof FeatureTypeInfo ) {
layer.setType( LayerInfo.Type.VECTOR );
} else if ( layer.getResource() instanceof CoverageInfo ) {
layer.setType( LayerInfo.Type.RASTER );
} else if ( layer.getResource() instanceof WMSLayerInfo ) {
layer.setType( LayerInfo.Type.WMS );
} else {
String msg = "Layer type not set and can't be derived from resource";
throw new IllegalArgumentException( msg );
}
}
LayerInfo added = facade.add(layer);
added(added);
}
public ValidationResult validate( LayerInfo layer, boolean isNew) {
// TODO: bring back when the layer/publishing split is in act
// if ( isNull(layer.getName()) ) {
// throw new NullPointerException( "Layer name must not be null" );
// }
if ( layer.getResource() == null ) {
throw new NullPointerException( "Layer resource must not be null" );
}
// calling LayerInfo.setName(String) updates the resource (until the layer/publishing split
// is in act), but that doesn't mean the resource was saved previously, which can leave the
// catalog in an inconsistent state
if (null == getResourceByName(layer.getResource().getNamespace(), layer.getResource()
.getName(), ResourceInfo.class)) {
throw new IllegalStateException("Found no resource named " + layer.prefixedName()
+ " , Layer with that name can't be added");
}
LayerInfo existing = getLayerByName( layer.getName() );
if ( existing != null && !existing.getId().equals( layer.getId() ) ) {
//JD: since layers are not qualified by anything (yet), check
// namespace of the resource, if they are different then allow the
// layer to be added
if ( existing.getResource().getNamespace().equals( layer.getResource().getNamespace() ) ) {
throw new IllegalArgumentException( "Layer named '"+layer.getName()+"' already exists.");
}
}
// if the style is missing associate a default one, to avoid breaking WMS
if ( layer.getDefaultStyle() == null ) {
try {
LOGGER.log(Level.INFO, "Layer " + layer.prefixedName() + " is missing the default style, assigning one automatically");
StyleInfo style = new CatalogBuilder(this).getDefaultStyle(layer.getResource());
layer.setDefaultStyle(style);
} catch(IOException e) {
LOGGER.log(Level.WARNING, "Layer " + layer.prefixedName() + " is missing the default style, "
+ "failed to associate one automatically", e);
}
}
// clean up eventual dangling references to missing alternate styles
Set<StyleInfo> styles = layer.getStyles();
for (Iterator it = styles.iterator(); it.hasNext();) {
StyleInfo styleInfo = (StyleInfo) it.next();
if(styleInfo == null) {
it.remove();
}
}
return postValidate(layer, isNew);
}
public void remove(LayerInfo layer) {
//ensure no references to the layer
for ( LayerGroupInfo lg : facade.getLayerGroups() ) {
if ( lg.getLayers().contains( layer ) || layer.equals( lg.getRootLayer() ) ) {
String msg = "Unable to delete layer referenced by layer group '"+lg.getName()+"'";
throw new IllegalArgumentException( msg );
}
}
facade.remove(layer);
removed(layer);
}
public void save(LayerInfo layer) {
validate( layer, false );
facade.save(layer);
}
public LayerInfo detach(LayerInfo layer) {
return detached(layer, facade.detach(layer));
}
public LayerInfo getLayer(String id) {
return facade.getLayer(id);
}
public LayerInfo getLayerByName(Name name) {
if ( name.getNamespaceURI() != null ) {
NamespaceInfo ns = getNamespaceByURI( name.getNamespaceURI() );
if ( ns != null ) {
return getLayerByName( ns.getPrefix() + ":" + name.getLocalPart() );
}
}
return getLayerByName( name.getLocalPart() );
}
public LayerInfo getLayerByName(String name) {
LayerInfo result = null;
int colon = name.indexOf( ':' );
if ( colon != -1 ) {
//search by resource name
String prefix = name.substring( 0, colon );
String resource = name.substring( colon + 1 );
result = getLayerByName(prefix, resource);
} else {
// search in default workspace first
WorkspaceInfo ws = getDefaultWorkspace();
if ( ws != null ) {
result = getLayerByName(ws.getName(), name);
}
}
if(result == null) {
result = facade.getLayerByName(name);
}
return result;
}
private LayerInfo getLayerByName(String workspace, String resourceName) {
ResourceInfo r = getResourceByName(workspace, resourceName, ResourceInfo.class);
if (r == null) {
return null;
}
List<LayerInfo> layers = getLayers(r);
if (layers.size() == 1) {
return layers.get(0);
} else {
return null;
}
}
public List<LayerInfo> getLayers(ResourceInfo resource) {
return facade.getLayers(resource);
}
public List<LayerInfo> getLayers(StyleInfo style) {
return facade.getLayers(style);
}
public List<LayerInfo> getLayers() {
return facade.getLayers();
}
// Map methods
public MapInfo getMap(String id) {
return facade.getMap(id);
}
public MapInfo getMapByName(String name) {
return facade.getMapByName(name);
}
public List<MapInfo> getMaps() {
return facade.getMaps();
}
public void add(LayerGroupInfo layerGroup) {
layerGroup = resolve(layerGroup);
validate(layerGroup,true);
if ( layerGroup.getStyles().isEmpty() ) {
for ( PublishedInfo l : layerGroup.getLayers() ) {
// default style
layerGroup.getStyles().add(null);
}
}
LayerGroupInfo added = facade.add(layerGroup);
added( added );
}
public ValidationResult validate( LayerGroupInfo layerGroup, boolean isNew ) {
if( isNull(layerGroup.getName()) ) {
throw new NullPointerException( "Layer group name must not be null");
}
WorkspaceInfo ws = layerGroup.getWorkspace();
LayerGroupInfo existing = getLayerGroupByName( ws, layerGroup.getName() );
if ( existing != null && !existing.getId().equals( layerGroup.getId() ) ) {
// null workspace can cause layer group in any workspace to be returned, check that
// workspaces match
WorkspaceInfo ews = existing.getWorkspace();
if ((ws == null && ews == null) || (ws != null && ws.equals(ews))) {
String msg = "Layer group named '" + layerGroup.getName() + "' already exists";
if (ws != null) {
msg += " in workspace " + ws.getName();
}
throw new IllegalArgumentException(msg);
}
}
// sanitize a bit broken layer references
List<PublishedInfo> layers = layerGroup.getLayers();
List<StyleInfo> styles = layerGroup.getStyles();
for (int i = 0; i < layers.size(); ) {
if(layers.get(i) == null) {
layers.remove(i);
styles.remove(i);
} else {
i++;
}
}
if ( layerGroup.getLayers() == null || layerGroup.getLayers().isEmpty() ) {
throw new IllegalArgumentException( "Layer group must not be empty");
}
if ( layerGroup.getStyles() != null && !layerGroup.getStyles().isEmpty() &&
!(layerGroup.getStyles().size() == layerGroup.getLayers().size()) ) {
throw new IllegalArgumentException( "Layer group has different number of styles than layers");
}
LayerGroupHelper helper = new LayerGroupHelper(layerGroup);
Stack<LayerGroupInfo> loopPath = helper.checkLoops();
if (loopPath != null) {
throw new IllegalArgumentException( "Layer group is in a loop: " + helper.getLoopAsString(loopPath));
}
// if the layer group has a workspace assigned, ensure that every resource in that layer
// group lives within the same workspace
if (ws != null) {
checkLayerGroupResourceIsInWorkspace(layerGroup, ws);
}
if (layerGroup.getMode() == null) {
throw new IllegalArgumentException("Layer group mode must not be null");
} else if (LayerGroupInfo.Mode.EO.equals(layerGroup.getMode())) {
if (layerGroup.getRootLayer() == null) {
throw new IllegalArgumentException("Layer group in mode " + LayerGroupInfo.Mode.EO.getName() + " must have a root layer");
}
if (layerGroup.getRootLayerStyle() == null) {
throw new IllegalArgumentException("Layer group in mode " + LayerGroupInfo.Mode.EO.getName() + " must have a root layer style");
}
} else {
if (layerGroup.getRootLayer() != null) {
throw new IllegalArgumentException("Layer group in mode " + layerGroup.getMode().getName() + " must not have a root layer");
}
if (layerGroup.getRootLayerStyle() != null) {
throw new IllegalArgumentException("Layer group in mode " + layerGroup.getMode().getName() + " must not have a root layer style");
}
}
return postValidate(layerGroup, isNew);
}
private void checkLayerGroupResourceIsInWorkspace(LayerGroupInfo layerGroup, WorkspaceInfo ws) {
if (layerGroup == null) return;
if (layerGroup.getWorkspace() != null && !ws.equals(layerGroup.getWorkspace())) {
throw new IllegalArgumentException("Layer group within a workspace (" +
ws.getName() + ") can not contain resources from other workspace: " +
layerGroup.getWorkspace().getName());
}
checkLayerGroupResourceIsInWorkspace(layerGroup.getRootLayer(), ws);
checkLayerGroupResourceIsInWorkspace(layerGroup.getRootLayerStyle(), ws);
if(layerGroup.getLayers() != null) {
for (PublishedInfo p : layerGroup.getLayers()) {
if (p instanceof LayerGroupInfo) {
checkLayerGroupResourceIsInWorkspace((LayerGroupInfo) p, ws);
} else {
checkLayerGroupResourceIsInWorkspace((LayerInfo) p, ws);
}
}
}
if (layerGroup.getStyles() != null) {
for (StyleInfo s : layerGroup.getStyles()) {
checkLayerGroupResourceIsInWorkspace(s, ws);
}
}
}
private void checkLayerGroupResourceIsInWorkspace(StyleInfo style, WorkspaceInfo ws) {
if (style == null) return;
if (style.getWorkspace() != null && !ws.equals(style.getWorkspace())) {
throw new IllegalArgumentException("Layer group within a workspace (" +
ws.getName() + ") can not contain styles from other workspace: " +
style.getWorkspace());
}
}
private void checkLayerGroupResourceIsInWorkspace(LayerInfo layer, WorkspaceInfo ws) {
if (layer == null) return;
ResourceInfo r = layer.getResource();
if (r.getStore().getWorkspace() != null && !ws.equals(r.getStore().getWorkspace())) {
throw new IllegalArgumentException("Layer group within a workspace (" +
ws.getName() + ") can not contain resources from other workspace: " +
r.getStore().getWorkspace().getName());
}
}
public void remove(LayerGroupInfo layerGroup) {
facade.remove(layerGroup);
removed( layerGroup );
}
public void save(LayerGroupInfo layerGroup) {
validate(layerGroup,false);
facade.save(layerGroup);
}
public LayerGroupInfo detach(LayerGroupInfo layerGroup) {
return detached(layerGroup, facade.detach(layerGroup));
}
public List<LayerGroupInfo> getLayerGroups() {
return facade.getLayerGroups();
}
public List<LayerGroupInfo> getLayerGroupsByWorkspace(String workspaceName) {
WorkspaceInfo workspace = null;
if ( workspaceName != null ) {
workspace = getWorkspaceByName(workspaceName);
if ( workspace == null ) {
return Collections.EMPTY_LIST;
}
}
return getLayerGroupsByWorkspace(workspace);
}
public List<LayerGroupInfo> getLayerGroupsByWorkspace(WorkspaceInfo workspace) {
return facade.getLayerGroupsByWorkspace(workspace);
}
public LayerGroupInfo getLayerGroup(String id) {
return facade.getLayerGroup(id);
}
@Override
public LayerGroupInfo getLayerGroupByName(String name) {
final LayerGroupInfo layerGroup = getLayerGroupByName((String) null, name);
if (layerGroup != null)
return layerGroup;
// last chance: checking handle prefixed name case
String workspaceName = null;
String layerGroupName = null;
int colon = name.indexOf(':');
if (colon == -1) {
layerGroupName = name;
}
if (colon != -1) {
workspaceName = name.substring(0, colon);
layerGroupName = name.substring(colon + 1);
}
return getLayerGroupByName(workspaceName, layerGroupName);
}
@Override
public LayerGroupInfo getLayerGroupByName(String workspaceName, String name) {
WorkspaceInfo workspace = null;
if (workspaceName != null) {
workspace = getWorkspaceByName(workspaceName);
if(workspace == null){
return null;
}
}
return getLayerGroupByName(workspace, name);
}
@Override
public LayerGroupInfo getLayerGroupByName(WorkspaceInfo workspace,
String name) {
if(null == workspace){
workspace = DefaultCatalogFacade.NO_WORKSPACE;
}
LayerGroupInfo layerGroup = facade.getLayerGroupByName(workspace, name);
return layerGroup;
}
public void add(MapInfo map) {
MapInfo added = facade.add(resolve(map));
added(added);
}
public void remove(MapInfo map) {
facade.remove(map);
removed(map);
}
public void save(MapInfo map) {
facade.save(map);
}
public MapInfo detach(MapInfo map) {
return detached(map, facade.detach(map));
}
// Namespace methods
public NamespaceInfo getNamespace(String id) {
return facade.getNamespace(id);
}
public NamespaceInfo getNamespaceByPrefix(String prefix) {
if (prefix == null || Catalog.DEFAULT.equals(prefix)) {
NamespaceInfo ns = getDefaultNamespace();
if (ns != null) {
prefix = ns.getPrefix();
}
}
return facade.getNamespaceByPrefix(prefix);
}
public NamespaceInfo getNamespaceByURI(String uri) {
return facade.getNamespaceByURI(uri);
}
public List getNamespaces() {
return facade.getNamespaces();
}
public void add(NamespaceInfo namespace) {
validate(namespace,true);
NamespaceInfo added;
synchronized (facade) {
added = facade.add(resolve(namespace));
if ( getDefaultNamespace() == null ) {
setDefaultNamespace(namespace);
}
}
added(added);
}
public ValidationResult validate(NamespaceInfo namespace, boolean isNew) {
if ( isNull(namespace.getPrefix()) ) {
throw new NullPointerException( "Namespace prefix must not be null");
}
if(namespace.getPrefix().equals(DEFAULT)) {
throw new IllegalArgumentException(DEFAULT + " is a reserved keyword, can't be used as the namespace prefix");
}
NamespaceInfo existing = getNamespaceByPrefix( namespace.getPrefix() );
if ( existing != null && !existing.getId().equals( namespace.getId() ) ) {
throw new IllegalArgumentException( "Namespace with prefix '" + namespace.getPrefix() + "' already exists.");
}
existing = getNamespaceByURI( namespace.getURI() );
if ( existing != null && !existing.getId().equals( namespace.getId() ) ) {
throw new IllegalArgumentException( "Namespace with URI '" + namespace.getURI() + "' already exists.");
}
if ( isNull(namespace.getURI()) ) {
throw new NullPointerException( "Namespace uri must not be null");
}
try {
new URI(namespace.getURI());
} catch(Exception e) {
throw new IllegalArgumentException("Invalid URI syntax for '" + namespace.getURI()
+ "' in namespace '" + namespace.getPrefix() + "'");
}
return postValidate(namespace, isNew);
}
public void remove(NamespaceInfo namespace) {
if ( !getResourcesByNamespace(namespace, ResourceInfo.class ).isEmpty() ) {
throw new IllegalArgumentException( "Unable to delete non-empty namespace.");
}
//TODO: remove synchronized block, need transactions
synchronized(facade) {
facade.remove(namespace);
NamespaceInfo defaultNamespace = getDefaultNamespace();
if (namespace.equals(defaultNamespace) || defaultNamespace == null) {
List<NamespaceInfo> namespaces = facade.getNamespaces();
defaultNamespace = null;
if (!namespaces.isEmpty()) {
defaultNamespace = namespaces.get(0);
}
setDefaultNamespace(defaultNamespace);
if(defaultNamespace != null) {
WorkspaceInfo defaultWorkspace = getWorkspaceByName(defaultNamespace.getPrefix());
if(defaultWorkspace != null) {
setDefaultWorkspace(defaultWorkspace);
}
}
}
}
removed(namespace);
}
public void save(NamespaceInfo namespace) {
validate(namespace,false);
facade.save(namespace);
}
public NamespaceInfo detach(NamespaceInfo namespace) {
return detached(namespace, facade.detach(namespace));
}
public NamespaceInfo getDefaultNamespace() {
return facade.getDefaultNamespace();
}
public void setDefaultNamespace(NamespaceInfo defaultNamespace) {
if(defaultNamespace != null) {
NamespaceInfo ns = getNamespaceByPrefix( defaultNamespace.getPrefix() );
if ( ns == null ) {
throw new IllegalArgumentException( "No such namespace: '" + defaultNamespace.getPrefix() + "'" );
}
}
facade.setDefaultNamespace(defaultNamespace);
}
// Workspace methods
public void add(WorkspaceInfo workspace) {
workspace = resolve(workspace);
validate(workspace,true);
if ( getWorkspaceByName(workspace.getName()) != null ) {
throw new IllegalArgumentException( "Workspace with name '" + workspace.getName() + "' already exists.");
}
WorkspaceInfo added;
synchronized (facade) {
added = facade.add(workspace);
// if there is no default workspace use this one as the default
if ( getDefaultWorkspace() == null ) {
setDefaultWorkspace(workspace);
}
}
added( added );
}
public ValidationResult validate(WorkspaceInfo workspace, boolean isNew) {
if ( isNull(workspace.getName()) ) {
throw new NullPointerException( "workspace name must not be null");
}
if(workspace.getName().equals(DEFAULT)) {
throw new IllegalArgumentException(DEFAULT + " is a reserved keyword, can't be used as the workspace name");
}
WorkspaceInfo existing = getWorkspaceByName( workspace.getName() );
if ( existing != null && !existing.getId().equals( workspace.getId() ) ) {
throw new IllegalArgumentException( "Workspace named '"+ workspace.getName() +"' already exists.");
}
return postValidate(workspace, isNew);
}
public void remove(WorkspaceInfo workspace) {
//JD: maintain the link between namespace and workspace, remove this when this is no
// longer necessary
if ( getNamespaceByPrefix( workspace.getName() ) != null ) {
throw new IllegalArgumentException ( "Cannot delete workspace with linked namespace");
}
if ( !getStoresByWorkspace( workspace, StoreInfo.class).isEmpty() ) {
throw new IllegalArgumentException( "Cannot delete non-empty workspace.");
}
//TODO: remove synchronized block, need transactions
synchronized(facade) {
facade.remove(workspace);
WorkspaceInfo defaultWorkspace = getDefaultWorkspace();
if (workspace.equals(defaultWorkspace) || defaultWorkspace == null) {
List<WorkspaceInfo> workspaces = facade.getWorkspaces();
defaultWorkspace = null;
if (!workspaces.isEmpty()) {
defaultWorkspace = workspaces.get(0);
}
setDefaultWorkspace(defaultWorkspace);
if(defaultWorkspace != null) {
NamespaceInfo defaultNamespace = getNamespaceByPrefix(defaultWorkspace.getName());
if(defaultNamespace != null) {
setDefaultNamespace(defaultNamespace);
}
}
}
}
removed( workspace );
}
public void save(WorkspaceInfo workspace) {
validate(workspace,false);
facade.save(workspace);
}
public WorkspaceInfo detach(WorkspaceInfo workspace) {
return detached(workspace, facade.detach(workspace));
}
public WorkspaceInfo getDefaultWorkspace() {
return facade.getDefaultWorkspace();
}
public void setDefaultWorkspace(WorkspaceInfo workspace) {
if (workspace != null && facade.getWorkspaceByName(workspace.getName()) == null) {
facade.add(workspace);
}
facade.setDefaultWorkspace(workspace);
}
public List<WorkspaceInfo> getWorkspaces() {
return facade.getWorkspaces();
}
public WorkspaceInfo getWorkspace(String id) {
return facade.getWorkspace(id);
}
public WorkspaceInfo getWorkspaceByName(String name) {
if (name == null || Catalog.DEFAULT.equals(name)) {
WorkspaceInfo ws = getDefaultWorkspace();
if (ws != null) {
name = ws.getName();
}
}
return facade.getWorkspaceByName(name);
}
// Style methods
public StyleInfo getStyle(String id) {
return facade.getStyle(id);
}
public StyleInfo getStyleByName(String name) {
return getStyleByName((WorkspaceInfo) null, name);
}
public StyleInfo getStyleByName(String workspaceName, String name) {
if (workspaceName == null) {
return getStyleByName((WorkspaceInfo)null, name);
}
WorkspaceInfo workspace = getWorkspaceByName(workspaceName);
if (workspace != null) {
return getStyleByName(workspace, name);
}
return null;
}
public StyleInfo getStyleByName(WorkspaceInfo workspace, String name) {
if (workspace == null) {
workspace = DefaultCatalogFacade.NO_WORKSPACE;
}
StyleInfo style = facade.getStyleByName(workspace, name);
return style;
}
public List getStyles() {
return facade.getStyles();
}
public List<StyleInfo> getStylesByWorkspace(String workspaceName) {
WorkspaceInfo workspace = null;
if ( workspaceName != null ) {
workspace = getWorkspaceByName(workspaceName);
if ( workspace == null ) {
return Collections.EMPTY_LIST;
}
}
return getStylesByWorkspace(workspace);
}
public List<StyleInfo> getStylesByWorkspace(WorkspaceInfo workspace) {
return facade.getStylesByWorkspace(workspace);
}
public void add(StyleInfo style) {
style = resolve(style);
validate(style,true);
StyleInfo added = facade.add(style);
added(added);
}
public ValidationResult validate( StyleInfo style, boolean isNew ) {
if ( isNull(style.getName()) ) {
throw new NullPointerException( "Style name must not be null");
}
if ( isNull(style.getFilename()) ) {
throw new NullPointerException( "Style fileName must not be null");
}
WorkspaceInfo ws = style.getWorkspace();
StyleInfo existing = getStyleByName( ws, style.getName() );
if ( existing != null && (isNew || !existing.getId().equals( style.getId() ) )) {
// null workspace can cause style in any workspace to be returned, check that
// workspaces match
WorkspaceInfo ews = existing.getWorkspace();
String msg = "Style named '" + style.getName() +"' already exists";
if (ews != null) {
msg += " in workspace " + ews.getName();
}
throw new IllegalArgumentException(msg);
}
return postValidate(style, isNew);
}
public void remove(StyleInfo style) {
//ensure no references to the style
for ( LayerInfo l : facade.getLayers() ) {
if ( style.equals( l.getDefaultStyle() ) || l.getStyles().contains( style )) {
throw new IllegalArgumentException( "Unable to delete style referenced by '"+ l.getName()+"'");
}
}
for ( LayerGroupInfo lg : facade.getLayerGroups() ) {
if ( lg.getStyles().contains( style ) || style.equals( lg.getRootLayerStyle() ) ) {
String msg = "Unable to delete style referenced by layer group '"+lg.getName()+"'";
throw new IllegalArgumentException( msg );
}
}
facade.remove(style);
removed(style);
}
public void save(StyleInfo style) {
validate(style,false);
facade.save(style);
}
public StyleInfo detach(StyleInfo style) {
return detached(style, facade.detach(style));
}
// Event methods
public Collection getListeners() {
return Collections.unmodifiableCollection(listeners);
}
public void addListener(CatalogListener listener) {
listeners.add(listener);
}
public void removeListener(CatalogListener listener) {
listeners.remove(listener);
}
@Override
public void removeListeners(Class listenerClass) {
for (Iterator it = listeners.iterator(); it.hasNext();) {
CatalogListener listener = (CatalogListener) it.next();
if(listenerClass.isInstance(listener)) {
it.remove();
}
}
}
public Iterator search(String cql) {
// TODO Auto-generated method stub
return null;
}
public ResourcePool getResourcePool() {
return resourcePool;
}
public void setResourcePool(ResourcePool resourcePool) {
this.resourcePool = resourcePool;
}
public GeoServerResourceLoader getResourceLoader() {
return resourceLoader;
}
public void setResourceLoader(GeoServerResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public void dispose() {
if ( resourcePool != null ) resourcePool.dispose();
facade.dispose();
}
protected void added(CatalogInfo object) {
fireAdded( object );
}
protected void removed(CatalogInfo object) {
fireRemoved( object );
}
public void fireAdded(CatalogInfo object) {
CatalogAddEventImpl event = new CatalogAddEventImpl();
event.setSource(object);
event(event);
}
public void fireModified(CatalogInfo object, List propertyNames, List oldValues,
List newValues) {
CatalogModifyEventImpl event = new CatalogModifyEventImpl();
event.setSource(object);
event.setPropertyNames(propertyNames);
event.setOldValues(oldValues);
event.setNewValues(newValues);
event(event);
}
public void firePostModified(CatalogInfo object) {
CatalogPostModifyEventImpl event = new CatalogPostModifyEventImpl();
event.setSource( object);
event(event);
}
public void fireRemoved(CatalogInfo object) {
CatalogRemoveEventImpl event = new CatalogRemoveEventImpl();
event.setSource(object);
event(event);
}
protected void event(CatalogEvent event) {
CatalogException toThrow = null;
for (Iterator l = listeners.iterator(); l.hasNext();) {
try {
CatalogListener listener = (CatalogListener) l.next();
if (event instanceof CatalogAddEvent) {
listener.handleAddEvent((CatalogAddEvent) event);
} else if (event instanceof CatalogRemoveEvent) {
listener.handleRemoveEvent((CatalogRemoveEvent) event);
} else if (event instanceof CatalogModifyEvent) {
listener.handleModifyEvent((CatalogModifyEvent) event);
} else if (event instanceof CatalogPostModifyEvent) {
listener.handlePostModifyEvent((CatalogPostModifyEvent)event);
}
} catch(Throwable t) {
if ( t instanceof CatalogException && toThrow == null) {
toThrow = (CatalogException) t;
}
else {
LOGGER.log(Level.WARNING, "Catalog listener threw exception handling event.", t);
}
}
}
if (toThrow != null) {
throw toThrow;
}
}
public static Object unwrap(Object obj) {
return obj;
}
public static void validateKeywords(List<KeywordInfo> keywords) {
if (keywords != null) {
for (KeywordInfo kw : keywords) {
Matcher m = KeywordInfo.RE.matcher(kw.getValue());
if (!m.matches()) {
throw new IllegalArgumentException("Illegal keyword '" + kw + "'. " +
"Keywords must not be empty and must not contain the '\\' character");
}
if (kw.getVocabulary() != null) {
m = KeywordInfo.RE.matcher(kw.getVocabulary());
if (!m.matches()) {
throw new IllegalArgumentException(
"Keyword vocbulary must not contain the '\\' character");
}
}
}
}
}
/**
* Implementation method for resolving all {@link ResolvingProxy} instances.
*/
public void resolve() {
facade.setCatalog(this);
facade.resolve();
if ( listeners == null ) {
listeners = new ArrayList<CatalogListener>();
}
if ( resourcePool == null ) {
resourcePool = ResourcePool.create(this);
}
}
protected WorkspaceInfo resolve(WorkspaceInfo workspace) {
resolveCollections(workspace);
return workspace;
}
protected NamespaceInfo resolve(NamespaceInfo namespace) {
resolveCollections(namespace);
return namespace;
}
protected StoreInfo resolve(StoreInfo store) {
resolveCollections(store);
StoreInfoImpl s = (StoreInfoImpl) store;
s.setCatalog( this );
return store;
}
protected ResourceInfo resolve(ResourceInfo resource) {
ResourceInfoImpl r = (ResourceInfoImpl) resource;
r.setCatalog(this);
if ( resource instanceof FeatureTypeInfo ) {
resolve( (FeatureTypeInfo) resource );
}
if(r instanceof CoverageInfo){
resolve((CoverageInfo) resource);
}
if(r instanceof WMSLayerInfo){
resolve((WMSLayerInfo) resource);
}
return resource;
}
private CoverageInfo resolve(CoverageInfo r) {
CoverageInfoImpl c = (CoverageInfoImpl)r;
if(c.getDimensions() != null) {
for (CoverageDimensionInfo dim : c.getDimensions()) {
if(dim.getNullValues() == null) {
((CoverageDimensionImpl) dim).setNullValues(new ArrayList<Double>());
}
}
}
resolveCollections(r);
return r;
}
/**
* We don't want the world to be able and call this without
* going trough {@link #resolve(ResourceInfo)}
* @param featureType
*/
private FeatureTypeInfo resolve(FeatureTypeInfo featureType) {
FeatureTypeInfoImpl ft = (FeatureTypeInfoImpl) featureType;
resolveCollections(ft);
return ft;
}
private WMSLayerInfo resolve(WMSLayerInfo wmsLayer) {
WMSLayerInfoImpl impl = (WMSLayerInfoImpl) wmsLayer;
resolveCollections(impl);
return wmsLayer;
}
protected LayerInfo resolve(LayerInfo layer) {
if (layer.getAttribution() == null) {
layer.setAttribution(getFactory().createAttribution());
}
resolveCollections(layer);
return layer;
}
protected LayerGroupInfo resolve(LayerGroupInfo layerGroup) {
resolveCollections(layerGroup);
return layerGroup;
}
protected StyleInfo resolve(StyleInfo style) {
((StyleInfoImpl)style).setCatalog( this );
return style;
}
protected MapInfo resolve(MapInfo map) {
resolveCollections(map);
return map;
}
/**
* Method which reflectively sets all collections when they are null.
*/
protected void resolveCollections(Object object) {
OwsUtils.resolveCollections(object);
}
protected boolean isNull( String string ) {
return string == null || "".equals( string.trim() );
}
<T extends CatalogInfo> T detached(T original, T detached) {
return detached != null ? detached : original;
}
protected ValidationResult postValidate(CatalogInfo info, boolean isNew) {
List<RuntimeException> errors = new ArrayList<RuntimeException>();
if (!extendedValidation) {
return new ValidationResult(null);
}
for (CatalogValidator constraint : getValidators()) {
try {
info.accept(new CatalogValidatorVisitor(constraint, isNew));
} catch (RuntimeException e) {
errors.add(e);
}
}
return new ValidationResult(errors);
}
static class CatalogValidatorVisitor implements CatalogVisitor {
CatalogValidator validator;
boolean isNew;
CatalogValidatorVisitor(CatalogValidator validator, boolean isNew) {
this.validator = validator;
this.isNew = isNew;
}
public void visit(Catalog catalog) {
}
public void visit(WorkspaceInfo workspace) {
validator.validate(workspace, isNew);
}
public void visit(NamespaceInfo namespace) {
validator.validate(namespace, isNew);
}
public void visit(DataStoreInfo dataStore) {
validator.validate(dataStore, isNew);
}
public void visit(CoverageStoreInfo coverageStore) {
validator.validate(coverageStore, isNew);
}
public void visit(WMSStoreInfo wmsStore) {
validator.validate(wmsStore, isNew);
}
public void visit(FeatureTypeInfo featureType) {
validator.validate(featureType, isNew);
}
public void visit(CoverageInfo coverage) {
validator.validate(coverage, isNew);
}
public void visit(LayerInfo layer) {
validator.validate(layer, isNew);
}
public void visit(StyleInfo style) {
validator.validate(style, isNew);
}
public void visit(LayerGroupInfo layerGroup) {
validator.validate(layerGroup, isNew);
}
public void visit(WMSLayerInfo wmsLayer) {
validator.validate(wmsLayer, isNew);
}
}
public void sync( CatalogImpl other ) {
other.facade.syncTo(facade);
listeners = other.listeners;
if ( resourcePool != other.resourcePool ) {
resourcePool.dispose();
resourcePool = other.resourcePool;
}
resourceLoader = other.resourceLoader;
}
public void accept(CatalogVisitor visitor) {
visitor.visit(this);
}
public void resolve(CatalogInfo info) {
if (info instanceof LayerGroupInfo) {
resolve((LayerGroupInfo) info);
} else if (info instanceof LayerInfo) {
resolve((LayerInfo) info);
} else if (info instanceof MapInfo) {
resolve((MapInfo) info);
} else if (info instanceof NamespaceInfo) {
resolve((NamespaceInfo) info);
} else if (info instanceof ResourceInfo) {
resolve((ResourceInfo) info);
} else if (info instanceof StoreInfo) {
resolve((StoreInfo) info);
} else if (info instanceof StyleInfo) {
resolve((StyleInfo) info);
} else if (info instanceof WorkspaceInfo) {
resolve((WorkspaceInfo) info);
} else {
throw new IllegalArgumentException("Unknown resource type: " + info);
}
}
@Override
public <T extends CatalogInfo> int count(final Class<T> of,
final Filter filter) {
final CatalogFacade facade = getFacade();
return facade.count(of, filter);
}
@Override
public <T extends CatalogInfo> CloseableIterator<T> list(final Class<T> of,
final Filter filter) {
return list(of, filter, null, null, null);
}
@Override
public <T extends CatalogInfo> CloseableIterator<T> list(final Class<T> of,
final Filter filter, Integer offset, Integer count, SortBy sortOrder) {
CatalogFacade facade = getFacade();
if (sortOrder != null && !facade.canSort(of, sortOrder.getPropertyName().getPropertyName())) {
// TODO: use GeoTools' merge-sort code to provide sorting anyways
throw new UnsupportedOperationException("Catalog backend can't sort on property "
+ sortOrder.getPropertyName() + " in-process sorting is pending implementation");
}
return facade.list(of, filter, offset, count, sortOrder);
}
@Override
public <T extends CatalogInfo> T get(Class<T> type, Filter filter)
throws IllegalArgumentException {
final Integer limit = Integer.valueOf(2);
CloseableIterator<T> it = list(type, filter, null, limit, null);
T result = null;
try {
if (it.hasNext()) {
result = it.next();
if (it.hasNext()) {
throw new IllegalArgumentException(
"Specified query predicate resulted in more than one object");
}
}
} finally {
it.close();
}
return result;
}
}