Skip to content

Commit

Permalink
Merge pull request #28 from PDOK/PDOK-13218-validate-xsd
Browse files Browse the repository at this point in the history
Fixes for validation errors.
  • Loading branch information
RoelvandenBerg authored Sep 10, 2021
2 parents f943d74 + bf5fef3 commit 6b35d50
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 45 deletions.
12 changes: 6 additions & 6 deletions pkg/wfs200/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,12 @@ type FeatureTypeList struct {

// FeatureType struct for the WFS 2.0.0
type FeatureType struct {
Name string `xml:"Name" yaml:"name"`
Title string `xml:"Title" yaml:"title"`
Abstract string `xml:"Abstract" yaml:"abstract"`
Keywords *wsc110.Keywords `xml:"ows:Keywords" yaml:"keywords"`
DefaultCRS *wsc110.CRS `xml:"DefaultCRS" yaml:"defaultcrs"`
OtherCRS *[]wsc110.CRS `xml:"OtherCRS" yaml:"othercrs"`
Name string `xml:"Name" yaml:"name"`
Title string `xml:"Title" yaml:"title"`
Abstract string `xml:"Abstract" yaml:"abstract"`
Keywords *[]wsc110.Keywords `xml:"ows:Keywords" yaml:"keywords"`
DefaultCRS *CRS `xml:"DefaultCRS" yaml:"defaultcrs"`
OtherCRS *[]CRS `xml:"OtherCRS" yaml:"othercrs"`
OutputFormats struct {
Format []string `xml:"Format" yaml:"format"`
} `xml:"OutputFormats" yaml:"outputformats"`
Expand Down
44 changes: 44 additions & 0 deletions pkg/wfs200/crs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package wfs200

import (
"regexp"
"strconv"
)

//
const (
codeSpace = `urn:ogc:def:crs:EPSG:`
)

// CRS struct with namespace/authority/registry and code
type CRS struct {
Namespace string //TODO maybe AuthorityType is a better name...?
Code int
}

// String of the EPSGCode
func (c *CRS) String() string {
return c.Namespace + `:` + strconv.Itoa(c.Code)
}

// Identifier returns the EPSG
func (c *CRS) Identifier() string {
return codeSpace + strconv.Itoa(c.Code)
}

// ParseString build CRS struct from input string
func (c *CRS) ParseString(s string) {
c.parseString(s)
}

func (c *CRS) parseString(s string) {
regex := regexp.MustCompile(`(^.*):([0-9]+)`)
code := regex.FindStringSubmatch(s)
if len(code) == 3 { // code[0] is the full match, the other the parts
c.Namespace = codeSpace

// the regex already checks if it [0-9]
i, _ := strconv.Atoi(code[2])
c.Code = i
}
}
60 changes: 60 additions & 0 deletions pkg/wfs200/crs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package wfs200

import (
"testing"

"gopkg.in/yaml.v3"
)

func TestCRSParseString(t *testing.T) {
var tests = []struct {
input string
expectedCRS CRS
}{
0: {}, // Empty input == empty struct
1: {input: `urn:ogc:def:crs:EPSG::4326`, expectedCRS: CRS{Code: 4326, Namespace: `urn:ogc:def:crs:EPSG:`}},
2: {input: `EPSG:4326`, expectedCRS: CRS{Code: 4326, Namespace: `urn:ogc:def:crs:EPSG:`}},
}

for k, test := range tests {
var crs CRS
crs.parseString(test.input)

if crs.Code != test.expectedCRS.Code || crs.Namespace != test.expectedCRS.Namespace {
t.Errorf("test: %d, expected: %v,\n got: %v", k, test.expectedCRS, crs)
}
}
}

func TestUnmarshalYAMLCrs(t *testing.T) {

var stringYAML = `defaultcrs: urn:ogc:def:crs:EPSG::4326
othercrs:
- EPSG:4258
- urn:ogc:def:crs:EPSG::3857`

type FeatureType struct {
DefaultCRS CRS `yaml:"defaultcrs"`
OtherCRS []CRS `yaml:"othercrs"`
}

var tests = []struct {
yaml []byte
expectedcrs CRS
}{
0: {yaml: []byte(stringYAML), expectedcrs: CRS{Code: 4326, Namespace: codeSpace}},
1: {yaml: []byte(`defaultcrs: urn:ogc:def:crs:EPSG::4326`), expectedcrs: CRS{Code: 4326, Namespace: codeSpace}},
2: {yaml: []byte(`defaultcrs: EPSG:4326`), expectedcrs: CRS{Code: 4326, Namespace: codeSpace}},
}
for k, test := range tests {
var ftl FeatureType
err := yaml.Unmarshal(test.yaml, &ftl)
if err != nil {
t.Errorf("test: %d, yaml.UnMarshal failed with '%s'\n", k, err)
} else {
if ftl.DefaultCRS.Code != test.expectedcrs.Code || ftl.DefaultCRS.Namespace != test.expectedcrs.Namespace {
t.Errorf("test: %d, expected: %v+,\n got: %v+", k, test.expectedcrs, ftl.DefaultCRS)
}
}
}
}
36 changes: 36 additions & 0 deletions pkg/wfs200/crs_xml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package wfs200

import (
"encoding/xml"
"fmt"
)

// MarshalXML Position
func (c *CRS) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
var s = ``
if c.Namespace != `` {
s = fmt.Sprintf("%s:%d", c.Namespace, c.Code)
}

return e.EncodeElement(s, start)
}

// UnmarshalXML Position
func (c *CRS) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var crs CRS
for {
token, err := d.Token()
if err != nil {
return err
}
switch el := token.(type) {
case xml.CharData:
crs.parseString(string([]byte(el)))
case xml.EndElement:
if el == start.End() {
*c = crs
return nil
}
}
}
}
16 changes: 16 additions & 0 deletions pkg/wfs200/crs_yaml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package wfs200

