UNPKG

terriajs

Version:

Geospatial data visualization platform.

795 lines 37.3 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import i18next from "i18next"; import { computed, makeObservable } from "mobx"; import CesiumMath from "terriajs-cesium/Source/Core/Math"; import Rectangle from "terriajs-cesium/Source/Core/Rectangle"; import URI from "urijs"; import { isJsonArray, isJsonString } from "../../../Core/Json"; import TerriaError from "../../../Core/TerriaError"; import containsAny from "../../../Core/containsAny"; import createDiscreteTimesFromIsoSegments from "../../../Core/createDiscreteTimes"; import filterOutUndefined from "../../../Core/filterOutUndefined"; import isDefined from "../../../Core/isDefined"; import isReadOnlyArray from "../../../Core/isReadOnlyArray"; import { terriaTheme } from "../../../ReactViews/StandardUserInterface/StandardTheme"; import { InfoSectionTraits, MetadataUrlTraits } from "../../../Traits/TraitsClasses/CatalogMemberTraits"; import { KeyValueTraits, WebCoverageServiceParameterTraits } from "../../../Traits/TraitsClasses/ExportWebCoverageServiceTraits"; import { FeatureInfoTemplateTraits } from "../../../Traits/TraitsClasses/FeatureInfoTraits"; import LegendTraits from "../../../Traits/TraitsClasses/LegendTraits"; import WebMapServiceCatalogItemTraits, { SUPPORTED_CRS_3857, SUPPORTED_CRS_4326 } from "../../../Traits/TraitsClasses/WebMapServiceCatalogItemTraits"; import LoadableStratum from "../../Definition/LoadableStratum"; import createStratumInstance from "../../Definition/createStratumInstance"; import proxyCatalogItemUrl from "../proxyCatalogItemUrl"; import WebMapServiceCapabilities, { getRectangleFromLayer } from "./WebMapServiceCapabilities"; import WebMapServiceCatalogItem from "./WebMapServiceCatalogItem"; import dateFormat from "dateformat"; /** Transforms WMS GetCapabilities XML into WebMapServiceCatalogItemTraits */ export default class WebMapServiceCapabilitiesStratum extends LoadableStratum(WebMapServiceCatalogItemTraits) { catalogItem; capabilities; static async load(catalogItem, capabilities) { if (!isDefined(catalogItem.getCapabilitiesUrl)) { throw new TerriaError({ title: i18next.t("models.webMapServiceCatalogItem.missingUrlTitle"), message: i18next.t("models.webMapServiceCatalogItem.missingUrlMessage") }); } if (!isDefined(capabilities)) capabilities = await WebMapServiceCapabilities.fromUrl(proxyCatalogItemUrl(catalogItem, catalogItem.getCapabilitiesUrl, catalogItem.getCapabilitiesCacheDuration)); return new WebMapServiceCapabilitiesStratum(catalogItem, capabilities); } constructor(catalogItem, capabilities) { super(); this.catalogItem = catalogItem; this.capabilities = capabilities; makeObservable(this); } duplicateLoadableStratum(model) { return new WebMapServiceCapabilitiesStratum(model, this.capabilities); } get metadataUrls() { const metadataUrls = []; Array.from(this.capabilitiesLayers.values()).forEach((layer) => { if (!layer?.MetadataURL) return; if (Array.isArray(layer?.MetadataURL)) { // eslint-disable-next-line no-unsafe-optional-chaining metadataUrls.push(...layer?.MetadataURL); } else { metadataUrls.push(layer?.MetadataURL); } }); return metadataUrls .filter((m) => m.OnlineResource?.["xlink:href"]) .map((m) => createStratumInstance(MetadataUrlTraits, { url: m.OnlineResource["xlink:href"] })); } get layers() { let layers; if (this.catalogItem.uri !== undefined) { // Try to extract a layer from the URL const query = this.catalogItem.uri.query(true) ?? {}; layers = query.layers ?? query.LAYERS; } if (layers === undefined) { // Use all the top-level, named layers layers = filterOutUndefined(this.capabilities.topLevelNamedLayers.map((layer) => layer.Name)).join(","); } return layers; } get tileWidth() { const queryParams = this.catalogItem.uri?.query(true) ?? {}; if (isDefined(queryParams.width ?? queryParams.WIDTH)) { return parseInt(queryParams.width ?? queryParams.WIDTH, 10); } } get tileHeight() { const queryParams = this.catalogItem.uri?.query(true) ?? {}; if (isDefined(queryParams.height ?? queryParams.HEIGHT)) { return parseInt(queryParams.height ?? queryParams.HEIGHT, 10); } } /** * **How we determine WMS legends (in order)** 1. Defined manually in catalog JSON 2. If `style` is undefined, and server doesn't support `GetLegendGraphic`, we must select first style as default - as there is no way to know what the default style is, and to request a legend for it 3. If `style` is is set and it has a `legendUrl` -> use it! 4. If server supports `GetLegendGraphic`, we can request a legend (with or without `style` parameter) */ get legends() { const availableStyles = this.catalogItem.availableStyles || []; const layers = this.catalogItem.layersArray; const styles = this.catalogItem.stylesArray; const result = []; for (let i = 0; i < layers.length; ++i) { const layer = layers[i]; const style = i < styles.length ? styles[i] : undefined; let legendUri; let legendUrlMimeType; let legendScaling; const layerAvailableStyles = availableStyles.find((candidate) => candidate.layerName === layer)?.styles; let layerStyle; if (isDefined(style)) { // Attempt to find layer style based on AvailableStyleTraits layerStyle = layerAvailableStyles?.find((candidate) => candidate.name === style); } // If no style is selected and this WMS doesn't support GetLegendGraphics - we must use the first style if none is explicitly specified. // (If WMS supports GetLegendGraphics we can use it and omit style parameter to get the "default" style's legend) if (!isDefined(layerStyle) && !this.catalogItem.supportsGetLegendGraphic) layerStyle = layerAvailableStyles?.[0]; // If legend found - proxy URL and set mimetype if (layerStyle?.legend?.url) { legendUri = URI(proxyCatalogItemUrl(this.catalogItem, layerStyle.legend.url)); legendUrlMimeType = layerStyle.legend.urlMimeType; } // If no legends found and WMS supports GetLegendGraphics - make one up! if (!isDefined(legendUri) && isDefined(this.catalogItem.url) && this.catalogItem.supportsGetLegendGraphic) { legendUri = URI(proxyCatalogItemUrl(this.catalogItem, this.catalogItem.getLegendBaseUrl())); legendUri .setQuery("service", "WMS") .setQuery("version", this.catalogItem.useWmsVersion130 ? "1.3.0" : "1.1.1") .setQuery("request", "GetLegendGraphic") .setQuery("format", "image/png") .setQuery("sld_version", "1.1.0") .setQuery("layer", layer); // From OGC — about style property for GetLegendGraphic request: // If not present, the default style is selected. The style may be any valid style available for a layer, including non-SLD internally-defined styles. if (style) { legendUri.setQuery("style", style); } legendUrlMimeType = "image/png"; } if (isDefined(legendUri)) { // Add geoserver related LEGEND_OPTIONS to match terria styling (if supported) if (this.catalogItem.isGeoServer && legendUri.hasQuery("request", "GetLegendGraphic")) { let legendOptions = "fontName:Courier;fontStyle:bold;fontSize:12;forceLabels:on;fontAntiAliasing:true;labelMargin:5"; // Geoserver fontColor must be a hex value - use `textLight` theme colour let fontColor = terriaTheme.textLight.split("#")?.[1]; if (isDefined(fontColor)) { // If fontColor is a 3-character hex -> turn into 6 if (fontColor.length === 3) { fontColor = `${fontColor[0]}${fontColor[0]}${fontColor[1]}${fontColor[1]}${fontColor[2]}${fontColor[2]}`; } legendOptions += `;fontColor:0x${fontColor}`; } legendOptions += ";dpi:182"; // enable if we can scale the image back down by 50%. legendScaling = 0.5; legendUri.setQuery("LEGEND_OPTIONS", legendOptions); legendUri.setQuery("transparent", "true"); } // Add colour scale range params if supported if (this.catalogItem.supportsColorScaleRange && this.catalogItem.colorScaleRange) { legendUri.setQuery("colorscalerange", this.catalogItem.colorScaleRange); } result.push(createStratumInstance(LegendTraits, { url: legendUri.toString(), urlMimeType: legendUrlMimeType, imageScaling: legendScaling })); } } return result; } get capabilitiesLayers() { const lookup = (name) => [name, this.capabilities && this.capabilities.findLayer(name)]; return new Map(this.catalogItem.layersArray.map(lookup)); } get availableCrs() { // Get set of supported CRS from layer hierarchy const layerCrs = new Set(); this.capabilitiesLayers.forEach((layer) => { if (layer) { const srs = this.capabilities.getInheritedValues(layer, "SRS"); const crs = this.capabilities.getInheritedValues(layer, "CRS"); [ ...(Array.isArray(srs) ? srs : [srs]), ...(Array.isArray(crs) ? crs : [crs]) ].forEach((c) => layerCrs.add(c)); } }); return Array.from(layerCrs); } get crs() { // Note order is important here, the first one found will be used const supportedCrs = [...SUPPORTED_CRS_3857, ...SUPPORTED_CRS_4326]; // First check to see if URL has CRS or SRS const queryParams = this.catalogItem.uri?.query(true) ?? {}; const urlCrs = queryParams.crs ?? queryParams.CRS ?? queryParams.srs ?? queryParams.SRS; if (urlCrs && supportedCrs.includes(urlCrs)) return urlCrs; // If nothing is supported, ask for EPSG:3857, and hope for the best. return (supportedCrs.find((crs) => this.availableCrs.includes(crs)) ?? "EPSG:3857"); } get availableDimensions() { const result = []; if (!this.capabilities) { return result; } const capabilitiesLayers = this.capabilitiesLayers; for (const layerTuple of capabilitiesLayers) { const layerName = layerTuple[0]; const layer = layerTuple[1]; const dimensions = layer ? this.capabilities.getInheritedValues(layer, "Dimension") : []; result.push({ layerName: layerName, dimensions: dimensions .filter((dim) => dim.name !== "time") .map((dim) => { return { name: dim.name, units: dim.units, unitSymbol: dim.unitSymbol, default: dim.default, multipleValues: dim.multipleValues, current: dim.current, nearestValue: dim.nearestValue, values: dim.text?.split(",") }; }) }); } return result; } get availableStyles() { const result = []; if (!this.capabilities) { return result; } const capabilitiesLayers = this.capabilitiesLayers; for (const layerTuple of capabilitiesLayers) { const layerName = layerTuple[0]; const layer = layerTuple[1]; const styles = layer ? this.capabilities.getInheritedValues(layer, "Style") : []; result.push({ layerName: layerName, styles: styles.map((style) => { const wmsLegendUrl = isReadOnlyArray(style.LegendURL) ? style.LegendURL[0] : style.LegendURL; let legendUri, legendMimeType; if (wmsLegendUrl && wmsLegendUrl.OnlineResource && wmsLegendUrl.OnlineResource["xlink:href"]) { legendUri = new URI(decodeURIComponent(wmsLegendUrl.OnlineResource["xlink:href"])); legendMimeType = wmsLegendUrl.Format; } const legend = !legendUri ? undefined : createStratumInstance(LegendTraits, { url: legendUri.toString(), urlMimeType: legendMimeType, title: (capabilitiesLayers.size > 1 && layer?.Title) || undefined // Add layer Title as legend title if showing multiple layers }); return { name: style.Name, title: style.Title, abstract: style.Abstract, legend: legend }; }) }); } return result; } /** There is no way of finding out default style if no style has been selected :( * If !supportsGetLegendGraphic - we have to just use the first available style (for each layer) * This is because, to request a "default" legend we need GetLegendGraphics **/ get styles() { if (this.catalogItem.uri !== undefined) { // Try to extract a styles from the URL const query = this.catalogItem.uri.query(true) ?? {}; if (isDefined(query.styles ?? query.STYLES)) return query.styles ?? query.STYLES; } if (!this.catalogItem.supportsGetLegendGraphic) { return this.catalogItem.availableStyles .map((layer) => { if (layer.layerName && layer.styles.length > 0) { return layer.styles[0].name ?? ""; } return ""; }) .join(","); } } get info() { const result = []; let firstDataDescription; result.push(createStratumInstance(InfoSectionTraits, { name: i18next.t("models.webMapServiceCatalogItem.serviceDescription"), contentAsObject: this.capabilities.Service, // Hide big ugly table by default show: false })); const onlyHasSingleLayer = this.catalogItem.layersArray.length === 1; if (onlyHasSingleLayer) { // Clone the capabilitiesLayer as we'll modify it in a second const out = Object.assign({}, this.capabilitiesLayers.get(this.catalogItem.layersArray[0])); if (out !== undefined) { // The Dimension object is really weird and has a bunch of stray text in there if ("Dimension" in out) { const goodDimension = {}; Object.keys(out.Dimension).forEach((k) => { if (isNaN(k)) { goodDimension[k] = out.Dimension[k]; } }); out.Dimension = goodDimension; } // remove a circular reference to the parent delete out._parent; try { result.push(createStratumInstance(InfoSectionTraits, { name: i18next.t("models.webMapServiceCatalogItem.dataDescription"), contentAsObject: out, // Hide big ugly table by default show: false })); } catch (e) { console.log(`FAILED to create InfoSection with WMS layer Capabilities`); console.log(e); } } } for (const layer of this.capabilitiesLayers.values()) { if (!layer || !layer.Abstract || containsAny(layer.Abstract, WebMapServiceCatalogItem.abstractsToIgnore)) { continue; } const suffix = this.capabilitiesLayers.size === 1 ? "" : ` - ${layer.Title}`; const name = `Web Map Service Layer Description${suffix}`; result.push(createStratumInstance(InfoSectionTraits, { name, content: layer.Abstract })); firstDataDescription = firstDataDescription || layer.Abstract; } // Show the service abstract if there is one and if it isn't the Geoserver default "A compliant implementation..." const service = this.capabilities && this.capabilities.Service; if (service) { if (service.ContactInformation !== undefined) { result.push(createStratumInstance(InfoSectionTraits, { name: i18next.t("models.webMapServiceCatalogItem.serviceContact"), content: getServiceContactInformation(service.ContactInformation) })); } result.push(createStratumInstance(InfoSectionTraits, { name: i18next.t("models.webMapServiceCatalogItem.getCapabilitiesUrl"), content: this.catalogItem.getCapabilitiesUrl })); if (service && service.Abstract && !containsAny(service.Abstract, WebMapServiceCatalogItem.abstractsToIgnore) && service.Abstract !== firstDataDescription) { result.push(createStratumInstance(InfoSectionTraits, { name: i18next.t("models.webMapServiceCatalogItem.serviceDescription"), content: service.Abstract })); } // Show the Access Constraints if it isn't "none" (because that's the default, and usually a lie). if (service.AccessConstraints && !/^none$/i.test(service.AccessConstraints)) { result.push(createStratumInstance(InfoSectionTraits, { name: i18next.t("models.webMapServiceCatalogItem.accessConstraints"), content: service.AccessConstraints })); } } return result; } get infoSectionOrder() { let layerDescriptions = [`Web Map Service Layer Description`]; // If more than one layer, push layer description titles for each applicable layer if (this.capabilitiesLayers.size > 1) { layerDescriptions = []; this.capabilitiesLayers.forEach((layer) => { if (layer && layer.Abstract && !containsAny(layer.Abstract, WebMapServiceCatalogItem.abstractsToIgnore)) { layerDescriptions.push(`Web Map Service Layer Description - ${layer.Title}`); } }); } return [ i18next.t("preview.disclaimer"), i18next.t("description.name"), ...layerDescriptions, i18next.t("preview.datasetDescription"), i18next.t("preview.serviceDescription"), i18next.t("models.webMapServiceCatalogItem.serviceDescription"), i18next.t("preview.resourceDescription"), i18next.t("preview.licence"), i18next.t("preview.accessConstraints"), i18next.t("models.webMapServiceCatalogItem.accessConstraints"), i18next.t("preview.author"), i18next.t("preview.contact"), i18next.t("models.webMapServiceCatalogItem.serviceContact"), i18next.t("preview.created"), i18next.t("preview.modified"), i18next.t("preview.updateFrequency"), i18next.t("models.webMapServiceCatalogItem.getCapabilitiesUrl") ]; } get shortReport() { const catalogItem = this.catalogItem; if (catalogItem.isShowingDiff) { const format = "yyyy/mm/dd"; const d1 = dateFormat(catalogItem.firstDiffDate, format); const d2 = dateFormat(catalogItem.secondDiffDate, format); return `Showing difference image computed for ${catalogItem.diffStyleId} style on dates ${d1} and ${d2}`; } } get rectangle() { const layers = [...this.capabilitiesLayers.values()] .filter((layer) => layer !== undefined) .map((l) => l); // Get union of bounding rectangles for all layers const allLayersRectangle = layers.reduce((unionRectangle, layer) => { // Convert to cesium Rectangle (so we can use Rectangle.union) const latLonRect = getRectangleFromLayer(layer); if (!isDefined(latLonRect?.west) || !isDefined(latLonRect?.south) || !isDefined(latLonRect?.east) || !isDefined(latLonRect?.north)) return; const cesiumRectangle = Rectangle.fromDegrees(latLonRect?.west, latLonRect?.south, latLonRect?.east, latLonRect?.north); if (!unionRectangle) { return cesiumRectangle; } return Rectangle.union(unionRectangle, cesiumRectangle); }, undefined); if (allLayersRectangle && isDefined(allLayersRectangle.west) && isDefined(allLayersRectangle.south) && isDefined(allLayersRectangle.east) && isDefined(allLayersRectangle.north)) { return { west: CesiumMath.toDegrees(allLayersRectangle.west), south: CesiumMath.toDegrees(allLayersRectangle.south), east: CesiumMath.toDegrees(allLayersRectangle.east), north: CesiumMath.toDegrees(allLayersRectangle.north) }; } } get isGeoServer() { const keyword = this.capabilities?.Service?.KeywordList?.Keyword; return ((isReadOnlyArray(keyword) && keyword.indexOf("GEOSERVER") >= 0) || keyword === "GEOSERVER" || this.catalogItem.url?.toLowerCase().includes("geoserver")); } // TODO - There is possibly a better way to do this get isThredds() { if (this.catalogItem.url && (this.catalogItem.url.indexOf("thredds") > -1 || this.catalogItem.url.indexOf("tds") > -1)) { return true; } return false; } // TODO - Geoserver also support NCWMS via a plugin, just need to work out how to detect that get isNcWMS() { if (this.catalogItem.isThredds) return true; return false; } get isEsri() { if (this.catalogItem.url !== undefined) return (this.catalogItem.url.toLowerCase().indexOf("mapserver/wmsserver") > -1); return false; } get supportsGetLegendGraphic() { const capabilities = this.capabilities?.json?.Capability; return (isDefined(this.capabilities?.json?.["xmlns:sld"]) || isDefined(capabilities?.Request?.GetLegendGraphic) || (Array.isArray(capabilities?.ExtendedCapabilities?.ExtendedRequest) && capabilities.ExtendedCapabilities.ExtendedRequest.find((r) => r?.Request === "GetLegendGraphic")) || (this.catalogItem.isGeoServer ?? false) || (this.catalogItem.isNcWMS ?? false)); } get supportsGetTimeseries() { // Don't use GetTimeseries if there is only one timeslice if ((this.catalogItem.discreteTimes?.length ?? 0) <= 1) return false; const capabilities = this.capabilities?.json?.Capability; return !!(isDefined(capabilities?.Request?.GetTimeseries) || (Array.isArray(capabilities?.ExtendedCapabilities?.ExtendedRequest) && capabilities.ExtendedCapabilities.ExtendedRequest.find((r) => r?.Request === "GetTimeseries"))); } get supportsColorScaleRange() { return this.catalogItem.isNcWMS; } get discreteTimes() { const result = []; for (const layer of this.capabilitiesLayers.values()) { if (!layer) { continue; } const dimensions = this.capabilities.getInheritedValues(layer, "Dimension"); const timeDimension = dimensions.find((dimension) => dimension.name.toLowerCase() === "time"); if (!timeDimension) { continue; } let extent = timeDimension; // WMS 1.1.1 puts dimension values in an Extent element instead of directly in the Dimension element. const extentElements = this.capabilities.getInheritedValues(layer, "Extent"); const extentElement = extentElements.find((extent) => extent.name.toLowerCase() === "time"); if (extentElement) { extent = extentElement; } if (!extent || !extent.split) { continue; } const values = extent.split(","); for (let i = 0; i < values.length; ++i) { const value = values[i]; const isoSegments = value.split("/"); if (isoSegments.length === 1) { result.push({ time: values[i], tag: undefined }); } else { createDiscreteTimesFromIsoSegments(result, isoSegments[0], isoSegments[1], isoSegments[2], this.catalogItem.maxRefreshIntervals); } } } return result; } get initialTimeSource() { return "now"; } get currentTime() { // Get default times for all layers const defaultTimes = filterOutUndefined(Array.from(this.capabilitiesLayers).map(([_layerName, layer]) => { if (!layer) return; const dimensions = this.capabilities.getInheritedValues(layer, "Dimension"); const timeDimension = dimensions.find((dimension) => dimension.name.toLowerCase() === "time"); return timeDimension?.default; })); // From WMS 1.3.0 spec: // For the TIME parameter, the special keyword “current” may be used if the <Dimension name="time"> service metadata element includes a nonzero value for the “current” attribute, as described in C.2. // The expression “TIME=current” means “send the most current data available”. // Here we return undefined, because WebMapServiceCapabilitiesStratum.initialTimeSource is set to "now" if (defaultTimes[0] === "current") { return undefined; } // Return first default time return defaultTimes[0]; } /** Prioritize format of GetFeatureInfo: * - JSON/GeoJSON * - If ESRI, then we prioritise XML next * - HTML * - GML * - XML * - Plain text * * If no matching format can be found in GetCapabilities, then Cesium will use defaults (see `WebMapServiceImageryProvider.DefaultGetFeatureInfoFormats`) * * If supportsGetTimeseries, use CSV */ get getFeatureInfoFormat() { const formats = this.capabilities.json?.Capability?.Request?.GetFeatureInfo?.Format; const formatsArray = isJsonArray(formats) ? formats : isJsonString(formats) ? [formats] : []; if (this.catalogItem.supportsGetTimeseries) { return { format: "text/csv", type: "text" }; } if (formatsArray.includes("application/json")) return { format: "application/json", type: "json" }; if (formatsArray.includes("application/geo+json")) return { format: "application/geo+json", type: "json" }; if (formatsArray.includes("application/vnd.geo+json")) return { format: "application/vnd.geo+json", type: "json" }; // Special case for Esri WMS, use XML before HTML/GML // as HTML includes <table> with rowbg that is hard to read if (this.isEsri && formatsArray.includes("text/xml")) { return { format: "text/xml", type: "xml" }; } if (formatsArray.includes("text/html")) return { format: "text/html", type: "html" }; if (formatsArray.includes("application/vnd.ogc.gml")) return { format: "application/vnd.ogc.gml", type: "xml" }; // For non-Esri services, we use XML after HTML/GML if (formatsArray.includes("text/xml")) { return { format: "text/xml", type: "xml" }; } if (formatsArray.includes("text/plain")) return { format: "text/plain", type: "text" }; } /** If supportsGetTimeseries, override the "request" parameter in GetFeatureInfo to be "GetTimeseries". * We also set time to empty, so we get values for all times (as opposed to just the current time) */ get getFeatureInfoParameters() { if (this.catalogItem.supportsGetTimeseries) { return { request: "GetTimeseries", time: "" }; } return undefined; } /** If getFeatureInfoFormat is text/csv, set featureInfoTemplate to show chart. */ get featureInfoTemplate() { if (this.catalogItem.getFeatureInfoFormat.format === "text/csv") return createStratumInstance(FeatureInfoTemplateTraits, { template: `{{terria.timeSeries.chart}}`, showFeatureInfoDownloadWithTemplate: true }); } get linkedWcsParameters() { // Get outputCrs // Note: this will be overridden by `WebCoverageServiceDescribeCoverageStratum` if a better outputCrs is found let outputCrs = this.availableCrs[0]; // Unless it is Web Mercator of course - that would be stupid // If this is the case - use 4326 outputCrs = outputCrs && SUPPORTED_CRS_3857.includes(outputCrs) ? "EPSG:4326" : outputCrs; // Get WCS subsets from time and WMS dimensions // These are used to "subset" WCS coverage (dataset) // This is used to flag subsets (dimensions) which have multiple values // Each element in this array represents the **actual** value used for a subset which has multiple values const duplicateSubsetValues = []; // Get dimensionSubsets const dimensionSubsets = []; if (this.catalogItem.dimensions) { Object.entries(this.catalogItem.dimensions).forEach(([key, values]) => { if (isDefined(values)) { // If we have multiple values for a particular dimension, they will be comma separated // WCS only supports a single value per dimension - so we take the first value const valuesArray = values.split(","); const value = valuesArray[0]; if (valuesArray.length > 1) { duplicateSubsetValues.push(createStratumInstance(KeyValueTraits, { key, value })); } // Wrap string values in double quotes dimensionSubsets.push({ key, value }); } }); } const subsets = filterOutUndefined([ // Add time dimension this.catalogItem.currentDiscreteTimeTag ? { key: "time", value: this.catalogItem.currentDiscreteTimeTag } : undefined, // Add other dimensions ...dimensionSubsets ]).map((subset) => createStratumInstance(KeyValueTraits, subset)); return createStratumInstance(WebCoverageServiceParameterTraits, { outputCrs, subsets, duplicateSubsetValues, // Add styles parameter for OpenDataCube WCS additionalParameters: [{ key: "styles", value: this.catalogItem.styles }] }); } } __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "metadataUrls", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "layers", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "tileWidth", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "tileHeight", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "legends", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "capabilitiesLayers", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "availableCrs", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "crs", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "availableDimensions", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "availableStyles", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "styles", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "info", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "infoSectionOrder", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "shortReport", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "rectangle", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "isGeoServer", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "isThredds", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "isNcWMS", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "isEsri", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "supportsGetLegendGraphic", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "supportsGetTimeseries", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "supportsColorScaleRange", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "discreteTimes", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "initialTimeSource", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "currentTime", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "getFeatureInfoFormat", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "getFeatureInfoParameters", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "featureInfoTemplate", null); __decorate([ computed ], WebMapServiceCapabilitiesStratum.prototype, "linkedWcsParameters", null); function getServiceContactInformation(contactInfo) { const primary = contactInfo.ContactPersonPrimary; let text = ""; if (isDefined(primary)) { if (isDefined(primary.ContactOrganization) && primary.ContactOrganization.length > 0 && // Geoserver default primary.ContactOrganization !== "The Ancient Geographers") { text += primary.ContactOrganization + "<br/>"; } } if (isDefined(contactInfo.ContactElectronicMailAddress) && contactInfo.ContactElectronicMailAddress.length > 0 && // Geoserver default contactInfo.ContactElectronicMailAddress !== "claudius.ptolomaeus@gmail.com") { text += `[${contactInfo.ContactElectronicMailAddress}](mailto:${contactInfo.ContactElectronicMailAddress})`; } return text; } //# sourceMappingURL=WebMapServiceCapabilitiesStratum.js.map