Skip to content

Commit

Permalink
improve wfs error reporting in server and client
Browse files Browse the repository at this point in the history
  • Loading branch information
jef-n committed Jul 14, 2013
1 parent 89ffc54 commit 838367e
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 38 deletions.
12 changes: 7 additions & 5 deletions src/core/qgsogcutils.cpp
Expand Up @@ -20,7 +20,9 @@ QgsGeometry* QgsOgcUtils::geometryFromGML( const QDomNode& geometryNode )
QDomElement geometryTypeElement = geometryNode.toElement();
QString geomType = geometryTypeElement.tagName();

if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" || geomType == "Box" || geomType == "Envelope" ) )
if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" ||
geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" ||
geomType == "Box" || geomType == "Envelope" ) )
{
QDomNode geometryChild = geometryNode.firstChild();
if ( geometryChild.isNull() )
Expand All @@ -31,7 +33,9 @@ QgsGeometry* QgsOgcUtils::geometryFromGML( const QDomNode& geometryNode )
geomType = geometryTypeElement.tagName();
}

if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" || geomType == "Box" || geomType == "Envelope" ) )
if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" ||
geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" ||
geomType == "Box" || geomType == "Envelope" ) )
return 0;

if ( geomType == "Point" )
Expand Down Expand Up @@ -525,7 +529,6 @@ QgsGeometry* QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement& geo
if ( nLines < 1 )
return 0;


//calculate the required wkb size
int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 * sizeof( int ) );
for ( std::list<std::list<QgsPoint> >::const_iterator it = lineCoordinates.begin(); it != lineCoordinates.end(); ++it )
Expand Down Expand Up @@ -560,9 +563,8 @@ QgsGeometry* QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement& geo
for ( std::list<QgsPoint>::const_iterator iter = it->begin(); iter != it->end(); ++iter )
{
x = iter->x();
//qWarning("x is: " + QString::number(x));
y = iter->y();
//qWarning("y is: " + QString::number(y));
// QgsDebugMsg( QString( "x, y is %1,%2" ).arg( x, 'f' ).arg( y, 'f' ) );
memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
wkbPosition += sizeof( double );
memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
Expand Down
14 changes: 10 additions & 4 deletions src/mapserver/qgswfsserver.cpp
Expand Up @@ -1348,6 +1348,7 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
// Commit the changes of the update elements
if ( !layer->commitChanges() )
{
QgsDebugMsg( QString( "update errors:\n %1" ).arg( layer->commitErrors().join( "\n " ) ) );
QDomElement trElem = doc.createElement( "TransactionResult" );
QDomElement stElem = doc.createElement( "Status" );
QDomElement successElem = doc.createElement( "PARTIAL" );
Expand Down Expand Up @@ -1384,6 +1385,7 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
// Commit the changes of the delete elements
if ( !layer->commitChanges() )
{
QgsDebugMsg( QString( "delete errors:\n %1" ).arg( layer->commitErrors().join( "\n " ) ) );
QDomElement trElem = doc.createElement( "TransactionResult" );
QDomElement stElem = doc.createElement( "Status" );
QDomElement successElem = doc.createElement( "PARTIAL" );
Expand All @@ -1401,8 +1403,7 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )

return resp;
}
// Start the insert transaction
layer->startEditing();

// Store the inserted features
QgsFeatureList inFeatList;
if ( cap & QgsVectorDataProvider::AddFeatures )
Expand Down Expand Up @@ -1466,7 +1467,7 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
}
}
}
// Commit the changes of the insert elements
// add the features
if ( !provider->addFeatures( inFeatList ) )
{
QDomElement trElem = doc.createElement( "TransactionResult" );
Expand All @@ -1488,7 +1489,12 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
mesErrors << "\n Provider errors:" << provider->errors();
provider->clearErrors();
}
mesElem.appendChild( doc.createTextNode( layer->commitErrors().join( "\n " ) ) );
else
{
mesErrors << "\n Provider didn't report any errors:";
}
QgsDebugMsg( QString( "add errors:\n %1" ).arg( mesErrors.join( "\n " ) ) );
mesElem.appendChild( doc.createTextNode( mesErrors.join( "\n " ) ) );
trElem.appendChild( mesElem );

return resp;
Expand Down
75 changes: 48 additions & 27 deletions src/providers/wfs/qgswfsprovider.cpp
Expand Up @@ -49,6 +49,8 @@ static const QString TEXT_PROVIDER_DESCRIPTION = "WFS data provider";

static const QString WFS_NAMESPACE = "http://www.opengis.net/wfs";
static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
static const QString OGC_NAMESPACE = "http://www.opengis.net/ogc";
static const QString OWS_NAMESPACE = "http://www.opengis.net/ows";

