/* Copyright (c) 2001 - 2013 OpenPlans - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps;
import java.awt.RenderingHints.Key;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.geoserver.config.ConfigurationListener;
import org.geoserver.config.ConfigurationListenerAdapter;
import org.geoserver.config.GeoServer;
import org.geoserver.config.ServiceInfo;
import org.geoserver.platform.ContextLoadedEvent;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.wps.process.GeoServerProcessors;
import org.geotools.data.Parameter;
import org.geotools.feature.NameImpl;
import org.geotools.process.Process;
import org.geotools.process.ProcessFactory;
import org.geotools.process.Processors;
import org.geotools.text.Text;
import org.opengis.feature.type.Name;
import org.opengis.util.InternationalString;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.ContextStartedEvent;
/**
* Process factory that maintains backward compatibility for deprecated process names.
*
* @author Justin Deoliveira, OpenGeo
*
*/
public class DeprecatedProcessFactory implements ProcessFactory, DisposableBean, ApplicationListener<ApplicationEvent> {
volatile Map<Name,Name> map;
GeoServer geoServer;
ConfigurationListener listener;
public DeprecatedProcessFactory() {
Processors.addProcessFactory(this);
}
@Override
public void destroy() throws Exception {
if (geoServer != null) {
geoServer.removeListener(listener);
}
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public Map<Key, ?> getImplementationHints() {
return null;
}
@Override
public InternationalString getTitle() {
return Text.text("Deprecated processes");
}
@Override
public Set<Name> getNames() {
return getProcessMappings().keySet();
}
@Override
public InternationalString getTitle(Name name) {
return doAction(name, new Action<InternationalString>() {
@Override
public InternationalString perform(ProcessFactory f, Name oldName, Name newName, Object... args) {
return f.getTitle(newName);
}
});
}
@Override
public InternationalString getDescription(Name name) {
return doAction(name, new Action<InternationalString>() {
@Override
public InternationalString perform(ProcessFactory f, Name oldName, Name newName, Object... args) {
return f.getDescription(newName);
}
});
}
@Override
public String getVersion(Name name) {
return doAction(name, new Action<String>() {
@Override
public String perform(ProcessFactory f, Name oldName, Name newName, Object... args) {
return f.getVersion(newName);
}
});
}
@Override
public Map<String, Parameter<?>> getParameterInfo(Name name) {
return doAction(name, new Action< Map<String, Parameter<?>>>() {
@Override
public Map<String, Parameter<?>> perform(ProcessFactory f, Name oldName, Name newName, Object... args) {
return f.getParameterInfo(newName);
}
});
}
@Override
public Map<String, Parameter<?>> getResultInfo(Name name,
Map<String, Object> parameters) throws IllegalArgumentException {
return doAction(name, new Action<Map<String, Parameter<?>>>() {
@Override
public Map<String, Parameter<?>> perform(ProcessFactory f, Name oldName, Name newName, Object... args ) {
return f.getResultInfo(newName, (Map<String, Object>) args[0]);
}
}, parameters);
}
@Override
public boolean supportsProgress(Name name) {
Boolean b = doAction(name, new Action<Boolean>() {
@Override
public Boolean perform(ProcessFactory f, Name oldName, Name newName, Object... args) {
return f.supportsProgress(newName);
}
});
return b != null ? b : false;
}
@Override
public Process create(Name name) {
return doAction(name, new Action<Process>() {
@Override
public Process perform(ProcessFactory f, Name oldName, Name newName, Object... args) {
return f.create(newName);
}
});
}
interface Action<T> {
T perform(ProcessFactory f, Name oldName, Name newName, Object... args);
}
<T> T doAction(Name oldName, Action<T> a, Object... args) {
Map<Name,Name> map = getProcessMappings();
if (map.containsKey(oldName)) {
Name newName = map.get(oldName);
ProcessFactory pf = GeoServerProcessors.createProcessFactory(newName);
if (pf != null) {
return a.perform(pf, oldName, newName, args);
}
}
return null;
}
Map<Name,Name> getProcessMappings() {
if (map == null) {
synchronized (DeprecatedProcessFactory.class) {
if (map == null) {
map = new LinkedHashMap();
//JTS namespace
registerProcessMapping(new NameImpl("JTS", "length"), new NameImpl("geo","length"), map);
registerProcessMapping(new NameImpl("JTS", "isEmpty"), new NameImpl("geo","isEmpty"), map);
registerProcessMapping(new NameImpl("JTS", "contains"), new NameImpl("geo","contains"), map);
registerProcessMapping(new NameImpl("JTS", "disjoint"), new NameImpl("geo","disjoint"), map);
registerProcessMapping(new NameImpl("JTS", "intersects"), new NameImpl("geo","intersects"), map);
registerProcessMapping(new NameImpl("JTS", "isClosed"), new NameImpl("geo","isClosed"), map);
registerProcessMapping(new NameImpl("JTS", "isValid"), new NameImpl("geo","isValid"), map);
registerProcessMapping(new NameImpl("JTS", "buffer"), new NameImpl("geo","buffer"), map);
registerProcessMapping(new NameImpl("JTS", "getY"), new NameImpl("geo","getY"), map);
registerProcessMapping(new NameImpl("JTS", "getX"), new NameImpl("geo","getX"), map);
registerProcessMapping(new NameImpl("JTS", "union"), new NameImpl("geo","union"), map);
registerProcessMapping(new NameImpl("JTS", "intersection"), new NameImpl("geo","intersection"), map);
registerProcessMapping(new NameImpl("JTS", "difference"), new NameImpl("geo","difference"), map);
registerProcessMapping(new NameImpl("JTS", "distance"), new NameImpl("geo","distance"), map);
registerProcessMapping(new NameImpl("JTS", "envelope"), new NameImpl("geo","envelope"), map);
registerProcessMapping(new NameImpl("JTS", "dimension"), new NameImpl("geo","dimension"), map);
registerProcessMapping(new NameImpl("JTS", "overlaps"), new NameImpl("geo","overlaps"), map);
registerProcessMapping(new NameImpl("JTS", "reproject"), new NameImpl("geo","reproject"), map);
registerProcessMapping(new NameImpl("JTS", "simplify"), new NameImpl("geo","simplify"), map);
registerProcessMapping(new NameImpl("JTS", "isSimple"), new NameImpl("geo","isSimple"), map);
registerProcessMapping(new NameImpl("JTS", "equalsExact"), new NameImpl("geo","equalsExact"), map);
registerProcessMapping(new NameImpl("JTS", "getGeometryN"), new NameImpl("geo","getGeometryN"), map);
registerProcessMapping(new NameImpl("JTS", "isWithinDistance"), new NameImpl("geo","isWithinDistance"), map);
registerProcessMapping(new NameImpl("JTS", "touches"), new NameImpl("geo","touches"), map);
registerProcessMapping(new NameImpl("JTS", "crosses"), new NameImpl("geo","crosses"), map);
registerProcessMapping(new NameImpl("JTS", "within"), new NameImpl("geo","within"), map);
registerProcessMapping(new NameImpl("JTS", "relate"), new NameImpl("geo","relate"), map);
registerProcessMapping(new NameImpl("JTS", "convexHull"), new NameImpl("geo","convexHull"), map);
registerProcessMapping(new NameImpl("JTS", "symDifference"), new NameImpl("geo","symDifference"), map);
registerProcessMapping(new NameImpl("JTS", "centroid"), new NameImpl("geo","centroid"), map);
registerProcessMapping(new NameImpl("JTS", "interiorPoint"), new NameImpl("geo","interiorPoint"), map);
registerProcessMapping(new NameImpl("JTS", "numPoints"), new NameImpl("geo","numPoints"), map);
registerProcessMapping(new NameImpl("JTS", "area"), new NameImpl("geo","area"), map);
registerProcessMapping(new NameImpl("JTS", "isRing"), new NameImpl("geo","isRing"), map);
registerProcessMapping(new NameImpl("JTS", "exteriorRing"), new NameImpl("geo","exteriorRing"), map);
registerProcessMapping(new NameImpl("JTS", "numInteriorRing"), new NameImpl("geo","numInteriorRing"), map);
registerProcessMapping(new NameImpl("JTS", "numGeometries"), new NameImpl("geo","numGeometries"), map);
registerProcessMapping(new NameImpl("JTS", "geometryType"), new NameImpl("geo","geometryType"), map);
registerProcessMapping(new NameImpl("JTS", "boundary"), new NameImpl("geo","boundary"), map);
registerProcessMapping(new NameImpl("JTS", "densify"), new NameImpl("geo","densify"), map);
registerProcessMapping(new NameImpl("JTS", "relatePattern"), new NameImpl("geo","relatePattern"), map);
registerProcessMapping(new NameImpl("JTS", "equalsExactTolerance"), new NameImpl("geo","equalsExactTolerance"), map);
registerProcessMapping(new NameImpl("JTS", "pointN"), new NameImpl("geo","pointN"), map);
registerProcessMapping(new NameImpl("JTS", "startPoint"), new NameImpl("geo","startPoint"), map);
registerProcessMapping(new NameImpl("JTS", "endPoint"), new NameImpl("geo","endPoint"), map);
registerProcessMapping(new NameImpl("JTS", "interiorRingN"), new NameImpl("geo","interiorRingN"), map);
registerProcessMapping(new NameImpl("JTS", "polygonize"), new NameImpl("geo","polygonize"), map);
registerProcessMapping(new NameImpl("JTS", "splitPolygon"), new NameImpl("geo","splitPolygon"), map);
//gs geometry processes
registerProcessMapping(new NameImpl("gs", "ReprojectGeometry"), new NameImpl("geo", "reproject"), map);
//gs feature processes
registerProcessMapping(new NameImpl("gs", "Aggregate"), new NameImpl("vec", "Aggregate"), map);
registerProcessMapping(new NameImpl("gs", "Bounds"), new NameImpl("vec", "Bounds"), map);
registerProcessMapping(new NameImpl("gs", "BufferFeatureCollection"), new NameImpl("vec", "BufferFeatureCollection"), map);
registerProcessMapping(new NameImpl("gs", "Centroid"), new NameImpl("vec", "Centroid"), map);
registerProcessMapping(new NameImpl("gs", "Clip"), new NameImpl("vec", "Clip"), map);
registerProcessMapping(new NameImpl("gs", "CollectGeometries"), new NameImpl("vec", "CollectGeometries"), map);
registerProcessMapping(new NameImpl("gs", "Count"), new NameImpl("vec", "Count"), map);
registerProcessMapping(new NameImpl("gs", "Feature"), new NameImpl("vec", "Feature"), map);
registerProcessMapping(new NameImpl("gs", "Grid"), new NameImpl("vec", "Grid"), map);
registerProcessMapping(new NameImpl("gs", "InclusionFeatureCollection"), new NameImpl("vec", "InclusionFeatureCollection"), map);
registerProcessMapping(new NameImpl("gs", "IntersectionFeatureCollection"), new NameImpl("vec", "IntersectionFeatureCollection"), map);
registerProcessMapping(new NameImpl("gs", "LRSGeocode"), new NameImpl("vec", "LRSGeocode"), map);
registerProcessMapping(new NameImpl("gs", "LRSMeasure"), new NameImpl("vec", "LRSMeasure"), map);
registerProcessMapping(new NameImpl("gs", "LRSSegment"), new NameImpl("vec", "LRSSegment"), map);
registerProcessMapping(new NameImpl("gs", "Nearest"), new NameImpl("vec", "Nearest"), map);
registerProcessMapping(new NameImpl("gs", "PointBuffers"), new NameImpl("vec", "PointBuffers"), map);
registerProcessMapping(new NameImpl("gs", "PointStacker"), new NameImpl("vec", "PointStacker"), map);
registerProcessMapping(new NameImpl("gs", "Query"), new NameImpl("vec", "Query"), map);
registerProcessMapping(new NameImpl("gs", "RectangularClip"), new NameImpl("vec", "RectangularClip"), map);
registerProcessMapping(new NameImpl("gs", "Reproject"), new NameImpl("vec", "Reproject"), map);
registerProcessMapping(new NameImpl("gs", "Simplify"), new NameImpl("vec", "Simplify"), map);
registerProcessMapping(new NameImpl("gs", "Snap"), new NameImpl("vec", "Snap"), map);
registerProcessMapping(new NameImpl("gs", "Transform"), new NameImpl("vec", "Transform"), map);
registerProcessMapping(new NameImpl("gs", "UnionFeatureCollection"), new NameImpl("vec", "UnionFeatureCollection"), map);
registerProcessMapping(new NameImpl("gs", "Unique"), new NameImpl("vec", "Unique"), map);
registerProcessMapping(new NameImpl("gs", "VectorZonalStatistics"), new NameImpl("vec", "VectorZonalStatistics"), map);
registerProcessMapping(new NameImpl("gs", "Heatmap"), new NameImpl("vec", "Heatmap"), map);
registerProcessMapping(new NameImpl("gs", "BarnesSurface"), new NameImpl("vec", "BarnesSurface"), map);
//gs raster processes
registerProcessMapping(new NameImpl("gs", "AddCoverages"), new NameImpl("ras", "AddCoverages"), map);
registerProcessMapping(new NameImpl("gs", "AreaGrid"), new NameImpl("ras", "AreaGrid"), map);
registerProcessMapping(new NameImpl("gs", "Contour"), new NameImpl("ras", "Contour"), map);
registerProcessMapping(new NameImpl("gs", "CropCoverage"), new NameImpl("ras", "CropCoverage"), map);
registerProcessMapping(new NameImpl("gs", "MultiplyCoverages"), new NameImpl("ras", "MultiplyCoverages"), map);
registerProcessMapping(new NameImpl("gs", "PolygonExtraction"), new NameImpl("ras", "PolygonExtraction"), map);
registerProcessMapping(new NameImpl("gs", "RangeLookup"), new NameImpl("ras", "RangeLookup"), map);
registerProcessMapping(new NameImpl("gs", "RasterAsPointCollection"), new NameImpl("ras", "RasterAsPointCollection"), map);
registerProcessMapping(new NameImpl("gs", "RasterZonalStatistics"), new NameImpl("ras", "RasterZonalStatistics"), map);
registerProcessMapping(new NameImpl("gs", "ScaleCoverage"), new NameImpl("ras", "ScaleCoverage"), map);
registerProcessMapping(new NameImpl("gs", "StyleCoverage"), new NameImpl("ras", "StyleCoverage"), map);
//gt vector processes
registerProcessMapping(new NameImpl("gt", "VectorToRaster"), new NameImpl("vec", "VectorToRaster"), map);
}
}
}
return map;
}
void resetProcessMappings() {
map = null;
}
static void registerProcessMapping(Name oldName, Name newName, Map<Name,Name> map) {
if (GeoServerProcessors.createProcess(newName) != null) {
map.put(oldName, newName);
}
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
// add and remove the process factory as necessary
if (event instanceof ContextLoadedEvent) {
//JD: look up GeoServer and register now rather than use constructor injection
// to avoid circular dependency during service loading startup
geoServer = GeoServerExtensions.bean(GeoServer.class,
((ContextLoadedEvent) event).getApplicationContext());
listener = new ConfigurationListenerAdapter() {
@Override
public void handleServiceChange(ServiceInfo service, List<String> propertyNames,
List<Object> oldValues, List<Object> newValues) {
if (service instanceof WPSInfo) {
resetProcessMappings();
}
}
};
geoServer.addListener(listener);
}
if (event instanceof ContextRefreshedEvent) {
Processors.addProcessFactory(this);
} else if (event instanceof ContextClosedEvent) {
Processors.removeProcessFactory(this);
}
}
}