959 changes: 935 additions & 24 deletions src/core/qgsgeometry.cpp

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions src/core/qgsgeometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ email : morb at ozemail dot com dot au

#include <QString>
#include <QVector>
#include <QDomDocument>

#include "qgis.h"

Expand Down Expand Up @@ -88,6 +89,11 @@ class CORE_EXPORT QgsGeometry
/** static method that creates geometry from Wkt */
static QgsGeometry* fromWkt( QString wkt );

/** static method that creates geometry from GML2
@note added in 1.9
*/
static QgsGeometry* fromGML2( const QDomNode& geometryNode );

/** construct geometry from a point */
static QgsGeometry* fromPoint( const QgsPoint& point );
/** construct geometry from a multipoint */
Expand Down Expand Up @@ -383,6 +389,12 @@ class CORE_EXPORT QgsGeometry
*/
QString exportToGeoJSON();

/** Exports the geometry to mGML2
@return true in case of success and false else
* @note added in 1.9
*/
QDomElement exportToGML2( QDomDocument& doc );

/* Accessor functions for getting geometry data */

/** return contents of the geometry as a point
Expand Down Expand Up @@ -488,6 +500,24 @@ class CORE_EXPORT QgsGeometry

// Private functions

/** static method that creates geometry from GML2 Point */
bool setFromGML2Point( const QDomElement& geometryElement );
/** static method that creates geometry from GML2 LineString */
bool setFromGML2LineString( const QDomElement& geometryElement );
/** static method that creates geometry from GML2 Polygon */
bool setFromGML2Polygon( const QDomElement& geometryElement );
/** static method that creates geometry from GML2 MultiPoint */
bool setFromGML2MultiPoint( const QDomElement& geometryElement );
/** static method that creates geometry from GML2 MultiLineString */
bool setFromGML2MultiLineString( const QDomElement& geometryElement );
/** static method that creates geometry from GML2 MultiPolygon */
bool setFromGML2MultiPolygon( const QDomElement& geometryElement );
/**Reads the <gml:coordinates> element and extracts the coordinates as points
@param coords list where the found coordinates are appended
@param elem the <gml:coordinates> element
@return boolean for success*/
bool readGML2Coordinates( std::list<QgsPoint>& coords, const QDomElement elem ) const;

/** Converts from the WKB geometry to the GEOS geometry.
@return true in case of success and false else
*/
Expand Down
20 changes: 20 additions & 0 deletions src/mapserver/qgis_map_serv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,26 @@ int main( int argc, char * argv[] )
continue;
}
}
else if ( request == "Transaction" )
{
QDomDocument transactionDocument;
try
{
transactionDocument = theServer->transaction( parameterMap.value( "REQUEST_BODY" ) );
}
catch ( QgsMapServiceException& ex )
{
theRequestHandler->sendServiceException( ex );
delete theRequestHandler;
delete theServer;
continue;
}
QgsDebugMsg( "sending Transaction response" );
theRequestHandler->sendGetCapabilitiesResponse( transactionDocument );
delete theRequestHandler;
delete theServer;
continue;
}

return 0;
}
Expand Down
3 changes: 3 additions & 0 deletions src/mapserver/qgsconfigparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ class QgsConfigParser
virtual QStringList identifyDisabledLayers() const { return QStringList(); }
/**Returns an ID-list of layers which queryable in WFS service*/
virtual QStringList wfsLayers() const { return QStringList(); }
virtual QStringList wfstUpdateLayers() const { return QStringList(); }
virtual QStringList wfstInsertLayers() const { return QStringList(); }
virtual QStringList wfstDeleteLayers() const { return QStringList(); }

/**Returns a set of supported epsg codes for the capabilities document. An empty list means
that all possible CRS should be advertised (which could result in very long capabilities documents)*/
Expand Down
33 changes: 32 additions & 1 deletion src/mapserver/qgspostrequesthandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "qgspostrequesthandler.h"
#include "qgslogger.h"
#include <QDomDocument>

