File

libs/core/src/lib/api-communication/connectors/dataset-api-v3-connector/dataset-api-v3-connector.ts

Index

Properties
Methods

Constructor

constructor(http: HttpService, api: ApiV3InterfaceService)
Parameters :
Name Type Optional
http HttpService No
api ApiV3InterfaceService No

Methods

canHandle
canHandle(url: string)
Parameters :
Name Type Optional
url string No
Returns : Observable<boolean>
Protected createCategory
createCategory(category: ApiV3Category)
Parameters :
Name Type Optional
category ApiV3Category No
Returns : Category
createCsvDataExportLink
createCsvDataExportLink(internalId: InternalDatasetId, params: HelgolandCsvExportLinkParams)
Parameters :
Name Type Optional
internalId InternalDatasetId No
params HelgolandCsvExportLinkParams No
Returns : Observable<string>
Protected createDataset
createDataset(ds: ApiV3Dataset, url: string)
Parameters :
Name Type Optional
ds ApiV3Dataset No
url string No
Returns : HelgolandDataset
Protected createFeature
createFeature(feature: ApiV3Feature)
Parameters :
Name Type Optional
feature ApiV3Feature No
Returns : Feature
Protected createFilter
createFilter(filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
filter HelgolandParameterFilter No
Protected createHelgolandPlatform
createHelgolandPlatform(feature: ApiV3Feature)
Parameters :
Name Type Optional
feature ApiV3Feature No
Returns : HelgolandPlatform
Protected createOffering
createOffering(offering: ApiV3Offering)
Parameters :
Name Type Optional
offering ApiV3Offering No
Returns : Offering
Protected createPhenomenon
createPhenomenon(phenomenon: ApiV3Phenomenon)
Parameters :
Name Type Optional
phenomenon ApiV3Phenomenon No
Returns : Phenomenon
Protected createProcedure
createProcedure(procedure: ApiV3Procedure)
Parameters :
Name Type Optional
procedure ApiV3Procedure No
Returns : Procedure
Protected createRequestTimespan
createRequestTimespan(timespan: Timespan)
Parameters :
Name Type Optional
timespan Timespan No
Returns : string
Protected createService
createService(service: ApiV3Service, url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
service ApiV3Service No
url string No
filter HelgolandParameterFilter No
Returns : HelgolandService
Protected createStation
createStation(feature: ApiV3Feature)
Parameters :
Name Type Optional
feature ApiV3Feature No
Returns : HelgolandPlatform
Protected createTimeseriesData
createTimeseriesData(res: Data)
Parameters :
Name Type Optional
res Data<TimeValueTuple> No
Protected createTrajectoryData
createTrajectoryData(res: Data)
Parameters :
Name Type Optional
res Data<LocatedTimeValueEntry> No
getCategories
getCategories(url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
url string No
filter HelgolandParameterFilter No
getCategory
getCategory(id: string, url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
id string No
url string No
filter HelgolandParameterFilter No
getDataset
getDataset(internalId: InternalDatasetId, filter: DatasetFilter)
Parameters :
Name Type Optional
internalId InternalDatasetId No
filter DatasetFilter No
Returns : Observable<HelgolandDataset>
getDatasetData
getDatasetData(dataset: HelgolandDataset, timespan: Timespan, filter: HelgolandDataFilter)
Parameters :
Name Type Optional
dataset HelgolandDataset No
timespan Timespan No
filter HelgolandDataFilter No
Returns : Observable<HelgolandData>
getDatasetExtras
getDatasetExtras(internalId: InternalDatasetId)
Parameters :
Name Type Optional
internalId InternalDatasetId No
getDatasets
getDatasets(url: string, filter: DatasetFilter)
Parameters :
Name Type Optional
url string No
filter DatasetFilter No
Returns : Observable<HelgolandDataset[]>
getFeature
getFeature(id: string, url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
id string No
url string No
filter HelgolandParameterFilter No
getFeatures
getFeatures(url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
url string No
filter HelgolandParameterFilter No
getOffering
getOffering(id: string, url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
id string No
url string No
filter HelgolandParameterFilter No
getOfferings
getOfferings(url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
url string No
filter HelgolandParameterFilter No
getPhenomena
getPhenomena(url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
url string No
filter HelgolandParameterFilter No
getPhenomenon
getPhenomenon(id: string, url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
id string No
url string No
filter HelgolandParameterFilter No
getPlatform
getPlatform(id: string, url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
id string No
url string No
filter HelgolandParameterFilter No
getPlatforms
getPlatforms(url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
url string No
filter HelgolandParameterFilter No
getProcedure
getProcedure(id: string, url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
id string No
url string No
filter HelgolandParameterFilter No
getProcedures
getProcedures(url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
url string No
filter HelgolandParameterFilter No
getServices
getServices(url: string, filter: HelgolandParameterFilter)
Parameters :
Name Type Optional
url string No
filter HelgolandParameterFilter No

Properties

name
Type : string
Default value : 'DatasetApiV3Connector'
import { Injectable } from '@angular/core';
import moment from 'moment';
import { forkJoin, Observable, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

import { HttpService } from '../../../dataset-api/http.service';
import { InternalDatasetId } from '../../../dataset-api/internal-id-handler.service';
import { Category } from '../../../model/dataset-api/category';
import { Data, LocatedTimeValueEntry, TimeValueTuple } from '../../../model/dataset-api/data';
import { FirstLastValue, PlatformParameter } from '../../../model/dataset-api/dataset';
import { Feature } from '../../../model/dataset-api/feature';
import { Offering } from '../../../model/dataset-api/offering';
import { Parameter } from '../../../model/dataset-api/parameter';
import { Phenomenon } from '../../../model/dataset-api/phenomenon';
import { Procedure } from '../../../model/dataset-api/procedure';
import { Timespan } from '../../../model/internal/timeInterval';
import { HELGOLAND_SERVICE_CONNECTOR_HANDLER } from '../../helgoland-services-connector';
import { UrlGenerator } from '../../helper/url-generator';
import { HelgolandServiceConnector } from '../../interfaces/service-connector-interfaces';
import {
  HelgolandData,
  HelgolandDataFilter,
  HelgolandTimeseriesData,
  HelgolandTrajectoryData,
} from '../../model/internal/data';
import {
  DatasetExtras,
  DatasetFilter,
  DatasetType,
  HelgolandDataset,
  HelgolandTimeseries,
} from '../../model/internal/dataset';
import { HelgolandCsvExportLinkParams, HelgolandParameterFilter } from '../../model/internal/filter';
import { HelgolandPlatform } from '../../model/internal/platform';
import { HelgolandService } from '../../model/internal/service';
import { PlatformTypes } from './../../../model/dataset-api/enums';
import { HelgolandProfile, HelgolandTrajectory } from './../../model/internal/dataset';
import {
  ApiV3Category,
  ApiV3Dataset,
  ApiV3DatasetTypes,
  ApiV3Feature,
  ApiV3InterfaceService,
  ApiV3ObservationTypes,
  ApiV3Offering,
  ApiV3ParameterFilter,
  ApiV3Phenomenon,
  ApiV3Procedure,
  ApiV3Service,
  ApiV3ValueTypes,
} from './api-v3-interface';

@Injectable({
  providedIn: 'root'
})
export class DatasetApiV3Connector implements HelgolandServiceConnector {

  name = 'DatasetApiV3Connector';

  constructor(
    protected http: HttpService,
    protected api: ApiV3InterfaceService
  ) { }

  canHandle(url: string): Observable<boolean> {
    return this.http.client().get(url).pipe(
      map(res => {
        if (res instanceof Array) {
          // check if endpoint 'trajectories' exists
          return res.findIndex(e => e.id === 'trajectories') >= 0;
        } else {
          return false;
        }
      }),
      catchError(() => of(false))
    );
  }

  getServices(url: string, filter: HelgolandParameterFilter): Observable<HelgolandService[]> {
    const clone = Object.create(filter);
    clone.expanded = true;
    return this.api.getServices(url, this.createFilter(clone)).pipe(map(res => res.map(s => this.createService(s, url, filter))));
  }

  getCategories(url: string, filter: HelgolandParameterFilter): Observable<Category[]> {
    return this.api.getCategories(url, this.createFilter(filter)).pipe(map(res => res.map(c => this.createCategory(c))));
  }

  getCategory(id: string, url: string, filter: HelgolandParameterFilter): Observable<Category> {
    return this.api.getCategory(id, url, this.createFilter(filter)).pipe(map(res => this.createCategory(res)));
  }

  getOfferings(url: string, filter: HelgolandParameterFilter): Observable<Offering[]> {
    return this.api.getOfferings(url, this.createFilter(filter)).pipe(map(res => res.map(o => this.createOffering(o))));
  }

  getOffering(id: string, url: string, filter: HelgolandParameterFilter): Observable<Offering> {
    return this.api.getOffering(id, url, this.createFilter(filter)).pipe(map(res => this.createOffering(res)));
  }

  getPhenomena(url: string, filter: HelgolandParameterFilter): Observable<Phenomenon[]> {
    return this.api.getPhenomena(url, this.createFilter(filter)).pipe(map(res => res.map(p => this.createPhenomenon(p))));
  }

  getPhenomenon(id: string, url: string, filter: HelgolandParameterFilter): Observable<Phenomenon> {
    return this.api.getPhenomenon(id, url, this.createFilter(filter)).pipe(map(res => this.createPhenomenon(res)));
  }

  getProcedures(url: string, filter: HelgolandParameterFilter): Observable<Procedure[]> {
    return this.api.getProcedures(url, this.createFilter(filter)).pipe(map(res => res.map(p => this.createProcedure(p))));
  }

  getProcedure(id: string, url: string, filter: HelgolandParameterFilter): Observable<Procedure> {
    return this.api.getProcedure(id, url, this.createFilter(filter)).pipe(map(res => this.createProcedure(res)));
  }

  getFeatures(url: string, filter: HelgolandParameterFilter): Observable<Feature[]> {
    return this.api.getFeatures(url, this.createFilter(filter)).pipe(map(res => res.map(f => this.createFeature(f))));
  }

  getFeature(id: string, url: string, filter: HelgolandParameterFilter): Observable<Feature> {
    return this.api.getFeature(id, url, this.createFilter(filter)).pipe(map(res => this.createFeature(res)));
  }

  getPlatforms(url: string, filter: HelgolandParameterFilter): Observable<HelgolandPlatform[]> {
    return this.api.getFeatures(url, this.createFilter(filter)).pipe(map(res => res.map(f => this.createStation(f))));
  }

  getPlatform(id: string, url: string, filter: HelgolandParameterFilter): Observable<HelgolandPlatform> {
    return this.api.getFeature(id, url, this.createFilter(filter)).pipe(map(res => this.createStation(res)));
  }

  getDatasets(url: string, filter: DatasetFilter): Observable<HelgolandDataset[]> {
    return this.api.getDatasets(url, this.createFilter(filter)).pipe(map(res => res.map(ds => this.createDataset(ds, url))));
  }

  protected createDataset(ds: ApiV3Dataset, url: string): HelgolandDataset {
    if (!(ds.firstValue && ds.lastValue && ds.parameters)) {
      return new HelgolandDataset(ds.id, url, ds.label);
    }
    let firstValue: FirstLastValue, lastValue: FirstLastValue;
    let category: Parameter, feature: Parameter, offering: Parameter, phenomenon: Parameter, procedure: Parameter, service: Parameter;
    let platform: PlatformParameter;
    if (ds.firstValue) {
      firstValue = { timestamp: new Date(ds.firstValue.timestamp).getTime(), value: ds.firstValue.value };
    }
    if (ds.lastValue) {
      lastValue = { timestamp: new Date(ds.lastValue.timestamp).getTime(), value: ds.lastValue.value };
    }
    if (ds.parameters) {
      category = { id: ds.parameters.category.id, label: ds.parameters.category.label };
      feature = { id: ds.feature.id, label: ds.feature.properties.label };
      offering = { id: ds.parameters.offering.id, label: ds.parameters.offering.label };
      phenomenon = { id: ds.parameters.phenomenon.id, label: ds.parameters.phenomenon.label };
      procedure = { id: ds.parameters.procedure.id, label: ds.parameters.procedure.label };
      service = { id: ds.parameters.service.id, label: ds.parameters.service.label };
      platform = { id: ds.parameters.service.id, label: ds.parameters.service.label, platformType: PlatformTypes.stationary };
    }
    switch (ds.datasetType) {
      case ApiV3DatasetTypes.Timeseries:
        if (ds.observationType === ApiV3ObservationTypes.Simple && (ds.valueType === ApiV3ValueTypes.Quantity || ds.valueType === ApiV3ValueTypes.Count)) {
          return new HelgolandTimeseries(ds.id, url, ds.label, ds.uom, this.createHelgolandPlatform(ds.feature), firstValue, lastValue, [], null,
            { category, feature, offering, phenomenon, procedure, service }
          );
        } else {
          return new HelgolandDataset(ds.id, url, ds.label);
        }
      case ApiV3DatasetTypes.Trajectory:
        if (ds.observationType === ApiV3ObservationTypes.Profil) {
          return new HelgolandProfile(ds.id, url, ds.label, ds.uom, true, firstValue, lastValue, { category, feature, offering, phenomenon, procedure, service, platform });
        } else {
          return new HelgolandTrajectory(ds.id, url, ds.label, ds.uom, firstValue, lastValue, { category, feature, offering, phenomenon, procedure, service, platform });
        }
      case ApiV3DatasetTypes.Profile:
      case ApiV3DatasetTypes.IndividualObservation:
        console.error(`'${ds.datasetType}' not implemented`);
        return new HelgolandDataset(ds.id, url, ds.label);
      default:
        return new HelgolandDataset(ds.id, url, ds.label);
    }
  }

  protected createHelgolandPlatform(feature: ApiV3Feature): HelgolandPlatform {
    return new HelgolandPlatform(feature.id, feature.properties.label, [], feature.geometry);
  }

  protected createService(service: ApiV3Service, url: string, filter: HelgolandParameterFilter): HelgolandService {
    // TODO: remove fix for dataset count, use just service.quantities.datasets.total for dataset
    let datasets;
    switch (filter.type) {
      case DatasetType.Timeseries:
        datasets = service.quantities.datasets.timeseries;
        break;
      case DatasetType.Trajectory:
        datasets = service.quantities.datasets.trajectories;
        break;
      case DatasetType.Profile:
        datasets = service.quantities.datasets.profiles;
        break;
      default:
        datasets = service.quantities.datasets.total;
        break;
    }
    return new HelgolandService(
      service.id,
      url,
      service.label,
      service.type,
      service.version,
      {
        categories: service.quantities.categories,
        features: service.quantities.features,
        offerings: service.quantities.offerings,
        phenomena: service.quantities.phenomena,
        procedures: service.quantities.procedures,
        datasets: datasets,
        platforms: service.quantities.platforms
      }
    );
  }

  getDataset(internalId: InternalDatasetId, filter: DatasetFilter): Observable<HelgolandDataset> {
    return this.api.getDataset(internalId.id, internalId.url, filter).pipe(map(res => this.createDataset(res, internalId.url)));
  }

  getDatasetData(dataset: HelgolandDataset, timespan: Timespan, filter: HelgolandDataFilter): Observable<HelgolandData> {

    if (dataset instanceof HelgolandTimeseries) {
      const maxTimeExtent = moment.duration(1, 'year').asMilliseconds();
      if ((timespan.to - timespan.from) > maxTimeExtent) {
        const requests: Array<Observable<HelgolandTimeseriesData>> = [];
        let start = moment(timespan.from).startOf('year');
        let end = moment(timespan.from).endOf('year');
        while (start.isBefore(moment(timespan.to))) {
          const chunkSpan = new Timespan(start.unix() * 1000, end.unix() * 1000);
          requests.push(
            this.api.getDatasetData<TimeValueTuple>(dataset.id, dataset.url, { timespan: this.createRequestTimespan(chunkSpan), format: 'flot' })
              .pipe(map(res => this.createTimeseriesData(res)))
          );
          start = end.add(1, 'millisecond');
          end = moment(start).endOf('year');
        }
        return forkJoin(requests).pipe(map((e) => {
          const mergedResult = e.reduce((previous, current) => {
            const next: HelgolandTimeseriesData = new HelgolandTimeseriesData(previous.values.concat(current.values));
            for (const key in previous.referenceValues) {
              if (previous.referenceValues.hasOwnProperty(key)) {
                next.referenceValues[key] = previous.referenceValues[key].concat(current.referenceValues[key]);
              }
            }
            return next;
          });
          if (mergedResult.values && mergedResult.values.length > 0) {
            // cut first
            const fromIdx = mergedResult.values.findIndex(el => el[0] >= timespan.from);
            mergedResult.values = mergedResult.values.slice(fromIdx);
            // cut last
            const toIdx = mergedResult.values.findIndex(el => el[0] >= timespan.to);
            if (toIdx >= 0) { mergedResult.values = mergedResult.values.slice(0, toIdx + 1); }
          }
          return mergedResult;
        }));
      } else {
        return this.api.getDatasetData<TimeValueTuple>(dataset.id, dataset.url, { timespan: this.createRequestTimespan(timespan), format: 'flot' })
          .pipe(map(res => this.createTimeseriesData(res)));
      }
    }

    if (dataset instanceof HelgolandTrajectory) {
      return this.api.getDatasetData<LocatedTimeValueEntry>(dataset.id, dataset.url, { timespan: this.createRequestTimespan(timespan), unixTime: true })
        .pipe(map(res => this.createTrajectoryData(res)));
    }
  }

  createCsvDataExportLink(internalId: InternalDatasetId, params: HelgolandCsvExportLinkParams): Observable<string> {
    const generator = new UrlGenerator();
    const url = generator.createBaseUrl(internalId.url, 'datasets', internalId.id) + '/data.zip';
    const reqParams = new Map<string, string>();
    if (params.timespan) {
      reqParams.set('timespan', generator.createTimespanRequestParam(params.timespan));
    }
    if (params.lang) { reqParams.set('locale', params.lang); }
    if (params.generalize) { reqParams.set('locale', params.generalize.toString()); }
    if (params.zip) { reqParams.set('locale', params.zip.toString()); }
    reqParams.set('bom', 'true');
    return of(generator.addUrlParams(url, reqParams));
  }

  getDatasetExtras(internalId: InternalDatasetId): Observable<DatasetExtras> {
    return this.api.getDatasetExtras(internalId.id, internalId.url);
  }

  protected createRequestTimespan(timespan: Timespan): string {
    return encodeURI(moment(timespan.from).format() + '/' + moment(timespan.to).format());
  }

  protected createTrajectoryData(res: Data<LocatedTimeValueEntry>): HelgolandTrajectoryData {
    return new HelgolandTrajectoryData(res.values);
  }

  protected createTimeseriesData(res: Data<TimeValueTuple>): HelgolandTimeseriesData {
    const data = new HelgolandTimeseriesData(res.values);
    data.referenceValues = res.referenceValues ? res.referenceValues : {};
    if (res.valueBeforeTimespan) {
      data.valueBeforeTimespan = res.valueBeforeTimespan;
    }
    if (res.valueAfterTimespan) {
      data.valueAfterTimespan = res.valueAfterTimespan;
    }
    return data;
  }

  protected createFilter(filter: HelgolandParameterFilter): ApiV3ParameterFilter {
    const apiFilter: ApiV3ParameterFilter = {};
    if (filter.category) { apiFilter.category = filter.category; }
    if (filter.offering) { apiFilter.offering = filter.offering; }
    if (filter.phenomenon) { apiFilter.phenomenon = filter.phenomenon; }
    if (filter.procedure) { apiFilter.procedure = filter.procedure; }
    if (filter.feature) { apiFilter.feature = filter.feature; }
    if (filter.expanded) { apiFilter.expanded = filter.expanded; }
    if (filter.lang) { apiFilter.locale = filter.lang; }
    switch (filter.type) {
      case DatasetType.Timeseries:
        apiFilter.datasetTypes = [ApiV3DatasetTypes.Timeseries];
        apiFilter.observationTypes = [ApiV3ObservationTypes.Simple];
        apiFilter.valueTypes = [ApiV3ValueTypes.Quantity, ApiV3ValueTypes.Count];
        break;
      case DatasetType.Trajectory:
        apiFilter.datasetTypes = [ApiV3DatasetTypes.Trajectory];
        apiFilter.observationTypes = [ApiV3ObservationTypes.Simple];
        apiFilter.valueTypes = [ApiV3ValueTypes.Quantity];
        break;
      case DatasetType.Profile:
        apiFilter.datasetTypes = [ApiV3DatasetTypes.Timeseries];
        apiFilter.observationTypes = [ApiV3ObservationTypes.Profil];
        apiFilter.valueTypes = [ApiV3ValueTypes.Quantity];
        break;
      default:
        break;
    }
    return apiFilter;
  }

  protected createStation(feature: ApiV3Feature): HelgolandPlatform {
    const datasetIds = [];
    for (const key in feature.properties.datasets) {
      if (feature.properties.datasets.hasOwnProperty(key)) {
        datasetIds.push(key);
      }
    }
    return new HelgolandPlatform(feature.id, feature.properties.label, datasetIds, feature.geometry);
  }

  protected createCategory(category: ApiV3Category): Category {
    return {
      id: category.id,
      label: category.label
    };
  }

  protected createOffering(offering: ApiV3Offering): Offering {
    return {
      id: offering.id,
      label: offering.label
    };
  }

  protected createPhenomenon(phenomenon: ApiV3Phenomenon): Phenomenon {
    return {
      id: phenomenon.id,
      label: phenomenon.label
    };
  }

  protected createProcedure(procedure: ApiV3Procedure): Procedure {
    return {
      id: procedure.id,
      label: procedure.label
    };
  }

  protected createFeature(feature: ApiV3Feature): Feature {
    return {
      id: feature.id,
      label: feature.properties.label
    };
  }

}

export const DatasetApiV3ConnectorProvider = {
  provide: HELGOLAND_SERVICE_CONNECTOR_HANDLER,
  useClass: DatasetApiV3Connector,
  multi: true
};

result-matching ""

    No results matching ""