// UnmarshalYAML CRS
func (c *CRS) UnmarshalYAML(unmarshal func(interface{}) error) error {
var s string
if err := unmarshal(&s); err != nil {
return err
}

var crs CRS
crs.parseString(s)

*c = crs

return nil
}
2 changes: 1 addition & 1 deletion pkg/wms130/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ func (c *Capabilities) GetLayer(layername string) (Layer, Exceptions) {
// RequestType containing the formats and DCPTypes available
type RequestType struct {
Format []string `xml:"Format" yaml:"format"`
DCPType DCPType `xml:"DCPType" yaml:"dcptype"`
DCPType *DCPType `xml:"DCPType" yaml:"dcptype"`
}

// Identifier in struct for repeatability
Expand Down
4 changes: 2 additions & 2 deletions pkg/wms130/getmap_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func BenchmarkGetMapValidate(b *testing.B) {
Request: Request{
GetMap: RequestType{
Format: []string{`image/jpeg`},
DCPType: DCPType{},
DCPType: &DCPType{},
},
},
Layer: []Layer{
Expand Down Expand Up @@ -251,7 +251,7 @@ func BenchmarkGetMapParseValidate(b *testing.B) {
Request: Request{
GetMap: RequestType{
Format: []string{`image/jpeg`},
DCPType: DCPType{},
DCPType: &DCPType{},
},
},
Layer: []Layer{
Expand Down
40 changes: 20 additions & 20 deletions pkg/wms130/getmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,18 +328,18 @@ func TestGetMapParseQueryParameters(t *testing.T) {
BGCOLOR: {`0x7F7F7F`},
},
exception: InvalidParameterValue(`zzzz`, TRANSPARENT),
},
},
//REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&LAYERS=Rivers,Roads,Houses&STYLES=CenterLine,CenterLine,Outline&CRS=EPSG:4326&BBOX=-180.0,-90.0,180.0,90.0&WIDTH=1024&HEIGHT=512&FORMAT=image/jpeg&EXCEPTIONS=XML
4: {query: map[string][]string{REQUEST: {getmap}, SERVICE: {Service}, VERSION: {Version},
LAYERS: {`Rivers,Roads,Houses`},
STYLES: {`CenterLine,CenterLine,Outline`},
"CRS": {`EPSG:4326`},
BBOX: {`-180.0,-90.0,180.0,90.0`},
WIDTH: {`1024`},
HEIGHT: {`512`},
FORMAT: {`image/jpeg`},
EXCEPTIONS: {`XML`},
BGCOLOR: {`0x7F7F7F`},
LAYERS: {`Rivers,Roads,Houses`},
STYLES: {`CenterLine,CenterLine,Outline`},
"CRS": {`EPSG:4326`},
BBOX: {`-180.0,-90.0,180.0,90.0`},
WIDTH: {`1024`},
HEIGHT: {`512`},
FORMAT: {`image/jpeg`},
EXCEPTIONS: {`XML`},
BGCOLOR: {`0x7F7F7F`},
},
excepted: GetMapRequest{
BaseRequest: BaseRequest{
Expand All @@ -365,15 +365,15 @@ func TestGetMapParseQueryParameters(t *testing.T) {
}},
//REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&LAYERS=Rivers&STYLES=&CRS=EPSG:4326&BBOX=-180.0,-90.0,180.0,90.0&WIDTH=1024&HEIGHT=512&FORMAT=image/jpeg&EXCEPTIONS=XML
5: {query: map[string][]string{REQUEST: {getmap}, SERVICE: {Service}, VERSION: {Version},
LAYERS: {`Rivers`},
STYLES: {``},
"CRS": {`EPSG:4326`},
BBOX: {`-180.0,-90.0,180.0,90.0`},
WIDTH: {`1024`},
HEIGHT: {`512`},
FORMAT: {`image/jpeg`},
EXCEPTIONS: {`XML`},
BGCOLOR: {`0x7F7F7F`},
LAYERS: {`Rivers`},
STYLES: {``},
"CRS": {`EPSG:4326`},
BBOX: {`-180.0,-90.0,180.0,90.0`},
WIDTH: {`1024`},
HEIGHT: {`512`},
FORMAT: {`image/jpeg`},
EXCEPTIONS: {`XML`},
BGCOLOR: {`0x7F7F7F`},
},
excepted: GetMapRequest{
BaseRequest: BaseRequest{
Expand Down Expand Up @@ -666,7 +666,7 @@ func TestGetMapValidate(t *testing.T) {
Request: Request{
GetMap: RequestType{
Format: []string{`image/jpeg`},
DCPType: DCPType{},
DCPType: &DCPType{},
},
},
Layer: []Layer{
Expand Down
4 changes: 2 additions & 2 deletions pkg/wmts100/capabilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ var contentsWithLegend = Contents{

func TestBuildStyleWithLegend(t *testing.T) {
expected := `<Style isDefault="true">
<ows:Identifier>default</ows:Identifier>
<ows:Title>default</ows:Title>
<ows:Identifier>default</ows:Identifier>
<LegendURL format="image/png" xlink:href="http://www.maps.bob/etopo2/legend.png"></LegendURL>
</Style>`
output, _ := xml.MarshalIndent(contentsWithLegend.Layer[0].Style, "", " ")
Expand Down Expand Up @@ -91,8 +91,8 @@ var contentsWithoutLegend = Contents{

func TestBuildStyleWithoutLegend(t *testing.T) {
expected := `<Style isDefault="true">
<ows:Identifier>default</ows:Identifier>
<ows:Title>default</ows:Title>
<ows:Identifier>default</ows:Identifier>
</Style>`
output, _ := xml.MarshalIndent(contentsWithoutLegend.Layer[0].Style, "", " ")
if string(output) != expected {
Expand Down
24 changes: 12 additions & 12 deletions pkg/wmts100/getcapabilities_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ func (gc GetCapabilitiesResponse) ToXML() []byte {
type GetCapabilitiesResponse struct {
XMLName xml.Name `xml:"Capabilities"`
Namespaces `yaml:"namespaces"`
ServiceIdentification ServiceIdentification `xml:"ows:ServiceIdentification" yaml:"serviceidentification"`
ServiceProvider wsc110.ServiceProvider `xml:"ows:ServiceProvider,omitempty" yaml:"serviceprovider"`
OperationsMetadata *OperationsMetadata `xml:"ows:OperationsMetadata,omitempty" yaml:"operationsmetadata"`
Contents Contents `xml:"Contents" yaml:"contents"`
ServiceMetadataURL *ServiceMetadataURL `xml:"ServiceMetadataURL,omitempty" yaml:"servicemetadataurl"`
ServiceIdentification ServiceIdentification `xml:"ows:ServiceIdentification" yaml:"serviceidentification"`
ServiceProvider *wsc110.ServiceProvider `xml:"ows:ServiceProvider,omitempty" yaml:"serviceprovider"`
OperationsMetadata *OperationsMetadata `xml:"ows:OperationsMetadata,omitempty" yaml:"operationsmetadata"`
Contents Contents `xml:"Contents" yaml:"contents"`
ServiceMetadataURL *ServiceMetadataURL `xml:"ServiceMetadataURL,omitempty" yaml:"servicemetadataurl"`
}

// Namespaces struct containing the namespaces needed for the XML document
Expand Down Expand Up @@ -97,13 +97,13 @@ type Method struct {

// ServiceIdentification struct should only be fill by the "template" configuration wmts100.yaml
type ServiceIdentification struct {
Title string `xml:"ows:Title" yaml:"title"`
Abstract string `xml:"ows:Abstract" yaml:"abstract"`
Keywords wsc110.Keywords `xml:"ows:Keywords,omitempty" yaml:"keywords"`
ServiceType string `xml:"ows:ServiceType" yaml:"servicetype"`
ServiceTypeVersion string `xml:"ows:ServiceTypeVersion" yaml:"servicetypeversion"`
Fees string `xml:"ows:Fees" yaml:"fees"`
AccessConstraints string `xml:"ows:AccessConstraints" yaml:"accessconstraints"`
Title string `xml:"ows:Title" yaml:"title"`
Abstract string `xml:"ows:Abstract" yaml:"abstract"`
Keywords *wsc110.Keywords `xml:"ows:Keywords,omitempty" yaml:"keywords"`
ServiceType string `xml:"ows:ServiceType" yaml:"servicetype"`
ServiceTypeVersion string `xml:"ows:ServiceTypeVersion" yaml:"servicetypeversion"`
Fees string `xml:"ows:Fees" yaml:"fees"`
AccessConstraints string `xml:"ows:AccessConstraints" yaml:"accessconstraints"`
}

// ServiceMetadataURL in struct for repeatability
Expand Down
7 changes: 5 additions & 2 deletions pkg/wsc110/keywords.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package wsc110

// Keywords in struct for repeatability
type Keywords struct {
Keyword []string `xml:"ows:Keyword" yaml:"keyword"`
Type string `xml:"ows:Type,omitempty" yaml:"type"`
Keyword []string `xml:"ows:Keyword"`
Type *struct {
Text string `xml:",chardata"`
CodeSpace *string `xml:"codeSpace,attr,omitempty"`
} `xml:"ows:Type"`
}

0 comments on commit 6b35d50

Please sign in to comment.