{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Data.Geospatial.Internal.CRS (
CRSObject(..)
, defaultCRS
, _NoCRS
, _NamedCRS
, _EPSG
, _LinkedCRS
) where
import Data.Geospatial.Internal.BasicTypes
import Control.Applicative ((<$>), (<*>))
import Control.Lens (makePrisms)
import Control.Monad (mzero)
import Data.Aeson (FromJSON (..), Object,
ToJSON (..), Value (..),
object, (.:), (.=))
import Data.Aeson.Types (Parser)
import Data.Text (Text)
data CRSObject =
NoCRS
| NamedCRS !Name
| EPSG Code
| LinkedCRS !Href !FormatString deriving (Show, Eq)
makePrisms ''CRSObject
defaultCRS :: CRSObject
defaultCRS = EPSG 4326
instance FromJSON CRSObject where
parseJSON Null = return NoCRS
parseJSON (Object obj) = do
crsType <- obj .: "type"
crsObjectFromAeson crsType obj
parseJSON _ = mzero
instance ToJSON CRSObject where
toJSON (NamedCRS name) = object ["type" .= ("name" :: Text), "properties" .= object ["name" .= name]]
toJSON (EPSG code) = object ["type" .= ("epsg" :: Text), "properties" .= object ["code" .= code]]
toJSON (LinkedCRS href format) = object ["type" .= ("link" :: Text), "properties" .= object ["href" .= href, "type" .= format]]
toJSON NoCRS = Null
crsPropertyFromAesonObj :: (FromJSON a) => Text -> Object -> Parser a
crsPropertyFromAesonObj name obj = do
props <- obj .: "properties"
props .: name
crsObjectFromAeson :: Text -> Object -> Parser CRSObject
crsObjectFromAeson "name" obj = NamedCRS <$> crsPropertyFromAesonObj "name" obj
crsObjectFromAeson "epsg" obj = EPSG <$> crsPropertyFromAesonObj "code" obj
crsObjectFromAeson "link" obj = LinkedCRS <$> crsPropertyFromAesonObj "href" obj <*> crsPropertyFromAesonObj "type" obj
crsObjectFromAeson _ _ = mzero