terriajs
Version:
Geospatial data visualization platform.
228 lines (197 loc) • 7.07 kB
text/typescript
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);
}
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;
}
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);
}
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);
}
}
}
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");
}
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();
}
}
}