/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.data.wms;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.geotools.data.ows.Layer;
import org.geotools.data.ows.WMSCapabilities;
import org.geotools.referencing.CRS;
import org.opengis.metadata.Identifier;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
/**
* Provides miscellaneous utility methods for use with WMSs.
*
* @author Richard Gould
*
* @source $URL$
*/
public class WMSUtils {
/**
* Utility method to return each layer that has a name. This method maintains no hierarchy at all.
*
* @return An array of Layers, each value has a it's name property set or an empty array if there are none. It will return null if there is no capabilities document
*
*/
public static Layer[] getNamedLayers(WMSCapabilities capabilities) {
if (capabilities == null) {
return null;
}
List namedLayersList = new ArrayList();
Layer[] layers = (Layer[]) capabilities.getLayerList().toArray(new Layer[capabilities.getLayerList().size()]);
for( int i = 0; i < layers.length; i++ ) {
if ((layers[i].getName() != null) && (layers[i].getName().length() != 0)) {
namedLayersList.add(layers[i]);
}
}
Layer[] namedLayers = new Layer[namedLayersList.size()];
for (int i = 0; i < namedLayersList.size(); i++) {
namedLayers[i] = (Layer) namedLayersList.get(i);
}
return namedLayers;
}
public static Set getQueryableLayers(WMSCapabilities capabilities) {
Set layers = new TreeSet();
Layer[] namedLayers = getNamedLayers(capabilities);
for( int i = 0; i < namedLayers.length; i++ ) {
Layer layer = namedLayers[i];
if (layer.isQueryable()) {
layers.add(layer);
}
}
return layers;
}
public static Set getSRSs(WMSCapabilities capabilities) {
Set srss = new TreeSet();
Layer[] layers = (Layer[]) capabilities.getLayerList().toArray(new Layer[capabilities.getLayerList().size()]);
for( int i = 0; i < layers.length; i++ ) {
if (layers[i].getSrs() != null) {
srss.addAll(layers[i].getSrs());
}
}
return srss;
}
/**
* Given a list of type Layer, return all EPSG codes that is supported
* by all of the layers. This is an intersection of each layer's SRS set.
*
* @param layers A List of type Layer
* @return a Set of type String, containin EPSG codes, or empty if none found
*/
public static Set findCommonEPSGs(List layers) {
TreeSet set = new TreeSet();
Layer first = (Layer) layers.get(0);
set.addAll(first.getSrs());
for (int i = 1; i < layers.size(); i++ ) {
Layer layer = (Layer) layers.get(i);
set.retainAll(layer.getSrs());
}
return set;
}
//Map<CoordinateReferenceSystem, TreeSet<String>>
private static Map crsCache;
static {
crsCache = new HashMap();
}
/**
* Given a CRS and a Set of type String consisting of EPSG CRS codes
* (such as "EPSG:4326"), it will check the transform that exists between
* each EPSG code's CRS and the given CRS. If this is the identity
* transform, meaning the CRS is equivalent to the EPSG code,
* the used EPSG code will be returned. The first valid EPSG code found
* is returned, so it is possibly that multiple valid codes exist.
*
* If no such identity transform can be found, null will be returned.
*
* If this method is succesful, the result is stored in a cache, which is
* called in subsequent calls.
*
* @param crs a CRS that is to be compared to each EPSG code in codes
* @param codes a Set of type String containing EPSG codes
* @return an EPSG code that correspondes to crs, or null if one can't be found
*/
public static String matchEPSG(CoordinateReferenceSystem crs, Set codes) {
TreeSet previous = (TreeSet) crsCache.get(crs);
if (previous != null) {
Iterator iter = previous.iterator();
while (iter.hasNext()) {
String code = (String) iter.next();
if (codes.contains(code)) {
return code;
}
}
}
Iterator iter = crs.getIdentifiers().iterator();
while (iter.hasNext()) {
Identifier ident = (Identifier) iter.next();
String epsgCode = ident.toString();
if (codes.contains(epsgCode)) {
if (crsCache.get(crs) == null) {
crsCache.put(crs, new TreeSet());
}
TreeSet set = (TreeSet) crsCache.get(crs);
set.add(epsgCode);
return epsgCode;
}
}
iter = null;
iter = codes.iterator();
while (iter.hasNext()) {
String epsgCode = (String) iter.next();
CoordinateReferenceSystem epsgCRS;
try {
epsgCRS = CRS.decode(epsgCode);
} catch (Exception e) {
// e.printStackTrace();
continue;
}
MathTransform transform;
try {
transform = CRS.findMathTransform(crs, epsgCRS, true);
} catch (FactoryException e) {
// e.printStackTrace();
continue;
}
if (transform.isIdentity()) {
if (crsCache.get(crs) == null) {
crsCache.put(crs, new TreeSet());
}
TreeSet set = (TreeSet) crsCache.get(crs);
set.add(epsgCode);
return epsgCode;
}
}
return null;
}
}