Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #46 from PDOK/code-cleanup
Browse files Browse the repository at this point in the history
Code cleanup
  • Loading branch information
arbakker authored Jun 29, 2021
2 parents 2120400 + 99a9681 commit 532ca5f
Show file tree
Hide file tree
Showing 48 changed files with 764 additions and 1,195 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ A a GeoJSON implementation with a Geopackage as a data provider.

The specification is a preliminary one, with `go generate` the routing based on api spec, provider interfaces en types structs and convenient parameter extractions are generated to stay easily up to date.

* FeatureCollectionGeoJSON is overridden in the GeoPackage provider to use the [GeoJSON](https://github.com/go-spatial/geom/tree/master/encoding/geojson) equivalent for decoding blobs
* FeatureCollection is overridden in the GeoPackage provider to use the [GeoJSON](https://github.com/go-spatial/geom/tree/master/encoding/geojson) equivalent for decoding blobs
* <https://github.com/opengeospatial/ogcapi-features/blob/master/core/openapi/ogcapi-features-1.yaml>

## Build
Expand Down
53 changes: 53 additions & 0 deletions core/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package core

import (
"net/http"
"oaf-server/codegen"

"github.com/getkin/kin-openapi/openapi3"
)

// GetApiProvider is returned by the NewGetApiProvider
// containing the data and contenttype for the response
type GetApiProvider struct {
data *openapi3.T
contenttype string
}

// NewGetApiProvider handles the request and return the GetApiProvider
func NewGetApiProvider(api *openapi3.T) func(r *http.Request) (codegen.Provider, error) {

return func(r *http.Request) (codegen.Provider, error) {
p := &GetApiProvider{}

ct, err := GetContentType(r, p.String())
if err != nil {
return nil, err
}

p.contenttype = ct
p.data = api

return p, nil
}
}

// Provide provides the data
func (gap *GetApiProvider) Provide() (interface{}, error) {
return gap.data, nil
}

// ContentType returns the ContentType
func (gap *GetApiProvider) ContentType() string {
return gap.contenttype
}

// String returns the provider name
func (gap *GetApiProvider) String() string {
return "api"
}

// SrsId returns the srsid
func (gap *GetApiProvider) SrsId() string {
return "n.a"
}
90 changes: 90 additions & 0 deletions core/collection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package core

import (
"fmt"
"net/http"
"oaf-server/codegen"
)

// DescribeCollectionProvider is returned by the NewDescribeCollectionProvider
// containing the data and contenttype for the response
type DescribeCollectionProvider struct {
data codegen.Collection
contenttype string
}

// NewDescribeCollectionProvider handles the request and return the DescribeCollectionProvider
func NewDescribeCollectionProvider(config Config) func(r *http.Request) (codegen.Provider, error) {

return func(r *http.Request) (codegen.Provider, error) {
path := r.URL.Path // collections/{{collectionId}}

collectionId, _ := codegen.ParametersForDescribeCollection(r)

p := &DescribeCollectionProvider{}

ct, err := GetContentType(r, p.String())
if err != nil {
return nil, err
}
p.contenttype = ct

for _, cn := range config.Datasource.Collections {
// maybe convert to map, but not thread safe!
if cn.Identifier != collectionId {
continue
}

cInfo := codegen.Collection{
Id: cn.Identifier,
Title: cn.Identifier,
Description: cn.Description,
Crs: []string{config.Crs[fmt.Sprintf("%d", cn.Srid)]},
Links: []codegen.Link{},
}

// create links
hrefBase := fmt.Sprintf("%s%s", config.Service.Url, path) // /collections
links, _ := CreateLinks(collectionId, p.String(), hrefBase, "self", ct)

cihrefBase := fmt.Sprintf("%s/items", hrefBase)
ilinks, _ := CreateLinks("items of "+collectionId, p.String(), cihrefBase, "item", ct)
cInfo.Links = append(links, ilinks...)

for _, c := range config.Datasource.Collections {
if c.Identifier == cn.Identifier {
if len(c.Links) != 0 {
cInfo.Links = append(cInfo.Links, c.Links...)
}
break
}
}

p.data = cInfo
break
}

return p, nil
}

}

// Provide returns the srsid
func (dcp *DescribeCollectionProvider) Provide() (interface{}, error) {
return dcp.data, nil
}

// ContentType returns the srsid
func (dcp *DescribeCollectionProvider) ContentType() string {
return dcp.contenttype
}

// SrsStringId returns the provider name
func (dcp *DescribeCollectionProvider) String() string {
return "collection"
}

// SrsId returns the srsid
func (dcp *DescribeCollectionProvider) SrsId() string {
return "n.a."
}
96 changes: 96 additions & 0 deletions core/collections.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package core

import (
"fmt"
"net/http"
"oaf-server/codegen"
)

// GetCollectionsProvider is returned by the NewGetCollectionsProvider
// containing the data and contenttype for the response
type GetCollectionsProvider struct {
data codegen.Collections
contenttype string
}

// NewGetCollectionsProvider handles the request and return the GetCollectionsProvider
func NewGetCollectionsProvider(config Config) func(r *http.Request) (codegen.Provider, error) {

return func(r *http.Request) (codegen.Provider, error) {
path := r.URL.Path // collections

p := &GetCollectionsProvider{}

ct, err := GetContentType(r, p.String())
if err != nil {
return nil, err
}

p.contenttype = ct

csInfo := codegen.Collections{Links: []codegen.Link{}, Collections: []codegen.Collection{}}
// create Links
hrefBase := fmt.Sprintf("%s%s", config.Service.Url, path) // /collections
links, _ := CreateLinks("collections ", p.String(), hrefBase, "self", ct)
csInfo.Links = append(csInfo.Links, links...)
for _, cn := range config.Datasource.Collections {
clinks, _ := CreateLinks("collection "+cn.Identifier, p.String(), fmt.Sprintf("%s/%s", hrefBase, cn.Identifier), "item", ct)
csInfo.Links = append(csInfo.Links, clinks...)
}

for _, cn := range config.Datasource.Collections {

cInfo := codegen.Collection{
Id: cn.Identifier,
Title: cn.Identifier,
Description: cn.Description,
Crs: []string{config.Crs[fmt.Sprintf("%d", cn.Srid)]},
Links: []codegen.Link{},
}

chrefBase := fmt.Sprintf("%s/%s", hrefBase, cn.Identifier)

clinks, _ := CreateLinks("collection "+cn.Identifier, p.String(), chrefBase, "self", ct)
cInfo.Links = append(cInfo.Links, clinks...)

cihrefBase := fmt.Sprintf("%s/items", chrefBase)
ilinks, _ := CreateLinks("items "+cn.Identifier, p.String(), cihrefBase, "item", ct)
cInfo.Links = append(cInfo.Links, ilinks...)

for _, c := range config.Datasource.Collections {
if c.Identifier == cn.Identifier {
if len(c.Links) != 0 {
cInfo.Links = append(cInfo.Links, c.Links...)
}
break
}
}

csInfo.Collections = append(csInfo.Collections, cInfo)
}

p.data = csInfo

return p, nil
}
}

// Provide provides the data
func (gcp *GetCollectionsProvider) Provide() (interface{}, error) {
return gcp.data, nil
}

// ContentType returns the ContentType
func (gcp *GetCollectionsProvider) ContentType() string {
return gcp.contenttype
}

// String returns the provider name
func (gcp *GetCollectionsProvider) String() string {
return "collections"
}

// SrsId returns the srsid
func (gcp *GetCollectionsProvider) SrsId() string {
return "n.a."
}
29 changes: 24 additions & 5 deletions provider/config.go → core/config.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
package provider
package core

import (
"io/ioutil"
"log"
"oaf-server/codegen"

"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
)

// Config wrappes all the available configuration
type Config struct {
ApplicationId string `yaml:"applicationid,omitempty"`
UserVersion string `yaml:"userversion,omitempty"`

Openapi string `yaml:"openapi"`
DefaultFeatureLimit int `yaml:"defaultfeaturelimit"`
MaxFeatureLimit int `yaml:"maxfeaturelimit"`
Openapi string `yaml:"openapi"`
DefaultFeatureLimit int `yaml:"defaultfeaturelimit"`
MaxFeatureLimit int `yaml:"maxfeaturelimit"`
Crs map[string]string `yaml:"crs"`
Datasource Datasource
Service Service `yaml:"service" json:"service"`
}

// ContactPoint needed for the ld+json
type ContactPoint struct {
Type string `yaml:"@type" json:"@type,omitempty"`
Email string `yaml:"email" json:"email,omitempty"`
Expand All @@ -27,6 +30,8 @@ type ContactPoint struct {
ContactType string `yaml:"contactType" json:"contactType,omitempty"`
Description string `yaml:"description" json:"description,omitempty"`
}

// Address needed for the ld+json
type Address struct {
Type string `yaml:"@type" json:"@type,omitempty"`
StreetAddress string `yaml:"streetAddress" json:"streetAddress,omitempty"`
Expand All @@ -36,6 +41,7 @@ type Address struct {
AddressCountry string `yaml:"addressCountry" json:"addressCountry,omitempty"`
}

// Provider needed for the ld+json
type Provider struct {
Type string `yaml:"@type" json:"@type"`
Name string `yaml:"name" json:"name"`
Expand All @@ -44,6 +50,7 @@ type Provider struct {
ContactPoint *ContactPoint `yaml:"contactPoint" json:"contactPoint,omitempty"` // pointer, omitting when empty
}

// Service contains the necessary information for building the right ld+json objects
type Service struct {
Context string `yaml:"@context" json:"@context"`
Type string `yaml:"@type" json:"@type"`
Expand All @@ -57,6 +64,7 @@ type Service struct {
Provider Provider `yaml:"provider" json:"provider"`
}

// Datasource wrappes the datasources, collections, dataset boundingbox and SRID
type Datasource struct {
Geopackage *Geopackage `yaml:"gpkg"`
PostGIS *PostGIS `yaml:"postgis"`
Expand All @@ -65,15 +73,18 @@ type Datasource struct {
Srid int `yaml:"srid"`
}

// Geopackage contains the Geopackage file locations and a alternative Fid column
type Geopackage struct {
File string `yaml:"file"`
Fid string `yaml:"fid"`
}

// PostGIS contains the PostGIS connection string
type PostGIS struct {
Connection string `yaml:"connection"`
}

// Collection contains all the needed information for a collections
type Collection struct {
Schemaname string `yaml:"schemaname"`
Tablename string `yaml:"tablename"`
Expand All @@ -92,13 +103,15 @@ type Collection struct {
Links []codegen.Link `yaml:"links"`
}

// Columns stores the Fid, Offset, BoundingBox and Geometry columns from the datasources
type Columns struct {
Fid string `yaml:"fid"`
Offset string `yaml:"offset"`
BBox string `yaml:"bbox"`
Geometry string `yaml:"geometry"`
}

// NewService initializes a Service
func NewService() Service {
address := Address{
Type: "PostalAddress",
Expand All @@ -119,6 +132,7 @@ func NewService() Service {
return service
}

// ReadConfig reads the from the given path the configuration
func (c *Config) ReadConfig(path string) {
bytes, err := ioutil.ReadFile(path)
if err != nil {
Expand Down Expand Up @@ -153,6 +167,11 @@ func (c *Config) ReadConfig(path string) {
c.MaxFeatureLimit = 500
}

if len(c.Crs) == 0 {
crs := map[string]string{`4326`: `http://www.opengis.net/def/crs/EPSG/0/4326`}
c.Crs = crs
}

if c.Openapi == "" {
c.Openapi = "spec/oaf.json"
}
Expand Down
Loading

0 comments on commit 532ca5f

Please sign in to comment.