UNPKG

terriajs

Version:

Geospatial data visualization platform.

228 lines (197 loc) 7.07 kB
import i18next from "i18next"; import { action, computed, runInAction, makeObservable, override } from "mobx"; import threddsCrawler from "thredds-catalog-crawler/src/entryBrowser"; import isDefined from "../../../Core/isDefined"; import CatalogMemberMixin from "../../../ModelMixins/CatalogMemberMixin"; import GroupMixin from "../../../ModelMixins/GroupMixin"; import UrlMixin from "../../../ModelMixins/UrlMixin"; import ModelReference from "../../../Traits/ModelReference"; import ThreddsCatalogGroupTraits from "../../../Traits/TraitsClasses/ThreddsCatalogGroupTraits"; import CatalogGroup from "../CatalogGroup"; import CommonStrata from "../../Definition/CommonStrata"; import CreateModel from "../../Definition/CreateModel"; import LoadableStratum from "../../Definition/LoadableStratum"; import { BaseModel } from "../../Definition/Model"; import { proxyCatalogItemBaseUrl } from "../proxyCatalogItemUrl"; import StratumOrder from "../../Definition/StratumOrder"; import { ModelConstructorParameters } from "../../Definition/Model"; import ThreddsItemReference from "../CatalogReferences/ThreddsItemReference"; interface ThreddsCatalog { id: string; name: string; title: string; isLoaded: boolean; url: string; supportsWms: boolean; hasDatasets: boolean; hasNestedCatalogs: boolean; datasets: ThreddsDataset[]; catalogs: ThreddsCatalog[]; getAllChildDatasets: () => void; loadAllNestedCatalogs: () => Promise<void>; loadNestedCatalogById: () => Promise<void>; parentCatalog: ThreddsCatalog; } export interface ThreddsDataset { id: string; name: string; url: string; wmsUrl: string; supportsWms: boolean; isParentDataset: boolean; datasets: ThreddsDataset[]; catalogs: ThreddsCatalog[]; loadAllNestedCatalogs: () => Promise<void>; } export class ThreddsStratum extends LoadableStratum(ThreddsCatalogGroupTraits) { static stratumName = "thredds"; private threddsCatalog: ThreddsCatalog | undefined = undefined; constructor(readonly _catalogGroup: ThreddsCatalogGroup) { super(); makeObservable(this); } duplicateLoadableStratum(model: BaseModel): this { return new ThreddsStratum(model as ThreddsCatalogGroup) as this; } static async load( catalogGroup: ThreddsCatalogGroup ): Promise<ThreddsStratum | undefined> { return new ThreddsStratum(catalogGroup); } @computed get members(): ModelReference[] { if (this.threddsCatalog === undefined) return []; const memberIds: ModelReference[] = []; this.threddsCatalog.catalogs.forEach((catalog: ThreddsCatalog) => { memberIds.push(`${this._catalogGroup.uniqueId}/${catalog.id}`); }); this.threddsCatalog.datasets.forEach((dataset: ThreddsDataset) => { dataset.catalogs.forEach((c) => { memberIds.push(`${this._catalogGroup.uniqueId}/${c.id}`); }); memberIds.push(`${this._catalogGroup.uniqueId}/${dataset.id}`); }); return memberIds; } @action createThreddsCatalog(catalog: ThreddsCatalog) { const id = `${this._catalogGroup.uniqueId}/${catalog.id}`; let model = this._catalogGroup.terria.getModelById(ThreddsCatalogGroup, id); if (!isDefined(model)) { model = new ThreddsCatalogGroup(id, this._catalogGroup.terria); this._catalogGroup.terria.addModel(model); } model.setTrait(CommonStrata.definition, "name", catalog.title); model.setTrait(CommonStrata.definition, "url", catalog.url); } @action async createMembers() { if (!isDefined(this._catalogGroup.url)) return; const proxy = proxyCatalogItemBaseUrl( this._catalogGroup, this._catalogGroup.url ); this.threddsCatalog = await threddsCrawler( this._catalogGroup.url, proxy ? { proxy } : undefined ); if (this.threddsCatalog === undefined) return; // Create sub-groups for any nested catalogs for (let i = 0; i < this.threddsCatalog.catalogs.length; i++) { this.createThreddsCatalog(this.threddsCatalog.catalogs[i]); } // Create members for individual datasets for (let i = 0; i < this.threddsCatalog.datasets.length; i++) { const ds = this.threddsCatalog.datasets[i]; await ds.loadAllNestedCatalogs(); for (let ii = 0; ii < ds.catalogs.length; ii++) { this.createThreddsCatalog(ds.catalogs[ii]); } if (ds.isParentDataset) { let parent: CatalogGroup | ThreddsCatalogGroup = this._catalogGroup; if (this.threddsCatalog.datasets.length > 1) { const id = `${this._catalogGroup.uniqueId}/${ds.id}`; let model = this._catalogGroup.terria.getModelById(CatalogGroup, id); if (!isDefined(model)) { model = new CatalogGroup(id, this._catalogGroup.terria); this._catalogGroup.terria.addModel(model); } model.setTrait(CommonStrata.definition, "name", ds.name); parent = model; } ds.datasets.forEach((dataset) => { const item = this.createMemberFromDataset(dataset); if (item !== undefined) parent.add(CommonStrata.definition, item); }); } else if (ds.supportsWms) { this.createMemberFromDataset(ds); } } } @action createMemberFromDataset( threddsDataset: ThreddsDataset ): BaseModel | undefined { if (!isDefined(threddsDataset.id)) { return undefined; } const itemId = this._catalogGroup.uniqueId + "/" + threddsDataset.id; let item = this._catalogGroup.terria.getModelById( ThreddsItemReference, itemId ); if (item === undefined) { item = new ThreddsItemReference(itemId, this._catalogGroup.terria); item.setTrait(CommonStrata.definition, "isGroup", true); item.setDataset(threddsDataset); item.setThreddsStrata(item); item.terria.addModel(item); } return item; } } StratumOrder.addLoadStratum(ThreddsStratum.stratumName); export default class ThreddsCatalogGroup extends UrlMixin( GroupMixin(CatalogMemberMixin(CreateModel(ThreddsCatalogGroupTraits))) ) { static readonly type = "thredds-group"; constructor(...args: ModelConstructorParameters) { super(...args); makeObservable(this); } get type() { return ThreddsCatalogGroup.type; } get typeName() { return i18next.t("models.thredds.nameGroup"); } @override get cacheDuration(): string { if (isDefined(super.cacheDuration)) { return super.cacheDuration; } return "1d"; } protected async forceLoadMetadata(): Promise<void> { if (!this.strata.get(ThreddsStratum.stratumName)) { const stratum = await ThreddsStratum.load(this); if (stratum === undefined) return; await stratum.createMembers(); runInAction(() => { this.strata.set(ThreddsStratum.stratumName, stratum); }); } } protected async forceLoadMembers() { const stratum = this.strata.get( ThreddsStratum.stratumName ) as ThreddsStratum; if (stratum) { await stratum.createMembers(); } } }