@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 7.31 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.33/esri/copyright.txt for details.
*/
import{createTask as e}from"../../../core/asyncUtils.js";import t from"../../../core/Error.js";import r from"../../../core/Logger.js";import{clamp as a}from"../../../core/mathUtils.js";import{throwIfAborted as s,isAbortError as o}from"../../../core/promiseUtils.js";import n from"../../../core/Warning.js";import{equals as i}from"../../../geometry/support/spatialReferenceUtils.js";import{convertFromGeometry as u,convertToGeometry as l}from"../featureConversionUtils.js";import{executeQueryForSnapping as c}from"../data/executeQueryForSnapping.js";import h from"../data/FeatureStore.js";import{checkProjectionSupport as m,project as p}from"../data/projectionSupport.js";import{QueryEngine as d}from"../data/QueryEngine.js";import{validateGeoJSON as f,createOptimizedFeatures as g}from"./geojson/geojson.js";import{mixAttributes as y}from"./support/sourceUtils.js";import{getGetFeatureSpatialReference as _,getFeatureCount as x,getFeature as C}from"../../ogc/wfsUtils.js";import w from"../../support/FieldsIndex.js";import{isNumber as R}from"../../../support/guards.js";import{utc as F}from"../../../time/constants.js";const S="esri.layers.WFSLayer";class j{constructor(){this._customParameters=null,this._queryEngine=null,this._supportsPagination=!0}destroy(){this._queryEngine?.destroy(),this._queryEngine=null}async load(e,r={}){const{getFeatureUrl:a,getFeatureOutputFormat:o,fields:n,geometryType:i,featureType:u,maxRecordCount:l,maxTotalRecordCount:c,maxPageCount:p,objectIdField:f,customParameters:g}=e,{spatialReference:y,getFeatureSpatialReference:x}=_(a,u,e.spatialReference);try{await m(x,y)}catch{throw new t("unsupported-projection","Projection not supported",{inSpatialReference:x,outSpatialReference:y})}s(r),this._customParameters=g,this._featureType=u,this._fieldsIndex=w.fromLayerJSON({fields:n,dateFieldsTimeReference:n.some((e=>"esriFieldTypeDate"===e.type))?{timeZoneIANA:F}:null}),this._geometryType=i,this._getFeatureUrl=a,this._getFeatureOutputFormat=o,this._getFeatureSpatialReference=x,this._maxRecordCount=l,this._maxTotalRecordCount=c,this._maxPageCount=p,this._objectIdField=f,this._spatialReference=y;let C=await this._snapshotFeatures(r);if(C.errors.length>0&&(this._supportsPagination=!1,C=await this._snapshotFeatures(r),C.errors.length>0))throw C.errors[0];const R={type:"object-id",fieldName:f};return this._queryEngine=new d({fieldsIndex:this._fieldsIndex,geometryType:i,hasM:!1,hasZ:!1,featureIdInfo:R,spatialReference:y,timeInfo:null,featureStore:new h({geometryType:i,hasM:!1,hasZ:!1})}),this._queryEngine.featureStore.addMany(C.features),{warnings:q(C),extent:(await this._queryEngine.fetchRecomputedExtents()).fullExtent}}async applyEdits(){throw new t("wfs-source:editing-not-supported","applyEdits() is not supported on WFSLayer")}async queryFeatures(e={},t={}){return await this._waitSnapshotComplete(),this._queryEngine.executeQuery(e,t.signal)}async queryFeatureCount(e={},t={}){return await this._waitSnapshotComplete(),this._queryEngine.executeQueryForCount(e,t.signal)}async queryObjectIds(e={},t={}){await this._waitSnapshotComplete();return(await this._queryEngine.executeQueryForIds(e,t.signal)).filter(R)}async queryExtent(e={},t={}){return await this._waitSnapshotComplete(),this._queryEngine.executeQueryForExtent(e,t.signal)}async querySnapping(e,t={}){return await this._waitSnapshotComplete(),c(this._queryEngine,e,t.signal)}async queryAttributeBins(e,t={}){return await this._waitSnapshotComplete(),this._queryEngine.executeAttributeBinsQuery(e,t.signal)}async refresh(t){return this._customParameters=t.customParameters,this._maxRecordCount=t.maxRecordCount,this._maxTotalRecordCount=t.maxTotalRecordCount,this._maxPageCount=t.maxPageCount,this._snapshotTask?.abort(),this._snapshotTask=e((e=>this._snapshotFeatures({signal:e}))),this._snapshotTask.promise.then((e=>{this._queryEngine.featureStore.clear(),this._queryEngine.featureStore.addMany(e.features);for(const t of q(e))r.getLogger(S).warn(new n("wfs-layer:refresh-warning",t.message,t.details));e.errors?.length&&r.getLogger(S).warn(new n("wfs-layer:refresh-error","Refresh completed with errors",{errors:e.errors}))}),(()=>{this._queryEngine.featureStore.clear()})),await this._waitSnapshotComplete(),{extent:(await this._queryEngine.fetchRecomputedExtents()).fullExtent}}async _waitSnapshotComplete(){if(this._snapshotTask&&!this._snapshotTask.finished){try{await this._snapshotTask.promise}catch{}return this._waitSnapshotComplete()}}async _snapshotFeatures(e){const t=e?.signal,r=this._maxTotalRecordCount,n=this._maxPageCount,i=this._supportsPagination&&n>1?await x(this._getFeatureUrl,this._featureType.typeName,{customParameters:this._customParameters,signal:t}):void 0;let u=[];const l=[];if(null==i)try{u=await this._singleQuery(t)}catch(c){o(c)||l.push(c)}else{const e=Math.min(i,r),s=T(this,a(Math.ceil(e/this._maxRecordCount),1,n),t);await Promise.allSettled(Array.from({length:10}).map((()=>E(s,u,l))))}return s(t),{features:u,totalRecordCount:i,maxTotalRecordCount:r,maxPageCount:n,errors:l}}async _singleQuery(e){const t=Number.isFinite(this._maxRecordCount)&&this._maxRecordCount>0?this._maxRecordCount:void 0,r=await C(this._getFeatureUrl,this._featureType.typeName,this._getFeatureSpatialReference,this._getFeatureOutputFormat,{customParameters:this._customParameters,count:t,signal:e});return this._processGeoJSON(r,{signal:e})}async _pageQuery(e,t){const r=e*this._maxRecordCount,a=await C(this._getFeatureUrl,this._featureType.typeName,this._getFeatureSpatialReference,this._getFeatureOutputFormat,{customParameters:this._customParameters,startIndex:r,count:this._maxRecordCount,signal:t});return this._processGeoJSON(a,{startIndex:r,signal:t})}_processGeoJSON(e,t){f(e,this._getFeatureSpatialReference.wkid);const{startIndex:r,signal:a}=t;s(a);const o=g(e,{geometryType:this._geometryType,hasZ:!1,objectIdField:this._objectIdField});if(!i(this._spatialReference,this._getFeatureSpatialReference))for(const s of o)null!=s.geometry&&(s.geometry=u(p(l(s.geometry,this._geometryType,!1,!1),this._getFeatureSpatialReference,this._spatialReference)));let n=r??1;for(const s of o){const e={};y(this._fieldsIndex,e,s.attributes,!0),s.attributes=e,null==e[this._objectIdField]&&(s.objectId=e[this._objectIdField]=n++)}return o}}function*T(e,t,r){for(let a=0;a<t;a++)yield e._pageQuery(a,r)}async function E(e,t,r){let a=e.next();for(;!a.done;){try{const e=await a.value;t.push(...e)}catch(s){o(s)||r.push(s)}a=e.next()}}function q(e){const t=[];return null!=e.totalRecordCount&&(e.features.length<e.totalRecordCount&&t.push({name:"wfs-layer:maxRecordCount-too-low",message:`Could only fetch ${e.features.length} of ${e.totalRecordCount} in ${e.maxPageCount} queries. Try increasing the value of WFSLayer.maxRecordCount.`,details:{recordCount:e.features.length,totalRecordCount:e.totalRecordCount}}),e.totalRecordCount>e.maxTotalRecordCount&&t.push({name:"wfs-layer:large-dataset",message:`The number of ${e.totalRecordCount} features exceeds the maximum allowed of ${e.maxTotalRecordCount}.`,details:{recordCount:e.features.length,totalRecordCount:e.totalRecordCount,maxTotalRecordCount:e.maxTotalRecordCount}})),t}export{j as default};