Skip to content

Commit 6bf5af0

Browse files
committedJul 12, 2012
wcs exceptions, simplified xml parsing
1 parent 6e0a80a commit 6bf5af0

File tree

5 files changed

+286
-477
lines changed

5 files changed

+286
-477
lines changed
 

‎src/providers/wcs/qgswcscapabilities.cpp

Lines changed: 105 additions & 231 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,6 @@
6565
#include <QDir>
6666
#endif
6767

68-
/*
69-
QgsWcsCapabilities::QgsWcsCapabilities( QString const &theUri )
70-
{
71-
mUri.setEncodedUri( theUri );
72-
73-
QgsDebugMsg( "theUri = " + theUri );
74-
}
75-
*/
76-
7768
QgsWcsCapabilities::QgsWcsCapabilities( QgsDataSourceURI const &theUri ):
7869
mUri( theUri ),
7970
mCoverageCount( 0 )
@@ -140,7 +131,7 @@ bool QgsWcsCapabilities::supportedCoverages( QVector<QgsWcsCoverageSummary> &cov
140131

141132
QString QgsWcsCapabilities::getCoverageUrl() const
142133
{
143-
QString url = mCapabilities.operationsMetadata.getCoverage.dcp.http.get.xlinkHref;
134+
QString url = mCapabilities.operationsMetadata.getCoverage.getUrl;
144135
if ( url.isEmpty() )
145136
{
146137
url = mUri.param( "url" );
@@ -404,44 +395,31 @@ bool QgsWcsCapabilities::parseCapabilitiesDom( QByteArray const &xml, QgsWcsCapa
404395
return false;
405396
}
406397

407-
// Start walking through XML.
408-
QDomNode n = docElem.firstChild();
398+
if ( mVersion.startsWith( "1.0" ) )
399+
{
400+
capabilities.title = domElementText( docElem, "Service.name" );
401+
capabilities.abstract = domElementText( docElem, "Service.description" );
402+
// There is also "label" in 1.0
403+
404+
capabilities.operationsMetadata.getCoverage.getUrl = domElement( docElem, "Capability.Request.GetCoverage.DCPType.HTTP.Get.OnlineResource" ).attribute( "xlink:href" );
409405

410-
while ( !n.isNull() )
406+
parseContentMetadata( domElement( docElem, "ContentMetadata" ), capabilities.contents );
407+
}
408+
else if ( mVersion.startsWith( "1.1" ) )
411409
{
412-
QDomElement e = n.toElement();
413-
if ( !e.isNull() )
410+
capabilities.title = domElementText( docElem, "ServiceIdentification.Title" );
411+
capabilities.abstract = domElementText( docElem, "ServiceIdentification.Abstract" );
412+
413+
QList<QDomElement> operationElements = domElements( docElem, "OperationsMetadata.Operation" );
414+
foreach( QDomElement el, operationElements )
414415
{
415-
// Version 1.0
416-
QString tagName = stripNS( e.tagName() );
417-
QgsDebugMsg( tagName );
418-
if ( tagName == "Service" )
419-
{
420-
parseService( e, capabilities.serviceIdentification );
421-
}
422-
else if ( tagName == "Capability" )
423-
{
424-
parseCapability( e, capabilities.operationsMetadata );
425-
}
426-
else if ( tagName == "ContentMetadata" )
416+
if ( el.attribute( "name" ) == "GetCoverage" )
427417
{
428-
parseContentMetadata( e, capabilities.contents );
429-
}
430-
// Version 1.1
431-
else if ( tagName == "ServiceIdentification" )
432-
{
433-
parseServiceIdentification( e, capabilities.serviceIdentification );
434-
}
435-
else if ( tagName == "OperationsMetadata" )
436-
{
437-
parseOperationsMetadata( e, capabilities.operationsMetadata );
438-
}
439-
else if ( tagName == "Contents" )
440-
{
441-
parseCoverageSummary( e, capabilities.contents );
418+
capabilities.operationsMetadata.getCoverage.getUrl = domElement( el, "DCP.HTTP.Get" ).attribute( "xlink:href" );
442419
}
443420
}
444-
n = n.nextSibling();
421+
422+
parseCoverageSummary( domElement( docElem, "Contents" ), capabilities.contents );
445423
}
446424

447425
return true;
@@ -458,13 +436,11 @@ QDomElement QgsWcsCapabilities::firstChild( const QDomElement &element, const QS
458436
QString tagName = stripNS( el.tagName() );
459437
if ( tagName == name )
460438
{
461-
//QgsDebugMsg( name + " found" );
462439
return el;
463440
}
464441
}
465442
n1 = n1.nextSibling();
466443
}
467-
//QgsDebugMsg( name + " not found" );
468444
return QDomElement();
469445
}
470446

@@ -473,7 +449,6 @@ QString QgsWcsCapabilities::firstChildText( const QDomElement &element, const QS
473449
QDomElement el = firstChild( element, name );
474450
if ( !el.isNull() )
475451
{
476-
//QgsDebugMsg( name + " : " + el.text() );
477452
return el.text();
478453
}
479454
return QString();
@@ -497,7 +472,6 @@ QList<QDomElement> QgsWcsCapabilities::domElements( const QDomElement &element,
497472
QString tagName = stripNS( el.tagName() );
498473
if ( tagName == name )
499474
{
500-
//QgsDebugMsg( name + " found" );
501475
if ( names.size() == 0 )
502476
{
503477
list.append( el );
@@ -514,6 +488,18 @@ QList<QDomElement> QgsWcsCapabilities::domElements( const QDomElement &element,
514488
return list;
515489
}
516490

491+
QStringList QgsWcsCapabilities::domElementsTexts( const QDomElement &element, const QString &path )
492+
{
493+
QStringList list;
494+
QList<QDomElement> elems = domElements( element, path );
495+
496+
foreach( QDomElement el, elems )
497+
{
498+
list << el.text();
499+
}
500+
return list;
501+
}
502+
517503
QDomElement QgsWcsCapabilities::domElement( const QDomElement &element, const QString & path )
518504
{
519505
QStringList names = path.split( "." );
@@ -568,42 +554,23 @@ QList<double> QgsWcsCapabilities::parseDoubles( const QString &text )
568554
return list;
569555
}
570556

571-
QString QgsWcsCapabilities::crsUrnToAuthId ( const QString &text )
557+
QString QgsWcsCapabilities::crsUrnToAuthId( const QString &text )
572558
{
573-
QString urnCrs = text;
574-
575559
QString authid;
576560

577-
// example: urn:ogc:def:crs:EPSG::4326
578-
QStringList split = urnCrs.remove("urn:ogc:def:crs:").split(":");
579-
if ( split.size() == 3 )
561+
// URN format: urn:ogc:def:objectType:authority:version:code
562+
// URN example: urn:ogc:def:crs:EPSG::4326
563+
QStringList urn = text.split( ":" );
564+
if ( urn.size() == 7 )
580565
{
581-
authid = QString("%1:%2").arg( split.value(0) ).arg(split.value(2) );
566+
authid = urn.value( 4 ) + ":" + urn.value( 6 );
582567
}
568+
583569
return authid;
584570
}
585571

586572
// ------------------------ 1.0 ----------------------------------------------
587-
void QgsWcsCapabilities::parseService( const QDomElement &e, QgsWcsServiceIdentification &serviceIdentification ) // 1.0
588-
{
589-
serviceIdentification.title = firstChildText( e, "name" );
590-
serviceIdentification.abstract = firstChildText( e, "description" );
591-
// 1.0 has also "label"
592-
}
593-
594-
void QgsWcsCapabilities::parseCapability( QDomElement const & e, QgsWcsOperationsMetadata &operationsMetadata )
595-
{
596-
QDomElement requestElement = firstChild( e, "Request" );
597-
QDomElement getCoverageElement = firstChild( requestElement, "GetCoverage" );
598-
QDomElement dcpTypeElement = firstChild( getCoverageElement, "DCPType" );
599-
QDomElement httpElement = firstChild( dcpTypeElement, "HTTP" );
600-
QDomElement getElement = firstChild( httpElement, "Get" );
601-
QDomElement onlineResourceElement = firstChild( getElement, "OnlineResource" );
602-
603-
operationsMetadata.getCoverage.dcp.http.get.xlinkHref = onlineResourceElement.attribute( "xlink:href" );
604573

605-
QgsDebugMsg( "getCoverage.dcp.http.get.xlinkHref = " + operationsMetadata.getCoverage.dcp.http.get.xlinkHref );
606-
}
607574

608575
void QgsWcsCapabilities::parseContentMetadata( QDomElement const & e, QgsWcsCoverageSummary &coverageSummary )
609576
{
@@ -619,13 +586,12 @@ void QgsWcsCapabilities::parseContentMetadata( QDomElement const & e, QgsWcsCove
619586
{
620587
QgsWcsCoverageSummary subCoverageSummary;
621588

622-
subCoverageSummary.described = false;
623-
subCoverageSummary.width = 0;
624-
subCoverageSummary.height = 0;
625-
subCoverageSummary.hasSize = false;
589+
initCoverageSummary( subCoverageSummary );
626590

627591
parseCoverageOfferingBrief( el, subCoverageSummary, &coverageSummary );
628592

593+
subCoverageSummary.valid = true;
594+
629595
coverageSummary.coverageSummary.push_back( subCoverageSummary );
630596
}
631597
}
@@ -643,44 +609,20 @@ void QgsWcsCapabilities::parseCoverageOfferingBrief( QDomElement const & e, QgsW
643609
coverageSummary.title = firstChildText( e, "label" );
644610
coverageSummary.abstract = firstChildText( e, "description" );
645611

646-
QDomElement lonLatEnvelopeElement = firstChild( e, "lonLatEnvelope" );
647-
648-
QDomNodeList posNodes = lonLatEnvelopeElement.elementsByTagName( "gml:pos" );
649-
QList<double> lon, lat;
650-
for ( int i = 0; i < posNodes.size(); i++ )
612+
QList<QDomElement> posElements = domElements( e, "lonLatEnvelope.pos" );
613+
if ( posElements.size() != 2 )
651614
{
652-
QDomNode posNode = posNodes.at( i );
653-
QString lonLatText = posNode.toElement().text();
654-
QStringList lonLat = lonLatText.split( QRegExp( " +" ) );
655-
if ( lonLat.size() != 2 )
656-
{
657-
QgsDebugMsg( "Cannot parse lonLatEnvelope: " + lonLatText );
658-
continue;
659-
}
660-
double lo, la;
661-
bool loOk, laOk;
662-
lo = lonLat.value( 0 ).toDouble( &loOk );
663-
la = lonLat.value( 1 ).toDouble( &laOk );
664-
if ( loOk && laOk )
665-
{
666-
lon << lo;
667-
lat << la;
668-
}
669-
else
670-
{
671-
QgsDebugMsg( "Cannot parse lonLatEnvelope: " + lonLatText );
672-
}
615+
QgsDebugMsg( "Wrong number of pos elements" );
673616
}
674-
if ( lon.size() == 2 )
617+
else
675618
{
676-
double w, e, s, n;
677-
w = qMin( lon[0], lon[1] );
678-
e = qMax( lon[0], lon[1] );
679-
n = qMax( lat[0], lat[1] );
680-
s = qMin( lat[0], lat[1] );
681-
682-
coverageSummary.wgs84BoundingBox = QgsRectangle( w, s, e, n );
683-
QgsDebugMsg( "wgs84BoundingBox = " + coverageSummary.wgs84BoundingBox.toString() );
619+
QList<double> low = parseDoubles( posElements.value( 0 ).text() );
620+
QList<double> high = parseDoubles( posElements.value( 1 ).text() );
621+
if ( low.size() == 2 && high.size() == 2 )
622+
{
623+
coverageSummary.wgs84BoundingBox = QgsRectangle( low[0], low[1], high[0], high[1] ) ;
624+
QgsDebugMsg( "wgs84BoundingBox = " + coverageSummary.wgs84BoundingBox.toString() );
625+
}
684626
}
685627

686628
if ( !coverageSummary.identifier.isEmpty() )
@@ -751,46 +693,15 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
751693
if ( coverageOfferingElement.isNull() ) return false;
752694
QDomElement supportedCRSsElement = firstChild( coverageOfferingElement, "supportedCRSs" );
753695

754-
QDomNode n1 = supportedCRSsElement.firstChild();
755-
while ( !n1.isNull() )
756-
{
757-
QDomElement el = n1.toElement();
758-
if ( !el.isNull() )
759-
{
760-
QString tagName = stripNS( el.tagName() );
761-
762-
if ( tagName == "requestResponseCRSs" ) // requestCRSs + responseCRSs alternative
763-
{
764-
coverage->supportedCrs << el.text();
765-
}
766-
else if ( tagName == "nativeCRSs" ) // optional
767-
{
768-
coverage->nativeCrs = el.text();
769-
}
770-
// TODO: requestCRSs, responseCRSs - must be then implemented also in provider
771-
}
772-
n1 = n1.nextSibling();
773-
}
696+
// requestResponseCRSs and requestCRSs + responseCRSs are alternatives
697+
coverage->supportedCrs = domElementsTexts( coverageOfferingElement, "supportedCRSs.requestResponseCRSs" );
698+
// TODO: requestCRSs, responseCRSs - must be then implemented also in provider
774699
QgsDebugMsg( "supportedCrs = " + coverage->supportedCrs.join( "," ) );
775700

776-
QDomElement supportedFormatsElement = firstChild( coverageOfferingElement, "supportedFormats" );
777-
778-
n1 = supportedFormatsElement.firstChild();
779-
while ( !n1.isNull() )
780-
{
781-
QDomElement el = n1.toElement();
782-
if ( !el.isNull() )
783-
{
784-
QString tagName = stripNS( el.tagName() );
701+
coverage->nativeCrs = domElementText( coverageOfferingElement, "supportedCRSs.nativeCRSs" );
785702

786-
if ( tagName == "formats" )
787-
{
788-
// may be GTiff, GeoTIFF, TIFF, GIF, ....
789-
coverage->supportedFormat << el.text();
790-
}
791-
}
792-
n1 = n1.nextSibling();
793-
}
703+
// may be GTiff, GeoTIFF, TIFF, GIF, ....
704+
coverage->supportedFormat = domElementsTexts( coverageOfferingElement, "supportedFormats.formats" );
794705
QgsDebugMsg( "supportedFormat = " + coverage->supportedFormat.join( "," ) );
795706

796707
// spatialDomain and Grid/RectifiedGrid are optional according to specificationi.
@@ -822,7 +733,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
822733
// it should contain gml:Point but mapserver 6.0.3 / WCS 1.0.0 is using gml:pos instead)
823734
// RectifiedGrid also contains 2 gml:offsetVector which could be used to get resolution
824735
// but it should be sufficient to calc resolution from size
825-
736+
826737
// TODO: check if coverage is rotated, in that case probably treat as without size
827738
// or recalc resolution from rotated grid to base CRS
828739
}
@@ -836,28 +747,28 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
836747
QString srsName = el.attribute( "srsName" );
837748

838749
QList<QDomElement> posElements = domElements( el, "pos" );
839-
if ( posElements.size() != 2 )
750+
if ( posElements.size() != 2 )
840751
{
841-
QgsDebugMsg ("Wrong number of pos elements");
752+
QgsDebugMsg( "Wrong number of pos elements" );
842753
continue;
843754
}
844755

845-
QList<double> low = parseDoubles( posElements.value(0).text() );
846-
QList<double> high = parseDoubles( posElements.value(1).text() );
756+
QList<double> low = parseDoubles( posElements.value( 0 ).text() );
757+
QList<double> high = parseDoubles( posElements.value( 1 ).text() );
847758
if ( low.size() == 2 && high.size() == 2 )
848759
{
849-
QgsRectangle box ( low[0], low[1], high[0], high[1] ) ;
760+
QgsRectangle box( low[0], low[1], high[0], high[1] ) ;
850761
coverage->boundingBoxes.insert( srsName, box );
851-
QgsDebugMsg ( "Envelope: " + srsName + " : " + box.toString() );
762+
QgsDebugMsg( "Envelope: " + srsName + " : " + box.toString() );
852763
}
853764
}
854765

855766
// Find native bounding box
856767
if ( !coverage->nativeCrs.isEmpty() )
857768
{
858-
foreach ( QString srsName, coverage->boundingBoxes.keys() )
769+
foreach( QString srsName, coverage->boundingBoxes.keys() )
859770
{
860-
if ( srsName == coverage->nativeCrs )
771+
if ( srsName == coverage->nativeCrs )
861772
{
862773
coverage->nativeBoundingBox = coverage->boundingBoxes.value( srsName );
863774
}
@@ -903,23 +814,23 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom11( QByteArray const &xml, QgsW
903814

904815
foreach( QDomElement el, boundingBoxElements )
905816
{
906-
QString authid = crsUrnToAuthId ( el.attribute( "crs" ) );
817+
QString authid = crsUrnToAuthId( el.attribute( "crs" ) );
907818
QList<double> low = parseDoubles( domElementText( el, "LowerCorner" ) );
908819
QList<double> high = parseDoubles( domElementText( el, "UpperCorner" ) );
909820

910821
if ( low.size() != 2 && high.size() != 2 ) continue;
911822

912823
if ( el.attribute( "crs" ) == "urn:ogc:def:crs:OGC::imageCRS" )
913824
{
914-
coverage->width = (int) ( high[0] - low[0] + 1 );
915-
coverage->height = (int) ( high[1] - low[1] + 1 );
825+
coverage->width = ( int )( high[0] - low[0] + 1 );
826+
coverage->height = ( int )( high[1] - low[1] + 1 );
916827
coverage->hasSize = true;
917828
}
918829
else
919830
{
920-
QgsRectangle box ( low[0], low[1], high[0], high[1] ) ;
831+
QgsRectangle box( low[0], low[1], high[0], high[1] ) ;
921832
coverage->boundingBoxes.insert( authid, box );
922-
QgsDebugMsg ( "BoundingBox: " + authid + " : " + box.toString() );
833+
QgsDebugMsg( "BoundingBox: " + authid + " : " + box.toString() );
923834
}
924835
}
925836
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( coverage->width ).arg( coverage->height ) );
@@ -929,7 +840,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom11( QByteArray const &xml, QgsW
929840

930841
if ( !gridCRSElement.isNull() )
931842
{
932-
QString crsUrn = firstChildText ( gridCRSElement, "GridBaseCRS" );
843+
QString crsUrn = firstChildText( gridCRSElement, "GridBaseCRS" );
933844
coverage->nativeCrs = crsUrnToAuthId( crsUrn );
934845
QgsDebugMsg( "nativeCrs = " + coverage->nativeCrs );
935846

@@ -941,48 +852,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom11( QByteArray const &xml, QgsW
941852

942853
return true;
943854
}
944-
void QgsWcsCapabilities::parseServiceIdentification( const QDomElement &e, QgsWcsServiceIdentification &serviceIdentification ) // 1.1
945-
{
946-
serviceIdentification.title = firstChildText( e, "Title" );
947-
serviceIdentification.abstract = firstChildText( e, "Abstract" );
948-
}
949-
950-
void QgsWcsCapabilities::parseHttp( QDomElement const & e, QgsWcsHTTP& http )
951-
{
952-
http.get.xlinkHref = firstChild( e, "Get" ).attribute( "xlink:href" );
953-
QgsDebugMsg( "http.get.xlinkHref = " + http.get.xlinkHref );
954-
}
955-
956-
void QgsWcsCapabilities::parseDcp( QDomElement const & e, QgsWcsDCP& dcp )
957-
{
958-
QDomElement el = firstChild( e, "HTTP" );
959-
parseHttp( el, dcp.http );
960-
}
961-
962-
void QgsWcsCapabilities::parseOperation( QDomElement const & e, QgsWcsOperation& operation )
963-
{
964-
QDomElement el = firstChild( e, "DCP" );
965-
parseDcp( el, operation.dcp );
966-
}
967-
968-
void QgsWcsCapabilities::parseOperationsMetadata( QDomElement const & e, QgsWcsOperationsMetadata &operationsMetadata )
969-
{
970-
QDomNode n1 = e.firstChild();
971-
while ( !n1.isNull() )
972-
{
973-
QDomElement el = n1.toElement();
974-
if ( !el.isNull() )
975-
{
976-
QString tagName = stripNS( el.tagName() );
977855

978-
if ( tagName == "Operation" && el.attribute( "name" ) == "GetCoverage" )
979-
{
980-
parseOperation( el, operationsMetadata.getCoverage );
981-
}
982-
}
983-
n1 = n1.nextSibling();
984-
}
985-
}
986856

987857
void QgsWcsCapabilities::parseCoverageSummary( QDomElement const & e, QgsWcsCoverageSummary &coverageSummary, QgsWcsCoverageSummary *parent )
988858
{
@@ -1009,35 +879,22 @@ void QgsWcsCapabilities::parseCoverageSummary( QDomElement const & e, QgsWcsCove
1009879
else if ( tagName == "SupportedCRS" )
1010880
{
1011881
// TODO: SupportedCRS may be URL referencing a document
1012-
// URN format: urn:ogc:def:objectType:authority:version:code
1013-
// URN example: urn:ogc:def:crs:EPSG::4326
1014-
QStringList urn = el.text().split( ":" );
1015-
if ( urn.size() == 7 )
1016-
{
1017-
coverageSummary.supportedCrs << urn.value( 4 ) + ":" + urn.value( 6 );
1018-
}
882+
coverageSummary.supportedCrs << crsUrnToAuthId( el.text() );
1019883
}
1020884
else if ( tagName == "WGS84BoundingBox" )
1021885
{
1022-
QDomElement wBoundLongitudeElem, eBoundLongitudeElem, sBoundLatitudeElem, nBoundLatitudeElem;
1023-
1024-
QStringList lower = n1.namedItem( "ows:LowerCorner" ).toElement().text().split( QRegExp( " +" ) );
1025-
QStringList upper = n1.namedItem( "ows:UpperCorner" ).toElement().text().split( QRegExp( " +" ) );
1026-
1027-
double w, e, s, n;
1028-
bool wOk, eOk, sOk, nOk;
1029-
w = lower.value( 0 ).toDouble( &wOk );
1030-
s = lower.value( 1 ).toDouble( &sOk );
1031-
e = upper.value( 0 ).toDouble( &eOk );
1032-
n = upper.value( 1 ).toDouble( &nOk );
1033-
if ( wOk && eOk && sOk && nOk )
886+
QList<double> low = parseDoubles( domElementText( el, "LowerCorner" ) );
887+
QList<double> high = parseDoubles( domElementText( el, "UpperCorner" ) );
888+
889+
if ( low.size() == 2 && high.size() == 2 )
1034890
{
1035-
coverageSummary.wgs84BoundingBox = QgsRectangle( w, s, e, n );
891+
coverageSummary.wgs84BoundingBox = QgsRectangle( low[0], low[1], high[0], high[1] );
1036892
}
1037893
}
1038894
}
1039895
n1 = n1.nextSibling();
1040896
}
897+
QgsDebugMsg( "supportedFormat = " + coverageSummary.supportedFormat.join( "," ) );
1041898

1042899
// We collected params to be inherited, do children
1043900
n1 = e.firstChild();
@@ -1054,16 +911,14 @@ void QgsWcsCapabilities::parseCoverageSummary( QDomElement const & e, QgsWcsCove
1054911

1055912
QgsWcsCoverageSummary subCoverageSummary;
1056913

1057-
subCoverageSummary.described = false;
1058-
subCoverageSummary.width = 0;
1059-
subCoverageSummary.height = 0;
1060-
subCoverageSummary.hasSize = false;
914+
initCoverageSummary( subCoverageSummary );
1061915

1062916
// Inherit
1063917
subCoverageSummary.supportedCrs = coverageSummary.supportedCrs;
1064918
subCoverageSummary.supportedFormat = coverageSummary.supportedFormat;
1065919

1066920
parseCoverageSummary( el, subCoverageSummary, &coverageSummary );
921+
subCoverageSummary.valid = true;
1067922

1068923
coverageSummary.coverageSummary.push_back( subCoverageSummary );
1069924
}
@@ -1097,6 +952,15 @@ void QgsWcsCapabilities::coverageParents( QMap<int, int> &parents, QMap<int, QSt
1097952
parentNames = mCoverageParentIdentifiers;
1098953
}
1099954

955+
void QgsWcsCapabilities::initCoverageSummary( QgsWcsCoverageSummary &coverageSummary )
956+
{
957+
coverageSummary.valid = false;
958+
coverageSummary.described = false;
959+
coverageSummary.width = 0;
960+
coverageSummary.height = 0;
961+
coverageSummary.hasSize = false;
962+
}
963+
1100964
QString QgsWcsCapabilities::lastErrorTitle()
1101965
{
1102966
return mErrorTitle;
@@ -1131,18 +995,28 @@ void QgsWcsCapabilities::showMessageBox( const QString& title, const QString& te
1131995
message->showMessage();
1132996
}
1133997

998+
QgsWcsCoverageSummary QgsWcsCapabilities::coverage( QString const & theIdentifier )
999+
{
1000+
QgsWcsCoverageSummary * cp = coverageSummary( theIdentifier );
1001+
QgsDebugMsg( "supportedFormat = " + ( *cp ).supportedFormat.join( "," ) );
1002+
if ( cp ) return *cp;
1003+
1004+
QgsWcsCoverageSummary c;
1005+
initCoverageSummary( c );
1006+
QgsDebugMsg( "supportedFormat = " + c.supportedFormat.join( "," ) );
1007+
return c;
1008+
}
1009+
11341010
QgsWcsCoverageSummary* QgsWcsCapabilities::coverageSummary( QString const & theIdentifier, QgsWcsCoverageSummary* parent )
11351011
{
1136-
//QgsDebugMsg( "theIdentifier = " + theIdentifier );
1012+
QgsDebugMsgLevel( "theIdentifier = " + theIdentifier, 5 );
11371013
if ( !parent )
11381014
{
11391015
parent = &( mCapabilities.contents );
11401016
}
11411017

1142-
//foreach( const QgsWcsCoverageSummary &c, parent->coverageSummary )
11431018
for ( QVector<QgsWcsCoverageSummary>::iterator c = parent->coverageSummary.begin(); c != parent->coverageSummary.end(); ++c )
11441019
{
1145-
//QgsDebugMsg( "c->identifier = " + c->identifier );
11461020
if ( c->identifier == theIdentifier )
11471021
{
11481022
return c;

‎src/providers/wcs/qgswcscapabilities.h

Lines changed: 44 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#ifndef QGSWCSCAPABILITIES_H
2121
#define QGSWCSCAPABILITIES_H
2222

23-
//#include "qgsrasterdataprovider.h"
2423
#include "qgsdatasourceuri.h"
2524
#include "qgsrectangle.h"
2625

@@ -31,45 +30,15 @@
3130
#include <QVector>
3231
#include <QUrl>
3332

34-
class QgsCoordinateTransform;
33+
//class QgsCoordinateTransform;
3534
class QNetworkAccessManager;
3635
class QNetworkReply;
3736
class QNetworkRequest;
3837

39-
/*
40-
* The following structs reflect the WCS XML schema,
41-
* as illustrated in ... the Web Coverage Service standard, version x.x xxxx-xx-xx.
42-
*/
43-
44-
/** Get Property structure */
45-
struct QgsWcsGet
46-
{
47-
QString xlinkHref;
48-
};
49-
50-
/** HTTP Property structure */
51-
struct QgsWcsHTTP
52-
{
53-
QgsWcsGet get;
54-
};
55-
56-
/** DCP Type Property structure */
57-
struct QgsWcsDCP
58-
{
59-
QgsWcsHTTP http;
60-
};
61-
62-
/** Version parameter */
63-
struct QgsWcsVersion
64-
{
65-
QStringList allowedValues;
66-
};
67-
6838
/** Operation type structure */
6939
struct QgsWcsOperation
7040
{
71-
QgsWcsVersion version;
72-
QgsWcsDCP dcp;
41+
QString getUrl;
7342
};
7443

7544
/** OperationsMetadata */
@@ -81,8 +50,8 @@ struct QgsWcsOperationsMetadata
8150
/** ServiceerviceIdentification structure */
8251
struct QgsWcsServiceIdentification
8352
{
84-
QString title;
85-
QString abstract;
53+
QString title;
54+
QString abstract;
8655
};
8756

8857
/** CoverageSummary structure */
@@ -95,44 +64,33 @@ struct QgsWcsCoverageSummary
9564
QStringList supportedCrs;
9665
QStringList supportedFormat;
9766
QgsRectangle wgs84BoundingBox; // almost useless, we need the native
98-
// Map of bounding boxes, key is CRS name (srsName), e.g. EPSG:4326
9967
QString nativeCrs;
100-
QMap<QString, QgsRectangle> boundingBoxes;
68+
// Map of bounding boxes, key is CRS name (srsName), e.g. EPSG:4326
69+
QMap<QString, QgsRectangle> boundingBoxes;
10170
QgsRectangle nativeBoundingBox;
10271
QVector<QgsWcsCoverageSummary> coverageSummary;
103-
bool described; // 1.0
104-
// non reflecting directly Capabilities structure:
72+
// non reflecting Capabilities structure:
73+
bool valid;
74+
bool described;
10575
// native size
106-
int width;
76+
int width;
10777
int height;
10878
bool hasSize;
10979
};
11080

111-
/** Contents structure */
112-
/*
113-
struct QgsWcsContents
114-
{
115-
QStringList supportedCrs;
116-
QStringList supportedFormat;
117-
QVector<QgsWcsCoverageSummary> coverageSummary;
118-
};
119-
*/
120-
12181
/** Capability Property structure */
12282
struct QgsWcsCapabilitiesProperty
12383
{
12484
QString version;
125-
QgsWcsServiceIdentification serviceIdentification;
85+
QString title;
86+
QString abstract;
12687
QgsWcsOperationsMetadata operationsMetadata;
127-
// QgsWcsContents contents;
12888
// using QgsWcsCoverageSummary for contents for simplification
12989
QgsWcsCoverageSummary contents;
13090
};
13191

13292
/**
133-
134-
\brief Data provider for OGC WCS layers.
135-
93+
\brief WCS Capabilities.
13694
*/
13795
class QgsWcsCapabilities : public QObject
13896
{
@@ -172,8 +130,8 @@ class QgsWcsCapabilities : public QObject
172130
*/
173131
void coverageParents( QMap<int, int> &parents, QMap<int, QStringList> &parentNames ) const;
174132

175-
//! Get coverage summare for identifier
176-
QgsWcsCoverageSummary * coverageSummary( QString const & theIdentifier, QgsWcsCoverageSummary* parent = 0 );
133+
//! Get coverage summary for identifier
134+
QgsWcsCoverageSummary coverage( QString const & theIdentifier );
177135

178136
/**
179137
* \brief Prepare the URI so that we can later simply append param=value
@@ -228,6 +186,29 @@ class QgsWcsCapabilities : public QObject
228186
*/
229187
QString lastErrorFormat();
230188

189+
//! Get tag name without namespace
190+
static QString stripNS( const QString &name );
191+
192+
//! Get text of first child of specified name, NS is ignored
193+
static QString firstChildText( const QDomElement &element, const QString &name );
194+
195+
//! Get first child of specified name, NS is ignored
196+
static QDomElement firstChild( const QDomElement &element, const QString &name );
197+
198+
/** Find sub elements by path which is string of dot separated tag names.
199+
* NS is ignored. Example path: domainSet.spatialDomain.RectifiedGrid */
200+
static QList<QDomElement> domElements( const QDomElement &element, const QString &path );
201+
202+
/** Find first sub element by path which is string of dot separated tag names.
203+
* NS is ignored. Example path: domainSet.spatialDomain.RectifiedGrid */
204+
static QDomElement domElement( const QDomElement &element, const QString &path );
205+
206+
/** Get text of element specified by path */
207+
static QString domElementText( const QDomElement &element, const QString &path );
208+
209+
/** Get sub elements texts by path */
210+
static QStringList domElementsTexts( const QDomElement &element, const QString &path );
211+
231212
signals:
232213

233214
/** \brief emit a signal to notify of a progress event */
@@ -241,33 +222,18 @@ class QgsWcsCapabilities : public QObject
241222
void capabilitiesReplyProgress( qint64, qint64 );
242223

243224
private:
244-
void clear();
245-
246-
void showMessageBox( const QString &title, const QString &text );
247-
248-
//! Get tag name without namespace
249-
QString stripNS( const QString &name );
250-
251-
//! Get text of first child of specified name, NS is ignored
252-
QString firstChildText( const QDomElement &element, const QString &name );
253-
254-
//! Get first child of specified name, NS is ignored
255-
QDomElement firstChild( const QDomElement &element, const QString &name );
225+
//! Get coverage summary for identifier
226+
QgsWcsCoverageSummary * coverageSummary( QString const & theIdentifier, QgsWcsCoverageSummary* parent = 0 );
256227

257-
/** Find sub elements by path which is string of dot separated tag names.
258-
* NS is ignored. Example path: domainSet.spatialDomain.RectifiedGrid */
259-
QList<QDomElement> domElements( const QDomElement &element, const QString &path );
228+
void initCoverageSummary( QgsWcsCoverageSummary &coverageSummary );
260229

261-
/** Find first sub element by path which is string of dot separated tag names.
262-
* NS is ignored. Example path: domainSet.spatialDomain.RectifiedGrid */
263-
QDomElement domElement( const QDomElement &element, const QString &path );
230+
void clear();
264231

265-
/** Get text of element specified by path */
266-
QString domElementText( const QDomElement &element, const QString &path );
232+
void showMessageBox( const QString &title, const QString &text );
267233

268234
QList<int> parseInts( const QString &text );
269235
QList<double> parseDoubles( const QString &text );
270-
QString crsUrnToAuthId ( const QString &text );
236+
QString crsUrnToAuthId( const QString &text );
271237
/**
272238
* \brief Retrieve and parse the (cached) Capabilities document from the server
273239
*
@@ -289,12 +255,6 @@ class QgsWcsCapabilities : public QObject
289255
bool parseCapabilitiesDom( QByteArray const &xml, QgsWcsCapabilitiesProperty &capabilities );
290256

291257
// ------------- 1.0 --------------------
292-
//! parse the WCS Service XML element
293-
void parseService( QDomElement const &e, QgsWcsServiceIdentification &serviceIdentification );
294-
295-
//! parse the WCS Capability XML element
296-
void parseCapability( QDomElement const &e, QgsWcsOperationsMetadata &operationsMetadata );
297-
298258
//! parse the WCS Layer XML element
299259
void parseContentMetadata( QDomElement const &e, QgsWcsCoverageSummary &coverageSummary );
300260

@@ -303,21 +263,6 @@ class QgsWcsCapabilities : public QObject
303263
QgsWcsCoverageSummary *parent = 0 );
304264

305265
// ------------- 1.1 --------------------
306-
//! parse the WCS ServiceIdentificatio XML element
307-
void parseServiceIdentification( QDomElement const &e, QgsWcsServiceIdentification &serviceIdentification );
308-
309-
//! parse the WCS OperationsMetadata XML element
310-
void parseOperationsMetadata( QDomElement const &e, QgsWcsOperationsMetadata &operationsMetadata );
311-
312-
//! parse the WCS GetCoverage
313-
void parseOperation( QDomElement const & e, QgsWcsOperation& operation );
314-
315-
//! parse the WCS HTTP XML element
316-
void parseHttp( QDomElement const &e, QgsWcsHTTP &http );
317-
318-
//! parse the WCS DCPType XML element
319-
void parseDcp( QDomElement const &e, QgsWcsDCP &dcp );
320-
321266
//! parse the WCS Layer XML element
322267
void parseCoverageSummary( QDomElement const &e, QgsWcsCoverageSummary &coverageSummary,
323268
QgsWcsCoverageSummary *parent = 0 );

‎src/providers/wcs/qgswcsprovider.cpp

Lines changed: 125 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
8080
, mErrors( 0 )
8181
, mUserName( QString::null )
8282
, mPassword( QString::null )
83-
, mCoverageSummary( 0 )
83+
, mCoverageSummary()
8484
, mCachedGdalDataset( 0 )
8585
, mCachedMemFile( 0 )
8686
, mWidth( 0 )
@@ -113,67 +113,67 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
113113
// 1.0 get additional coverage info
114114
if ( !mCapabilities.describeCoverage( mIdentifier ) )
115115
{
116-
QgsDebugMsg( "Cannot describe coverage" );
116+
QgsMessageLog::logMessage( tr( "Cannot describe coverage" ), tr( "WCS" ) );
117117
return;
118118
}
119119

120-
mCoverageSummary = mCapabilities.coverageSummary( mIdentifier );
121-
if ( !mCoverageSummary )
120+
mCoverageSummary = mCapabilities.coverage( mIdentifier );
121+
if ( !mCoverageSummary.valid )
122122
{
123-
QgsDebugMsg( "coverage not found" );
123+
// Should not happen if describeCoverage() did not fail
124+
QgsMessageLog::logMessage( tr( "Coverage not found" ), tr( "WCS" ) );
124125
return;
125126
}
126127

127-
// It could happen (usually not with current QgsWCSSourceSelect if at least
128-
// one CRS is available) that crs is not set in uri, in that case we
128+
// It could happen (usually not with current QgsWCSSourceSelect if at least
129+
// one CRS is available) that crs is not set in uri, in that case we
129130
// use the native, if available, or the first supported
130131
if ( mCoverageCrs.isEmpty() )
131132
{
132-
if ( !mCoverageSummary->nativeCrs.isEmpty() )
133+
if ( !mCoverageSummary.nativeCrs.isEmpty() )
133134
{
134-
setCoverageCrs( mCoverageSummary->nativeCrs );
135+
setCoverageCrs( mCoverageSummary.nativeCrs );
135136
}
136-
else if ( mCoverageSummary->supportedCrs.size() > 0 )
137+
else if ( mCoverageSummary.supportedCrs.size() > 0 )
137138
{
138-
setCoverageCrs( mCoverageSummary->supportedCrs.value(0) );
139+
setCoverageCrs( mCoverageSummary.supportedCrs.value( 0 ) );
139140
}
140141
}
141142

142-
mWidth = mCoverageSummary->width;
143-
mHeight = mCoverageSummary->height;
144-
mHasSize = mCoverageSummary->hasSize;
143+
mWidth = mCoverageSummary.width;
144+
mHeight = mCoverageSummary.height;
145+
mHasSize = mCoverageSummary.hasSize;
145146

146147
QgsDebugMsg( QString( "mWidth = %1 mHeight = %2" ).arg( mWidth ).arg( mHeight ) ) ;
147148

148149
if ( !calculateExtent() )
149150
{
150-
QgsDebugMsg( "Cannot calculate extent" );
151+
QgsMessageLog::logMessage( tr( "Cannot calculate extent" ), tr( "WCS" ) );
151152
return;
152153
}
153154

154155
mCachedMemFilename = QString( "/vsimem/qgis/wcs/%0.dat" ).arg(( qlonglong )this );
155156

156157
// Get small piece of coverage to find GDAL data type and nubmer of bands
157-
// Using non native CRS (if we don't know which is native) it could easily happen,
158-
// that a small part of bbox in request CRS near margin falls outside
158+
// Using non native CRS (if we don't know which is native) it could easily happen,
159+
// that a small part of bbox in request CRS near margin falls outside
159160
// coverage native bbox and server reports error => take a piece from center
160161

161162
int bandNo = 0; // All bands
162-
// just a number to get smaller piece of coverage
163-
int width;
163+
int width;
164164
int height;
165165
QString crs;
166-
QgsRectangle box; // box to use to calc extent
166+
QgsRectangle box; // box to use to calc extent
167167
// Prefer native CRS
168-
if ( !mCoverageSummary->nativeCrs.isEmpty() &&
169-
!mCoverageSummary->nativeBoundingBox.isEmpty() &&
170-
mCoverageSummary->supportedCrs.contains ( mCoverageSummary->nativeCrs ) &&
168+
if ( !mCoverageSummary.nativeCrs.isEmpty() &&
169+
!mCoverageSummary.nativeBoundingBox.isEmpty() &&
170+
mCoverageSummary.supportedCrs.contains( mCoverageSummary.nativeCrs ) &&
171171
mHasSize )
172172
{
173-
box = mCoverageSummary->nativeBoundingBox;
173+
box = mCoverageSummary.nativeBoundingBox;
174174
width = mWidth;
175175
height = mHeight;
176-
crs = mCoverageSummary->nativeCrs;
176+
crs = mCoverageSummary.nativeCrs;
177177
}
178178
else
179179
{
@@ -185,7 +185,8 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
185185
}
186186
else
187187
{
188-
width = 1000;
188+
// just a number to get smaller piece of coverage
189+
width = 1000;
189190
height = 1000;
190191
}
191192
}
@@ -195,14 +196,14 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
195196

196197
int half = 2; // to be requested
197198

198-
// extent to be used for test request
199-
QgsRectangle extent = QgsRectangle ( p.x() - half * xRes, p.y() - half * yRes, p.x() + half * xRes, p.y() + half * yRes );
200-
199+
// extent to be used for test request
200+
QgsRectangle extent = QgsRectangle( p.x() - half * xRes, p.y() - half * yRes, p.x() + half * xRes, p.y() + half * yRes );
201+
201202
getCache( bandNo, extent, 2*half, 2*half, crs );
202203

203204
if ( !mCachedGdalDataset )
204205
{
205-
QgsDebugMsg( "Cannot get test dataset." );
206+
QgsMessageLog::logMessage( tr( "Cannot get test dataset." ), tr( "WCS" ) );
206207
return;
207208
}
208209

@@ -276,7 +277,7 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
276277

277278
// Create and store color table
278279
// TODO: never tested because mapserver (6.0.3) does not support color tables
279-
mColorTables.append ( QgsGdalProviderBase::colorTable( mCachedGdalDataset, i ) );
280+
mColorTables.append( QgsGdalProviderBase::colorTable( mCachedGdalDataset, i ) );
280281
}
281282

282283
clearCache();
@@ -311,7 +312,7 @@ void QgsWcsProvider::parseUri( QString uriString )
311312
mBaseUrl = prepareUri( mHttpUri );
312313
QgsDebugMsg( "mBaseUrl = " + mBaseUrl );
313314

314-
mIgnoreGetMapUrl = uri.hasParam( "IgnoreGetMapUrl" );
315+
mIgnoreGetCoverageUrl = uri.hasParam( "IgnoreGetMapUrl" );
315316
mIgnoreAxisOrientation = uri.hasParam( "IgnoreAxisOrientation" ); // must be before parsing!
316317
mInvertAxisOrientation = uri.hasParam( "InvertAxisOrientation" ); // must be before parsing!
317318

@@ -409,13 +410,14 @@ void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
409410
{
410411
QgsDebugMsg( "Entered" );
411412

413+
// TODO: set block to null values, move that to function and call only if fails
414+
memset( block, 0, pixelWidth * pixelHeight * typeSize( dataType( bandNo ) ) / 8 );
415+
412416
// Requested extent must at least partialy overlap coverage extent, otherwise
413417
// server gives error. QGIS usually does not request blocks outside raster extent
414418
// (higher level checks) but it is better to do check here as well
415419
if ( !viewExtent.intersects( mCoverageExtent ) )
416420
{
417-
// TODO: set block to null values
418-
memset( block, 0, pixelWidth * pixelHeight * typeSize( dataType( bandNo ) ) / 8 );
419421
return;
420422
}
421423

@@ -463,7 +465,7 @@ void QgsWcsProvider::getCache( int bandNo, QgsRectangle const & viewExtent, int
463465
// delete cached data
464466
clearCache();
465467

466-
if ( crs.isEmpty() )
468+
if ( crs.isEmpty() )
467469
{
468470
crs = mCoverageCrs;
469471
}
@@ -508,7 +510,7 @@ void QgsWcsProvider::getCache( int bandNo, QgsRectangle const & viewExtent, int
508510
.arg( extent.xMaximum(), 0, 'f', 16 )
509511
.arg( extent.yMaximum(), 0, 'f', 16 );
510512

511-
QUrl url( mIgnoreGetMapUrl ? mBaseUrl : mCapabilities.getCoverageUrl() );
513+
QUrl url( mIgnoreGetCoverageUrl ? mBaseUrl : mCapabilities.getCoverageUrl() );
512514

513515
// Version 1.0.0, 1.1.0, 1.1.2
514516
setQueryItem( url, "SERVICE", "WCS" );
@@ -654,9 +656,9 @@ void QgsWcsProvider::cacheReplyFinished()
654656
if ( contentType.startsWith( "text/", Qt::CaseInsensitive ) ||
655657
contentType.toLower() == "application/vnd.ogc.se_xml" )
656658
{
657-
// TODO: test also if it is really exception (from content)
658659
QByteArray text = mCacheReply->readAll();
659-
if ( contentType.toLower() == "text/xml" && parseServiceExceptionReportDom( text ) )
660+
if (( contentType.toLower() == "text/xml" || contentType.toLower() == "application/vnd.ogc.se_xml" )
661+
&& parseServiceExceptionReportDom( text ) )
660662
{
661663
QgsMessageLog::logMessage( tr( "Map request error (Title:%1; Error:%2; URL: %3)" )
662664
.arg( mErrorCaption ).arg( mError )
@@ -941,33 +943,22 @@ bool QgsWcsProvider::parseServiceExceptionReportDom( QByteArray const & xml )
941943

942944
QDomElement docElem = mServiceExceptionReportDom.documentElement();
943945

944-
// TODO: Assert the docElem.tagName() is "ServiceExceptionReport"
946+
// TODO: Assert the docElem.tagName() is
947+
// ServiceExceptionReport // 1.0
948+
// ows:ExceptionReport // 1.1
945949

946-
// serviceExceptionProperty.version = docElem.attribute("version");
950+
//QString version = docElem.attribute("version");
947951

948-
// Start walking through XML.
949-
QDomNode n = docElem.firstChild();
950-
951-
while ( !n.isNull() )
952+
QDomElement e;
953+
if ( mCapabilities.version().startsWith( "1.0" ) )
952954
{
953-
QDomElement e = n.toElement(); // try to convert the node to an element.
954-
if ( !e.isNull() )
955-
{
956-
//QgsDebugMsg(e.tagName() ); // the node really is an element.
957-
958-
QString tagName = e.tagName();
959-
if ( tagName.startsWith( "wcs:" ) )
960-
tagName = tagName.mid( 4 );
961-
962-
if ( tagName == "ServiceException" )
963-
{
964-
QgsDebugMsg( " ServiceException." );
965-
parseServiceException( e );
966-
}
967-
968-
}
969-
n = n.nextSibling();
955+
e = QgsWcsCapabilities::domElement( docElem, "ServiceException" );
956+
}
957+
else // 1.1
958+
{
959+
e = QgsWcsCapabilities::domElement( docElem, "Exception" );
970960
}
961+
parseServiceException( e );
971962

972963
QgsDebugMsg( "exiting." );
973964

@@ -978,67 +969,58 @@ void QgsWcsProvider::parseServiceException( QDomElement const & e )
978969
{
979970
QgsDebugMsg( "entering." );
980971

981-
QString seCode = e.attribute( "code" );
982-
QString seText = e.text();
983972

984-
mErrorFormat = "text/plain";
973+
QMap<QString, QString> exceptions;
974+
975+
// Some codes are in both 1.0 and 1.1, in that case the 'meaning of code' is
976+
// taken from 1.0 specification
985977

986978
// set up friendly descriptions for the service exception
987-
if ( seCode == "InvalidFormat" )
988-
{
989-
mError = tr( "Request contains a format not offered by the server." );
990-
}
991-
else if ( seCode == "InvalidCRS" )
992-
{
993-
mError = tr( "Request contains a CRS not offered by the server for one or more of the Layers in the request." );
994-
}
995-
else if ( seCode == "InvalidSRS" ) // legacy WCS < 1.3.0
996-
{
997-
mError = tr( "Request contains a SRS not offered by the server for one or more of the Layers in the request." );
998-
}
999-
else if ( seCode == "LayerNotDefined" )
1000-
{
1001-
mError = tr( "GetMap request is for a Layer not offered by the server, "
1002-
"or GetFeatureInfo request is for a Layer not shown on the map." );
1003-
}
1004-
else if ( seCode == "StyleNotDefined" )
1005-
{
1006-
mError = tr( "Request is for a Layer in a Style not offered by the server." );
1007-
}
1008-
else if ( seCode == "LayerNotQueryable" )
1009-
{
1010-
mError = tr( "GetFeatureInfo request is applied to a Layer which is not declared queryable." );
1011-
}
1012-
else if ( seCode == "InvalidPoint" )
1013-
{
1014-
mError = tr( "GetFeatureInfo request contains invalid X or Y value." );
1015-
}
1016-
else if ( seCode == "CurrentUpdateSequence" )
1017-
{
1018-
mError = tr( "Value of (optional) UpdateSequence parameter in GetCapabilities request is equal to "
1019-
"current value of service metadata update sequence number." );
1020-
}
1021-
else if ( seCode == "InvalidUpdateSequence" )
1022-
{
1023-
mError = tr( "Value of (optional) UpdateSequence parameter in GetCapabilities request is greater "
1024-
"than current value of service metadata update sequence number." );
1025-
}
1026-
else if ( seCode == "MissingDimensionValue" )
979+
// 1.0
980+
exceptions["InvalidFormat"] = tr( "Request contains a format not offered by the server." );
981+
exceptions["CoverageNotDefined"] = tr( "Request is for a Coverage not offered by the service instance." );
982+
exceptions["CurrentUpdateSequence"] = tr( "Value of (optional) UpdateSequence parameter in GetCapabilities request is equal to current value of service metadata update sequence number." );
983+
exceptions["InvalidUpdateSequence"] = tr( "Value of (optional) UpdateSequence parameter in GetCapabilities request is greater than current value of service metadata update sequence number." );
984+
// 1.0, 1.1
985+
exceptions["MissingParameterValue"] = tr( "Request does not include a parameter value, and the servervice instance did not declare a default value for that dimension." );
986+
exceptions["InvalidParameterValue"] = tr( "Request contains an invalid parameter value." );
987+
// 1.1
988+
exceptions["NoApplicableCode"] = tr( "No other exceptionCode specified by this service and server applies to this exception." );
989+
exceptions["UnsupportedCombination"] = tr( "Operation request contains an output CRS that can not be used within the output format." );
990+
exceptions["NotEnoughStorage"] = tr( "Operation request specifies \"store\" the result, but not enough storage is available to do this." );
991+
992+
QString seCode;
993+
QString seText;
994+
if ( mCapabilities.version().startsWith( "1.0" ) )
1027995
{
1028-
mError = tr( "Request does not include a sample dimension value, and the server did not declare a "
1029-
"default value for that dimension." );
996+
seCode = e.attribute( "code" );
997+
seText = e.text();
1030998
}
1031-
else if ( seCode == "InvalidDimensionValue" )
999+
else
10321000
{
1033-
mError = tr( "Request contains an invalid sample dimension value." );
1001+
QStringList codes;
1002+
seCode = e.attribute( "exceptionCode" );
1003+
// UMN Mapserver (6.0.3) has messed/switched 'locator' and 'exceptionCode'
1004+
if ( ! exceptions.contains( seCode ) )
1005+
{
1006+
seCode = e.attribute( "locator" );
1007+
if ( ! exceptions.contains( seCode ) )
1008+
{
1009+
seCode = "";
1010+
}
1011+
}
1012+
seText = QgsWcsCapabilities::firstChildText( e, "ExceptionText" );
10341013
}
1035-
else if ( seCode == "OperationNotSupported" )
1014+
1015+
mErrorFormat = "text/plain";
1016+
1017+
if ( seCode.isEmpty() )
10361018
{
1037-
mError = tr( "Request is for an optional operation that is not supported by the server." );
1019+
mError = tr( "(No error code was reported)" );
10381020
}
1039-
else if ( seCode.isEmpty() )
1021+
else if ( exceptions.contains( seCode ) )
10401022
{
1041-
mError = tr( "(No error code was reported)" );
1023+
mError = exceptions.value( seCode );
10421024
}
10431025
else
10441026
{
@@ -1048,8 +1030,6 @@ void QgsWcsProvider::parseServiceException( QDomElement const & e )
10481030
mError += "\n" + tr( "The WCS vendor also reported: " );
10491031
mError += seText;
10501032

1051-
// TODO = e.attribute("locator");
1052-
10531033
QgsMessageLog::logMessage( tr( "composed error message '%1'." ).arg( mError ), tr( "WCS" ) );
10541034
QgsDebugMsg( "exiting." );
10551035
}
@@ -1077,20 +1057,28 @@ bool QgsWcsProvider::isValid()
10771057

10781058
QString QgsWcsProvider::wcsVersion()
10791059
{
1080-
// TODO
1081-
return NULL;
1060+
return mCapabilities.version();
10821061
}
10831062

10841063
bool QgsWcsProvider::calculateExtent()
10851064
{
10861065
QgsDebugMsg( "entered." );
10871066

10881067
// Make sure we know what extents are available
1089-
if ( !mCoverageSummary )
1068+
if ( !mCoverageSummary.described )
10901069
{
10911070
return false;
10921071
}
10931072

1073+
// Prefer to use extent from capabilities / coverage description because
1074+
// transformation from WGS84 increases the extent
1075+
mCoverageExtent = mCoverageSummary.boundingBoxes.value( mCoverageCrs );
1076+
if ( !mCoverageExtent.isEmpty() && !mCoverageExtent.isFinite() )
1077+
{
1078+
QgsDebugMsg( "mCoverageExtent = " + mCoverageExtent.toString() );
1079+
return true;
1080+
}
1081+
10941082
// Set up the coordinate transform from the WCS standard CRS:84 bounding
10951083
// box to the user's selected CRS
10961084
if ( !mCoordinateTransform )
@@ -1107,11 +1095,11 @@ bool QgsWcsProvider::calculateExtent()
11071095
mCoordinateTransform = new QgsCoordinateTransform( qgisSrsSource, qgisSrsDest );
11081096
}
11091097

1110-
QgsDebugMsg( "mCoverageSummary->wgs84BoundingBox= " + mCoverageSummary->wgs84BoundingBox.toString() );
1098+
QgsDebugMsg( "mCoverageSummary.wgs84BoundingBox= " + mCoverageSummary.wgs84BoundingBox.toString() );
11111099
// Convert to the user's CRS as required
11121100
try
11131101
{
1114-
mCoverageExtent = mCoordinateTransform->transformBoundingBox( mCoverageSummary->wgs84BoundingBox, QgsCoordinateTransform::ForwardTransform );
1102+
mCoverageExtent = mCoordinateTransform->transformBoundingBox( mCoverageSummary.wgs84BoundingBox, QgsCoordinateTransform::ForwardTransform );
11151103
}
11161104
catch ( QgsCsException &cse )
11171105
{
@@ -1160,18 +1148,21 @@ QString QgsWcsProvider::coverageMetadata( QgsWcsCoverageSummary coverage )
11601148
metadata += tr( "Value" );
11611149
metadata += "</th></tr>";
11621150

1163-
metadata += htmlRow ( tr( "Name (identifier)" ), coverage.identifier );
1164-
metadata += htmlRow ( tr( "Title" ), coverage.title );
1165-
metadata += htmlRow ( tr( "Abstract" ), coverage.abstract );
1151+
metadata += htmlRow( tr( "Name (identifier)" ), coverage.identifier );
1152+
metadata += htmlRow( tr( "Title" ), coverage.title );
1153+
metadata += htmlRow( tr( "Abstract" ), coverage.abstract );
11661154
// We dont have size, nativeCrs, nativeBoundingBox etc. until describe coverage which would be heavy for all coverages
11671155
//metadata += htmlRow ( tr( "Fixed Width" ), QString::number( coverage.width ) );
11681156
//metadata += htmlRow ( tr( "Fixed Height" ), QString::number( coverage.height ) );
11691157
//metadata += htmlRow ( tr( "Native CRS" ), coverage.nativeCrs );
11701158
//metadata += htmlRow ( tr( "Native Bounding Box" ), coverage.nativeBoundingBox.toString() );
11711159

1172-
metadata += htmlRow ( tr( "WGS 84 Bounding Box" ), coverage.wgs84BoundingBox.toString() );
1160+
metadata += htmlRow( tr( "WGS 84 Bounding Box" ), coverage.wgs84BoundingBox.toString() );
11731161

11741162
// Layer Coordinate Reference Systems
1163+
// TODO(?): supportedCrs and supportedFormat are not available in 1.0
1164+
// until coverage is described - it would be confusing to show it only if available
1165+
/*
11751166
for ( int j = 0; j < qMin( coverage.supportedCrs.size(), 10 ); j++ )
11761167
{
11771168
metadata += htmlRow ( tr( "Available in CRS" ), coverage.supportedCrs.value(j) );
@@ -1191,6 +1182,7 @@ QString QgsWcsProvider::coverageMetadata( QgsWcsCoverageSummary coverage )
11911182
{
11921183
metadata += htmlRow ( tr( "Available in format" ), tr( "(and %n more)", "crs", coverage.supportedFormat.size() - 10 ) );
11931184
}
1185+
*/
11941186

11951187
// Close the nested table
11961188
metadata += "</table>";
@@ -1235,22 +1227,21 @@ QString QgsWcsProvider::metadata()
12351227
metadata += tr( "Value" );
12361228
metadata += "</th></tr>";
12371229

1238-
metadata += htmlRow ( ( "Coverage" ), mIdentifier );
1239-
metadata += htmlRow ( ( "WCS Version" ), mCapabilities.version() );
1240-
metadata += htmlRow ( tr( "Title" ), mCapabilities.capabilities().serviceIdentification.title );
1241-
metadata += htmlRow ( tr( "Abstract" ), mCapabilities.capabilities().serviceIdentification.abstract );
1242-
// TODO
1230+
metadata += htmlRow(( "WCS Version" ), mCapabilities.version() );
1231+
metadata += htmlRow( tr( "Title" ), mCapabilities.capabilities().title );
1232+
metadata += htmlRow( tr( "Abstract" ), mCapabilities.capabilities().abstract );
1233+
// TODO
12431234
//metadata += htmlRow ( tr( "Keywords" ), mCapabilities.service.keywordList.join( "<br />" ) );
12441235
//metadata += htmlRow ( tr( "Online Resource" ), "-" );
1245-
//metadata += htmlRow ( tr( "Contact Person" ),
1236+
//metadata += htmlRow ( tr( "Contact Person" ),
12461237
// mCapabilities.service.contactInformation.contactPersonPrimary.contactPerson
12471238
// + "<br />" + mCapabilities.service.contactInformation.contactPosition;
12481239
// + "<br />" + mCapabilities.service.contactInformation.contactPersonPrimary.contactOrganization );
12491240
//metadata += htmlRow ( tr( "Fees" ), mCapabilities.service.fees );
12501241
//metadata += htmlRow ( tr( "Access Constraints" ), mCapabilities.service.accessConstraints );
12511242
//metadata += htmlRow ( tr( "Image Formats" ), mCapabilities.capability.request.getMap.format.join( "<br />" ) );
12521243
//metadata += htmlRow ( tr( "GetCapabilitiesUrl" ), mBaseUrl );
1253-
//metadata += htmlRow ( tr( "GetMapUrl" ), getMapUrl() + ( mIgnoreGetMapUrl ? tr( "&nbsp;<font color=\"red\">(advertised but ignored)</font>" ) : "" ) );
1244+
metadata += htmlRow( tr( "Get Coverage Url" ), mCapabilities.capabilities().operationsMetadata.getCoverage.getUrl + ( mIgnoreGetCoverageUrl ? tr( "&nbsp;<font color=\"red\">(advertised but ignored)</font>" ) : "" ) );
12541245

12551246
// Close the nested table
12561247
metadata += "</table>";
@@ -1263,7 +1254,7 @@ QString QgsWcsProvider::metadata()
12631254

12641255
for ( int i = 0; i < mCapabilities.capabilities().contents.coverageSummary.size(); i++ )
12651256
{
1266-
QgsWcsCoverageSummary c = mCapabilities.capabilities().contents.coverageSummary.value(i);
1257+
QgsWcsCoverageSummary c = mCapabilities.capabilities().contents.coverageSummary.value( i );
12671258
metadata += coverageMetadata( c );
12681259
}
12691260

@@ -1274,14 +1265,14 @@ QString QgsWcsProvider::metadata()
12741265
return metadata;
12751266
}
12761267

1277-
QString QgsWcsProvider::htmlCell ( const QString &text )
1268+
QString QgsWcsProvider::htmlCell( const QString &text )
12781269
{
12791270
return "<td>" + text + "</td>";
12801271
}
12811272

1282-
QString QgsWcsProvider:: htmlRow ( const QString &text1, const QString &text2 )
1273+
QString QgsWcsProvider:: htmlRow( const QString &text1, const QString &text2 )
12831274
{
1284-
return "<tr>" + htmlCell ( text1 ) + htmlCell ( text2 ) + "</tr>";
1275+
return "<tr>" + htmlCell( text1 ) + htmlCell( text2 ) + "</tr>";
12851276
}
12861277

12871278
bool QgsWcsProvider::identify( const QgsPoint& thePoint, QMap<QString, QString>& theResults )

‎src/providers/wcs/qgswcsprovider.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,10 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
238238
void clearCache();
239239

240240
//! Create html cell (used by metadata)
241-
QString htmlCell ( const QString &text );
241+
QString htmlCell( const QString &text );
242242

243243
//! Create html row with 2 cells (used by metadata)
244-
QString htmlRow ( const QString &text1, const QString &text2 );
244+
QString htmlRow( const QString &text1, const QString &text2 );
245245

246246
//! Data source URI of the WCS for this layer
247247
QString mHttpUri;
@@ -264,7 +264,7 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
264264
QgsWcsCapabilities mCapabilities;
265265

266266
/** Coverage summary */
267-
QgsWcsCoverageSummary * mCoverageSummary;
267+
QgsWcsCoverageSummary mCoverageSummary;
268268

269269
/** Spatial reference id of the layer */
270270
QString mSrid;
@@ -400,8 +400,7 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
400400

401401
//! whether to use hrefs from GetCapabilities (default) or
402402
// the given base urls for GetMap and GetFeatureInfo
403-
bool mIgnoreGetMapUrl;
404-
bool mIgnoreGetFeatureInfoUrl;
403+
bool mIgnoreGetCoverageUrl;
405404
bool mIgnoreAxisOrientation;
406405
bool mInvertAxisOrientation;
407406

‎src/providers/wcs/qgswcssourceselect.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ void QgsWCSSourceSelect::addClicked( )
135135
// without that param user is asked for CRS
136136
//if ( selectedLayersCRSs().size() > 1 )
137137
//{
138-
uri.setParam( "crs", selectedCRS() );
138+
uri.setParam( "crs", selectedCRS() );
139139
//}
140140

141141
QgsDebugMsg( "selectedFormat = " + selectedFormat() );
@@ -219,11 +219,11 @@ QStringList QgsWCSSourceSelect::selectedLayersFormats()
219219
QString identifier = selectedIdentifier();
220220
if ( identifier.isEmpty() ) { return QStringList(); }
221221

222-
QgsWcsCoverageSummary * c = mCapabilities.coverageSummary( identifier );
223-
if ( !c ) { return QStringList(); }
222+
QgsWcsCoverageSummary c = mCapabilities.coverage( identifier );
223+
if ( !c.valid ) { return QStringList(); }
224224

225-
QgsDebugMsg( "supportedFormat = " + c->supportedFormat.join( "," ) );
226-
return c->supportedFormat;
225+
QgsDebugMsg( "supportedFormat = " + c.supportedFormat.join( "," ) );
226+
return c.supportedFormat;
227227
}
228228

229229
QStringList QgsWCSSourceSelect::selectedLayersCRSs()
@@ -233,10 +233,10 @@ QStringList QgsWCSSourceSelect::selectedLayersCRSs()
233233
QString identifier = selectedIdentifier();
234234
if ( identifier.isEmpty() ) { return QStringList(); }
235235

236-
QgsWcsCoverageSummary * c = mCapabilities.coverageSummary( identifier );
237-
if ( !c ) { return QStringList(); }
236+
QgsWcsCoverageSummary c = mCapabilities.coverage( identifier );
237+
if ( !c.valid ) { return QStringList(); }
238238

239-
return c->supportedCrs;
239+
return c.supportedCrs;
240240
}
241241

242242
void QgsWCSSourceSelect::enableLayersForCrs( QTreeWidgetItem * )

0 commit comments

Comments
 (0)
Please sign in to comment.