1 /*************************************************************************** 2 qgswfsprovider.h 3 ------------------- 4 begin : July 25, 2006 5 copyright : (C) 2006 by Marco Hugentobler 6 (C) 2016 by Even Rouault 7 email : marco dot hugentobler at karto dot baug dot ethz dot ch 8 even.rouault at spatialys.com 9 ***************************************************************************/ 10 11 /*************************************************************************** 12 * * 13 * This program is free software; you can redistribute it and/or modify * 14 * it under the terms of the GNU General Public License as published by * 15 * the Free Software Foundation; either version 2 of the License, or * 16 * (at your option) any later version. * 17 * * 18 ***************************************************************************/ 19 20 #ifndef QGSWFSPROVIDER_H 21 #define QGSWFSPROVIDER_H 22 23 #include "qgis.h" 24 #include "qgsrectangle.h" 25 #include "qgscoordinatereferencesystem.h" 26 #include "qgsvectordataprovider.h" 27 #include "qgswfscapabilities.h" 28 #include "qgswfsfeatureiterator.h" 29 #include "qgswfsdatasourceuri.h" 30 31 #include "qgsprovidermetadata.h" 32 33 class QgsRectangle; 34 class QgsWFSSharedData; 35 36 37 /** 38 * \ingroup WFSProvider 39 * 40 * \brief A provider reading/write features from/into a WFS server. 41 * 42 * Below quick design notes on the whole provider. 43 * 44 * QgsWFSProvider class purpose: 45 * 46 * - in constructor, do a GetCapabilities request to determine server-side feature limit, 47 paging capabilities, WFS version, edition capabilities. Do a DescribeFeatureType request 48 to determine fields, geometry name and type. 49 * - in other methods, mostly WFS-T related operations. 50 * 51 * QgsWFSSharedData class purpose: 52 * 53 * - contains logic shared by QgsWFSProvider, QgsWFSFeatureIterator and QgsWFSFeatureDownloader. 54 * - one of its main function is to maintain a on-disk cache of the features retrieved 55 * from the server. This cache is a SpatiaLite database. 56 * 57 * QgsWFSRequest class purpose: abstract base class to create WFS network requests, 58 * such as QgsWFSCapabilities, QgsWFSDescribeFeatureType, QgsWFSFeatureDownloader, 59 * QgsWFSFeatureHitsAsyncRequest, QgsWFSFeatureHitsRequest, QgsWFSTransactionRequest 60 * 61 * QgsWFSDataSourceURI class purpose: wrapper above QgsDataSourceUri to get/set 62 * the specific attributes of a WFS URI. 63 * 64 */ 65 class QgsWFSProvider final: public QgsVectorDataProvider 66 { 67 Q_OBJECT 68 public: 69 70 static const QString WFS_PROVIDER_KEY; 71 static const QString WFS_PROVIDER_DESCRIPTION; 72 73 explicit QgsWFSProvider( const QString &uri, const QgsDataProvider::ProviderOptions &providerOptions, const QgsWfsCapabilities::Capabilities &caps = QgsWfsCapabilities::Capabilities() ); 74 ~QgsWFSProvider() override; 75 76 /* Inherited from QgsVectorDataProvider */ 77 78 QgsAbstractFeatureSource *featureSource() const override; 79 80 QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) const override; 81 82 QgsWkbTypes::Type wkbType() const override; 83 long featureCount() const override; 84 85 QgsFields fields() const override; 86 87 QgsCoordinateReferenceSystem crs() const override; 88 89 QString subsetString() const override; 90 bool setSubsetString( const QString &theSQL, bool updateFeatureCount = true ) override; 91 supportsSubsetString()92 bool supportsSubsetString() const override { return true; } 93 94 /* Inherited from QgsDataProvider */ 95 96 QgsRectangle extent() const override; 97 bool isValid() const override; 98 QString name() const override; 99 QString description() const override; 100 101 QgsVectorDataProvider::Capabilities capabilities() const override; 102 storageType()103 QString storageType() const override { return QStringLiteral( "OGC WFS (Web Feature Service)" ); } 104 105 /* new functions */ 106 107 QString geometryAttribute() const; 108 processSQLErrorMsg()109 const QString processSQLErrorMsg() const { return mProcessSQLErrorMsg; } 110 processSQLWarningMsg()111 const QString processSQLWarningMsg() const { return mProcessSQLWarningMsg; } 112 113 //Editing operations 114 115 bool addFeatures( QgsFeatureList &flist, QgsFeatureSink::Flags flags = QgsFeatureSink::Flags() ) override; 116 bool deleteFeatures( const QgsFeatureIds &id ) override; 117 bool changeGeometryValues( const QgsGeometryMap &geometry_map ) override; 118 bool changeAttributeValues( const QgsChangedAttributesMap &attr_map ) override; 119 QVariantMap metadata() const override; 120 QString translateMetadataKey( const QString &mdKey ) const override; 121 QString translateMetadataValue( const QString &mdKey, const QVariant &value ) const override; 122 123 bool empty() const override; 124 125 private slots: 126 127 void featureReceivedAnalyzeOneFeature( QVector<QgsFeatureUniqueIdPair> ); 128 129 void pushErrorSlot( const QString &errorMsg ); 130 131 132 private: 133 //! Mutable data shared between provider and feature sources 134 std::shared_ptr<QgsWFSSharedData> mShared; 135 136 /** 137 * Invalidates cache of shared object 138 */ 139 void reloadProviderData() override; 140 141 friend class QgsWFSFeatureSource; 142 143 /** 144 * Create the geometry element 145 */ 146 QDomElement geometryElement( const QgsGeometry &geometry, QDomDocument &transactionDoc ); 147 148 protected: 149 150 //! String used to define a subset of the layer 151 QString mSubsetString; 152 153 //! Flag if provider is valid 154 bool mValid = true; 155 //! Namespace URL of the server (comes from DescribeFeatureDocument) 156 QString mApplicationNamespace; 157 //! Server capabilities for this layer (generated from capabilities document) 158 QgsVectorDataProvider::Capabilities mCapabilities = QgsVectorDataProvider::Capabilities(); 159 //! Fields of this typename. Might be different from mShared->mFields in case of SELECT 160 QgsFields mThisTypenameFields; 161 162 QString mProcessSQLErrorMsg; 163 QString mProcessSQLWarningMsg; 164 165 /** 166 * Collects information about the field types. Is called internally from QgsWFSProvider ctor. 167 * The method gives back the name of 168 * the geometry attribute and the thematic attributes with their types. 169 */ 170 bool describeFeatureType( QString &geometryAttribute, 171 QgsFields &fields, QgsWkbTypes::Type &geomType ); 172 173 /** 174 * For a given typename, reads the name of the geometry attribute, the 175 * thematic attributes and their types from a dom document. Returns true in case of success. 176 */ 177 bool readAttributesFromSchema( QDomDocument &schemaDoc, 178 const QString &prefixedTypename, 179 QString &geometryAttribute, 180 QgsFields &fields, QgsWkbTypes::Type &geomType, QString &errorMsg ); 181 182 //helper methods for WFS-T 183 184 /** 185 * Sends the transaction document to the server using HTTP POST 186 * \returns true if transmission to the server succeeded, otherwise false 187 * \note true does not automatically mean that the transaction succeeded 188 */ 189 bool sendTransactionDocument( const QDomDocument &doc, QDomDocument &serverResponse ); 190 191 //! Creates a transaction element and adds it (normally as first element) to the document 192 QDomElement createTransactionElement( QDomDocument &doc ) const; 193 194 //! True if the server response means success 195 bool transactionSuccess( const QDomDocument &serverResponse ) const; 196 //! Returns the inserted ids 197 QStringList insertedFeatureIds( const QDomDocument &serverResponse ) const; 198 //! Retrieve version and capabilities for this layer from GetCapabilities document (will be stored in mCapabilities) 199 bool getCapabilities(); 200 //! Records provider error 201 void handleException( const QDomDocument &serverResponse ); 202 //! Converts DescribeFeatureType schema geometry property type to WKBType 203 QgsWkbTypes::Type geomTypeFromPropertyType( const QString &attName, const QString &propType ); 204 //! Convert the value to its appropriate XML representation 205 QString convertToXML( const QVariant &value ); 206 207 bool processSQL( const QString &sqlString, QString &errorMsg, QString &warningMsg ); 208 }; 209 210 class QgsWfsProviderMetadata final: public QgsProviderMetadata 211 { 212 public: 213 QgsWfsProviderMetadata(); 214 QList<QgsDataItemProvider *> dataItemProviders() const override; 215 QgsWFSProvider *createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() ) override; 216 }; 217 218 219 #endif /* QGSWFSPROVIDER_H */ 220