QgsPostRequestHandler::QgsPostRequestHandler()
{
Expand All @@ -32,6 +33,36 @@ QMap<QString, QString> QgsPostRequestHandler::parseInput()
QMap<QString, QString> parameters;
QString inputString = readPostBody();
QgsDebugMsg( inputString );
requestStringToParameterMap( inputString, parameters );

QDomDocument doc;
QString errorMsg;
if ( !doc.setContent( inputString, true, &errorMsg ) )
{
requestStringToParameterMap( inputString, parameters );
}
else
{
QString queryString;
const char* qs = getenv( "QUERY_STRING" );
if ( qs )
{
queryString = QString( qs );
QgsDebugMsg( "query string is: " + queryString );
}
else
{
QgsDebugMsg( "error, no query string found but a QDomDocument" );
return parameters; //no query string? something must be wrong...
}

requestStringToParameterMap( queryString, parameters );

QDomElement docElem = doc.documentElement();
parameters.insert( "VERSION", docElem.attribute( "version" ) );
parameters.insert( "SERVICE", docElem.attribute( "service" ) );
parameters.insert( "REQUEST", docElem.localName() );
parameters.insert( "REQUEST_BODY", inputString );
}

return parameters;
}
151 changes: 151 additions & 0 deletions src/mapserver/qgsprojectparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ void QgsProjectParser::layersAndStylesCapabilities( QDomElement& parentElement,
void QgsProjectParser::featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const
{
QStringList wfsLayersId = wfsLayers();
QStringList wfstUpdateLayersId = wfstUpdateLayers();
QStringList wfstInsertLayersId = wfstInsertLayers();
QStringList wfstDeleteLayersId = wfstDeleteLayers();

if ( mProjectLayerElements.size() < 1 )
{
Expand Down Expand Up @@ -193,6 +196,37 @@ void QgsProjectParser::featureTypeList( QDomElement& parentElement, QDomDocument
bBoxElement.setAttribute( "maxx", QString::number( layerExtent.xMaximum() ) );
bBoxElement.setAttribute( "maxy", QString::number( layerExtent.yMaximum() ) );
layerElem.appendChild( bBoxElement );

//wfs:Operations element
QDomElement operationsElement = doc.createElement( "Operations"/*wfs:Operations*/ );
//wfs:Query element
QDomElement queryElement = doc.createElement( "Query"/*wfs:Query*/ );
operationsElement.appendChild( queryElement );

QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( layer );
QgsVectorDataProvider* provider = vlayer->dataProvider();
if ( ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) )
{
//wfs:Insert element
QDomElement insertElement = doc.createElement( "Insert"/*wfs:Insert*/ );
operationsElement.appendChild( insertElement );
}
if ( (provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) &&
(provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) &&
wfstUpdateLayersId.contains( layer->id() ) )
{
//wfs:Update element
QDomElement updateElement = doc.createElement( "Update"/*wfs:Update*/ );
operationsElement.appendChild( updateElement );
}
if ( ( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) )
{
//wfs:Delete element
QDomElement deleteElement = doc.createElement( "Delete"/*wfs:Delete*/ );
operationsElement.appendChild( deleteElement );
}

layerElem.appendChild( operationsElement );

parentElement.appendChild( layerElem );
}
Expand Down Expand Up @@ -954,6 +988,123 @@ QStringList QgsProjectParser::wfsLayers() const
return wfsList;
}

QStringList QgsProjectParser::wfstUpdateLayers() const
{
QStringList publiedIds = wfsLayers();
QStringList wfsList;
if ( !mXMLDoc )
{
return wfsList;
}

QDomElement qgisElem = mXMLDoc->documentElement();
if ( qgisElem.isNull() )
{
return wfsList;
}
QDomElement propertiesElem = qgisElem.firstChildElement( "properties" );
if ( propertiesElem.isNull() )
{
return wfsList;
}
QDomElement wfstLayersElem = propertiesElem.firstChildElement( "WFSTLayers" );
if ( wfstLayersElem.isNull() )
{
return wfsList;
}
QDomElement wfstUpdateLayersElem = wfstLayersElem.firstChildElement( "Update" );
if ( wfstUpdateLayersElem.isNull() )
{
return wfsList;
}
QDomNodeList valueList = wfstUpdateLayersElem.elementsByTagName( "value" );
for ( int i = 0; i < valueList.size(); ++i )
{
QString id = valueList.at( i ).toElement().text();
if ( publiedIds.contains( id ) )
wfsList << id;
}
return wfsList;
}

QStringList QgsProjectParser::wfstInsertLayers() const
{
QStringList updateIds = wfstUpdateLayers();
QStringList wfsList;
if ( !mXMLDoc )
{
return wfsList;
}

QDomElement qgisElem = mXMLDoc->documentElement();
if ( qgisElem.isNull() )
{
return wfsList;
}
QDomElement propertiesElem = qgisElem.firstChildElement( "properties" );
if ( propertiesElem.isNull() )
{
return wfsList;
}
QDomElement wfstLayersElem = propertiesElem.firstChildElement( "WFSTLayers" );
if ( wfstLayersElem.isNull() )
{
return wfsList;
}
QDomElement wfstInsertLayersElem = wfstLayersElem.firstChildElement( "Insert" );
if ( wfstInsertLayersElem.isNull() )
{
return wfsList;
}
QDomNodeList valueList = wfstInsertLayersElem.elementsByTagName( "value" );
for ( int i = 0; i < valueList.size(); ++i )
{
QString id = valueList.at( i ).toElement().text();
if ( updateIds.contains( id ) )
wfsList << id;
}
return wfsList;
}

QStringList QgsProjectParser::wfstDeleteLayers() const
{
QStringList insertIds = wfstInsertLayers();
QStringList wfsList;
if ( !mXMLDoc )
{
return wfsList;
}

QDomElement qgisElem = mXMLDoc->documentElement();
if ( qgisElem.isNull() )
{
return wfsList;
}
QDomElement propertiesElem = qgisElem.firstChildElement( "properties" );
if ( propertiesElem.isNull() )
{
return wfsList;
}
QDomElement wfstLayersElem = propertiesElem.firstChildElement( "WFSTLayers" );
if ( wfstLayersElem.isNull() )
{
return wfsList;
}
QDomElement wfstDeleteLayersElem = wfstLayersElem.firstChildElement( "Delete" );
if ( wfstDeleteLayersElem.isNull() )
{
return wfsList;
}
QDomNodeList valueList = wfstDeleteLayersElem.elementsByTagName( "value" );
for ( int i = 0; i < valueList.size(); ++i )
{
QString id = valueList.at( i ).toElement().text();
if ( insertIds.contains( id ) )
wfsList << id;
}
return wfsList;
}

QStringList QgsProjectParser::supportedOutputCrsList() const
{
QStringList crsList;
Expand Down
3 changes: 3 additions & 0 deletions src/mapserver/qgsprojectparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class QgsProjectParser: public QgsConfigParser

/**Returns an ID-list of layers queryable for WFS service (comes from <properties> -> <WFSLayers> in the project file*/
virtual QStringList wfsLayers() const;
virtual QStringList wfstUpdateLayers() const;
virtual QStringList wfstInsertLayers() const;
virtual QStringList wfstDeleteLayers() const;

/**Returns a set of supported epsg codes for the capabilities document. The list comes from the property <WMSEpsgList> in the project file.
An empty set means that all possible CRS should be advertised (which could result in very long capabilities documents)
Expand Down
662 changes: 444 additions & 218 deletions src/mapserver/qgswfsserver.cpp

Large diffs are not rendered by default.

22 changes: 12 additions & 10 deletions src/mapserver/qgswfsserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <QMap>
#include <QString>
#include <map>
#include "qgis.h"
#include "qgsvectorlayer.h"

class QgsCoordinateReferenceSystem;
class QgsComposerLayerItem;
Expand Down Expand Up @@ -66,6 +68,10 @@ class QgsWFSServer
@return 0 in case of success*/
int getFeature( QgsRequestHandler& request, const QString& format );

/**Read and apply the transaction
@return 0 in case of success*/
QDomDocument transaction( const QString& requestBody );

/**Sets configuration parser for administration settings. Does not take ownership*/
void setAdminConfigParser( QgsConfigParser* parser ) { mConfigParser = parser; }

Expand All @@ -85,26 +91,22 @@ class QgsWFSServer
void sendGetFeature( QgsRequestHandler& request, const QString& format, QgsFeature* feat, int featIdx, QgsCoordinateReferenceSystem& crs, QMap< int, QgsField > fields, QSet<QString> excludedAttributes );
void endGetFeature( QgsRequestHandler& request, const QString& format );

//method for transaction
QgsFeatureIds getFeatureIdsFromFilter( QDomElement filter, QgsVectorLayer* layer );

//methods to write GeoJSON
QString createFeatureGeoJSON( QgsFeature* feat, QgsCoordinateReferenceSystem& crs, QMap< int, QgsField > fields, QSet<QString> excludedAttributes ) /*const*/;

//methods to write GML2
QDomElement createFeatureElem( QgsFeature* feat, QDomDocument& doc, QgsCoordinateReferenceSystem& crs, QMap< int, QgsField > fields, QSet<QString> excludedAttributes ) /*const*/;
QDomElement createFeatureGML2( QgsFeature* feat, QDomDocument& doc, QgsCoordinateReferenceSystem& crs, QMap< int, QgsField > fields, QSet<QString> hiddenAttributes ) /*const*/;

QDomElement createBoxElem( QgsRectangle* box, QDomDocument& doc ) /* const */;
QDomElement createGeometryElem( QgsGeometry* g, QDomDocument& doc ) /*const*/;
QDomElement createLineStringElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createMultiLineStringElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createPointElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createMultiPointElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createPolygonElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createMultiPolygonElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createBoxGML2( QgsRectangle* box, QDomDocument& doc ) /* const */;

/**Create a GML coordinate string from a point list.
@param points list of data points
@param coordString out: GML coord string
@return 0 in case of success*/
QDomElement createCoordinateElem( const QVector<QgsPoint> points, QDomDocument& doc ) const;
QDomElement createCoordinateGML2( const QVector<QgsPoint> points, QDomDocument& doc ) const;
};

#endif
764 changes: 16 additions & 748 deletions src/providers/wfs/qgswfsprovider.cpp

Large diffs are not rendered by default.

31 changes: 0 additions & 31 deletions src/providers/wfs/qgswfsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,20 +226,6 @@ class QgsWFSProvider: public QgsVectorDataProvider
int getExtentFromGML2( QgsRectangle* extent, const QDomElement& wfsCollectionElement ) const;

int getFeaturesFromGML2( const QDomElement& wfsCollectionElement, const QString& geometryAttribute );

int getWkbFromGML2( const QDomNode& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WkbType* type ) const;
/**Creates WKB from a <Point> element*/
int getWkbFromGML2Point( const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WkbType* type ) const;
/**Creates WKB from a <Polygon> element*/
int getWkbFromGML2Polygon( const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WkbType* type ) const;
/**Creates WKB from a <LineString> element*/
int getWkbFromGML2LineString( const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WkbType* type ) const;
/**Creates WKB from a <MultiPoint> element*/
int getWkbFromGML2MultiPoint( const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WkbType* type ) const;
/**Creates WKB from a <MultiLineString> element*/
int getWkbFromGML2MultiLineString( const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WkbType* type ) const;
/**Creates WKB from a <MultiPolygon> element*/
int getWkbFromGML2MultiPolygon( const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WkbType* type ) const;
/**Reads the <gml:coordinates> element and extracts the coordinates as points
@param coords list where the found coordinates are appended
@param elem the <gml:coordinates> element
Expand All @@ -248,23 +234,6 @@ class QgsWFSProvider: public QgsVectorDataProvider
/**Tries to create a QgsCoordinateReferenceSystem object and assign it to mSourceCRS. Returns 0 in case of success*/
int setCRSFromGML2( const QDomElement& wfsCollectionElement );


//methods to write GML2

QDomElement createGeometryElem( QgsGeometry* g, QDomDocument& doc ) /*const*/;
QDomElement createLineStringElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createMultiLineStringElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createPointElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createMultiPointElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createPolygonElem( QgsGeometry* geom, QDomDocument& doc ) const;
QDomElement createMultiPolygonElem( QgsGeometry* geom, QDomDocument& doc ) const;

/**Create a GML coordinate string from a point list.
@param points list of data points
@param coordString out: GML coord string
@return 0 in case of success*/
QDomElement createCoordinateElem( const QVector<QgsPoint> points, QDomDocument& doc ) const;

//helper methods for WFS-T

/**Returns HTTP parameter value from url (or empty string if it does not exist)*/
Expand Down
15 changes: 15 additions & 0 deletions src/ui/qgsprojectpropertiesbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,21 @@
<string>Published</string>
</property>
</column>
<column>
<property name="text">
<string>Update</string>
</property>
</column>
<column>
<property name="text">
<string>Insert</string>
</property>
</column>
<column>
<property name="text">
<string>Delete</string>
</property>
</column>
</widget>
</item>
<item row="1" column="1">
Expand Down