packages feed

hydra-0.15.0: src/main/haskell/Hydra/Sources/Other/GeoJson.hs

module Hydra.Sources.Other.GeoJson where

-- Standard imports for type-level sources outside of the kernel
import           Hydra.Kernel
import           Hydra.Dsl.Annotations
import           Hydra.Dsl.Bootstrap
import           Hydra.Dsl.Types                 ((>:))
import qualified Hydra.Dsl.Types                 as T
import qualified Hydra.Sources.Kernel.Types.Core as Core
import qualified Data.List                       as L
import qualified Data.Map                        as M
import qualified Data.Set                        as S
import qualified Data.Maybe                      as Y

-- Additional imports
import qualified Hydra.Sources.Json.Model        as JsonModel


ns :: Namespace
ns = Namespace "hydra.geojson.model"

define :: String -> Type -> Binding
define = defineType ns

geoj :: String -> Type
geoj = typeref ns

json :: String -> Type
json = typeref $ JsonModel.ns

module_ :: Module
module_ = Module {
            moduleNamespace = ns,
            moduleDefinitions = (map toTypeDef definitions),
            moduleTermDependencies = [JsonModel.ns],
            moduleTypeDependencies = [],
            moduleDescription = Just ("A GeoJSON model based on the specification at https://www.rfc-editor.org/rfc/rfc7946. " ++
          "This model provides some additional structure beyond the JSON encoding described in the specification; " ++
          "For example, it provides MultiPoint not as an object with an array of coordinates which encode points, " ++
          "but as an array of Points. A BoundingBox is not simply an list of numbers, but a list of CoordinateRanges.")}
  where
    definitions = [
      boundingBox,
      coordinateRange,
      feature,
      featureCollection,
      geometryCollection,
      geometry,
      id_,
      lineString,
      multiLineString,
      multiPoint,
      multiPolygon,
      object_,
      point,
      polygon,
      position]

boundingBox :: Binding
boundingBox = define "BoundingBox" $
  doc ("A GeoJSON object MAY have a member named \"bbox\" to include " ++
       "information on the coordinate range for its Geometries, Features, or " ++
       "FeatureCollections.  The value of the bbox member MUST be an array of " ++
       "length 2*n where n is the number of dimensions represented in the " ++
       "contained geometries, with all axes of the most southwesterly point " ++
       "followed by all axes of the more northeasterly point.  The axes order " ++
       "of a bbox follows the axes order of geometries.") $
  T.wrap $ T.list $ geoj "CoordinateRange"

coordinateRange :: Binding
coordinateRange = define "CoordinateRange" $
  T.record [
    "min">: T.bigfloat,
    "max">: T.bigfloat]

feature :: Binding
feature = define "Feature" $
 doc ("A Feature object represents a spatially bounded thing.  Every Feature " ++
      "object is a GeoJSON object no matter where it occurs in a GeoJSON " ++
      "text.") $
 T.record [
  "geometry">:
    doc ("A Feature object has a member with the name \"geometry\".  The value " ++
         "of the geometry member SHALL be either a Geometry object as " ++
         "defined above or, in the case that the Feature is unlocated, a " ++
         "JSON null value.") $
    T.maybe $ geoj "Geometry",
  "properties">:
    doc ("A Feature object has a member with the name \"properties\".  The " ++
         "value of the properties member is an object (any JSON object or a " ++
         "JSON null value).") $
    T.maybe $ T.map T.string (json "Value"),
  "id">:
    doc ("If a Feature has a commonly used identifier, that identifier " ++
         "SHOULD be included as a member of the Feature object with the name " ++
         "\"id\", and the value of this member is either a JSON string or " ++
         "number.") $
    T.maybe $ geoj "Id",
  "bbox">: T.maybe $ geoj "BoundingBox"]

featureCollection :: Binding
featureCollection = define "FeatureCollection" $
  doc ("A GeoJSON object with the type \"FeatureCollection\" is a " ++
       "FeatureCollection object.  A FeatureCollection object has a member " ++
       "with the name \"features\".  The value of \"features\" is a JSON array. " ++
       "Each element of the array is a Feature object as defined above.  It " ++
       "is possible for this array to be empty.") $
  T.record [
    "features">: T.list $ geoj "Feature",
    "bbox">: T.maybe $ geoj "BoundingBox"]

