{-# LANGUAGE OverloadedStrings #-}

-- | Many fields in OpenAPI can be either a reference or a concrete object.
-- This module adds this capabilities.
--
-- For more information see http://spec.openapis.org/oas/v3.0.3#reference-object
module OpenAPI.Generate.Types.Referencable where

import Data.Text (Text)
import Data.Yaml

-- | Represents either a reference or a concrete value
data Referencable a
  = -- | A reference with the JSON reference string pointing to the referenced target
    Reference Text
  | -- | A concrete value which can be used directly
    Concrete a
  deriving (Int -> Referencable a -> ShowS
[Referencable a] -> ShowS
Referencable a -> String
(Int -> Referencable a -> ShowS)
-> (Referencable a -> String)
-> ([Referencable a] -> ShowS)
-> Show (Referencable a)
forall a. Show a => Int -> Referencable a -> ShowS
forall a. Show a => [Referencable a] -> ShowS
forall a. Show a => Referencable a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Referencable a -> ShowS
showsPrec :: Int -> Referencable a -> ShowS
$cshow :: forall a. Show a => Referencable a -> String
show :: Referencable a -> String
$cshowList :: forall a. Show a => [Referencable a] -> ShowS
showList :: [Referencable a] -> ShowS
Show, Referencable a -> Referencable a -> Bool
(Referencable a -> Referencable a -> Bool)
-> (Referencable a -> Referencable a -> Bool)
-> Eq (Referencable a)
forall a. Eq a => Referencable a -> Referencable a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Referencable a -> Referencable a -> Bool
== :: Referencable a -> Referencable a -> Bool
$c/= :: forall a. Eq a => Referencable a -> Referencable a -> Bool
/= :: Referencable a -> Referencable a -> Bool
Eq, Eq (Referencable a)
Eq (Referencable a) =>
(Referencable a -> Referencable a -> Ordering)
-> (Referencable a -> Referencable a -> Bool)
-> (Referencable a -> Referencable a -> Bool)
-> (Referencable a -> Referencable a -> Bool)
-> (Referencable a -> Referencable a -> Bool)
-> (Referencable a -> Referencable a -> Referencable a)
-> (Referencable a -> Referencable a -> Referencable a)
-> Ord (Referencable a)
Referencable a -> Referencable a -> Bool
Referencable a -> Referencable a -> Ordering
Referencable a -> Referencable a -> Referencable a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Referencable a)
forall a. Ord a => Referencable a -> Referencable a -> Bool
forall a. Ord a => Referencable a -> Referencable a -> Ordering
forall a.
Ord a =>
Referencable a -> Referencable a -> Referencable a
$ccompare :: forall a. Ord a => Referencable a -> Referencable a -> Ordering
compare :: Referencable a -> Referencable a -> Ordering
$c< :: forall a. Ord a => Referencable a -> Referencable a -> Bool
< :: Referencable a -> Referencable a -> Bool
$c<= :: forall a. Ord a => Referencable a -> Referencable a -> Bool
<= :: Referencable a -> Referencable a -> Bool
$c> :: forall a. Ord a => Referencable a -> Referencable a -> Bool
> :: Referencable a -> Referencable a -> Bool
$c>= :: forall a. Ord a => Referencable a -> Referencable a -> Bool
>= :: Referencable a -> Referencable a -> Bool
$cmax :: forall a.
Ord a =>
Referencable a -> Referencable a -> Referencable a
max :: Referencable a -> Referencable a -> Referencable a
$cmin :: forall a.
Ord a =>
Referencable a -> Referencable a -> Referencable a
min :: Referencable a -> Referencable a -> Referencable a
Ord)

instance (FromJSON a) => FromJSON (Referencable a) where
  parseJSON :: Value -> Parser (Referencable a)
parseJSON (Object Object
v) = do
    Maybe Text
maybeReference <- Object
v Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"$ref"
    case Maybe Text
maybeReference of
      (Just Text
reference) -> Referencable a -> Parser (Referencable a)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Referencable a
forall a. Text -> Referencable a
Reference Text
reference)
      Maybe Text
Nothing -> a -> Referencable a
forall a. a -> Referencable a
Concrete (a -> Referencable a) -> Parser a -> Parser (Referencable a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser a
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
v)
  parseJSON Value
v = a -> Referencable a
forall a. a -> Referencable a
Concrete (a -> Referencable a) -> Parser a -> Parser (Referencable a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser a
forall a. FromJSON a => Value -> Parser a
parseJSON Value
v