3232QgsAfsProvider::QgsAfsProvider ( const QString &uri )
3333 : QgsVectorDataProvider( uri )
3434 , mValid( false )
35- , mGeometryType( QgsWkbTypes::Unknown )
3635 , mObjectIdFieldIdx( -1 )
3736{
38- mDataSource = QgsDataSourceUri ( uri );
37+ mSharedData = QSharedPointer<QgsAfsSharedData>( new QgsAfsSharedData () );
38+ mSharedData ->mGeometryType = QgsWkbTypes::Unknown;
39+ mSharedData ->mDataSource = QgsDataSourceUri ( uri );
3940
4041 // Set CRS
41- mSourceCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs ( mDataSource .param ( QStringLiteral ( " crs" ) ) );
42+ mSharedData -> mSourceCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs ( mSharedData -> mDataSource .param ( QStringLiteral ( " crs" ) ) );
4243
4344 // Get layer info
4445 QString errorTitle, errorMessage;
45- QVariantMap layerData = QgsArcGisRestUtils::getLayerInfo ( mDataSource .param ( QStringLiteral ( " url" ) ), errorTitle, errorMessage );
46+ QVariantMap layerData = QgsArcGisRestUtils::getLayerInfo ( mSharedData -> mDataSource .param ( QStringLiteral ( " url" ) ), errorTitle, errorMessage );
4647 if ( layerData.isEmpty () )
4748 {
4849 pushError ( errorTitle + " : " + errorMessage );
@@ -53,25 +54,25 @@ QgsAfsProvider::QgsAfsProvider( const QString &uri )
5354 mLayerDescription = layerData[QStringLiteral ( " description" )].toString ();
5455
5556 // Set extent
56- QStringList coords = mDataSource .param ( QStringLiteral ( " bbox" ) ).split ( QStringLiteral ( " ," ) );
57+ QStringList coords = mSharedData -> mDataSource .param ( QStringLiteral ( " bbox" ) ).split ( QStringLiteral ( " ," ) );
5758 if ( coords.size () == 4 )
5859 {
5960 bool xminOk = false , yminOk = false , xmaxOk = false , ymaxOk = false ;
60- mExtent .setXMinimum ( coords[0 ].toDouble ( &xminOk ) );
61- mExtent .setYMinimum ( coords[1 ].toDouble ( &yminOk ) );
62- mExtent .setXMaximum ( coords[2 ].toDouble ( &xmaxOk ) );
63- mExtent .setYMaximum ( coords[3 ].toDouble ( &ymaxOk ) );
61+ mSharedData -> mExtent .setXMinimum ( coords[0 ].toDouble ( &xminOk ) );
62+ mSharedData -> mExtent .setYMinimum ( coords[1 ].toDouble ( &yminOk ) );
63+ mSharedData -> mExtent .setXMaximum ( coords[2 ].toDouble ( &xmaxOk ) );
64+ mSharedData -> mExtent .setYMaximum ( coords[3 ].toDouble ( &ymaxOk ) );
6465 if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk )
65- mExtent = QgsRectangle ();
66+ mSharedData -> mExtent = QgsRectangle ();
6667 }
67- if ( mExtent .isEmpty () )
68+ if ( mSharedData -> mExtent .isEmpty () )
6869 {
6970 QVariantMap layerExtentMap = layerData[QStringLiteral ( " extent" )].toMap ();
7071 bool xminOk = false , yminOk = false , xmaxOk = false , ymaxOk = false ;
71- mExtent .setXMinimum ( layerExtentMap[QStringLiteral ( " xmin" )].toDouble ( &xminOk ) );
72- mExtent .setYMinimum ( layerExtentMap[QStringLiteral ( " ymin" )].toDouble ( &yminOk ) );
73- mExtent .setXMaximum ( layerExtentMap[QStringLiteral ( " xmax" )].toDouble ( &xmaxOk ) );
74- mExtent .setYMaximum ( layerExtentMap[QStringLiteral ( " ymax" )].toDouble ( &ymaxOk ) );
72+ mSharedData -> mExtent .setXMinimum ( layerExtentMap[QStringLiteral ( " xmin" )].toDouble ( &xminOk ) );
73+ mSharedData -> mExtent .setYMinimum ( layerExtentMap[QStringLiteral ( " ymin" )].toDouble ( &yminOk ) );
74+ mSharedData -> mExtent .setXMaximum ( layerExtentMap[QStringLiteral ( " xmax" )].toDouble ( &xmaxOk ) );
75+ mSharedData -> mExtent .setYMaximum ( layerExtentMap[QStringLiteral ( " ymax" )].toDouble ( &ymaxOk ) );
7576 if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk )
7677 {
7778 appendError ( QgsErrorMessage ( tr ( " Could not retrieve layer extent" ), QStringLiteral ( " AFSProvider" ) ) );
@@ -83,7 +84,7 @@ QgsAfsProvider::QgsAfsProvider( const QString &uri )
8384 appendError ( QgsErrorMessage ( tr ( " Could not parse spatial reference" ), QStringLiteral ( " AFSProvider" ) ) );
8485 return ;
8586 }
86- mExtent = QgsCoordinateTransform ( extentCrs, mSourceCRS ).transformBoundingBox ( mExtent );
87+ mSharedData -> mExtent = QgsCoordinateTransform ( extentCrs, mSharedData -> mSourceCRS ).transformBoundingBox ( mSharedData -> mExtent );
8788 }
8889
8990 // Read fields
@@ -98,24 +99,24 @@ QgsAfsProvider::QgsAfsProvider( const QString &uri )
9899 continue ;
99100 }
100101 QgsField field ( fieldName, type, fieldDataMap[QStringLiteral ( " type" )].toString (), fieldDataMap[QStringLiteral ( " length" )].toInt () );
101- mFields .append ( field );
102+ mSharedData -> mFields .append ( field );
102103 }
103104
104105 // Determine geometry type
105106 bool hasM = layerData[QStringLiteral ( " hasM" )].toBool ();
106107 bool hasZ = layerData[QStringLiteral ( " hasZ" )].toBool ();
107- mGeometryType = QgsArcGisRestUtils::mapEsriGeometryType ( layerData[QStringLiteral ( " geometryType" )].toString () );
108- if ( mGeometryType == QgsWkbTypes::Unknown )
108+ mSharedData -> mGeometryType = QgsArcGisRestUtils::mapEsriGeometryType ( layerData[QStringLiteral ( " geometryType" )].toString () );
109+ if ( mSharedData -> mGeometryType == QgsWkbTypes::Unknown )
109110 {
110111 appendError ( QgsErrorMessage ( tr ( " Failed to determine geometry type" ), QStringLiteral ( " AFSProvider" ) ) );
111112 return ;
112113 }
113- mGeometryType = QgsWkbTypes::zmType ( mGeometryType , hasZ, hasM );
114+ mSharedData -> mGeometryType = QgsWkbTypes::zmType ( mSharedData -> mGeometryType , hasZ, hasM );
114115
115116 // Read OBJECTIDs of all features: these may not be a continuous sequence,
116117 // and we need to store these to iterate through the features. This query
117118 // also returns the name of the ObjectID field.
118- QVariantMap objectIdData = QgsArcGisRestUtils::getObjectIds ( mDataSource .param ( QStringLiteral ( " url" ) ), errorTitle, errorMessage );
119+ QVariantMap objectIdData = QgsArcGisRestUtils::getObjectIds ( mSharedData -> mDataSource .param ( QStringLiteral ( " url" ) ), errorTitle, errorMessage );
119120 if ( objectIdData.isEmpty () )
120121 {
121122 appendError ( QgsErrorMessage ( tr ( " getObjectIds failed: %1 - %2" ).arg ( errorTitle, errorMessage ), QStringLiteral ( " AFSProvider" ) ) );
@@ -126,137 +127,72 @@ QgsAfsProvider::QgsAfsProvider( const QString &uri )
126127 appendError ( QgsErrorMessage ( tr ( " Failed to determine objectIdFieldName and/or objectIds" ), QStringLiteral ( " AFSProvider" ) ) );
127128 return ;
128129 }
129- mObjectIdFieldName = objectIdData[QStringLiteral ( " objectIdFieldName" )].toString ();
130- for ( int idx = 0 , nIdx = mFields .count (); idx < nIdx; ++idx )
130+ QString objectIdFieldName = objectIdData[QStringLiteral ( " objectIdFieldName" )].toString ();
131+ for ( int idx = 0 , nIdx = mSharedData -> mFields .count (); idx < nIdx; ++idx )
131132 {
132- if ( mFields .at ( idx ).name () == mObjectIdFieldName )
133+ if ( mSharedData -> mFields .at ( idx ).name () == objectIdFieldName )
133134 {
134135 mObjectIdFieldIdx = idx;
135136
136137 // primary key is not null, unique
137- QgsFieldConstraints constraints = mFields .at ( idx ).constraints ();
138+ QgsFieldConstraints constraints = mSharedData -> mFields .at ( idx ).constraints ();
138139 constraints.setConstraint ( QgsFieldConstraints::ConstraintNotNull, QgsFieldConstraints::ConstraintOriginProvider );
139140 constraints.setConstraint ( QgsFieldConstraints::ConstraintUnique, QgsFieldConstraints::ConstraintOriginProvider );
140- mFields [ idx ].setConstraints ( constraints );
141+ mSharedData -> mFields [ idx ].setConstraints ( constraints );
141142
142143 break ;
143144 }
144145 }
145146 foreach ( const QVariant &objectId, objectIdData[" objectIds" ].toList () )
146147 {
147- mObjectIds .append ( objectId.toInt () );
148+ mSharedData -> mObjectIds .append ( objectId.toInt () );
148149 }
149150
150151 mValid = true ;
151152}
152153
153154QgsAbstractFeatureSource *QgsAfsProvider::featureSource () const
154155{
155- return new QgsAfsFeatureSource ( this );
156+ return new QgsAfsFeatureSource ( mSharedData );
156157}
157158
158159QgsFeatureIterator QgsAfsProvider::getFeatures ( const QgsFeatureRequest &request ) const
159160{
160- return new QgsAfsFeatureIterator ( new QgsAfsFeatureSource ( this ), true , request );
161+ return new QgsAfsFeatureIterator ( new QgsAfsFeatureSource ( mSharedData ), true , request );
161162}
162163
163- bool QgsAfsProvider::getFeature ( QgsFeatureId id, QgsFeature &f, bool fetchGeometry, const QList< int > & /* fetchAttributes */ , const QgsRectangle &filterRect )
164+ QgsWkbTypes::Type QgsAfsProvider::wkbType () const
164165{
165- // If cached, return cached feature
166- QMap<QgsFeatureId, QgsFeature>::const_iterator it = mCache .find ( id );
167- if ( it != mCache .end () )
168- {
169- f = it.value ();
170- return filterRect.isNull () || f.geometry ().intersects ( filterRect );
171- }
172-
173- // Determine attributes to fetch
174- /* QStringList fetchAttribNames;
175- foreach ( int idx, fetchAttributes )
176- fetchAttribNames.append( mFields.at( idx ).name() );
177- */
178-
179- // When fetching from server, fetch all attributes and geometry by default so that we can cache them
180- QStringList fetchAttribNames;
181- QList<int > fetchAttribIdx;
182- fetchAttribIdx.reserve ( mFields .size () );
183- for ( int idx = 0 , n = mFields .size (); idx < n; ++idx )
184- {
185- fetchAttribNames.append ( mFields .at ( idx ).name () );
186- fetchAttribIdx.append ( idx );
187- }
188- fetchGeometry = true ;
189-
190- // Fetch 100 features at the time
191- int startId = ( id / 100 ) * 100 ;
192- int stopId = qMin ( startId + 100 , mObjectIds .length () );
193- QList<quint32> objectIds;
194- objectIds.reserve ( stopId );
195- for ( int i = startId; i < stopId; ++i )
196- {
197- objectIds.append ( mObjectIds [i] );
198- }
199-
166+ return mSharedData ->mGeometryType ;
167+ }
200168
201- // Query
202- QString errorTitle, errorMessage;
203- QVariantMap queryData = QgsArcGisRestUtils::getObjects (
204- mDataSource .param ( QStringLiteral ( " url" ) ), objectIds, mDataSource .param ( QStringLiteral ( " crs" ) ), fetchGeometry,
205- fetchAttribNames, QgsWkbTypes::hasM ( mGeometryType ), QgsWkbTypes::hasZ ( mGeometryType ),
206- filterRect, errorTitle, errorMessage );
207- if ( queryData.isEmpty () )
208- {
209- const_cast <QgsAfsProvider *>( this )->pushError ( errorTitle + " : " + errorMessage );
210- QgsDebugMsg ( " Query returned empty result" );
211- return false ;
212- }
169+ long QgsAfsProvider::featureCount () const
170+ {
171+ return mSharedData ->mObjectIds .size ();
172+ }
213173
214- QVariantList featuresData = queryData[QStringLiteral ( " features" )].toList ();
215- if ( featuresData.isEmpty () )
216- {
217- QgsDebugMsg ( " Query returned no features" );
218- return false ;
219- }
220- for ( int i = 0 , n = featuresData.size (); i < n; ++i )
221- {
222- QVariantMap featureData = featuresData[i].toMap ();
223- QgsFeature feature;
174+ QgsFields QgsAfsProvider::fields () const
175+ {
176+ return mSharedData ->mFields ;
177+ }
224178
225- // Set FID
226- feature.setId ( startId + i );
179+ void QgsAfsProvider::setDataSourceUri ( const QString &uri )
180+ {
181+ mSharedData ->mDataSource = QgsDataSourceUri ( uri );
182+ QgsDataProvider::setDataSourceUri ( uri );
183+ }
227184
228- // Set attributes
229- if ( !fetchAttribIdx.isEmpty () )
230- {
231- QVariantMap attributesData = featureData[QStringLiteral ( " attributes" )].toMap ();
232- feature.setFields ( mFields );
233- QgsAttributes attributes ( mFields .size () );
234- foreach ( int idx, fetchAttribIdx )
235- {
236- attributes[idx] = attributesData[mFields .at ( idx ).name ()];
237- }
238- feature.setAttributes ( attributes );
239- }
185+ QgsCoordinateReferenceSystem QgsAfsProvider::crs () const
186+ {
187+ return mSharedData ->crs ();
188+ }
240189
241- // Set geometry
242- if ( fetchGeometry )
243- {
244- QVariantMap geometryData = featureData[QStringLiteral ( " geometry" )].toMap ();
245- QgsAbstractGeometry *geometry = QgsArcGisRestUtils::parseEsriGeoJSON ( geometryData, queryData[QStringLiteral ( " geometryType" )].toString (),
246- QgsWkbTypes::hasM ( mGeometryType ), QgsWkbTypes::hasZ ( mGeometryType ) );
247- // Above might return 0, which is ok since in theory empty geometries are allowed
248- feature.setGeometry ( QgsGeometry ( geometry ) );
249- }
250- feature.setValid ( true );
251- mCache .insert ( feature.id (), feature );
252- }
253- f = mCache [id];
254- Q_ASSERT ( f.isValid () );
255- return filterRect.isNull () || ( f.hasGeometry () && f.geometry ().intersects ( filterRect ) );
190+ QgsRectangle QgsAfsProvider::extent () const
191+ {
192+ return mSharedData ->extent ();
256193}
257194
258- void QgsAfsProvider::setDataSourceUri ( const QString &uri )
195+ void QgsAfsProvider::reloadData ( )
259196{
260- mDataSource = QgsDataSourceUri ( uri );
261- QgsDataProvider::setDataSourceUri ( uri );
197+ mSharedData ->mCache .clear ();
262198}
0 commit comments