import { Injectable , NgZone } from '@angular/core' ; import Feature from 'ol/Feature' ; import { Geometry } from 'ol/geom' ; import { forkJoin } from 'rxjs' ; import { DatasetType , HsAddDataService } from '../add-data.service' ; import { EndpointsWithDatasourcesPipe } from '../../../common/widgets/endpoints-with-datasources.pipe' ; import { HsAddDataCatalogueMapService } from './catalogue-map.service' ; import { HsAddDataLayerDescriptor } from './layer-descriptor.model' ; import { HsAddDataOwsService } from '../url/add-data-ows.service' ; import { HsAddDataVectorService } from '../vector/vector.service' ; import { HsCommonEndpointsService } from '../../../common/endpoints/endpoints.service' ; import { HsCommonLaymanService } from '../../../common/layman/layman.service' ; import { HsConfig } from '../../../config.service' ; import { HsEndpoint } from '../../../common/endpoints/endpoint.interface' ; import { HsEventBusService } from '../../core/event-bus.service' ; import { HsLaymanBrowserService } from './layman/layman.service' ; import { HsLayoutService } from '../../layout/layout.service' ; import { HsMapService } from '../../map/map.service' ; import { HsMickaBrowserService } from './micka/micka.service' ; import { HsUtilsService } from '../../utils/utils.service' ; type WhatToAddDescriptor = { type : string ; dsType ? : string ; layer ? ; link ? ; name ? ; title ? : string ; abstract ? : string ; projection ? ; extractStyles ? ; editable ? : boolean ; workspace ? : string ; style ? : string ; } ; @ Injectable ( { providedIn : 'root' , } ) export class HsAddDataCatalogueService { data : any = { } ; selectedEndpoint : HsEndpoint ; selectedLayer : HsAddDataLayerDescriptor ; catalogEntries = [ ] ; dataLoading : boolean ; itemsPerPage = 20 ; listStart = 0 ; listNext = this . itemsPerPage ; catalogQuery ; endpointsWithDatasources : any [ ] ; matchedRecords : number ; extentChangeSuppressed = false ; constructor ( public hsConfig , public hsAddDataVectorService , public hsEventBusService , public hsMickaBrowserService , public hsLaymanBrowserService , public hsLayoutService , public hsCommonEndpointsService , public hsUtilsService , public hsMapService , public hsAddDataCatalogueMapService , public hsAddDataService , public endpointsWithDatasourcesPipe , private zone , public hsCommonLaymanService , public hsAddDataOwsService ) { this . data . query = { textFilter : '' , title : '' , type : 'service' , Subject : '' , sortby : 'date' , } ; this . data . textField = 'AnyText' ; this . data . selectedLayer = null ; this . data . id_selected = 'OWS' ; this . data . filterByExtent = true ; this . data . onlyMine = false ; if ( this . dataSourceExistsAndEmpty ( ) && this . panelVisible ( ) ) { this . queryCatalogs ( ) ; } this . endpointsWithDatasources = this . endpointsWithDatasourcesPipe . transform ( this . hsCommonEndpointsService . endpoints ) ; this . hsEventBusService . mapExtentChanges . subscribe ( this . hsUtilsService . debounce ( ( e ) => { if ( ! this . panelVisible ( ) || this . extentChangeSuppressed ) { this . extentChangeSuppressed = false ; return ; } if ( this . data . filterByExtent ) { this . zone . run ( ( ) => { this . reloadData ( ) ; } ) ; } } , 500 , false , this ) ) ; this . hsEventBusService . mainPanelChanges . subscribe ( ( ) => { if ( this . dataSourceExistsAndEmpty ( ) && this . panelVisible ( ) ) { this . reloadData ( ) ; this . extentChangeSuppressed = true ; } this . calcExtentLayerVisibility ( ) ; } ) ; this . hsCommonLaymanService . authChange . subscribe ( ( ) => { if ( this . panelVisible ( ) ) { this . reloadData ( ) ; } } ) ; this . hsAddDataService . datasetSelected . subscribe ( ( { type } ) => { if ( type == 'catalogue' && this . panelVisible ( ) ) { this . reloadData ( ) ; } } ) ; } resetList ( ) { this . listStart = 0 ; this . listNext = this . itemsPerPage ; this . selectedLayer = < HsAddDataLayerDescriptor > { } ; this . endpointsWithDatasources . forEach ( ( ep ) => { ep . datasourcePaging . start = 0 ; ep . datasourcePaging . next = ep . datasourcePaging . limit ; ep . datasourcePaging . matched = 0 ; } ) ; } reloadData ( ) { this . endpointsWithDatasources = this . endpointsWithDatasourcesPipe . transform ( this . hsCommonEndpointsService . endpoints ) ; this . resetList ( ) ; this . queryCatalogs ( ) ; this . calcExtentLayerVisibility ( ) ; } param suspendLimitCalculation queryCatalogs ( suspendLimitCalculation ? ) { if ( this . endpointsWithDatasources . length > 0 ) { if ( this . catalogQuery ) { this . catalogQuery . unsubscribe ( ) ; delete this . catalogQuery ; } this . clearLoadedData ( ) ; this . hsMapService . loaded ( ) . then ( ( ) => { this . dataLoading = true ; this . hsAddDataCatalogueMapService . clearExtentLayer ( ) ; const observables = [ ] ; for ( const endpoint of this . endpointsWithDatasources ) { if ( ! this . data . onlyMine || endpoint . type == 'layman' ) { const promise = this . queryCatalog ( endpoint ) ; observables . push ( promise ) ; } } this . catalogQuery = forkJoin ( observables ) . subscribe ( ( ) => { suspendLimitCalculation ? this . createLayerList ( ) : this . calculateEndpointLimits ( ) ; } ) ; } ) ; } } /**
     * Calculates each endpoint layer request limit, based on the matched layers ratio
     * from all endpoint matched layers
     */ calculateEndpointLimits ( ) { this . matchedRecords = 0 ; this . itemsPerPage = 20 ; this . endpointsWithDatasources = this . endpointsWithDatasources . filter ( ( ep ) => ep . datasourcePaging . matched != 0 ) ; if ( this . endpointsWithDatasources . length == 0 ) { this . dataLoading = false ; return ; } this . endpointsWithDatasources . forEach ( ( ep ) => ( this . matchedRecords += ep . datasourcePaging . matched ) ) ; let sumLimits = 0 ; this . endpointsWithDatasources . forEach ( ( ep ) => { ep . datasourcePaging . limit = Math . floor ( ( ep . datasourcePaging . matched / this . matchedRecords ) * this . itemsPerPage ) ; if ( ep . datasourcePaging . limit == 0 ) { ep . datasourcePaging . limit = 1 ; } sumLimits += ep . datasourcePaging . limit ; } ) ; this . itemsPerPage = sumLimits ; this . queryCatalogs ( true ) ; } createLayerList ( ) { for ( const endpoint of this . endpointsWithDatasources ) { if ( ! this . data . onlyMine || endpoint . type == 'layman' ) { if ( endpoint . layers ) { endpoint . layers . forEach ( ( layer ) => { layer . endpoint = endpoint ; } ) ; if ( this . catalogEntries . length > 0 ) { this . filterDuplicates ( endpoint ) ; } else { this . catalogEntries = this . catalogEntries . concat ( endpoint . layers ) ; } } } } if ( this . matchedRecords < this . itemsPerPage ) { this . listNext = this . matchedRecords ; } this . catalogEntries . sort ( ( a , b ) => a . title . localeCompare ( b . title ) ) ; this . dataLoading = false ; } filterDuplicates ( endpoint ) { if ( endpoint . layers === undefined || endpoint . layers ?. length == 0 ) { return [ ] ; } const filteredLayers = endpoint . layers . filter ( ( layer ) => this . catalogEntries . filter ( ( u ) => u . id == layer . id ) . length == 0 ) ; if ( endpoint . type != 'layman' ) { this . matchedRecords -= endpoint . layers . length - filteredLayers . length ; } this . catalogEntries = this . catalogEntries . concat ( filteredLayers ) ; } getNextRecords ( ) { this . listStart += this . itemsPerPage ; this . listNext += this . itemsPerPage ; if ( this . listNext > this . matchedRecords ) { this . listNext = this . matchedRecords ; } this . endpointsWithDatasources . forEach ( ( ep ) => ( ep . datasourcePaging . start += ep . datasourcePaging . limit ) ) ; this . queryCatalogs ( true ) ; } getPreviousRecords ( ) { if ( this . listStart - this . itemsPerPage <= 0 ) { this . listStart = 0 ; this . listNext = this . itemsPerPage ; this . endpointsWithDatasources . forEach ( ( ep ) => ( ep . datasourcePaging . start = 0 ) ) ; } else { this . listStart -= this . itemsPerPage ; this . listNext = this . listStart + this . itemsPerPage ; this . endpointsWithDatasources . forEach ( ( ep ) => ( ep . datasourcePaging . start -= ep . datasourcePaging . limit ) ) ; } this . queryCatalogs ( true ) ; } clearLoadedData ( ) { this . catalogEntries = [ ] ; this . endpointsWithDatasources . forEach ( ( ep ) => ( ep . layers = [ ] ) ) ; } param catalog queryCatalog ( catalog ) { this . hsAddDataCatalogueMapService . clearDatasetFeatures ( catalog ) ; let query ; switch ( catalog . type ) { case 'micka' : query = this . hsMickaBrowserService . queryCatalog ( catalog , this . data , ( feature ) => this . hsAddDataCatalogueMapService . addExtentFeature ( feature ) , this . data . textField ) ; return query ; case 'layman' : query = this . hsLaymanBrowserService . queryCatalog ( catalog , this . data , ( feature ) => this . hsAddDataCatalogueMapService . addExtentFeature ( feature ) ) ; return query ; default : break ; } } param ds param layer returns layerDownload ( ds , layer ) { if ( ds . download == true ) { if ( [ 'kml' , 'geojson' , 'json' ] . includes ( layer . formats [ 0 ] . toLowerCase ( ) ) && layer . url . length > 0 ) { return layer . url ; } } return '#' ; } param ds param layer returns layerRDF ( ds , layer ) { return `${ ds . url }?request=GetRecordById&id=${ layer . id }&outputschema=http://www.w3.org/ns/dcat%23` ; } param ds param layer param type returns async addLayerToMap ( ds , layer , type ? ) { let whatToAdd ; if ( ds . type == 'micka' ) { whatToAdd = await this . hsMickaBrowserService . describeWhatToAdd ( ds , layer ) ; } else if ( ds . type == 'layman' ) { whatToAdd = await this . hsLaymanBrowserService . describeWhatToAdd ( ds , layer ) ; } else { whatToAdd = { type : 'none' } ; } if ( ! whatToAdd ) { return ; } if ( type ) { whatToAdd . type = type ; } if ( Array . isArray ( whatToAdd . type ) ) { return whatToAdd . type ; } if ( whatToAdd . type == 'WMS' ) { whatToAdd . link = Array . isArray ( whatToAdd . link ) ? whatToAdd . link . filter ( ( link ) => link . toLowerCase ( ) . includes ( 'wms' ) ) [ 0 ] : whatToAdd . link ; this . datasetSelect ( 'url' ) ; await this . hsAddDataOwsService . connectToOWS ( { type : whatToAdd . type . toLowerCase ( ) , uri : decodeURIComponent ( whatToAdd . link ) , layer : ds . type == 'layman' ? layer . name : undefined , } ) ; } else if ( whatToAdd . type == 'WFS' ) { this . datasetSelect ( 'url' ) ; if ( ds . type == 'micka' ) { whatToAdd . link = Array . isArray ( whatToAdd . link ) ? whatToAdd . link . filter ( ( link ) => link . toLowerCase ( ) . includes ( 'wfs' ) ) [ 0 ] : whatToAdd . link ; await this . hsAddDataOwsService . connectToOWS ( { type : whatToAdd . type . toLowerCase ( ) , uri : decodeURIComponent ( whatToAdd . link ) , layer : undefined , style : whatToAdd . style , } ) ; } else { if ( whatToAdd . editable ) { const layer = await this . hsAddDataVectorService . addVectorLayer ( 'wfs' , whatToAdd . link . replace ( '_wms/ows' , '/wfs' ) , whatToAdd . name , whatToAdd . title , whatToAdd . abstract , whatToAdd . projection , { extractStyles : whatToAdd . extractStyles , workspace : whatToAdd . workspace , style : whatToAdd . style , } ) ; this . hsAddDataVectorService . fitExtent ( layer ) ; this . hsAddDataService . dsSelected = 'catalogue' ; } else { await this . hsAddDataOwsService . connectToOWS ( { type : 'wfs' , uri : whatToAdd . link . replace ( '_wms/ows' , '/wfs' ) , style : whatToAdd . style , layer : `${ whatToAdd . workspace }:${ whatToAdd . name }` , } ) ; } this . hsLayoutService . setMainPanel ( 'layermanager' ) ; } } else if ( [ 'KML' , 'GEOJSON' ] . includes ( whatToAdd . type ) ) { const layer = await this . hsAddDataVectorService . addVectorLayer ( whatToAdd . type . toLowerCase ( ) , whatToAdd . link , whatToAdd . name , whatToAdd . title , whatToAdd . abstract , whatToAdd . projection , { extractStyles : whatToAdd . extractStyles } ) ; this . hsAddDataVectorService . fitExtent ( layer ) ; } else { this . hsLayoutService . setMainPanel ( 'layermanager' ) ; } return whatToAdd . type ; } datasetSelect ( id_selected ) { this . data . id_selected = id_selected ; this . hsAddDataService . selectType ( id_selected ) ; this . calcExtentLayerVisibility ( ) ; } /**
     * Clear query variable
     */ clear ( ) { this . data . query . textFilter = '' ; this . data . query . title = '' ; this . data . query . Subject = '' ; this . data . query . keywords = '' ; this . data . query . OrganisationName = '' ; this . data . query . sortby = '' ; } /**
     *
     */ private dataSourceExistsAndEmpty ( ) { return ! ! this . endpointsWithDatasources ; } /**
     *
     */ private panelVisible ( ) { return this . hsLayoutService . panelVisible ( 'addData' ) ; } calcExtentLayerVisibility ( ) { this . hsAddDataCatalogueMapService . extentLayer . setVisible ( this . panelVisible ( ) && this . hsAddDataService . dsSelected == 'catalogue' ) ; } }