# HG changeset patch # User Sascha L. Teichmann # Date 1546177186 -3600 # Node ID 6caf5cd6249e5900e014cb5476791e4490212702 # Parent 774174d09d30bfa68e59c91e494b51219e3d6560 WFS: Made golint happy. diff -r 774174d09d30 -r 6caf5cd6249e pkg/scheduler/scheduler.go --- a/pkg/scheduler/scheduler.go Sun Dec 30 13:23:10 2018 +0100 +++ b/pkg/scheduler/scheduler.go Sun Dec 30 14:39:46 2018 +0100 @@ -129,7 +129,7 @@ global.unbindByID(cfgID) } -// UnbindUser unbinds all schedules for a given user. +// UnbindByIDs unbinds all schedules for a given user. func UnbindByIDs(ids map[int64]struct{}) { global.unbindByIDs(ids) } diff -r 774174d09d30 -r 6caf5cd6249e pkg/wfs/capabilities.go --- a/pkg/wfs/capabilities.go Sun Dec 30 13:23:10 2018 +0100 +++ b/pkg/wfs/capabilities.go Sun Dec 30 14:39:46 2018 +0100 @@ -23,15 +23,19 @@ "golang.org/x/net/html/charset" ) +// Keyword stores a value. type Keyword struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 Keyword"` Value string `xml:",cdata"` } + +// Keywords stores a list of keywords. type Keywords struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 Keywords"` Keywords []Keyword `xml:"Keyword"` } +// ServiceIdentification contains meta informations about a WFS. type ServiceIdentification struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 ServiceIdentification"` Title string @@ -41,48 +45,58 @@ ServiceTypeVersion string } +// Get stores the link to the GET method type Get struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 Get"` HRef string `xml:"http://www.w3.org/1999/xlink href,attr"` } +// Post stores the link to the POST method. type Post struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 Post"` HRef string `xml:"http://www.w3.org/1999/xlink href,attr"` } +// HTTP is a container for HTTP methods. type HTTP struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 HTTP"` Get *Get `xml:"Get"` Post *Post `xml:"Post"` } +// DCP wraps the HTTP container. type DCP struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 DCP"` HTTP HTTP `xml:"HTTP"` } +// Value is a simple string value. type Value struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 Value"` Value string `xml:",cdata"` } +// AllowedValues is list positive list of values. type AllowedValues struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 AllowedValues"` Values []Value `xml:"Value"` } +// Parameter is a named parameter with a list of allowed values. type Parameter struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 Parameter"` Name string `xml:"name,attr"` AllowedValues AllowedValues `xml:"AllowedValues"` } +// DefaultValue is the default value of a constraint. type DefaultValue struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 DefaultValue"` Value string `xml:",cdata"` } +// Constraint is a named constraint with a list of allowed values +// and a default value. type Constraint struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 Constraint"` Name string `xml:"name,attr"` @@ -90,6 +104,7 @@ DefaultValue *DefaultValue `xml:"DefaultValue"` } +// Operation contains informations of a WFS operation. type Operation struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 Operation"` Name string `xml:"name,attr"` @@ -98,18 +113,21 @@ Constraints []*Constraint `xml:"Constraint"` } +// OperationsMetadata is list of operations and constraints. type OperationsMetadata struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 OperationsMetadata"` Operations []*Operation `xml:"Operation"` Constraints []*Constraint `xml:"Constraint"` } +// WGS84BoundingBox is a bounding box feature type in WGS84. type WGS84BoundingBox struct { XMLName xml.Name `xml:"http://www.opengis.net/ows/1.1 WGS84BoundingBox"` LowerCorner string `xml:"LowerCorner"` UpperCorner string `xml:"UpperCorner"` } +// FeatureType is layer served by the WFS: type FeatureType struct { XMLName xml.Name `xml:"http://www.opengis.net/wfs/2.0 FeatureType"` Name string `xml:"Name"` @@ -135,6 +153,7 @@ Namespaces []xml.Name `xml:"-"` } +// UnmarshalXML implements xml.Unmarshaler for better namespace handling. func (ft *FeatureType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { // Filter out the namespaces for this feature type. var ns []xml.Name @@ -152,11 +171,13 @@ return nil } +// FeatureTypeList is the list of layers served by the WFS. type FeatureTypeList struct { XMLName xml.Name `xml:"http://www.opengis.net/wfs/2.0 FeatureTypeList"` FeatureTypes []*FeatureType `xml:"FeatureType"` } +// Capabilities is the top level metadata struct. type Capabilities struct { XMLName xml.Name `xml:"http://www.opengis.net/wfs/2.0 WFS_Capabilities"` @@ -167,6 +188,8 @@ FeatureTypeList FeatureTypeList } +// FindOperation searches the capabilities for a specifc operation. +// Returns nil if not found. func (c *Capabilities) FindOperation(name string) *Operation { for _, op := range c.OperationsMetadata.Operations { if op.Name == name { @@ -176,8 +199,9 @@ return nil } -func (o *Operation) SupportsHits() bool { - for _, p := range o.Parameters { +// SupportsHits checks if a operation supports the hits request. +func (op *Operation) SupportsHits() bool { + for _, p := range op.Parameters { if p.Name == "resultType" { for _, av := range p.AllowedValues.Values { if av.Value == "hits" { @@ -189,8 +213,9 @@ return false } -func (o *Operation) SupportsOutputFormat(formats ...string) bool { - for _, p := range o.Parameters { +// SupportsOutputFormat checks if one of the given formats is supported. +func (op *Operation) SupportsOutputFormat(formats ...string) bool { + for _, p := range op.Parameters { if p.Name == "outputFormat" { for _, av := range p.AllowedValues.Values { for _, f := range formats { @@ -204,8 +229,10 @@ return false } -func (o *Operation) FeaturesPerPage() (int, bool) { - for _, c := range o.Constraints { +// FeaturesPerPage returns the number of features per page. +// Returns if paging is not supported by the operation. +func (op *Operation) FeaturesPerPage() (int, bool) { + for _, c := range op.Constraints { if c.Name == "CountDefault" { if c.DefaultValue != nil { if v, err := strconv.Atoi(c.DefaultValue.Value); err == nil { @@ -223,6 +250,8 @@ return 0, false } +// FindFeatureType searches the layers for a given name. +// Returns nil if not found. func (c *Capabilities) FindFeatureType(name string) *FeatureType { for _, ft := range c.FeatureTypeList.FeatureTypes { if ft.Name == name { @@ -232,6 +261,8 @@ return nil } +// FindParameter searches for named parameter. Returns nil +// if not found. func (op *Operation) FindParameter(name string) *Parameter { for _, p := range op.Parameters { if p.Name == name { @@ -241,7 +272,8 @@ return nil } -const WFS2_0_0 = "2.0.0" +// WFS200 is dotted version string of version 2.0.0. +const WFS200 = "2.0.0" var versionRe = regexp.MustCompile(`(\d+)\.(\d+)\.(\d+)`) @@ -295,6 +327,8 @@ return a } +// HighestWFSVersion figures out the highest supported WFS version. +// Defaults to def. func (c *Capabilities) HighestWFSVersion(def string) string { op := c.FindOperation("GetCapabilities") if op == nil { @@ -317,10 +351,12 @@ } var ( + // ErrInvalidCRS is returned if a given string is not valid CRS URN. ErrInvalidCRS = errors.New("Invalid CRS string") crsRe = regexp.MustCompile(`urn:ogc:def:crs:EPSG:[^:]*:(\d+)`) ) +// CRSToEPSG extracts the EPSG code from a given CRS URN string. func CRSToEPSG(s string) (int, error) { m := crsRe.FindStringSubmatch(s) if m == nil { @@ -329,6 +365,7 @@ return strconv.Atoi(m[1]) } +// ParseCapabilities constructs a capabilities document from an io.Reader. func ParseCapabilities(r io.Reader) (*Capabilities, error) { decoder := xml.NewDecoder(r) diff -r 774174d09d30 -r 6caf5cd6249e pkg/wfs/download.go --- a/pkg/wfs/download.go Sun Dec 30 13:23:10 2018 +0100 +++ b/pkg/wfs/download.go Sun Dec 30 14:39:46 2018 +0100 @@ -1,4 +1,4 @@ -// This is Free Software under GNU Affero General Public License v >= 3.0 +// This is Free Software under GNU Affero General Public License v >= 3.0.Reader. // without warranty, see README.md and license for details. // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -28,13 +28,20 @@ ) var ( - ErrNoSuchFeatureType = errors.New("No such feature type") - ErrGetFeatureNotSupported = errors.New("GetFeature not supported") - ErrMethodGetNotSupported = errors.New("GET not supported") - ErrNoNumberMatchedFound = errors.New("No numberMatched attribute found") + // ErrNoSuchFeatureType is returned when a feature is not supported. + ErrNoSuchFeatureType = errors.New("No such feature type") + // ErrGetFeatureNotSupported is returned when GetFeature is not supported. + ErrGetFeatureNotSupported = errors.New("GetFeature not supported") + // ErrMethodGetNotSupported is returned when the GET is not supported. + ErrMethodGetNotSupported = errors.New("GET not supported") + // ErrNoNumberMatchedFound is returned if feature count cannot be extracted. + ErrNoNumberMatchedFound = errors.New("No numberMatched attribute found") + // ErrOutputFormatNotSupported is returned if a output format is + // not supported. ErrOutputFormatNotSupported = errors.New("Output format not supported") ) +// GetCapabilities downloads a capabilities document for a given URL. func GetCapabilities(capURL string) (*Capabilities, error) { base, err := url.Parse(capURL) @@ -95,6 +102,8 @@ return *result.NumberMatched, nil } +// GetFeaturesGET constructs a list of URLs to get features +// for a given feature type from a WFS servers. func GetFeaturesGET( caps *Capabilities, featureTypeName, @@ -133,7 +142,7 @@ return nil, ErrOutputFormatNotSupported } - wfsVersion := caps.HighestWFSVersion(WFS2_0_0) + wfsVersion := caps.HighestWFSVersion(WFS200) featuresPerPage, supportsPaging := op.FeaturesPerPage() @@ -157,7 +166,7 @@ } var downloadURLs []string - wfs2 := !versionIsLess(wfsVersion, WFS2_0_0) + wfs2 := !versionIsLess(wfsVersion, WFS200) addNS := func(v url.Values) { if len(feature.Namespaces) == 0 { @@ -250,6 +259,8 @@ return handler(resp.Body) } +// DownloadURLs does the actual GetFeature requests downloads +// and hands the resulting io.Readers over to the given handler. func DownloadURLs(urls []string, handler func(io.Reader) error) error { for _, url := range urls { if err := downloadURL(url, handler); err != nil { diff -r 774174d09d30 -r 6caf5cd6249e pkg/wfs/rawfeaturecollection.go --- a/pkg/wfs/rawfeaturecollection.go Sun Dec 30 13:23:10 2018 +0100 +++ b/pkg/wfs/rawfeaturecollection.go Sun Dec 30 14:39:46 2018 +0100 @@ -18,6 +18,8 @@ "io" ) +// RawFeatureCollection is a template for a feature collection +// returned by a WFS server. type RawFeatureCollection struct { CRS *struct { Properties struct { @@ -33,6 +35,7 @@ } `json:"features"` } +// ParseRawFeatureCollection turns a io.Reader into raw feature collection. func ParseRawFeatureCollection(r io.Reader) (*RawFeatureCollection, error) { rfc := new(RawFeatureCollection) if err := json.NewDecoder(r).Decode(rfc); err != nil {