diff --git a/api/v2beta1/wms_conversion.go b/api/v2beta1/wms_conversion.go index c1d01dc..4fda47e 100644 --- a/api/v2beta1/wms_conversion.go +++ b/api/v2beta1/wms_conversion.go @@ -43,6 +43,13 @@ func (src *WMS) ConvertTo(dstRaw conversion.Hub) error { dst := dstRaw.(*pdoknlv3.WMS) log.Printf("ConvertTo: Converting WMS from Spoke version v2beta1 to Hub version v3;"+ "source: %s/%s, target: %s/%s", src.Namespace, src.Name, dst.Namespace, dst.Name) + V3HubFromV2(src, dst) + + return nil +} + +func V3HubFromV2(src *WMS, target *pdoknlv3.WMS) { + dst := target dst.ObjectMeta = src.ObjectMeta dst.Annotations[SERVICE_METADATA_IDENTIFIER_ANNOTATION] = src.Spec.Service.MetadataIdentifier @@ -126,8 +133,6 @@ func (src *WMS) ConvertTo(dstRaw conversion.Hub) error { } dst.Spec.Service = service - - return nil } // ConvertFrom converts the Hub version (v3) to this WMS (v2beta1). diff --git a/api/v2beta1/wms_conversion_test.go b/api/v2beta1/wms_conversion_test.go new file mode 100644 index 0000000..08ac014 --- /dev/null +++ b/api/v2beta1/wms_conversion_test.go @@ -0,0 +1,20 @@ +package v2beta1 + +import ( + pdoknlv3 "github.com/pdok/mapserver-operator/api/v3" + "github.com/stretchr/testify/assert" + "sigs.k8s.io/yaml" + "testing" +) + +func TestV2ToV3(t *testing.T) { + input := "apiVersion: pdok.nl/v2beta1\nkind: WMS\nmetadata:\n name: rws-nwbwegen-v1-0\n labels:\n dataset-owner: rws\n dataset: nwbwegen\n service-version: v1_0\n service-type: wms\n annotations:\n lifecycle-phase: prod\n service-bundle-id: b39c152b-393b-52f5-a50c-e1ffe904b6fb\nspec:\n general:\n datasetOwner: rws\n dataset: nwbwegen\n serviceVersion: v1_0\n kubernetes:\n healthCheck:\n boundingbox: 135134.89,457152.55,135416.03,457187.82\n resources:\n limits:\n ephemeralStorage: 1535Mi\n memory: 4G\n requests:\n cpu: 2000m\n ephemeralStorage: 1535Mi\n memory: 4G\n options:\n automaticCasing: true\n disableWebserviceProxy: false\n includeIngress: true\n validateRequests: true\n service:\n title: NWB - Wegen WMS\n abstract:\n Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen.\n Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen\n Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland.\n Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk,\n provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien\n van een straatnaam of nummer.\n authority:\n name: rws\n url: https://www.rijkswaterstaat.nl\n dataEPSG: EPSG:28992\n extent: -59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961\n inspire: true\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n - Hectometerpunten\n - HVD\n - Mobiliteit\n stylingAssets:\n configMapRefs:\n - name: includes\n keys:\n - nwb_wegen_hectopunten.symbol\n - hectopunten.style\n - wegvakken.style\n blobKeys:\n - resources/fonts/liberation-sans.ttf\n layers:\n - abstract:\n Deze laag bevat de wegvakken uit het Nationaal Wegen bestand (NWB)\n en geeft gedetailleerde informatie per wegvak zoals straatnaam, wegnummer,\n routenummer, wegbeheerder, huisnummers, enz. weer.\n data:\n gpkg:\n columns:\n - objectid\n - wvk_id\n - wvk_begdat\n - jte_id_beg\n - jte_id_end\n - wegbehsrt\n - wegnummer\n - wegdeelltr\n - hecto_lttr\n - bst_code\n - rpe_code\n - admrichtng\n - rijrichtng\n - stt_naam\n - stt_bron\n - wpsnaam\n - gme_id\n - gme_naam\n - hnrstrlnks\n - hnrstrrhts\n - e_hnr_lnks\n - e_hnr_rhts\n - l_hnr_lnks\n - l_hnr_rhts\n - begafstand\n - endafstand\n - beginkm\n - eindkm\n - pos_tv_wol\n - wegbehcode\n - wegbehnaam\n - distrcode\n - distrnaam\n - dienstcode\n - dienstnaam\n - wegtype\n - wgtype_oms\n - routeltr\n - routenr\n - routeltr2\n - routenr2\n - routeltr3\n - routenr3\n - routeltr4\n - routenr4\n - wegnr_aw\n - wegnr_hmp\n - geobron_id\n - geobron_nm\n - bronjaar\n - openlr\n - bag_orl\n - frc\n - fow\n - alt_naam\n - alt_nr\n - rel_hoogte\n - st_lengthshape\n geometryType: MultiLineString\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: wegvakken\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n maxScale: 50000.0\n minScale: 1.0\n name: wegvakken\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: wegvakken\n title: NWB - Wegvakken\n visualization: wegvakken.style\n title: Wegvakken\n visible: true\n - abstract:\n Deze laag bevat de hectopunten uit het Nationaal Wegen Bestand (NWB)\n en geeft gedetailleerde informatie per hectopunt zoals hectometrering, afstand,\n zijde en hectoletter weer.\n data:\n gpkg:\n columns:\n - objectid\n - hectomtrng\n - afstand\n - wvk_id\n - wvk_begdat\n - zijde\n - hecto_lttr\n geometryType: MultiPoint\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: hectopunten\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Hectometerpunten\n maxScale: 50000.0\n minScale: 1.0\n name: hectopunten\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: hectopunten\n title: NWB - Hectopunten\n visualization: hectopunten.style\n title: Hectopunten\n visible: true\n metadataIdentifier: f2437a92-ddd3-4777-a1bc-fdf4b4a7fcb8\n" + var v2wms WMS + err := yaml.Unmarshal([]byte(input), &v2wms) + assert.NoError(t, err) + var target pdoknlv3.WMS + V3HubFromV2(&v2wms, &target) + assert.Equal(t, "NWB - Wegen WMS", target.Spec.Service.Title) + a := 0 + _ = a +} diff --git a/api/v3/shared_types.go b/api/v3/shared_types.go index e08a688..c56bc74 100644 --- a/api/v3/shared_types.go +++ b/api/v3/shared_types.go @@ -35,6 +35,7 @@ type WMSWFS interface { HasPostgisData() bool // Sha1 hash of the objects name ID() string + URLPath() string } type Mapfile struct { @@ -112,18 +113,7 @@ func GetHost() string { } func GetBaseURLPath[T WMSWFS](o T) string { - var serviceURL string - switch any(o).(type) { - case *WFS: - if WFS, ok := any(o).(*WFS); ok { - serviceURL = WFS.Spec.Service.URL - } - case *WMS: - if WMS, ok := any(o).(*WMS); ok { - serviceURL = WMS.Spec.Service.URL - } - } - + serviceURL := o.URLPath() parsed, _ := url.Parse(serviceURL) return strings.TrimPrefix(parsed.Path, "/") } diff --git a/api/v3/wfs_types.go b/api/v3/wfs_types.go index 7eadf44..f94b49b 100644 --- a/api/v3/wfs_types.go +++ b/api/v3/wfs_types.go @@ -150,3 +150,7 @@ func (wfs *WFS) Options() *Options { func (wfs *WFS) ID() string { return Sha1HashOfName(wfs) } + +func (wfs *WFS) URLPath() string { + return wfs.Spec.Service.URL +} diff --git a/api/v3/wms_types.go b/api/v3/wms_types.go index f0e32e0..874ac9b 100644 --- a/api/v3/wms_types.go +++ b/api/v3/wms_types.go @@ -267,3 +267,7 @@ func (wms *WMS) Options() *Options { func (wms *WMS) ID() string { return Sha1HashOfName(wms) } + +func (wms *WMS) URLPath() string { + return wms.Spec.Service.URL +} diff --git a/go.mod b/go.mod index b8dff2c..0baf18e 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/onsi/ginkgo/v2 v2.22.2 github.com/onsi/gomega v1.36.2 github.com/pdok/ogc-capabilities-generator v1.0.0-beta5 - github.com/pdok/ogc-specifications v1.0.0-beta4 + github.com/pdok/ogc-specifications v1.0.0-beta5 github.com/pdok/smooth-operator v0.0.9 github.com/traefik/traefik/v3 v3.3.4 k8s.io/api v0.32.0 diff --git a/go.sum b/go.sum index 0ab6cd6..2b76737 100644 --- a/go.sum +++ b/go.sum @@ -362,6 +362,8 @@ github.com/pdok/ogc-capabilities-generator v1.0.0-beta5 h1:nwkIbFcUW4FIYnf6fLfzp github.com/pdok/ogc-capabilities-generator v1.0.0-beta5/go.mod h1:qG2auFy7MDL8Zp1eOfdaUJat+jNW5oLGVd+g7Mbth4Q= github.com/pdok/ogc-specifications v1.0.0-beta4 h1:/Dgi6ArgR0YPCkErpNyCQTCYMkH/cIfWe+VCoUUZZN0= github.com/pdok/ogc-specifications v1.0.0-beta4/go.mod h1:YDngwkwrWOfc5MYnEYseiv97K1Y9bZXlVzwi/8EaIl8= +github.com/pdok/ogc-specifications v1.0.0-beta5 h1:j7JrXUeW55mVU9ZmJ67r8V6DhbKdgTDiGE1YKFpRWx4= +github.com/pdok/ogc-specifications v1.0.0-beta5/go.mod h1:YDngwkwrWOfc5MYnEYseiv97K1Y9bZXlVzwi/8EaIl8= github.com/pdok/smooth-operator v0.0.9 h1:UaOPc23BaHDWzBatSWnOxEjffV0WMiy1LPUkRdqdIGI= github.com/pdok/smooth-operator v0.0.9/go.mod h1:oZWFuIKJGjN/C6ocgMNfMZ7SbLQi+N0qaWj7j95Wdec= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= diff --git a/internal/controller/capabilitiesgenerator/capabilities_generator.go b/internal/controller/capabilitiesgenerator/capabilities_generator.go index bbd3076..5fbd7ac 100644 --- a/internal/controller/capabilitiesgenerator/capabilities_generator.go +++ b/internal/controller/capabilitiesgenerator/capabilities_generator.go @@ -1,7 +1,6 @@ package capabilitiesgenerator import ( - "errors" "fmt" pdoknlv3 "github.com/pdok/mapserver-operator/api/v3" @@ -37,8 +36,8 @@ func GetInput[W pdoknlv3.WMSWFS](webservice W, ownerInfo *smoothoperatorv1.Owner return createInputForWFS(WFS, ownerInfo) } case *pdoknlv3.WMS: - if _, ok := any(webservice).(*pdoknlv3.WMS); ok { - return "", errors.New("not implemented for WMS") + if WMS, ok := any(webservice).(*pdoknlv3.WMS); ok { + return createInputForWMS(WMS, ownerInfo) } default: return "", fmt.Errorf("unexpected input, webservice should be of type WFS or WMS, webservice: %v", webservice) @@ -58,3 +57,16 @@ func createInputForWFS(wfs *pdoknlv3.WFS, ownerInfo *smoothoperatorv1.OwnerInfo) return string(yamlInput), nil } + +func createInputForWMS(wms *pdoknlv3.WMS, ownerInfo *smoothoperatorv1.OwnerInfo) (config string, err error) { + input, err := MapWMSToCapabilitiesGeneratorInput(wms, ownerInfo) + if err != nil { + return "", err + } + yamlInput, err := yaml.Marshal(input) + if err != nil { + return "", fmt.Errorf("failed to marshal the capabilities generator input to yaml: %w", err) + } + + return string(yamlInput), nil +} diff --git a/internal/controller/capabilitiesgenerator/capabilities_generator_test.go b/internal/controller/capabilitiesgenerator/capabilities_generator_test.go index b723f21..b04e71d 100644 --- a/internal/controller/capabilitiesgenerator/capabilities_generator_test.go +++ b/internal/controller/capabilitiesgenerator/capabilities_generator_test.go @@ -1,9 +1,12 @@ package capabilitiesgenerator import ( + "github.com/pdok/mapserver-operator/api/v2beta1" pdoknlv3 "github.com/pdok/mapserver-operator/api/v3" smoothoperatorv1 "github.com/pdok/smooth-operator/api/v1" + "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/yaml" "testing" @@ -87,6 +90,467 @@ services: - urn:ogc:def:crs:EPSG::4326 metadataUrl: href: https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id=datadata-data-data-data-datadatadata +` + WMSInput = `global: + prefix: prefix + namespace: http://prefix.geonovum.nl + onlineResourceUrl: http://localhost + path: /rws/nwbwegen/wms/v1_0 + version: v1_0 + additionalSchemaLocations: http://inspire.ec.europa.eu/schemas/inspire_dls/1.0 http://inspire.ec.europa.eu/schemas/inspire_dls/1.0/inspire_dls.xsd +services: + wms130: + filename: /var/www/config/capabilities_wms_130.xml + definition: + wmsCapabilities: + space: "" + local: "" + namespaces: + wms: "" + sld: "" + xlink: "" + xsi: "" + version: "" + schemaLocation: "" + service: + name: WMS + title: NWB - Wegen WMS + abstract: Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen. Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland. Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk, provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien van een straatnaam of nummer. + keywordList: + keyword: + - Vervoersnetwerken + - Menselijke gezondheid en veiligheid + - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai) + - Nationaal + - Voertuigen + - Verkeer + - Wegvakken + - Hectometerpunten + - HVD + - Mobiliteit + onlineResource: + xlink: null + type: null + href: https://service.pdok.nl + contactInformation: + contactPersonPrimary: + contactPerson: KlantContactCenter PDOK + contactOrganization: PDOK + contactPosition: pointOfContact + contactAddress: + addressType: Work + address: "" + city: Apeldoorn + stateOrProvince: "" + postalCode: "" + country: The Netherlands + contactVoiceTelephone: null + contactFacsimileTelephone: null + contactElectronicMailAddress: BeheerPDOK@kadaster.nl + fees: NONE + accessConstraints: https://creativecommons.org/publicdomain/zero/1.0/deed.nl + layerLimit: null + maxWidth: 4000 + maxHeight: 4000 + capability: + wmsCapabilities: + request: + getCapabilities: + format: + - text/xml + dcpType: + http: + get: + onlineResource: + xlink: null + type: null + href: https://service.pdok.nl/rws/nwbwegen/wms/v1_0 + post: null + getMap: + format: + - image/png + - image/jpeg + - image/png; mode=8bit + - image/vnd.jpeg-png + - image/vnd.jpeg-png8 + dcpType: + http: + get: + onlineResource: + xlink: null + type: null + href: https://service.pdok.nl/rws/nwbwegen/wms/v1_0 + post: + onlineResource: + xlink: null + type: null + href: https://service.pdok.nl/rws/nwbwegen/wms/v1_0 + getFeatureInfo: + format: + - application/json + - application/json; subtype=geojson + - application/vnd.ogc.gml + - text/html + - text/plain + - text/xml + - text/xml; subtype=gml/3.1.1 + dcpType: + http: + get: + onlineResource: + xlink: null + type: null + href: https://service.pdok.nl/rws/nwbwegen/wms/v1_0 + post: + onlineResource: + xlink: null + type: null + href: https://service.pdok.nl/rws/nwbwegen/wms/v1_0 + exception: + format: + - XML + - BLANK + extendedCapabilities: + metadataUrl: + url: https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id=f2437a92-ddd3-4777-a1bc-fdf4b4a7fcb8 + mediaType: application/vnd.ogc.csw.GetRecordByIdResponse_xml + supportedLanguages: + defaultLanguage: + language: nl + supportedLanguage: + - language: nl + responseLanguage: + language: nl + layer: + - queryable: 1 + opaque: null + name: null + title: NWB - Wegen WMS + abstract: Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen. Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland. Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk, provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien van een straatnaam of nummer. + keywordList: + keyword: + - Vervoersnetwerken + - Menselijke gezondheid en veiligheid + - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai) + - Nationaal + - Voertuigen + - Verkeer + - Wegvakken + - Hectometerpunten + - HVD + - Mobiliteit + crs: + - namespace: EPSG + code: 28992 + - namespace: EPSG + code: 25831 + - namespace: EPSG + code: 25832 + - namespace: EPSG + code: 3034 + - namespace: EPSG + code: 3035 + - namespace: EPSG + code: 3857 + - namespace: EPSG + code: 4258 + - namespace: EPSG + code: 4326 + - namespace: CRS + code: 84 + exGeographicBoundingBox: + westBoundLongitude: 2.52713 + eastBoundLongitude: 7.37403 + southBoundLatitude: 50.2129 + northBoundLatitude: 55.7212 + boundingBox: + - crs: EPSG:28992 + minx: -25000 + miny: 250000 + maxx: 280000 + maxy: 860000 + - crs: EPSG:25831 + minx: -470271 + miny: 5.56231e+06 + maxx: 795163 + maxy: 6.18197e+06 + - crs: EPSG:25832 + minx: 62461.6 + miny: 5.56555e+06 + maxx: 397827 + maxy: 6.19042e+06 + - crs: EPSG:3034 + minx: 2.61336e+06 + miny: 3.509e+06 + maxx: 3.22007e+06 + maxy: 3.84003e+06 + - crs: EPSG:3035 + minx: 3.01676e+06 + miny: 3.81264e+06 + maxx: 3.64485e+06 + maxy: 4.15586e+06 + - crs: EPSG:3857 + minx: 281318 + miny: 6.48322e+06 + maxx: 820873 + maxy: 7.50311e+06 + - crs: EPSG:4258 + minx: 50.2129 + miny: 2.52713 + maxx: 55.7212 + maxy: 7.37403 + - crs: EPSG:4326 + minx: 50.2129 + miny: 2.52713 + maxx: 55.7212 + maxy: 7.37403 + - crs: CRS:84 + minx: 2.52713 + miny: 50.2129 + maxx: 7.37403 + maxy: 55.7212 + dimension: [] + attribution: null + authorityUrl: null + identifier: null + metadataUrl: [] + dataUrl: null + featureListUrl: null + style: [] + minScaleDenominator: null + maxScaleDenominator: null + layer: + - queryable: 1 + opaque: null + name: wegvakken + title: Wegvakken + abstract: Deze laag bevat de wegvakken uit het Nationaal Wegen bestand (NWB) en geeft gedetailleerde informatie per wegvak zoals straatnaam, wegnummer, routenummer, wegbeheerder, huisnummers, enz. weer. + keywordList: + keyword: + - Vervoersnetwerken + - Menselijke gezondheid en veiligheid + - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai) + - Nationaal + - Voertuigen + - Verkeer + - Wegvakken + crs: + - namespace: EPSG + code: 28992 + - namespace: EPSG + code: 25831 + - namespace: EPSG + code: 25832 + - namespace: EPSG + code: 3034 + - namespace: EPSG + code: 3035 + - namespace: EPSG + code: 3857 + - namespace: EPSG + code: 4258 + - namespace: EPSG + code: 4326 + - namespace: CRS + code: 84 + exGeographicBoundingBox: + westBoundLongitude: 2.52713 + eastBoundLongitude: 7.37403 + southBoundLatitude: 50.2129 + northBoundLatitude: 55.7212 + boundingBox: + - crs: EPSG:28992 + minx: -25000 + miny: 250000 + maxx: 280000 + maxy: 860000 + - crs: EPSG:25831 + minx: -470271 + miny: 5.56231e+06 + maxx: 795163 + maxy: 6.18197e+06 + - crs: EPSG:25832 + minx: 62461.6 + miny: 5.56555e+06 + maxx: 397827 + maxy: 6.19042e+06 + - crs: EPSG:3034 + minx: 2.61336e+06 + miny: 3.509e+06 + maxx: 3.22007e+06 + maxy: 3.84003e+06 + - crs: EPSG:3035 + minx: 3.01676e+06 + miny: 3.81264e+06 + maxx: 3.64485e+06 + maxy: 4.15586e+06 + - crs: EPSG:3857 + minx: 281318 + miny: 6.48322e+06 + maxx: 820873 + maxy: 7.50311e+06 + - crs: EPSG:4258 + minx: 50.2129 + miny: 2.52713 + maxx: 55.7212 + maxy: 7.37403 + - crs: EPSG:4326 + minx: 50.2129 + miny: 2.52713 + maxx: 55.7212 + maxy: 7.37403 + - crs: CRS:84 + minx: 2.52713 + miny: 50.2129 + maxx: 7.37403 + maxy: 55.7212 + dimension: [] + attribution: null + authorityUrl: null + identifier: + authority: rws + value: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff + metadataUrl: + - type: TC211 + format: text/plain + onlineResource: + xlink: null + type: simple + href: https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id=a9b7026e-0a81-4813-93bd-ba49e6f28502 + dataUrl: null + featureListUrl: null + style: + - name: wegvakken + title: NWB - Wegvakken + abstract: null + legendUrl: + width: 78 + height: 20 + format: image/png + onlineResource: + xlink: null + type: simple + href: https://service.pdok.nl/rws/nwbwegen/wms/v1_0/legend/wegvakken/wegvakken.png + styleSheetUrl: null + minScaleDenominator: 1 + maxScaleDenominator: 50000 + layer: [] + - queryable: 1 + opaque: null + name: hectopunten + title: Hectopunten + abstract: Deze laag bevat de hectopunten uit het Nationaal Wegen Bestand (NWB) en geeft gedetailleerde informatie per hectopunt zoals hectometrering, afstand, zijde en hectoletter weer. + keywordList: + keyword: + - Vervoersnetwerken + - Menselijke gezondheid en veiligheid + - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai) + - Nationaal + - Voertuigen + - Verkeer + - Hectometerpunten + crs: + - namespace: EPSG + code: 28992 + - namespace: EPSG + code: 25831 + - namespace: EPSG + code: 25832 + - namespace: EPSG + code: 3034 + - namespace: EPSG + code: 3035 + - namespace: EPSG + code: 3857 + - namespace: EPSG + code: 4258 + - namespace: EPSG + code: 4326 + - namespace: CRS + code: 84 + exGeographicBoundingBox: + westBoundLongitude: 2.52713 + eastBoundLongitude: 7.37403 + southBoundLatitude: 50.2129 + northBoundLatitude: 55.7212 + boundingBox: + - crs: EPSG:28992 + minx: -25000 + miny: 250000 + maxx: 280000 + maxy: 860000 + - crs: EPSG:25831 + minx: -470271 + miny: 5.56231e+06 + maxx: 795163 + maxy: 6.18197e+06 + - crs: EPSG:25832 + minx: 62461.6 + miny: 5.56555e+06 + maxx: 397827 + maxy: 6.19042e+06 + - crs: EPSG:3034 + minx: 2.61336e+06 + miny: 3.509e+06 + maxx: 3.22007e+06 + maxy: 3.84003e+06 + - crs: EPSG:3035 + minx: 3.01676e+06 + miny: 3.81264e+06 + maxx: 3.64485e+06 + maxy: 4.15586e+06 + - crs: EPSG:3857 + minx: 281318 + miny: 6.48322e+06 + maxx: 820873 + maxy: 7.50311e+06 + - crs: EPSG:4258 + minx: 50.2129 + miny: 2.52713 + maxx: 55.7212 + maxy: 7.37403 + - crs: EPSG:4326 + minx: 50.2129 + miny: 2.52713 + maxx: 55.7212 + maxy: 7.37403 + - crs: CRS:84 + minx: 2.52713 + miny: 50.2129 + maxx: 7.37403 + maxy: 55.7212 + dimension: [] + attribution: null + authorityUrl: null + identifier: + authority: rws + value: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff + metadataUrl: + - type: TC211 + format: text/plain + onlineResource: + xlink: null + type: simple + href: https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id=a9b7026e-0a81-4813-93bd-ba49e6f28502 + dataUrl: null + featureListUrl: null + style: + - name: hectopunten + title: NWB - Hectopunten + abstract: null + legendUrl: + width: 78 + height: 20 + format: image/png + onlineResource: + xlink: null + type: simple + href: https://service.pdok.nl/rws/nwbwegen/wms/v1_0/legend/hectopunten/hectopunten.png + styleSheetUrl: null + minScaleDenominator: 1 + maxScaleDenominator: 50000 + layer: [] + optionalConstraints: {} ` ) @@ -116,6 +580,7 @@ func TestGetInputForWFS(t *testing.T) { }, Spec: pdoknlv3.WFSSpec{ Service: pdoknlv3.WFSService{ + URL: "/datasetOwner/dataset/theme/wfs/v1_0", Title: "some Service title", Abstract: "some \"Service\" abstract", Keywords: []string{"service-keyword-1", "service-keyword-2", "infoFeatureAccessService"}, @@ -201,3 +666,50 @@ func TestGetInputForWFS(t *testing.T) { }) } } + +func TestInputForWMS(t *testing.T) { + v2wmsstring := "apiVersion: pdok.nl/v2beta1\nkind: WMS\nmetadata:\n name: rws-nwbwegen-v1-0\n labels:\n dataset-owner: rws\n dataset: nwbwegen\n service-version: v1_0\n service-type: wms\n annotations:\n lifecycle-phase: prod\n service-bundle-id: b39c152b-393b-52f5-a50c-e1ffe904b6fb\nspec:\n general:\n datasetOwner: rws\n dataset: nwbwegen\n serviceVersion: v1_0\n kubernetes:\n healthCheck:\n boundingbox: 135134.89,457152.55,135416.03,457187.82\n resources:\n limits:\n ephemeralStorage: 1535Mi\n memory: 4G\n requests:\n cpu: 2000m\n ephemeralStorage: 1535Mi\n memory: 4G\n options:\n automaticCasing: true\n disableWebserviceProxy: false\n includeIngress: true\n validateRequests: true\n service:\n title: NWB - Wegen WMS\n abstract:\n Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen.\n Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen\n Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland.\n Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk,\n provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien\n van een straatnaam of nummer.\n authority:\n name: rws\n url: https://www.rijkswaterstaat.nl\n dataEPSG: EPSG:28992\n extent: -59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961\n inspire: true\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n - Hectometerpunten\n - HVD\n - Mobiliteit\n stylingAssets:\n configMapRefs:\n - name: includes\n keys:\n - nwb_wegen_hectopunten.symbol\n - hectopunten.style\n - wegvakken.style\n blobKeys:\n - resources/fonts/liberation-sans.ttf\n layers:\n - abstract:\n Deze laag bevat de wegvakken uit het Nationaal Wegen bestand (NWB)\n en geeft gedetailleerde informatie per wegvak zoals straatnaam, wegnummer,\n routenummer, wegbeheerder, huisnummers, enz. weer.\n data:\n gpkg:\n columns:\n - objectid\n - wvk_id\n - wvk_begdat\n - jte_id_beg\n - jte_id_end\n - wegbehsrt\n - wegnummer\n - wegdeelltr\n - hecto_lttr\n - bst_code\n - rpe_code\n - admrichtng\n - rijrichtng\n - stt_naam\n - stt_bron\n - wpsnaam\n - gme_id\n - gme_naam\n - hnrstrlnks\n - hnrstrrhts\n - e_hnr_lnks\n - e_hnr_rhts\n - l_hnr_lnks\n - l_hnr_rhts\n - begafstand\n - endafstand\n - beginkm\n - eindkm\n - pos_tv_wol\n - wegbehcode\n - wegbehnaam\n - distrcode\n - distrnaam\n - dienstcode\n - dienstnaam\n - wegtype\n - wgtype_oms\n - routeltr\n - routenr\n - routeltr2\n - routenr2\n - routeltr3\n - routenr3\n - routeltr4\n - routenr4\n - wegnr_aw\n - wegnr_hmp\n - geobron_id\n - geobron_nm\n - bronjaar\n - openlr\n - bag_orl\n - frc\n - fow\n - alt_naam\n - alt_nr\n - rel_hoogte\n - st_lengthshape\n geometryType: MultiLineString\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: wegvakken\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n maxScale: 50000.0\n minScale: 1.0\n name: wegvakken\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: wegvakken\n title: NWB - Wegvakken\n visualization: wegvakken.style\n title: Wegvakken\n visible: true\n - abstract:\n Deze laag bevat de hectopunten uit het Nationaal Wegen Bestand (NWB)\n en geeft gedetailleerde informatie per hectopunt zoals hectometrering, afstand,\n zijde en hectoletter weer.\n data:\n gpkg:\n columns:\n - objectid\n - hectomtrng\n - afstand\n - wvk_id\n - wvk_begdat\n - zijde\n - hecto_lttr\n geometryType: MultiPoint\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: hectopunten\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Hectometerpunten\n maxScale: 50000.0\n minScale: 1.0\n name: hectopunten\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: hectopunten\n title: NWB - Hectopunten\n visualization: hectopunten.style\n title: Hectopunten\n visible: true\n metadataIdentifier: f2437a92-ddd3-4777-a1bc-fdf4b4a7fcb8\n" + var v2wms v2beta1.WMS + err := yaml.Unmarshal([]byte(v2wmsstring), &v2wms) + assert.NoError(t, err) + var wms pdoknlv3.WMS + v2beta1.V3HubFromV2(&v2wms, &wms) + pdoknlv3.SetHost("http://localhost") + + contactPersonPrimary := smoothoperatorv1.ContactPersonPrimary{ + ContactPerson: asPtr("KlantContactCenter PDOK"), + ContactOrganization: asPtr("PDOK"), + } + + ownerInfo := smoothoperatorv1.OwnerInfo{ + Spec: smoothoperatorv1.OwnerInfoSpec{ + NamespaceTemplate: "http://{{prefix}}.geonovum.nl", + MetadataUrls: smoothoperatorv1.MetadataUrls{ + CSW: smoothoperatorv1.MetadataURL{ + HrefTemplate: "https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id={{identifier}}", + }, + }, + WMS: smoothoperatorv1.WMS{ + ContactInformation: &smoothoperatorv1.ContactInformation{ + ContactPersonPrimary: &contactPersonPrimary, + ContactPosition: asPtr("pointOfContact"), + ContactAddress: &smoothoperatorv1.ContactAddress{ + AddressType: asPtr("Work"), + Address: nil, + City: asPtr("Apeldoorn"), + StateOrProvince: nil, + PostCode: nil, + Country: asPtr("The Netherlands"), + }, + ContactVoiceTelephone: nil, + ContactFacsimileTelephone: nil, + ContactElectronicMailAddress: asPtr("BeheerPDOK@kadaster.nl"), + }, + }, + }, + } + + input, err := GetInput(&wms, &ownerInfo) + assert.NoError(t, err) + assert.Equal(t, WMSInput, input) +} diff --git a/internal/controller/capabilitiesgenerator/mapper.go b/internal/controller/capabilitiesgenerator/mapper.go index dc655ab..a2994ce 100644 --- a/internal/controller/capabilitiesgenerator/mapper.go +++ b/internal/controller/capabilitiesgenerator/mapper.go @@ -2,6 +2,7 @@ package capabilitiesgenerator import ( "fmt" + "github.com/pdok/ogc-specifications/pkg/wms130" "strconv" "strings" @@ -15,9 +16,10 @@ import ( ) const ( - inspireSchemaLocations = "http://inspire.ec.europa.eu/schemas/inspire_dls/1.0 http://inspire.ec.europa.eu/schemas/inspire_dls/1.0/inspire_dls.xsd" - capabilitiesFilename = "/var/www/config/capabilities_wfs_200.xml" - metadataMediaType = "application/vnd.ogc.csw.GetRecordByIdResponse_xml" + inspireSchemaLocations = "http://inspire.ec.europa.eu/schemas/inspire_dls/1.0 http://inspire.ec.europa.eu/schemas/inspire_dls/1.0/inspire_dls.xsd" + wfsCapabilitiesFilename = "/var/www/config/capabilities_wfs_200.xml" + wmsCapabilitiesFilename = "/var/www/config/capabilities_wms_130.xml" + metadataMediaType = "application/vnd.ogc.csw.GetRecordByIdResponse_xml" ) func MapWFSToCapabilitiesGeneratorInput(wfs *pdoknlv3.WFS, ownerInfo *smoothoperatorv1.OwnerInfo) (*capabilitiesgenerator.Config, error) { @@ -31,12 +33,12 @@ func MapWFSToCapabilitiesGeneratorInput(wfs *pdoknlv3.WFS, ownerInfo *smoothoper Namespace: mapperutils.GetNamespaceURI(wfs.Spec.Service.Prefix, ownerInfo), Prefix: wfs.Spec.Service.Prefix, Onlineresourceurl: pdoknlv3.GetHost(), - Path: mapperutils.GetPath(wfs), + Path: "/" + pdoknlv3.GetBaseURLPath(wfs), Version: *mapperutils.GetLabelValueByKey(wfs.ObjectMeta.Labels, "service-version"), }, Services: capabilitiesgenerator.Services{ WFS200Config: &capabilitiesgenerator.WFS200Config{ - Filename: capabilitiesFilename, + Filename: wfsCapabilitiesFilename, Wfs200: wfs200.GetCapabilitiesResponse{ ServiceProvider: mapServiceProvider(&ownerInfo.Spec.WFS.ServiceProvider), @@ -200,3 +202,448 @@ func mapServiceProvider(provider *smoothoperatorv1.ServiceProvider) (serviceProv return serviceProvider } + +func MapWMSToCapabilitiesGeneratorInput(wms *pdoknlv3.WMS, ownerInfo *smoothoperatorv1.OwnerInfo) (*capabilitiesgenerator.Config, error) { + hostBaseUrl := "https://service.pdok.nl" + canonicalServiceUrl := hostBaseUrl + "/" + pdoknlv3.GetBaseURLPath(wms) + + abstract := mapperutils.EscapeQuotes(wms.Spec.Service.Abstract) + var fees *string = nil + if wms.Spec.Service.Fees != nil { + feesPtr := mapperutils.EscapeQuotes(*wms.Spec.Service.Fees) + fees = &feesPtr + } else { + fees = asPtr("NONE") + } + + maxWidth := 4000 + maxHeight := 4000 + + accessContraints := wms.Spec.Service.AccessConstraints + if accessContraints == "" { + accessContraints = "https://creativecommons.org/publicdomain/zero/1.0/deed.nl" + } + + config := capabilitiesgenerator.Config{ + Global: capabilitiesgenerator.Global{ + Namespace: mapperutils.GetNamespaceURI("prefix", ownerInfo), + Prefix: "prefix", + Onlineresourceurl: pdoknlv3.GetHost(), + Path: "/" + pdoknlv3.GetBaseURLPath(wms), + Version: *mapperutils.GetLabelValueByKey(wms.ObjectMeta.Labels, "service-version"), + }, + Services: capabilitiesgenerator.Services{ + WMS130Config: &capabilitiesgenerator.WMS130Config{ + Filename: wmsCapabilitiesFilename, + Wms130: wms130.GetCapabilitiesResponse{ + WMSService: wms130.WMSService{ + Name: "WMS", + Title: mapperutils.EscapeQuotes(wms.Spec.Service.Title), + Abstract: &abstract, + KeywordList: &wms130.Keywords{Keyword: wms.Spec.Service.Keywords}, + OnlineResource: wms130.OnlineResource{Href: &hostBaseUrl}, + ContactInformation: getContactInformation(ownerInfo), + Fees: fees, + AccessConstraints: &accessContraints, + LayerLimit: nil, + MaxWidth: &maxWidth, + MaxHeight: &maxHeight, + }, + Capabilities: wms130.Capabilities{ + WMSCapabilities: wms130.WMSCapabilities{ + Request: wms130.Request{ + GetCapabilities: wms130.RequestType{ + Format: []string{"text/xml"}, + DCPType: getDcpType(canonicalServiceUrl, false), + }, + GetMap: wms130.RequestType{ + Format: []string{"image/png", "image/jpeg", "image/png; mode=8bit", "image/vnd.jpeg-png", "image/vnd.jpeg-png8"}, + DCPType: getDcpType(canonicalServiceUrl, true), + }, + GetFeatureInfo: &wms130.RequestType{ + Format: []string{"application/json", "application/json; subtype=geojson", "application/vnd.ogc.gml", "text/html", "text/plain", "text/xml", "text/xml; subtype=gml/3.1.1"}, + DCPType: getDcpType(canonicalServiceUrl, true), + }, + }, + Exception: wms130.ExceptionType{Format: []string{"XML", "BLANK"}}, + ExtendedCapabilities: nil, + Layer: getLayers(wms, canonicalServiceUrl), + }, + OptionalConstraints: wms130.OptionalConstraints{}, + }, + }, + }, + }, + } + + if wms.Spec.Service.Inspire != nil { + config.Global.AdditionalSchemaLocations = inspireSchemaLocations + metadataURL, _ := replaceMustachTemplate(ownerInfo.Spec.MetadataUrls.CSW.HrefTemplate, wms.Spec.Service.Inspire.ServiceMetadataURL.CSW.MetadataIdentifier) + + defaultLanguage := wms130.Language{Language: wms.Spec.Service.Inspire.Language} + + config.Services.WMS130Config.Wms130.Capabilities.ExtendedCapabilities = &wms130.ExtendedCapabilities{ + MetadataURL: wms130.ExtendedMetadataURL{URL: metadataURL, MediaType: metadataMediaType}, + SupportedLanguages: wms130.SupportedLanguages{ + DefaultLanguage: defaultLanguage, + SupportedLanguage: &[]wms130.Language{defaultLanguage}, + }, + ResponseLanguage: defaultLanguage, + } + } + + return &config, nil +} + +func getContactInformation(ownerInfo *smoothoperatorv1.OwnerInfo) *wms130.ContactInformation { + result := wms130.ContactInformation{ + ContactPersonPrimary: nil, + ContactPosition: nil, + ContactAddress: nil, + ContactVoiceTelephone: nil, + ContactFacsimileTelephone: nil, + ContactElectronicMailAddress: nil, + } + + providedContactInformation := ownerInfo.Spec.WMS.ContactInformation + + if providedContactInformation == nil { + return &result + } + + if providedContactInformation.ContactPersonPrimary != nil { + contactPerson := "" + if providedContactInformation.ContactPersonPrimary.ContactPerson != nil { + contactPerson = *providedContactInformation.ContactPersonPrimary.ContactPerson + } + contactOrganisation := "" + if providedContactInformation.ContactPersonPrimary.ContactOrganization != nil { + contactOrganisation = *providedContactInformation.ContactPersonPrimary.ContactOrganization + } + + contactPersonPrimary := wms130.ContactPersonPrimary{ + ContactPerson: contactPerson, + ContactOrganization: contactOrganisation, + } + result.ContactPersonPrimary = &contactPersonPrimary + } + + result.ContactPosition = providedContactInformation.ContactPosition + if providedContactInformation.ContactAddress != nil { + contactAddressInput := providedContactInformation.ContactAddress + contactAddress := wms130.ContactAddress{ + AddressType: pointerValOrDefault(contactAddressInput.AddressType, ""), + Address: pointerValOrDefault(contactAddressInput.Address, ""), + City: pointerValOrDefault(contactAddressInput.City, ""), + StateOrProvince: pointerValOrDefault(contactAddressInput.StateOrProvince, ""), + PostalCode: pointerValOrDefault(contactAddressInput.PostCode, ""), + Country: pointerValOrDefault(contactAddressInput.Country, ""), + } + result.ContactAddress = &contactAddress + } + + result.ContactVoiceTelephone = providedContactInformation.ContactVoiceTelephone + result.ContactFacsimileTelephone = providedContactInformation.ContactFacsimileTelephone + result.ContactElectronicMailAddress = providedContactInformation.ContactElectronicMailAddress + + return &result +} + +func getDcpType(url string, fillPost bool) *wms130.DCPType { + get := wms130.Method{ + OnlineResource: wms130.OnlineResource{ + Xlink: nil, + Type: nil, + Href: asPtr(url), + }, + } + + var post *wms130.Method = nil + if fillPost { + post = &get + } + + result := wms130.DCPType{ + HTTP: struct { + Get wms130.Method `xml:"Get" yaml:"get"` + Post *wms130.Method `xml:"Post" yaml:"post"` + }{ + Get: get, + Post: post, + }, + } + return &result +} + +func getLayers(wms *pdoknlv3.WMS, canonicalUrl string) []wms130.Layer { + result := make([]wms130.Layer, 0) + referenceLayer := wms.Spec.Service.Layer + title := referenceLayer.Title + if title != nil { + title = asPtr(mapperutils.EscapeQuotes(*referenceLayer.Title)) + } else { + title = asPtr("") + } + + defaultCrs := []wms130.CRS{{ + Namespace: "EPSG", + Code: 28992, + }, { + Namespace: "EPSG", + Code: 25831, + }, { + Namespace: "EPSG", + Code: 25832, + }, { + Namespace: "EPSG", + Code: 3034, + }, { + Namespace: "EPSG", + Code: 3035, + }, { + Namespace: "EPSG", + Code: 3857, + }, { + Namespace: "EPSG", + Code: 4258, + }, { + Namespace: "EPSG", + Code: 4326, + }, { + Namespace: "CRS", + Code: 84, + }} + + defaultBoundingBox := wms130.EXGeographicBoundingBox{ + WestBoundLongitude: 2.52713, + EastBoundLongitude: 7.37403, + SouthBoundLatitude: 50.2129, + NorthBoundLatitude: 55.7212, + } + + allDefaultBoundingBoxes := make([]*wms130.LayerBoundingBox, 0) + allDefaultBoundingBoxes = append(allDefaultBoundingBoxes, + &wms130.LayerBoundingBox{ + CRS: "EPSG:28992", + Minx: -25000, + Miny: 250000, + Maxx: 280000, + Maxy: 860000, + Resx: 0, + Resy: 0, + }, + &wms130.LayerBoundingBox{ + CRS: "EPSG:25831", + Minx: -470271, + Miny: 5.56231e+06, + Maxx: 795163, + Maxy: 6.18197e+06, + Resx: 0, + Resy: 0, + }, + &wms130.LayerBoundingBox{ + CRS: "EPSG:25832", + Minx: 62461.6, + Miny: 5.56555e+06, + Maxx: 397827, + Maxy: 6.19042e+06, + Resx: 0, + Resy: 0, + }, + &wms130.LayerBoundingBox{ + CRS: "EPSG:3034", + Minx: 2.61336e+06, + Miny: 3.509e+06, + Maxx: 3.22007e+06, + Maxy: 3.84003e+06, + Resx: 0, + Resy: 0, + }, + &wms130.LayerBoundingBox{ + CRS: "EPSG:3035", + Minx: 3.01676e+06, + Miny: 3.81264e+06, + Maxx: 3.64485e+06, + Maxy: 4.15586e+06, + Resx: 0, + Resy: 0, + }, + &wms130.LayerBoundingBox{ + CRS: "EPSG:3857", + Minx: 281318, + Miny: 6.48322e+06, + Maxx: 820873, + Maxy: 7.50311e+06, + Resx: 0, + Resy: 0, + }, + &wms130.LayerBoundingBox{ + CRS: "EPSG:4258", + Minx: 50.2129, + Miny: 2.52713, + Maxx: 55.7212, + Maxy: 7.37403, + Resx: 0, + Resy: 0, + }, + &wms130.LayerBoundingBox{ + CRS: "EPSG:4326", + Minx: 50.2129, + Miny: 2.52713, + Maxx: 55.7212, + Maxy: 7.37403, + Resx: 0, + Resy: 0, + }, + &wms130.LayerBoundingBox{ + CRS: "CRS:84", + Minx: 2.52713, + Miny: 50.2129, + Maxx: 7.37403, + Maxy: 55.7212, + Resx: 0, + Resy: 0, + }) + + var authorityUrl *wms130.AuthorityURL = nil + var identifier *wms130.Identifier = nil + + if referenceLayer.Authority != nil { + authorityUrl = &wms130.AuthorityURL{ + Name: referenceLayer.Authority.Name, + OnlineResource: wms130.OnlineResource{ + Xlink: nil, + Type: nil, + Href: &referenceLayer.Authority.URL, + }, + } + identifier = &wms130.Identifier{ + Authority: referenceLayer.Authority.Name, + Value: referenceLayer.Authority.SpatialDatasetIdentifier, + } + } + + topLayer := wms130.Layer{ + Queryable: asPtr(1), + Opaque: nil, + Name: nil, + Title: *title, + Abstract: asPtr(mapperutils.EscapeQuotes(wms.Spec.Service.Abstract)), + KeywordList: &wms130.Keywords{Keyword: referenceLayer.Keywords}, + CRS: defaultCrs, + EXGeographicBoundingBox: &defaultBoundingBox, + BoundingBox: allDefaultBoundingBoxes, + Dimension: nil, + Attribution: nil, + AuthorityURL: authorityUrl, + Identifier: identifier, + MetadataURL: nil, + DataURL: nil, + FeatureListURL: nil, + Style: nil, + MinScaleDenominator: nil, + MaxScaleDenominator: nil, + Layer: []*wms130.Layer{}, + } + + for _, layer := range *referenceLayer.Layers { + var minScaleDenom *float64 + var maxScaleDenom *float64 + var innerIdentifier *wms130.Identifier + metadataUrls := make([]*wms130.MetadataURL, 0) + + if layer.MinScaleDenominator != nil { + float, err := strconv.ParseFloat(*layer.MinScaleDenominator, 64) + if err == nil { + minScaleDenom = &float + } + } + + if layer.MaxScaleDenominator != nil { + float, err := strconv.ParseFloat(*layer.MaxScaleDenominator, 64) + if err == nil { + maxScaleDenom = &float + } + } + + if layer.DatasetMetadataURL != nil { + metadataUrls = append(metadataUrls, &wms130.MetadataURL{ + Type: asPtr("TC211"), + Format: asPtr("text/plain"), + OnlineResource: wms130.OnlineResource{ + Xlink: nil, + Type: asPtr("simple"), + Href: asPtr("https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id=" + layer.DatasetMetadataURL.CSW.MetadataIdentifier), + }, + }) + } + + if layer.Authority != nil { + innerIdentifier = &wms130.Identifier{ + Authority: layer.Authority.Name, + Value: layer.Authority.SpatialDatasetIdentifier, + } + } + + nestedLayer := wms130.Layer{ + Queryable: asPtr(1), + Opaque: nil, + Name: &layer.Name, + Title: pointerValOrDefault(layer.Title, ""), + Abstract: layer.Abstract, + KeywordList: &wms130.Keywords{ + Keyword: layer.Keywords, + }, + CRS: defaultCrs, + EXGeographicBoundingBox: &defaultBoundingBox, + BoundingBox: allDefaultBoundingBoxes, + Dimension: nil, + Attribution: nil, + AuthorityURL: authorityUrl, + Identifier: innerIdentifier, + MetadataURL: metadataUrls, + DataURL: nil, + FeatureListURL: nil, + Style: []*wms130.Style{}, + MinScaleDenominator: minScaleDenom, + MaxScaleDenominator: maxScaleDenom, + Layer: nil, + } + for _, style := range layer.Styles { + newStyle := wms130.Style{ + Name: style.Name, + Title: pointerValOrDefault(style.Title, ""), + Abstract: style.Abstract, + LegendURL: &wms130.LegendURL{ + Width: 78, + Height: 20, + Format: "image/png", + OnlineResource: wms130.OnlineResource{ + Xlink: nil, + Type: asPtr("simple"), + Href: asPtr(canonicalUrl + "/legend/" + layer.Name + "/" + layer.Name + ".png"), + }, + }, + StyleSheetURL: nil, + } + nestedLayer.Style = append(nestedLayer.Style, &newStyle) + } + + topLayer.Layer = append(topLayer.Layer, &nestedLayer) + } + + result = append(result, topLayer) + return result +} + +func pointerValOrDefault[T any](pointer *T, defaultValue T) T { + if pointer != nil { + return *pointer + } else { + return defaultValue + } +} + +func asPtr[T any](value T) *T { + return &value +}