@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 9.54 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 e from"../../../../../request.js";import has from"../../../../../core/has.js";import{ignoreAbortErrors as t,throwIfNotAbortError as s}from"../../../../../core/promiseUtils.js";import{diff as r,hasRootDiffOnly as a,hasRootDiff as i}from"../../../../../core/accessorSupport/diffUtils.js";import{OptimizedFeature as n}from"../../../../../layers/graphics/OptimizedFeature.js";import{QueryEngine as o}from"../../../../../layers/graphics/data/QueryEngine.js";import{executeQuery as c,executeQueryForCount as d}from"../../../../../rest/query/operations/query.js";import u from"../../../../../rest/support/StatisticDefinition.js";import{FeatureStoreStatistics as h}from"../FeatureStoreStatistics.js";import{FeatureSourceQueryInfo as m}from"./FeatureSourceQueryInfo.js";import{StreamMessenger as p}from"./StreamMessenger.js";import{DrillDownTileLoadStrategy as l}from"./strategies/DrillDownTileLoadStrategy.js";import{PagedTileLoadStrategy as y}from"./strategies/PagedTileLoadStrategy.js";import{ParquetLoadStrategy as _}from"./strategies/ParquetLoadStrategy.js";import{SnapshotLoadStrategy as g}from"./strategies/SnapshotLoadStrategy.js";import{StreamLoadStrategy as f}from"./strategies/StreamLoadStrategy.js";import{FeatureSourceChunkStore as S}from"./strategies/chunks/SourceChunkStore.js";import{FeatureMetadata as v}from"../support/FeatureMetadata.js";import{UpdateTracking2D as b}from"../../support/UpdateTracking2D.js";class E{constructor(e,t,s,r,a){this.service=e,this._aggregateAdapter=t,this._subscriptions=s,this._connection=r,this._cachedObjectIds=a,this._updateTracking=new b({debugName:"FeatureSource"}),this._didInvalidateData=!1,this._metadata=v.createFeature(e.metadata),this._store=new S(this._metadata)}destroy(){this._strategy?.destroy(),this._store.destroy(),this._streamMessenger?.destroy(),"memory"===this.service.type&&this.service.source.map((e=>e.close()))}get metadata(){if(!this._metadata)throw new Error("InternalError: Metadata not defined. Was update called?");return this._metadata}get store(){return this._store}get streamMessenger(){return null==this._streamMessenger&&this._initStreamMessenger(),this._streamMessenger}get statistics(){return h.from(this._store)}get updateTracking(){return this._updateTracking}get queryEngine(){if(!this._queryEngine){if(!this._schema)return null;const{dataFilter:e}=this._schema.mutable,t=this._schema.mutable.availableFields,s=this._metadata;this._queryEngine=new o({featureStore:this._store,fieldsIndex:s.fieldsIndex,geometryType:s.geometryType,featureIdInfo:s.featureIdInfo,hasM:!1,hasZ:!1,spatialReference:this.service.outSpatialReference,aggregateAdapter:this._aggregateAdapter,timeInfo:s.timeInfo,definitionExpression:e.definitionExpression,availableFields:t})}return this._queryEngine}get isStream(){return"stream"===this._schema.type}get hasDisplayFilter(){return!!this._schema&&("displayFilterInfo"in this._schema.mutable&&null!=this._schema.mutable.displayFilterInfo)}chunks(){return Array.from(this._store.chunks())}prepareCacheUpdate(e,t){const s=new Set,r=new Set;for(const a of e)this._cachedObjectIds.has(a)||(this._cachedObjectIds.add(a),s.add(a));for(const a of t)this._cachedObjectIds.delete(a),r.add(a);this.hasDisplayFilter&&this._strategy.prepareCacheUpdate(s,r)}async applyCacheUpdate(){this.hasDisplayFilter&&await this._updateTracking.addPromise(this._strategy.applyCacheUpdate())}cleanup(){return this._store.cleanup()}onSubscribe(e){this._connection.onEvent({type:"subscribe",tile:e.tile.id});const t=this._strategy?.load(e);t&&(t.then((()=>this._connection.onEvent({type:"loaded",tile:e.tile.id}))).catch((t=>this._connection.onEvent({type:"error",tile:e.tile.id,error:t}))),this._updateTracking.addPromise(t))}onResume(e){this._updateTracking.addPromise(t(this._strategy?.load(e)))}onUnsubscribe(e){this._connection.onEvent({type:"unsubscribe",tile:e.tile.id}),this._strategy?.unload(e)}applyOverride(e){this._didInvalidateData=!0,this._store.applyOverride(e)}takeOverrideUpdate(){return this._store.takeOverrideUpdate()}async update(e,t){const s=e.source,n=r(this._schema?.mutable,s.mutable);if(!n)return!1;if(has("esri-2d-update-debug")&&console.debug(`Version[${t}] FeatureSource.update`,{changes:n}),this._schema=s,this._queryEngine?.destroy(),this._queryEngine=null,"feature-service"===this.service.type&&null!=this.service.queryMetadata.lastEditDate&&(this._lastEditDate=this.service.queryMetadata.lastEditDate),null==this._streamMessenger&&"stream"===this._schema.type&&this._initStreamMessenger(),a(n,"sourceRefreshVersion")&&this._strategy?.refresh)return this._strategy.refresh();if(("feature"===s.type||"parquet"===s.type)&&a(n,"availableFields")){if(await this._queryLastEditDateChanged()||this._didInvalidateData)this._didInvalidateData=!1,await this._updateStrategy(t);else{this._connection.onEvent({type:"updateFieldsStart"});try{await this._strategy.updateFields(s.mutable.availableFields),this._connection.onEvent({type:"updateFieldsEnd"})}catch(o){this._connection.onEvent({type:"updateFieldsError",error:o})}}return!1}return!!(i(n,"dataFilter")||i(n,"sourceRefreshVersion")||this._strategy.about.supportsDisplayFilter&&i(n,"displayFilterInfo"))&&(await this._updateStrategy(t),!0)}async addParquetFile(e){this._strategy.addParquetFile(e)}unsafeSetQueryHistoricMoment(e){"feature"===this._schema.type&&(this._schema.mutable.dataFilter.historicMoment=e,this._strategy.unsafeSetQueryHistoricMoment(new Date(e)))}_initStreamMessenger(){null==this._streamMessenger&&(this._streamMessenger=new p(this._connection))}async normalizeOverrides(e){const t={historicMoment:e.historicMoment,commands:{updateWeak:e.commands.updateWeak.map(n.fromJSON),removeWeak:e.commands.removeWeak,update:e.commands.update.map(n.fromJSON),remove:e.commands.remove,release:e.commands.release}},s=e.commands.updateByIdWeak,r=await this._queryOptimizedFeatures(s);return t.commands.updateWeak.push(...r),t}async _queryOptimizedFeatures(e){if(0===e.length)return[];const t=[],s=(await this._strategy.queryByObjectId(e)).getCursor();for(;s.next();)t.push(s.readOptimizedFeatureWorldSpace());return t}getObjectIdsFromGlobalIds(e){const t=this.metadata.globalIdField;if(null==t)throw new Error("InternalError: Recieved an edit with globalIds, but not supported by the service");const s=this._store.mapObjectIdsFromGlobalIds(e,t).values();return Array.from(s)}async _queryLastEditDateChanged(){if(null==this._lastEditDate)return!1;const t=this.service.source,s={...t.query,f:"json"},r=(await e(t.path,{query:s,responseType:"json"})).data.editingInfo.lastEditDate;return r!==this._lastEditDate&&(this._lastEditDate=r,!0)}async _createStrategy(){const e="isSourceHosted"in this.service&&this.service.isSourceHosted,t=Array.isArray(this.service.source),s=this.service.source&&"collection"in this.service.source,r=e||t||s;if("stream"===this._schema.type){const e=new f(this.service,this._schema.mutable.dataFilter,this._store,{outSR:this.service.outSpatialReference},this.metadata);return this._streamMessenger.strategy=e,e}if("parquet"===this._schema.type){const e=this.service;return new _(e,this._metadata,this._schema,this._store)}const a=this.service,i=m.fromSchema(a,this._schema,this._metadata),n=await this._supportSnapshotMode(a,i);return n?new g(a,i,this._store,n,this.metadata,this._connection):r?new y(a,i,this._store,this.metadata,this._connection):new l(a,i,this._store,this.metadata,this._connection)}async _updateStrategy(e){const t=await this._createStrategy();this._connection.onEvent({type:"updateStrategyStart",about:t.about});const r=!!this._strategy;this._store.clear(),this._strategy?.destroy(),this._strategy=t,has("esri-2d-update-debug")&&console.debug(`Version[${e}] FeatureSource.updateStrategy`,{strategy:t});const a=Array.from(this._subscriptions.values());if(!a.length)return void this._connection.onEvent({type:"updateStrategyEnd"});const i=Promise.all(a.map((e=>this._strategy.load(e).then((()=>this._connection.onEvent({type:"loaded",tile:e.tile.id}))).catch((t=>this._connection.onEvent({type:"error",tile:e.tile.id,error:t}))))));this._updateTracking.addPromise(i),this._strategy.prepareCacheUpdate(this._cachedObjectIds);try{r&&await i}catch(n){s(n)}this._connection.onEvent({type:"updateStrategyEnd"}),has("esri-2d-update-debug")&&console.debug(`Version[${e}] FeatureSource.updateStrategyEnd`,{strategy:t})}async _supportSnapshotMode(e,t){const{queryMetadata:s}=e,r=s.snapshotInfo;if(!r)return null;return await this._executeExceedsLimitQuery(e,t,r)?null:r}async _executeExceedsLimitQuery(e,t,s){if(!s.supportsExceedsLimit)return this._executeExceedsLimitFallbackQuery(e,t,s);try{const r=e.source,a=t.createQuery();a.inner.orderByFields=[],a.inner.returnGeometry=!1;const i=new u;i.statisticType="exceedslimit",i.maxPointCount=s.maxFeatureCount,i.maxRecordCount=s.maxFeatureCount,i.outStatisticFieldName="exceedslimit",s.maxVertexCount&&(i.maxVertexCount=s.maxVertexCount),a.inner.outStatistics=[i],a.inner.cacheHint=!0;const n=await c(r,a.inner,void 0,{query:a.customParameters}),o=n.data.features[0]?.attributes.exceedslimit;return!(0===o)}catch(r){return!0}}async _executeExceedsLimitFallbackQuery(e,t,s){if(s.maxVertexCount)return!0;const r=e.source,a=t.createQuery();a.inner.orderByFields=[],a.inner.returnGeometry=!1,a.inner.cacheHint=!0;try{return(await d(r,a.inner,{query:a.customParameters})).data.count>s.maxFeatureCount}catch(i){return!0}}}export{E as FeatureSource};