/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
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; either
version 2.1 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53177 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.ogcwebservices.wms;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.deegree.datatypes.QualifiedName;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.xml.NamespaceContext;
import org.deegree.framework.xml.XMLParsingException;
import org.deegree.framework.xml.schema.XMLSchemaException;
import org.deegree.graphics.sld.AbstractLayer;
import org.deegree.graphics.sld.FeatureTypeConstraint;
import org.deegree.graphics.sld.LayerFeatureConstraints;
import org.deegree.graphics.sld.UserLayer;
import org.deegree.model.crs.UnknownCRSException;
import org.deegree.model.feature.schema.FeatureType;
import org.deegree.model.feature.schema.GMLSchema;
import org.deegree.model.feature.schema.GMLSchemaDocument;
import org.deegree.model.feature.schema.GeometryPropertyType;
import org.deegree.ogcbase.ElementStep;
import org.deegree.ogcbase.PropertyPath;
import org.deegree.ogcbase.PropertyPathStep;
import org.deegree.ogcwebservices.InconsistentRequestException;
import org.deegree.ogcwebservices.InvalidParameterValueException;
import org.deegree.ogcwebservices.OGCWebServiceException;
import org.deegree.ogcwebservices.OWSUtils;
import org.deegree.ogcwebservices.wfs.WFService;
import org.deegree.ogcwebservices.wfs.operation.DescribeFeatureType;
import org.deegree.ogcwebservices.wfs.operation.FeatureTypeDescription;
import org.deegree.ogcwebservices.wms.capabilities.Layer;
import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource;
import org.xml.sax.SAXException;
/**
*
*
*
* @version $Revision: 1.4 $
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author: poth $
*
* @version 1.0. $Revision: 1.4 $, $Date: 2006/11/29 21:28:30 $
*
* @since 2.0
*/
public abstract class GetMapServiceInvoker {
private static final ILogger LOG = LoggerFactory.getLogger( GetMapServiceInvoker.class );
private static Map<QualifiedName, List<PropertyPath>> geoProps;
static {
if ( geoProps == null ) {
geoProps = new HashMap<QualifiedName, List<PropertyPath>>();
}
}
protected final DefaultGetMapHandler handler;
protected int index = 0;
protected double scaleDen = 0;
/**
*
* @param handler
* @param index
* @param scaleDen
*/
public GetMapServiceInvoker( DefaultGetMapHandler handler, int index, double scaleDen ) {
this.handler = handler;
this.index = index;
this.scaleDen = scaleDen;
}
/**
* the method accesses the GML schema of the feature types being part of
* the passed FeatureTypeConstraints and extracts the geometry property
* definition. The names of the geometry properties will be added as
* PropertyPath's to passed list
*
* @param layer
* @param ftc
* @param pp
* @return
* @throws OGCWebServiceException
* @throws SAXException
* @throws IOException
* @throws XMLParsingException
* @throws XMLSchemaException
* @throws UnknownCRSException
*/
protected List<PropertyPath> findGeoProperties( AbstractLayer layer, FeatureTypeConstraint[] ftc,
List<PropertyPath> pp )
throws OGCWebServiceException, IOException, SAXException, XMLSchemaException, XMLParsingException, UnknownCRSException {
GMLSchemaDocument doc = null;
for ( int i = 0; i < ftc.length; i++ ) {
if ( geoProps.get( ftc[i].getFeatureTypeName() ) == null ) {
if ( layer instanceof UserLayer && ((UserLayer)layer).getRemoteOWS() != null) {
doc = getSchemaFromRemoteWFS( (UserLayer)layer, ftc[i] );
} else {
doc = getSchemaFromLocalWFS( layer, ftc[i] );
}
GMLSchema schema = doc.parseGMLSchema();
FeatureType ft = schema.getFeatureType( ftc[i].getFeatureTypeName() );
GeometryPropertyType[] gpt = ft.getGeometryProperties();
List<PropertyPath> tmp = new ArrayList<PropertyPath>( gpt.length );
for ( int j = 0; j < gpt.length; j++ ) {
try {
String pre = ftc[i].getFeatureTypeName().getPrefix();
QualifiedName qn = new QualifiedName( pre, gpt[j].getName().getLocalName() ,
gpt[j].getName().getNamespace() );
PropertyPathStep step = new ElementStep( qn );
List<PropertyPathStep> steps = new ArrayList<PropertyPathStep>();
steps.add( step );
PropertyPath prop = new PropertyPath( steps );
pp.add( prop );
tmp.add( prop );
} catch ( Exception e ) {
e.printStackTrace();
}
}
geoProps.put( ftc[i].getFeatureTypeName(), tmp );
} else {
List<PropertyPath> tmp = geoProps.get( ftc[i].getFeatureTypeName() );
pp.addAll( tmp );
}
}
return pp;
}
/**
* accesses the GML schema assigned to the feature type contained within the
* passed FeatureTypeConstraint from a remote WFS by performing a
* DescribeFeatureType request
*
* @param layer
* @param ftc
* @return
* @throws InconsistentRequestException
* @throws InvalidParameterValueException
* @throws OGCWebServiceException
*/
private GMLSchemaDocument getSchemaFromLocalWFS( AbstractLayer layer, FeatureTypeConstraint ftc )
throws InconsistentRequestException, InvalidParameterValueException, OGCWebServiceException {
StringBuffer sb = new StringBuffer( 300 );
sb.append( "SERVICE=WFS&VERSION=1.1.0&REQUEST=DescribeFeatureType&TYPENAME=" );
QualifiedName qn = ftc.getFeatureTypeName();
sb.append( qn.getAsString() );
sb.append( "&NAMESPACE=xmlns(" ).append( qn.getPrefix() ).append( '=' );
sb.append( qn.getNamespace().toASCIIString() ).append( ')' );
LOG.logDebug( "DescribeFeaturetType for UserLayer: ", sb );
DescribeFeatureType dft = DescribeFeatureType.create( "rt", sb.toString() );
WFService wfs = getResponsibleService( layer );
FeatureTypeDescription ftd = (FeatureTypeDescription)wfs.doService( dft );
GMLSchemaDocument doc = new GMLSchemaDocument();
doc.setRootElement( ftd.getFeatureTypeSchema().getRootElement() );
return doc;
}
/**
* accesses the GML schema assigned to the feature type contained within the
* passed FeatureTypeConstraint from a local WFS by performing a
* DescribeFeatureType request
*
* @param ftc
* @return
* @throws IOException
* @throws SAXException
* @throws MalformedURLException
*/
private GMLSchemaDocument getSchemaFromRemoteWFS( UserLayer layer, FeatureTypeConstraint ftc )
throws IOException, SAXException, MalformedURLException {
URL url = layer.getRemoteOWS().getOnlineResource();
StringBuffer sb = new StringBuffer( 300 );
sb.append( OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) );
sb.append( "SERVICE=WFS&VERSION=1.1.0&REQUEST=DescribeFeatureType&TYPENAME=" );
QualifiedName qn = ftc.getFeatureTypeName();
sb.append( qn.getAsString() );
sb.append( "&NAMESPACE=xmlns(" ).append( qn.getPrefix() ).append( '=' );
sb.append( qn.getNamespace().toASCIIString() ).append( ')' );
LOG.logDebug( "DescribeFeaturetType for UserLayer: ", sb );
GMLSchemaDocument doc = new GMLSchemaDocument();
doc.load( new URL( sb.toString() ) );
return doc;
}
/**
* @return the service instance
* @throws OGCWebServiceException if no service could be found
*/
protected WFService getResponsibleService(AbstractLayer layer)
throws OGCWebServiceException {
LayerFeatureConstraints lfc = layer.getLayerFeatureConstraints();
FeatureTypeConstraint[] ftc = lfc.getFeatureTypeConstraint();
Layer root = handler.getConfiguration().getLayer();
WFService wfs = findService( root, ftc[0].getFeatureTypeName() );
if ( wfs == null ) {
throw new OGCWebServiceException( this.getClass().getName(), "feature type: "
+ ftc[0].getFeatureTypeName()
+ " is not served by this WMS/WFS" );
}
return wfs;
}
/**
* searches/findes the WFService that is resposible for handling the feature
* types of the current request. If no WFService instance can be found
* <code>null</code> will be returned to indicated that the current feature
* type is not served by the internal WFS of a WMS
* @param layer
* @param featureType
* @return the service instance or null
* @throws OGCWebServiceException
*/
private WFService findService( Layer layer, QualifiedName featureType )
throws OGCWebServiceException {
Layer[] layers = layer.getLayer();
for ( int i = 0; i < layers.length; i++ ) {
AbstractDataSource[] ad = layers[i].getDataSource();
if ( ad != null ) {
for ( int j = 0; j < ad.length; j++ ) {
if ( ad[j].getName().equals( featureType ) ) {
return (WFService) ad[j].getOGCWebService();
}
}
}
// recursion
WFService wfs = findService( layers[i], featureType );
if ( wfs != null ) {
return wfs;
}
}
return null;
}
/**
* extracts all used namespace definiations from a set of PropertyPath's
* @param pp
* @return
*/
protected Map extractNameSpaceDef( List<PropertyPath> pp ) {
Map<String, URI> map = new HashMap<String, URI>();
for ( int i = 0; i < pp.size(); i++ ) {
NamespaceContext nsc = pp.get( i ).getNamespaceContext();
map.putAll( nsc.getNamespaceMap() );
}
return map;
}
}
/* ********************************************************************
Changes to this class. What the people have been up to:
$Log: GetMapServiceInvoker.java,v $
Revision 1.4 2006/11/29 21:28:30 poth
bug fixing - SLD GetMap requests containing user layers with featuretypeconstraints
Revision 1.3 2006/11/27 09:07:52 poth
JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
Revision 1.2 2006/10/17 20:31:17 poth
*** empty log message ***
Revision 1.1 2006/10/07 15:04:03 poth
initial check in
********************************************************************** */