geometryCollection :: Binding
geometryCollection = define "GeometryCollection" $
  doc ("A GeoJSON object with type \"GeometryCollection\" is a Geometry object. " ++
       "A GeometryCollection has a member with the name \"geometries\".  The " ++
       "value of \"geometries\" is an array.  Each element of this array is a " ++
       "GeoJSON Geometry object.  It is possible for this array to be empty.") $
  T.record [
    "geometries">: T.list $ geoj "Geometry",
    "bbox">: T.maybe $ geoj "BoundingBox"]

geometry :: Binding
geometry = define "Geometry" $
  doc ("A Geometry object represents points, curves, and surfaces in " ++
       "coordinate space.  Every Geometry object is a GeoJSON object no " ++
       "matter where it occurs in a GeoJSON text.") $
  T.union [
    "point">: geoj "Point",
    "multiPoint">: geoj "MultiPoint",
    "lineString">: geoj "LineString",
    "multiLineString">: geoj "MultiLineString",
    "polygon">: geoj "Polygon",
    "multiPolygon">: geoj "MultiPolygon",
    "geometryCollection">: geoj "GeometryCollection"]

id_ :: Binding
id_ = define "Id" $
  T.union [
    "number">: T.bigfloat,
    "string">: T.string]

lineString :: Binding
lineString = define "LineString" $
  doc ("For type \"LineString\", the \"coordinates\" member is an array of two or " ++
       "more positions.") $
  T.record [
    "coordinates">: T.list $ geoj "Position",
    "bbox">: T.maybe $ geoj "BoundingBox"]

multiLineString :: Binding
multiLineString = define "MultiLineString" $
  doc ("For type \"MultiLineString\", the \"coordinates\" member is an array of " ++
       "LineString coordinate arrays.") $
  T.record [
    "coordinates">: T.list $ geoj "LineString",
    "bbox">: T.maybe $ geoj "BoundingBox"]

multiPoint :: Binding
multiPoint = define "MultiPoint" $
  doc ("For type \"MultiPoint\", the \"coordinates\" member is an array of " ++
       "positions.") $
  T.record [
    "coordinates">: T.list $ geoj "Point",
    "bbox">: T.maybe $ geoj "BoundingBox"]

multiPolygon :: Binding
multiPolygon = define "MultiPolygon" $
  doc ("For type \"MultiPolygon\", the \"coordinates\" member is an array of " ++
       "Polygon coordinate arrays.") $
  T.record [
    "coordinates">: T.list $ geoj "Polygon",
    "bbox">: T.maybe $ geoj "BoundingBox"]

object_ :: Binding
object_ = define "Object" $
  doc ("A GeoJSON object represents a Geometry, Feature, or collection of " ++
       "Features.") $
  T.union [
    "geometry">: geoj "Geometry",
    "feature">: geoj "Feature",
    "featureCollection">: geoj "FeatureCollection"]

point :: Binding
point = define "Point" $
  doc ("For type \"Point\", the \"coordinates\" member is a single position.") $
  T.record [
    "coordinates">: geoj "Position",
    "bbox">: T.maybe $ geoj "BoundingBox"]

polygon :: Binding
polygon = define "Polygon" $
  doc ("For type \"Polygon\", the \"coordinates\" member MUST be an array of " ++
       "linear ring coordinate arrays.\n" ++
       "For Polygons with more than one of these rings, the first MUST be " ++
       "the exterior ring, and any others MUST be interior rings.  The " ++
       "exterior ring bounds the surface, and the interior rings (if " ++
       "present) bound holes within the surface.") $
  T.record [
    "coordinates">: T.list $ geoj "Position",
    "bbox">: T.maybe $ geoj "BoundingBox"]

position :: Binding
position = define "Position" $
  doc ("A position is an array of numbers.  There MUST be two or more " ++
       "elements.  The first two elements are longitude and latitude, or " ++
       "easting and northing, precisely in that order and using decimal " ++
       "numbers.  Altitude or elevation MAY be included as an optional third " ++
       "element.") $
  T.record [
    "latitude">: T.bigfloat,
    "longitude">: T.bigfloat,
    "altitude">: T.maybe T.bigfloat]