-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[OAPIF provider] Add support for edition capabilities (OGC API Featur…
…es Part 4) - Issues OPTIONS on /collections/{coll_id} and collections/{coll_id}/{feature_id} endpoints to check server capabilities - Add support for addFeature() through POST /collections/{coll_id} endpoint - Add support for changeGeometryValues()/changeAttributeValues() through PUT /collections/{coll_id}/{feature_id} endpoint. Or through PATCH /collections/{coll_id}/{feature_id} with just the updated subset, if available - Add support for deleteFeatures() through DELETE /collections/{coll_id}/{feature_id} endpoint. - For POST/PUT/PATCH, takes into account Part 2 (CRS support) when implemented by the server.
- Loading branch information
Showing
18 changed files
with
1,374 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/*************************************************************************** | ||
qgsoapifcreatefeaturerequest.cpp | ||
-------------------------------- | ||
begin : March 2023 | ||
copyright : (C) 2023 by Even Rouault | ||
email : even.rouault at spatialys.com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include <nlohmann/json.hpp> | ||
using namespace nlohmann; | ||
|
||
#include "qgslogger.h" | ||
#include "qgsjsonutils.h" | ||
#include "qgsoapifcreatefeaturerequest.h" | ||
#include "qgsoapifprovider.h" | ||
|
||
#include <QTransform> | ||
|
||
QgsOapifCreateFeatureRequest::QgsOapifCreateFeatureRequest( const QgsDataSourceUri &uri ): | ||
QgsBaseNetworkRequest( QgsAuthorizationSettings( uri.username(), uri.password(), uri.authConfigId() ), "OAPIF" ) | ||
{ | ||
} | ||
|
||
QString QgsOapifCreateFeatureRequest::createFeature( const QgsOapifSharedData *sharedData, const QgsFeature &f, const QString &contentCrs, bool hasAxisInverted ) | ||
{ | ||
QgsJsonExporter exporter; | ||
|
||
QgsFeature fModified( f ); | ||
if ( hasAxisInverted && f.hasGeometry() ) | ||
{ | ||
QgsGeometry g = f.geometry(); | ||
g.transform( QTransform( 0, 1, 1, 0, 0, 0 ) ); | ||
fModified.setGeometry( g ); | ||
} | ||
|
||
json j = exporter.exportFeatureToJsonObject( fModified ); | ||
if ( j.contains( "id" ) ) | ||
j.erase( "id" ); | ||
if ( j.contains( "bbox" ) ) | ||
j.erase( "bbox" ); | ||
if ( !sharedData->mFoundIdInProperties && j["properties"].contains( "id" ) ) | ||
j["properties"].erase( "id" ); | ||
const QString jsonFeature = QString::fromStdString( j.dump() ); | ||
QgsDebugMsgLevel( jsonFeature, 5 ); | ||
mEmptyResponseIsValid = true; | ||
mFakeResponseHasHeaders = true; | ||
QList<QNetworkReply::RawHeaderPair> extraHeaders; | ||
if ( !contentCrs.isEmpty() ) | ||
extraHeaders.append( QNetworkReply::RawHeaderPair( QByteArray( "Content-Crs" ), contentCrs.toUtf8() ) ); | ||
if ( !sendPOST( sharedData->mItemsUrl, "application/geo+json", jsonFeature.toUtf8(), extraHeaders ) ) | ||
return QString(); | ||
|
||
QString location; | ||
for ( const auto &headerKeyValue : mResponseHeaders ) | ||
{ | ||
if ( headerKeyValue.first == QByteArray( "Location" ) ) | ||
{ | ||
location = QString::fromUtf8( headerKeyValue.second ); | ||
break; | ||
} | ||
} | ||
|
||
const int posItems = location.lastIndexOf( QLatin1String( "/items/" ) ); | ||
if ( posItems < 0 ) | ||
return QString(); | ||
|
||
QString createdId = location.mid( posItems + static_cast<int>( strlen( "/items/" ) ) ); | ||
QgsDebugMsgLevel( "createdId = " + createdId, 5 ); | ||
return createdId; | ||
} | ||
|
||
QString QgsOapifCreateFeatureRequest::errorMessageWithReason( const QString &reason ) | ||
{ | ||
return tr( "Create Feature request failed: %1" ).arg( reason ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/*************************************************************************** | ||
qgsoapifcreatefeaturerequest.h | ||
------------------------------ | ||
begin : March 2023 | ||
copyright : (C) 2023 by Even Rouault | ||
email : even.rouault at spatialys.com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSOAPIFCREATEFEATUREREQUEST_H | ||
#define QGSOAPIFCREATEFEATUREREQUEST_H | ||
|
||
#include <QObject> | ||
|
||
#include "qgsdatasourceuri.h" | ||
#include "qgsfeature.h" | ||
#include "qgsbasenetworkrequest.h" | ||
|
||
class QgsOapifSharedData; | ||
|
||
//! Manages the Create Feature request | ||
class QgsOapifCreateFeatureRequest : public QgsBaseNetworkRequest | ||
{ | ||
Q_OBJECT | ||
public: | ||
explicit QgsOapifCreateFeatureRequest( const QgsDataSourceUri &uri ); | ||
|
||
//! Issue a POST request to create the feature and return its id | ||
QString createFeature( const QgsOapifSharedData *sharedData, const QgsFeature &f, const QString &contentCrs, bool hasAxisInverted ); | ||
|
||
protected: | ||
QString errorMessageWithReason( const QString &reason ) override; | ||
}; | ||
|
||
#endif // QGSOAPIFCREATEFEATUREREQUEST_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/*************************************************************************** | ||
qgsoapifdeletefeaturerequest.cpp | ||
-------------------------------- | ||
begin : March 2023 | ||
copyright : (C) 2023 by Even Rouault | ||
email : even.rouault at spatialys.com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgslogger.h" | ||
#include "qgsoapifdeletefeaturerequest.h" | ||
|
||
QgsOapifDeleteFeatureRequest::QgsOapifDeleteFeatureRequest( const QgsDataSourceUri &uri ): | ||
QgsBaseNetworkRequest( QgsAuthorizationSettings( uri.username(), uri.password(), uri.authConfigId() ), "OAPIF" ) | ||
{ | ||
} | ||
|
||
QString QgsOapifDeleteFeatureRequest::errorMessageWithReason( const QString &reason ) | ||
{ | ||
return tr( "Delete Feature request failed: %1" ).arg( reason ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/*************************************************************************** | ||
qgsoapifdeletefeaturerequest.h | ||
------------------------------ | ||
begin : March 2023 | ||
copyright : (C) 2023 by Even Rouault | ||
email : even.rouault at spatialys.com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSOAPIFDELETEFEATUREREQUEST_H | ||
#define QGSOAPIFDELETEFEATUREREQUEST_H | ||
|
||
#include <QObject> | ||
|
||
#include "qgsdatasourceuri.h" | ||
#include "qgsbasenetworkrequest.h" | ||
|
||
//! Manages the Delete Feature request | ||
class QgsOapifDeleteFeatureRequest : public QgsBaseNetworkRequest | ||
{ | ||
Q_OBJECT | ||
public: | ||
explicit QgsOapifDeleteFeatureRequest( const QgsDataSourceUri &uri ); | ||
|
||
protected: | ||
QString errorMessageWithReason( const QString &reason ) override; | ||
}; | ||
|
||
#endif // QGSOAPIFDELETEFEATUREREQUEST_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/*************************************************************************** | ||
qgsoapifoptionsrequest.cpp | ||
-------------------------- | ||
begin : March 2023 | ||
copyright : (C) 2023 by Even Rouault | ||
email : even.rouault at spatialys.com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgsoapifoptionsrequest.h" | ||
|
||
QgsOapifOptionsRequest::QgsOapifOptionsRequest( const QgsDataSourceUri &uri ): | ||
QgsBaseNetworkRequest( QgsAuthorizationSettings( uri.username(), uri.password(), uri.authConfigId() ), "OAPIF" ) | ||
{ | ||
} | ||
|
||
QString QgsOapifOptionsRequest::errorMessageWithReason( const QString &reason ) | ||
{ | ||
return tr( "Download of OPTIONS failed: %1" ).arg( reason ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/*************************************************************************** | ||
qgsoapifoptionsrequest.h | ||
------------------------ | ||
begin : March 2023 | ||
copyright : (C) 2023 by Even Rouault | ||
email : even.rouault at spatialys.com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSOAPIFOPTIONSREQUEST_H | ||
#define QGSOAPIFOPTIONSREQUEST_H | ||
|
||
#include <QObject> | ||
|
||
#include "qgsdatasourceuri.h" | ||
#include "qgsbasenetworkrequest.h" | ||
|
||
//! Manages the Options request | ||
class QgsOapifOptionsRequest : public QgsBaseNetworkRequest | ||
{ | ||
Q_OBJECT | ||
public: | ||
explicit QgsOapifOptionsRequest( const QgsDataSourceUri &uri ); | ||
|
||
protected: | ||
QString errorMessageWithReason( const QString &reason ) override; | ||
}; | ||
|
||
#endif // QGSOAPIFOPTIONSREQUEST_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/*************************************************************************** | ||
qgsoapifpatchfeaturerequest.cpp | ||
------------------------------- | ||
begin : March 2023 | ||
copyright : (C) 2023 by Even Rouault | ||
email : even.rouault at spatialys.com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include <nlohmann/json.hpp> | ||
using namespace nlohmann; | ||
|
||
#include "qgsjsonutils.h" | ||
|
||
#include "qgsoapifpatchfeaturerequest.h" | ||
#include "qgsoapifprovider.h" | ||
|
||
#include <QTransform> | ||
|
||
QgsOapifPatchFeatureRequest::QgsOapifPatchFeatureRequest( const QgsDataSourceUri &uri ): | ||
QgsBaseNetworkRequest( QgsAuthorizationSettings( uri.username(), uri.password(), uri.authConfigId() ), "OAPIF" ) | ||
{ | ||
} | ||
|
||
bool QgsOapifPatchFeatureRequest::patchFeature( const QgsOapifSharedData *sharedData, const QString &jsonId, const QgsGeometry &geom, const QString &contentCrs, bool hasAxisInverted ) | ||
{ | ||
QgsGeometry geomModified( geom ); | ||
if ( hasAxisInverted ) | ||
{ | ||
geomModified.transform( QTransform( 0, 1, 1, 0, 0, 0 ) ); | ||
} | ||
|
||
json j; | ||
j["geometry"] = geomModified.asJsonObject(); | ||
QList<QNetworkReply::RawHeaderPair> extraHeaders; | ||
if ( !contentCrs.isEmpty() ) | ||
extraHeaders.append( QNetworkReply::RawHeaderPair( QByteArray( "Content-Crs" ), contentCrs.toUtf8() ) ); | ||
mEmptyResponseIsValid = true; | ||
mFakeURLIncludesContentType = true; | ||
QUrl url( sharedData->mItemsUrl + QString( QStringLiteral( "/" ) + jsonId ) ); | ||
return sendPATCH( url, "application/merge-patch+json", QString::fromStdString( j.dump() ).toUtf8(), extraHeaders ); | ||
} | ||
|
||
bool QgsOapifPatchFeatureRequest::patchFeature( const QgsOapifSharedData *sharedData, const QString &jsonId, const QgsAttributeMap &attrMap ) | ||
{ | ||
json properties; | ||
QgsAttributeMap::const_iterator attMapIt = attrMap.constBegin(); | ||
for ( ; attMapIt != attrMap.constEnd(); ++attMapIt ) | ||
{ | ||
QString fieldName = sharedData->mFields.at( attMapIt.key() ).name(); | ||
properties[ fieldName.toStdString() ] = QgsJsonUtils::jsonFromVariant( attMapIt.value() ); | ||
} | ||
json j; | ||
j[ "properties" ] = properties; | ||
mEmptyResponseIsValid = true; | ||
mFakeURLIncludesContentType = true; | ||
QUrl url( sharedData->mItemsUrl + QString( QStringLiteral( "/" ) + jsonId ) ); | ||
return sendPATCH( url, "application/merge-patch+json", QString::fromStdString( j.dump() ).toUtf8() ); | ||
} | ||
|
||
QString QgsOapifPatchFeatureRequest::errorMessageWithReason( const QString &reason ) | ||
{ | ||
return tr( "Patch Feature request failed: %1" ).arg( reason ); | ||
} |
Oops, something went wrong.