/* Package GeoTools/WMS Implementation
* Copyright (C) 2001 Cameron Shorter (camerons@users.sourceforge.net)
* Artur Hefczyc (kobit@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: OGCCapabilities.java,v 1.15 2002/01/31 10:16:58 ianturton Exp $
* $Author: ianturton $
* $Date: 2002/01/31 10:16:58 $
*/
package uk.ac.leeds.ccg.ogc;
import java.util.*;
import java.io.*;
import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.*;
import org.apache.xerces.dom.*;
import org.apache.xml.serialize.*;
import org.xml.sax.*;
/**
* Class OGCCapabilities
contains methods for parsing
* WMSCapabilities
data in XML
format.
* As a result of parsing, instance of this class, may return information
* if this is realy capabilities file and than can create objects
* representing special kind of info stored in capabilities.
* For example, after parsing capabilities file you can request
* for available services on WMSServer
. As a result
* you will get array with class instances representing every
* kind of service available on WMSServer
.
* Through the service instance you can exchange data between
* service on WMSServer
and local client displaing
* geo data on the screen.
*
OGCWebMapService
. According to OGC implementation
* specification ver. 1.1.0 every Web Map Server should make
* accesible at least Web Map Service
.
*
* @author Cameron Shorter
* @author Artur Hefczyc
* @version $Revision: 1.15 $
*/
public class OGCCapabilities {
private Document doc = null;
private String capa_version = null;
private int parseWarnings = 0;
private int parseErrors = 0;
private int parseFatalErrors = 0;
/**
* Creates a new OGCCapabilities
instance.
*
* @param is an InputStream
value
* @exception IOException if an error occurs
* @exception SAXException if an error occurs
*/
public OGCCapabilities(InputStream is)
throws IOException, SAXException, Exception {
parseCapabilities(is);
}
/**
* initialize
method initializes OGCCapabilities
* object for reuse with another document to parse.
*
*/
public void initialize() {
doc = null;
capa_version = null;
parseWarnings = 0;
parseErrors = 0;
parseFatalErrors = 0;
}
/**
* parseCapabilities
method checks correctness of capability
* data received from Web Map Server. It checks both XML syntax and
* structure.
*
* @param is an InputStream
where from method should read capability data.
*/
public void parseCapabilities(InputStream is) throws Exception {
/* I am not sure if "is" should be checked that it is not equal null */
if(is != null) {
CapabilitiesParser parser = new CapabilitiesParser();
//try {
doc = parser.parse(is);
System.out.println("Finished reading/parsing capabilities");
is.close();
try {
Element root = doc.getDocumentElement();
Attr at = root.getAttributeNode(OGCXMLConstants.ATT_VERSION);
capa_version = new String(at.getValue());
} catch(NullPointerException npe) {
capa_version = null;
}
//} catch (Exception e) {
//prln("error in OGCCapabilities");
//e.printStackTrace();
//}
}
}
/**
* getAvailableServices
method returns array of available
* WebServices
on remote WMS.
*
* @return an OGCWebService[]
value
*/
/*
public OGCWebService[] getAvailableServices()
{
if(doc != null) {
NodeList nl = doc.getElementsByTagName(OGCXMLConstants.TAG_SERVICE);
if(nl.getLength() > 0) {
OGCWebService[] services = new OGCWebService[nl.getLength()];
for(int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
String service_type = getSubtagText(node, OGCXMLConstants.TAG_NAME);
services[i] = OGCServiceFactory.createOGCService(service_type);
services[i].setServiceName(getSubtagText(node, OGCXMLConstants.TAG_TITLE));
services[i].setServiceDescription(getSubtagText(node, OGCXMLConstants.TAG_ABSTRACT));
services[i].setCapabilities(this);
}
return services;
}
}
return null;
}
*/
/**
* getAvailableLayers
method build list of geo layers available
* on remote WebMap Server.
*
* @return an ArrayList
WMS layers list.
*/
public ArrayList getAvailableLayers() {
if(doc != null) {
NodeList nl = doc.getElementsByTagName(OGCXMLConstants.TAG_LAYER);
System.out.println("OGC Cap: "+nl.getLength()+" layers");
if(nl.getLength() > 0) {
ArrayList layers = new ArrayList();
for(int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
System.out.println(""+i+" "+node+" "+node.getNodeType());
if(node.getNodeType() == Node.ELEMENT_NODE) {
String attr_value = ((Element)node).getAttribute(OGCXMLConstants.ATT_QUERYABLE);
System.out.println("\t"+attr_value);
//if(attr_value != null && attr_value.equals("1")) {
String lay_name = null, lay_title = null, lay_abstr = null;
double ll_maxx = 0, ll_maxy = 0, ll_minx = 0, ll_miny = 0;
String st_name = null, st_title = null;
double leg_h = 0, leg_w = 0;
String leg_format = null, leg_resource = null;
lay_name = getSubtagText(node, OGCXMLConstants.TAG_NAME);
lay_title = getSubtagText(node, OGCXMLConstants.TAG_TITLE);
lay_abstr = getSubtagText(node, OGCXMLConstants.TAG_ABSTRACT);
System.out.println("\t"+lay_name+" "+lay_title+" "+lay_abstr);
Node sub_node = getFirstSubnodeByTagName(node, OGCXMLConstants.TAG_LAT_LON_BB);
try {
System.out.println("ll_maxx:"+((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MAXX));
ll_maxx =
Double.parseDouble(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MAXX));
ll_maxy =
Double.parseDouble(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MAXY));
ll_minx =
Double.parseDouble(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MINX));
ll_miny =
Double.parseDouble(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MINY));
} catch(Exception e) {
ll_maxx = 0; ll_maxy = 0; ll_minx = 0; ll_miny = 0;
}
sub_node = getFirstSubnodeByTagName(node, OGCXMLConstants.TAG_STYLE);
st_name = getSubtagText(sub_node, OGCXMLConstants.TAG_NAME);
st_title = getSubtagText(sub_node, OGCXMLConstants.TAG_TITLE);
sub_node = getFirstSubnodeByTagName(sub_node, OGCXMLConstants.TAG_LEGEND_URL);
try {
leg_h =
Integer.parseInt(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_HEIGHT));
leg_w =
Integer.parseInt(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_WIDTH));
} catch(Exception e) {
leg_h = 0; leg_w = 0;
}
leg_format = getSubtagText(sub_node, OGCXMLConstants.TAG_FORMAT);
sub_node = getFirstSubnodeByTagName(sub_node, OGCXMLConstants.TAG_ONLINE_RES);
if(sub_node != null)
leg_resource = ((Element)sub_node).getAttribute(OGCXMLConstants.ATT_XLNK_HREF);
if(lay_name != null && !lay_name.equals("")) {
ExternalWMSLayer ext_wms_lay =
new ExternalWMSLayer(lay_name, lay_title, ll_maxx, ll_maxy, ll_minx, ll_miny);
ext_wms_lay.setLayerAbstract(lay_abstr);
// ext_wms_lay.setLayerStyle(st_name, st_title);
ext_wms_lay.setLayerLegend(leg_h, leg_w, leg_format, leg_resource);
layers.add(ext_wms_lay);
}
//}
}else{
System.out.println("not a Node.ELEMENT_NODE");
}
}
return layers;
}
System.out.println("No layers found");
}
System.out.println("OGC Cap - Doc == null");
return null;
}
/**
* getAvailableFormats
method builds ArrayList
* with available formats which support remote WMS.
*
* @param service_type a String
value
* @return an ArrayList
value
*/
public ArrayList getAvailableFormats(String service_type) {
ArrayList formats = new ArrayList();
WMSFormat format = new WMSFormat("JPEG");
formats.add(format);
return formats;
/*
if(doc != null) {
System.out.println("Asking for "+service_type+" formats");
NodeList service = doc.getElementsByTagName(service_type);
for(int i=0;igetCapabilitiesVersion
method returns capability version
* found in received capability data.
*
* @return a String
value
*/
String getCapabilitiesVersion() {
return capa_version;
}
protected Node getFirstSubnodeByTagName(Node node, String tagName) {
if(node != null) {
NodeList nl = ((Element)node).getElementsByTagName(tagName);
if(nl.getLength() > 0)
return nl.item(0);
}
return null;
}
protected String getTagText(Node node) {
if(node != null) {
Node text_node = node.getFirstChild();
if(text_node.getNodeType() == Node.TEXT_NODE) {
return ((Text)text_node).getData();
}
}
return null;
}
protected String getSubtagText(Node node, String tagName) {
if(node != null) {
NodeList subnodes = node.getChildNodes();
for(int i = 0; i < subnodes.getLength(); i++) {
if(subnodes.item(i).getNodeName().equals(tagName)) {
Node subnode = subnodes.item(i);
Node text_node = subnode.getFirstChild();
if(null==text_node) return null;
if(text_node.getNodeType() == Node.TEXT_NODE) {
return ((Text)text_node).getData();
}
}
}
}
return null;
}
/**
* printCapabilitiesXML
method sends capability in XML
* format to given OutputStream
*
*/
public void printCapabilitiesXML(OutputStream out) {
try {
OutputFormat of = new OutputFormat();
of.setIndenting(true);
of.setIndent(2);
of.setLineWidth(80);
of.setMethod("xml");
// of.setOmitComments(false);
// of.setOmitDocumentType(false);
of.setOmitXMLDeclaration(false);
// SerializerFactory sf = SerializerFactory.getSerializerFactory("xml");
// DOMSerializer serializer = (DOMSerializer)sf.makeSerializer(out, of);
XMLSerializer serializer = new XMLSerializer(out, of);
serializer.serialize(doc);
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
/**
* capabilitiesQuery
method returns query for capabilities
* to WMS server.
*
* @param version a String
value contains version of WMS
* specification which we need to build query.
* @return a String
value contains query for capabilities
* including '?' at the beginning of string.
*/
public static String capabilitiesQuery(String version) {
System.err.println("Version string request "+version);
if(version.equals("1.1.0"))
return OGCConstants.PAR_V110_VERSION+"="+OGCConstants.VERSION_V110+
"&"+OGCConstants.PAR_V110_SERVICE+"="+OGCConstants.VAL_V110_WMS+
"&"+OGCConstants.PAR_V110_REQUEST+"="+OGCConstants.VAL_V110_GETCAPABILITIES+
"&"+OGCConstants.PAR_V110_UPDATESEQUENCE+"=0";
if(version.equals("1.0.0"))
return OGCConstants.PAR_V100_VERSION+"="+OGCConstants.VERSION_V100+
"&"+OGCConstants.PAR_V100_REQUEST+"="+OGCConstants.VAL_V100_GETCAPABILITIES;
return null;
}
protected void prln(String str) {
System.err.println(str);
}
/**
* Wraps the Xerces DOM parser and extends NonValidatingDOMParser.
* Code based on xercesSamples.dom.wrappers.DOMParser.
* @version $id$
*/
class CapabilitiesParser implements ErrorHandler {
/** Parser. */
private DOMParser parser = new DOMParser();
/** Default constructor. */
public CapabilitiesParser() {
try {
parser.setFeature( "http://xml.org/sax/features/validation", false);
parser.setFeature( "http://apache.org/xml/features/validation/schema", false);
parser.setFeature( "http://apache.org/xml/features/validation/dynamic", false);
parser.setFeature( "http://apache.org/xml/features/validation/schema-full-checking",
false);
parser.setFeature( "http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
parser.setFeature( "http://apache.org/xml/features/nonvalidating/load-external-dtd",
false);
} catch (SAXException e) {
prln("error in setting up parser feature");
}
parser.setErrorHandler(this);
// String[] features = parser.getFeaturesRecognized();
// String[] properts = parser.getPropertiesRecognized();
// System.err.println("Features: "+features.length);
// for (int i = 0; i < features.length; i++) {
// try {
// System.err.println(features[i]+ " = " +parser.getFeature(features[i]));
// } catch (SAXException e) {
// System.err.println("Problem with: "+features[i]);
// }
// } // end of for (int i = 0; i < features.length; i++)
// System.err.println("Properties: "+properts.length);
// for (int i = 0; i < properts.length; i++) {
// try {
// System.err.println(properts[i]+ " = " +parser.getProperty(properts[i]));
// } catch (SAXException e) {
// System.err.println("Problem with: "+properts[i]);
// }
// } // end of for (int i = 0; i < properts.length; i++)
}
/** Parses the specified URI and returns the document. */
public Document parse(String uri) throws Exception {
parser.parse(uri);
System.out.println("Cap Parsed");
return parser.getDocument();
}
/** Parses the specified URI and returns the document. */
public Document parse(InputStream is) throws Exception {
parser.parse(new InputSource(is));
return parser.getDocument();
}
public void setFeature(String featureId, boolean state)
throws SAXNotRecognizedException, SAXNotSupportedException {
try {
parser.setFeature(featureId, state);
} catch (SAXException e) {
prln("error in setting up parser feature");
}
}
/** Warning. */
public void warning(SAXParseException ex) {
parseWarnings++;
prln("[Warning] "+getLocationString(ex)+": "+ex.getMessage());
}
/** Error. */
public void error(SAXParseException ex) {
parseErrors++;
prln("[Error] "+getLocationString(ex)+": "+ex.getMessage());
}
/** Fatal error. */
public void fatalError(SAXParseException ex) throws SAXException {
parseFatalErrors++;
prln("[Fatal Error] "+getLocationString(ex)+": "+ex.getMessage());
throw ex;
}
/** Returns a string of the location. */
private String getLocationString(SAXParseException ex) {
StringBuffer str = new StringBuffer();
String systemId = ex.getSystemId();
if(systemId != null) {
int index = systemId.lastIndexOf('/');
if (index != -1)
systemId = systemId.substring(index + 1);
str.append(systemId);
}
str.append(':');
str.append(ex.getLineNumber());
str.append(':');
str.append(ex.getColumnNumber());
return str.toString();
}
}
}
/*
* Changes in file:
*
* $Log: OGCCapabilities.java,v $
* Revision 1.15 2002/01/31 10:16:58 ianturton
* initial changes to support new format xml capabilities files now look like
*