QgsWFSProvider::QgsWFSProvider( const QString& uri )
: QgsVectorDataProvider( uri )
Expand Down Expand Up @@ -332,7 +334,7 @@ bool QgsWFSProvider::addFeatures( QgsFeatureList &flist )
for ( ; featureIt != flist.end(); ++featureIt )
{
//Insert element
QDomElement insertElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Insert" );
QDomElement insertElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Insert" );
transactionElem.appendChild( insertElem );

QDomElement featureElem = transactionDoc.createElementNS( mWfsNamespace, tname );
Expand Down Expand Up @@ -424,9 +426,9 @@ bool QgsWFSProvider::deleteFeatures( const QgsFeatureIds &id )
QDomElement transactionElem = createTransactionElement( transactionDoc );
transactionDoc.appendChild( transactionElem );
//delete element
QDomElement deleteElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Delete" );
QDomElement deleteElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Delete" );
deleteElem.setAttribute( "typeName", tname );
QDomElement filterElem = transactionDoc.createElementNS( "http://www.opengis.net/ogc", "Filter" );
QDomElement filterElem = transactionDoc.createElementNS( OGC_NAMESPACE, "Filter" );


QgsFeatureIds::const_iterator idIt = id.constBegin();
Expand All @@ -438,7 +440,7 @@ bool QgsWFSProvider::deleteFeatures( const QgsFeatureIds &id )
{
continue;
}
QDomElement featureIdElem = transactionDoc.createElementNS( "http://www.opengis.net/ogc", "FeatureId" );
QDomElement featureIdElem = transactionDoc.createElementNS( OGC_NAMESPACE, "FeatureId" );
featureIdElem.setAttribute( "fid", fidIt.value() );
filterElem.appendChild( featureIdElem );
}
Expand Down Expand Up @@ -502,23 +504,23 @@ bool QgsWFSProvider::changeGeometryValues( QgsGeometryMap & geometry_map )
continue;
}

QDomElement updateElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Update" );
QDomElement updateElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Update" );
updateElem.setAttribute( "typeName", tname );
//Property
QDomElement propertyElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Property" );
QDomElement nameElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Name" );
QDomElement propertyElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Property" );
QDomElement nameElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Name" );
QDomText nameText = transactionDoc.createTextNode( mGeometryAttribute );
nameElem.appendChild( nameText );
propertyElem.appendChild( nameElem );
QDomElement valueElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Value" );
QDomElement valueElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Value" );
QDomElement gmlElem = QgsOgcUtils::geometryToGML( &geomIt.value(), transactionDoc );
valueElem.appendChild( gmlElem );
propertyElem.appendChild( valueElem );
updateElem.appendChild( propertyElem );

//filter
QDomElement filterElem = transactionDoc.createElementNS( "http://www.opengis.net/ogc", "Filter" );
QDomElement featureIdElem = transactionDoc.createElementNS( "http://www.opengis.net/ogc", "FeatureId" );
QDomElement filterElem = transactionDoc.createElementNS( OGC_NAMESPACE, "Filter" );
QDomElement featureIdElem = transactionDoc.createElementNS( OGC_NAMESPACE, "FeatureId" );
featureIdElem.setAttribute( "fid", fidIt.value() );
filterElem.appendChild( featureIdElem );
updateElem.appendChild( filterElem );
Expand Down Expand Up @@ -589,21 +591,21 @@ bool QgsWFSProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
continue;
}

QDomElement updateElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Update" );
QDomElement updateElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Update" );
updateElem.setAttribute( "typeName", tname );

QgsAttributeMap::const_iterator attMapIt = attIt.value().constBegin();
for ( ; attMapIt != attIt.value().constEnd(); ++attMapIt )
{
QString fieldName = mFields.at( attMapIt.key() ).name();
QDomElement propertyElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Property" );
QDomElement propertyElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Property" );

QDomElement nameElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Name" );
QDomElement nameElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Name" );
QDomText nameText = transactionDoc.createTextNode( fieldName );
nameElem.appendChild( nameText );
propertyElem.appendChild( nameElem );

QDomElement valueElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Value" );
QDomElement valueElem = transactionDoc.createElementNS( WFS_NAMESPACE, "Value" );
QDomText valueText = transactionDoc.createTextNode( attMapIt.value().toString() );
valueElem.appendChild( valueText );
propertyElem.appendChild( valueElem );
Expand All @@ -612,8 +614,8 @@ bool QgsWFSProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
}

//Filter
QDomElement filterElem = transactionDoc.createElementNS( "http://www.opengis.net/ogc", "Filter" );
QDomElement featureIdElem = transactionDoc.createElementNS( "http://www.opengis.net/ogc", "FeatureId" );
QDomElement filterElem = transactionDoc.createElementNS( OGC_NAMESPACE, "Filter" );
QDomElement featureIdElem = transactionDoc.createElementNS( OGC_NAMESPACE, "FeatureId" );
featureIdElem.setAttribute( "fid", fidIt.value() );
filterElem.appendChild( featureIdElem );
updateElem.appendChild( filterElem );
Expand Down Expand Up @@ -1407,7 +1409,7 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument& doc, QDomDocum

