package org.geotools.demo;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.geotools.data.ows.CRSEnvelope;
import org.geotools.data.ows.Layer;
import org.geotools.data.ows.OperationType;
import org.geotools.data.ows.Service;
import org.geotools.data.ows.StyleImpl;
import org.geotools.data.ows.WMSCapabilities;
import org.geotools.data.ows.WMSRequest;
import org.geotools.data.wms.WMSUtils;
import org.geotools.data.wms.WebMapServer;
import org.geotools.data.wms.request.GetLegendGraphicRequest;
import org.geotools.data.wms.request.GetMapRequest;
/**
* This lab explores the use of the GeoTools WMS client code.
* <p>
* The GeoTools WMS client is a little bit more than simply sending away GetMap
* request, the trick is to send the correct GetMap request based on the version
* of the web map server specification the server supports, and be able to chose
* layers and styles supported by the server.
*
* @author Jody Garnett
*
* @source $URL$
*/
public class WMSLab2 extends JFrame {
private static final long serialVersionUID = -3039255518595806472L;
/** Original coverage we are working on */
WebMapServer wms;
CoveragePanel panel;
Image image;
JList layers;
JButton getMapButton;
JComboBox styleCombo;
/**
* Map<Layer,Style> as controlled by styleCombo box
*/
Map styles = new HashMap();
Layer selectedLayer = null;
DefaultComboBoxModel availableStyles;
/**
* Explore the functionality of the provided GridCoverage (think
* BufferedImage + CRS).
* <p>
* A GridCoverage literally a set of features that "covers" an area without
* gaps; in the case of grid coverage the area is covered by an regular
* grid.
* <p>
* Coverage work by letting you call a "sample" operation in order to
* retrieve a Record of the data at the location. A grid coverage lets you
* express the location using row and column.
* <p>
*
* @param coverage
*/
public WMSLab2(WebMapServer server) {
this.wms = server;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
String title = getWMSTitle(wms);
setTitle(title);
Set good = new HashSet( Arrays.asList( WMSUtils.getNamedLayers(wms.getCapabilities())));
this.layers = new JList(good.toArray());
layers.setCellRenderer(new LayerCellRenderer());
layers.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
setSelectedLayer((Layer) layers.getSelectedValue());
}
});
JScrollPane scrollPane = new JScrollPane(layers);
scrollPane.setPreferredSize(new Dimension(200, 400));
add(scrollPane, BorderLayout.WEST);
this.panel = new CoveragePanel();
add(panel, BorderLayout.CENTER);
JPanel buttons = new JPanel();
getMapButton = new JButton("GetMap");
getMapButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
getMap();
}
});
buttons.add(getMapButton);
availableStyles = new DefaultComboBoxModel();
styleCombo = new JComboBox(availableStyles);
styleCombo.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (selectedLayer != null) {
styles.put(selectedLayer, styleCombo.getSelectedItem());
}
}
});
styleCombo.setRenderer(new StyleCellRenderer());
buttons.add(styleCombo);
add(buttons, BorderLayout.NORTH);
pack();
}
public String getWMSTitle(WebMapServer wms) {
WMSCapabilities capabilities = wms.getCapabilities();
Service service = capabilities.getService();
String title = service.getTitle();
return title;
}
public void setSelectedLayer(Layer selected) {
availableStyles.removeAllElements();
this.selectedLayer = selected;
if (selected != null) {
// availableStyles.addElement("default");
for( StyleImpl style : selected.getStyles() ){
availableStyles.addElement(style);
}
}
styleCombo.repaint();
}
class StyleCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 7421698429520525469L;
public Component getListCellRendererComponent(JList list, Object value, // value
// to
// display
int index, // cell index
boolean iss, // is the cell selected
boolean chf) // the list and the cell have the focus
{
super.getListCellRendererComponent(list, value, index, iss, chf);
StyleImpl style = (StyleImpl) value;
if (style == null)
return this;
String title = style.getTitle() == null ? style.getName() : style
.getTitle().toString();
setText(title);
return this;
}
Icon getIcon(StyleImpl style) {
List urlList = style.getLegendURLs();
if (urlList == null || urlList.isEmpty())
return null;
URL url = (URL) style.getLegendURLs().get(0);
ImageIcon icon = new ImageIcon(url);
return icon;
}
}
class LayerCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 1173012107250651733L;
HashMap icons = new HashMap();
public Component getListCellRendererComponent(JList list, Object value, // value
// to
// display
int index, // cell index
boolean iss, // is the cell selected
boolean chf) // the list and the cell have the focus
{
super.getListCellRendererComponent(list, value, index, iss, chf);
Layer layer = (Layer) value;
setText(layer.getTitle());
Icon glyph;
if (icons.containsKey(layer)) {
glyph = (Icon) icons.get(layer);
} else {
glyph = getLegendGraphics(layer);
icons.put(layer, glyph);
}
setIcon(glyph);
setToolTipText(layer.getName());
return this;
}
}
public Icon getLegendGraphics(Layer layer) {
Icon icon = null;
WMSCapabilities capabilities = wms.getCapabilities();
WMSRequest request = capabilities.getRequest();
OperationType description = request.getGetLegendGraphic();
if (description == null) return null;
GetLegendGraphicRequest legendGraphicsRequest = wms
.createGetLegendGraphicRequest();
legendGraphicsRequest.setLayer(layer.getName());
legendGraphicsRequest.setStyle(getNamedStyle(layer));
legendGraphicsRequest.setFormat((String) description.getFormats()
.iterator().next());
URL url = legendGraphicsRequest.getFinalURL();
return new ImageIcon(url);
}
private String getNamedStyle(Layer layer) {
Object layerStyle = styles.get(layer);
String namedStyle = null;
if (layerStyle == null) {
namedStyle = null;
} else if (layerStyle instanceof String) {
namedStyle = (String) layerStyle;
} else if (layerStyle instanceof StyleImpl) {
StyleImpl style = (StyleImpl) layerStyle;
namedStyle = style.getName();
}
return namedStyle;
}
public void getMap() {
try {
if (true) {
Layer selected = (Layer) layers.getSelectedValue();
getMap(selected);
}
Object selection[] = layers.getSelectedValues();
List layerList = Arrays.asList(selection);
getMap(layerList);
} catch (Exception e1) {
image = null;
}
}
private void getMap(Layer layer) throws Exception {
GetMapRequest mapRequest = wms.createGetMapRequest();
String style = getNamedStyle( layer );
mapRequest.addLayer(layer, style);
mapRequest.setFormat(getImageFormat(wms));
CRSEnvelope box = getCRSEnvelope(layer, null);
if (box == null) {
box = layer.getLatLonBoundingBox();
box.setEPSGCode("EPSG:4326");
}
mapRequest.setSRS(box.getEPSGCode());
mapRequest.setBBox(box);
mapRequest.setDimensions(panel.getWidth(), panel.getHeight());
URL url = mapRequest.getFinalURL();
ImageIcon load = new ImageIcon(url);
image = load.getImage();
panel.repaint();
}
private void getMap(List layers) throws Exception {
if (layers == null || layers.isEmpty())
return;
GetMapRequest mapRequest = wms.createGetMapRequest();
CRSEnvelope bounds = null;
for (Iterator i = layers.iterator(); i.hasNext();) {
Layer layer = (Layer) i.next();
String namedStyle = getNamedStyle(layer);
mapRequest.addLayer(layer, namedStyle);
CRSEnvelope box = layer.getLatLonBoundingBox();
box.setEPSGCode("EPSG:4326");
if (box != null) {
if (bounds != null) {
bounds.setMinX(Math.min(bounds.getMinX(), box.getMinX()));
bounds.setMaxX(Math.max(bounds.getMaxX(), box.getMaxX()));
bounds.setMinY(Math.min(bounds.getMinY(), box.getMinY()));
bounds.setMaxY(Math.max(bounds.getMaxY(), box.getMaxY()));
} else {
bounds = box;
}
}
}
if (bounds == null) {
bounds = new CRSEnvelope();
bounds.setEPSGCode("EPSG:4326");
}
mapRequest.setFormat(getImageFormat(wms));
mapRequest.setSRS(bounds.getEPSGCode());
mapRequest.setBBox(bounds);
mapRequest.setDimensions(panel.getWidth(), panel.getHeight());
URL url = mapRequest.getFinalURL();
ImageIcon load = new ImageIcon(url);
image = load.getImage();
panel.repaint();
}
/**
* Some WMS Servers like GeoServer support strange formats like KML and PDF
*
* @return
*/
String getImageFormat(WebMapServer wms) {
OperationType description = wms.getCapabilities().getRequest()
.getGetMap();
List formats = description.getFormats();
for (Iterator i = formats.iterator(); i.hasNext();) {
String format = (String) i.next();
if (format.indexOf("pdf") != -1)
continue;
return format;
}
return "image/jpeg";
}
/**
* Search through the layer data structure for bounds for the provided srs
* (if null we will return the first bounds).
*
* @param srs
* @return CRSEnvelope
*/
CRSEnvelope getCRSEnvelope(Layer layer, String srs) {
if (layer == null)
return null;
Map boundingBoxes = layer.getBoundingBoxes();
if (boundingBoxes != null && !boundingBoxes.isEmpty()) {
for (Iterator i = boundingBoxes.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Entry) i.next();
String layerSrs = (String) entry.getKey();
CRSEnvelope box = (CRSEnvelope) entry.getValue();
if (srs == null || srs.equals(layerSrs)) {
return box;
}
}
}
return getCRSEnvelope(layer.getParent(), srs);
}
class CoveragePanel extends JPanel {
private static final long serialVersionUID = -4755270758709990530L;
CoveragePanel() {
setBackground(Color.WHITE);
}
public Dimension getPreferredSize() {
return new Dimension(640, 400);
}
public void paintComponent(Graphics graphics) {
super.paintComponents(graphics);
if (image != null) {
Graphics2D g = (Graphics2D) graphics;
g.drawImage(image, 0, 0, null);
}
}
}
/**
* Prompt the user for a file and open up ImageLab.
*
* @param args
* filename of image
*/
public static void main(String[] args) throws Exception {
URL server = getServerURL(args);
WebMapServer wms;
System.out.println("Connecting to " + server);
wms = new WebMapServer(server);
System.out.println("Welcome");
WMSLab2 wmsLab = new WMSLab2(wms);
wmsLab.setVisible(true);
}
public static String[] getLayerNames(WebMapServer wms) {
Layer[] namedLayers = WMSUtils.getNamedLayers(wms.getCapabilities());
String[] names = new String[namedLayers.length];
for (int i = 0; i < namedLayers.length; i++) {
Layer layer = namedLayers[i];
names[i] = layer.getName();
}
return names;
}
public static URL getServerURL(String[] args) throws MalformedURLException {
if (args.length == 0) {
Object[] servers = new Object[] {
"http://localhost:8080/geoserver/wms?service=WMS&request=GetCapabilities",
"http://www2.dmsolutions.ca/cgi-bin/mswms_gmap?Service=WMS&VERSION=1.1.0&REQUEST=GetCapabilities",
"http://wms.jpl.nasa.gov/wms.cgi?Service=WMS&Version=1.1.1&Request=GetCapabilities",
"http://giswebservices.massgis.state.ma.us/geoserver/wms?service=WMS&request=GetCapabilities",
"http://wms.cits.rncan.gc.ca/cgi-bin/cubeserv.cgi?VERSION=1.1.0&REQUEST=GetCapabilities",
"http://atlas.gc.ca/cgi-bin/atlaswms_en?VERSION=1.1.1&Request=GetCapabilities&Service=WMS", };
Object selected = JOptionPane.showInputDialog(null,
"WMS GetCapabilities URL", "Choose a WMS Server",
JOptionPane.QUESTION_MESSAGE, null, servers, null);
if (selected == null)
System.exit(0);
return new URL((String) selected);
} else {
return new URL(args[0]);
}
}
}