QDomElement QgsWFSProvider::createTransactionElement( QDomDocument& doc ) const
{
QDomElement transactionElem = doc.createElementNS( "http://www.opengis.net/wfs", "Transaction" );
QDomElement transactionElem = doc.createElementNS( WFS_NAMESPACE, "Transaction" );
transactionElem.setAttribute( "version", "1.0.0" );
transactionElem.setAttribute( "service", "WFS" );
transactionElem.setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" );
Expand Down Expand Up @@ -1437,13 +1439,13 @@ bool QgsWFSProvider::transactionSuccess( const QDomDocument& serverResponse ) co
return false;
}

QDomNodeList transactionResultList = documentElem.elementsByTagNameNS( "http://www.opengis.net/wfs", "TransactionResult" );
QDomNodeList transactionResultList = documentElem.elementsByTagNameNS( WFS_NAMESPACE, "TransactionResult" );
if ( transactionResultList.size() < 1 )
{
return false;
}

QDomNodeList statusList = transactionResultList.at( 0 ).toElement().elementsByTagNameNS( "http://www.opengis.net/wfs", "Status" );
QDomNodeList statusList = transactionResultList.at( 0 ).toElement().elementsByTagNameNS( WFS_NAMESPACE, "Status" );
if ( statusList.size() < 1 )
{
return false;
Expand Down Expand Up @@ -1473,10 +1475,10 @@ QStringList QgsWFSProvider::insertedFeatureIds( const QDomDocument& serverRespon
return ids;
}

QDomNodeList insertResultList = rootElem.elementsByTagNameNS( "http://www.opengis.net/wfs", "InsertResult" );
QDomNodeList insertResultList = rootElem.elementsByTagNameNS( WFS_NAMESPACE, "InsertResult" );
for ( int i = 0; i < insertResultList.size(); ++i )
{
QDomNodeList featureIdList = insertResultList.at( i ).toElement().elementsByTagNameNS( "http://www.opengis.net/ogc", "FeatureId" );
QDomNodeList featureIdList = insertResultList.at( i ).toElement().elementsByTagNameNS( OGC_NAMESPACE, "FeatureId" );
for ( int j = 0; j < featureIdList.size(); ++j )
{
QString fidString = featureIdList.at( j ).toElement().attribute( "fid" );
Expand Down Expand Up @@ -1640,21 +1642,40 @@ QGis::WkbType QgsWFSProvider::geomTypeFromPropertyType( QString attName, QString
return ( QGis::WkbType ) i;
}

void QgsWFSProvider::handleException( const QDomDocument& serverResponse ) const
void QgsWFSProvider::handleException( const QDomDocument& serverResponse )
{
QgsDebugMsg( QString( "server response: %1" ).arg( serverResponse.toString() ) );

QDomElement exceptionElem = serverResponse.documentElement();
if ( exceptionElem.isNull() || exceptionElem.tagName() != "ServiceExceptionReport" )
if ( exceptionElem.isNull() )
{
pushError( QObject::tr( "empty response" ).arg( exceptionElem.tagName() ) );
return;
}

if ( exceptionElem.tagName() == "ServiceExceptionReport" )
{
pushError( QObject::tr( "WFS service exception:%1" ).arg( exceptionElem.firstChildElement( "ServiceException" ).text() ) );
return;
}

//possibly this class is used not in a gui application
if ( QApplication::topLevelWidgets().size() < 1 )
if ( exceptionElem.tagName() == "WFS_TransactionResponse" )
{
pushError( QObject::tr( "unsuccessful service response: %1" ).arg( exceptionElem.firstChildElement( "TransactionResult" ).firstChildElement( "Message" ).text() ) );
return;
}
QString message = exceptionElem.firstChildElement( "ServiceException" ).text();
QMessageBox::critical( 0, tr( "Error" ), message );

if ( exceptionElem.tagName() == "ExceptionReport" )
{
QDomElement exception = exceptionElem.firstChildElement( "Exception" );
pushError( QObject::tr( "WFS exception report (code=%1 text=%2)" )
.arg( exception.attribute( "exceptionCode", QObject::tr( "missing" ) ) )
.arg( exception.firstChildElement( "ExceptionText" ).text() )
);
return;
}

pushError( QObject::tr( "unhandled response: %1" ).arg( exceptionElem.tagName() ) );
}

QGISEXTERN QgsWFSProvider* classFactory( const QString *uri )
Expand Down
4 changes: 2 additions & 2 deletions src/providers/wfs/qgswfsprovider.h
Expand Up @@ -232,8 +232,8 @@ class QgsWFSProvider: public QgsVectorDataProvider
void getLayerCapabilities();
/**Takes <Operations> element and updates the capabilities*/
void appendSupportedOperations( const QDomElement& operationsElem, int& capabilities ) const;
/**Shows a message box with the exception string (or does nothing if the xml document is not an exception)*/
void handleException( const QDomDocument& serverResponse ) const;
/**records provider error*/
void handleException( const QDomDocument& serverResponse );
/**Initializes "Cache Features" inactive processing*/
bool initGetRenderedOnly( QgsRectangle );
/**Converts DescribeFeatureType schema geometry property type to WKBType*/
Expand Down

0 comments on commit 838367e

Please sign in to comment.