{-# LANGUAGE DeriveGeneric, GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleContexts #-}

module OpenSuse.Types.ProjectId
  ( ProjectId, mkProjectId, unProjectId
  )
  where

import OpenSuse.Prelude
import OpenSuse.Prelude.Parser as Parse
import OpenSuse.Prelude.PrettyPrinting as Pretty

import Data.Aeson as Json
import Data.Aeson.Types as Json ( toJSONKeyText )

-- | Projects are identified on OBS by a string path.
--
-- >>> parse "project id" "SUSE:SLE-12-SP2:Update" :: ProjectId
-- ProjectId ["SUSE","SLE-12-SP2","Update"]
-- >>> parseM "project id" "SUSE::SLE-12-SP2" :: Maybe ProjectId
-- Nothing
-- >>> parseM "project id" ":SUSE" :: Maybe ProjectId
-- Nothing
-- >>> parseM "project id" "SUSE:" :: Maybe ProjectId
-- Nothing

newtype ProjectId = ProjectId [String]
  deriving (Int -> ProjectId -> ShowS
[ProjectId] -> ShowS
ProjectId -> String
(Int -> ProjectId -> ShowS)
-> (ProjectId -> String)
-> ([ProjectId] -> ShowS)
-> Show ProjectId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ProjectId] -> ShowS
$cshowList :: [ProjectId] -> ShowS
show :: ProjectId -> String
$cshow :: ProjectId -> String
showsPrec :: Int -> ProjectId -> ShowS
$cshowsPrec :: Int -> ProjectId -> ShowS
Show, ProjectId -> ProjectId -> Bool
(ProjectId -> ProjectId -> Bool)
-> (ProjectId -> ProjectId -> Bool) -> Eq ProjectId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ProjectId -> ProjectId -> Bool
$c/= :: ProjectId -> ProjectId -> Bool
== :: ProjectId -> ProjectId -> Bool
$c== :: ProjectId -> ProjectId -> Bool
Eq, Eq ProjectId
Eq ProjectId
-> (ProjectId -> ProjectId -> Ordering)
-> (ProjectId -> ProjectId -> Bool)
-> (ProjectId -> ProjectId -> Bool)
-> (ProjectId -> ProjectId -> Bool)
-> (ProjectId -> ProjectId -> Bool)
-> (ProjectId -> ProjectId -> ProjectId)
-> (ProjectId -> ProjectId -> ProjectId)
-> Ord ProjectId
ProjectId -> ProjectId -> Bool
ProjectId -> ProjectId -> Ordering
ProjectId -> ProjectId -> ProjectId
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
min :: ProjectId -> ProjectId -> ProjectId
$cmin :: ProjectId -> ProjectId -> ProjectId
max :: ProjectId -> ProjectId -> ProjectId
$cmax :: ProjectId -> ProjectId -> ProjectId
>= :: ProjectId -> ProjectId -> Bool
$c>= :: ProjectId -> ProjectId -> Bool
> :: ProjectId -> ProjectId -> Bool
$c> :: ProjectId -> ProjectId -> Bool
<= :: ProjectId -> ProjectId -> Bool
$c<= :: ProjectId -> ProjectId -> Bool
< :: ProjectId -> ProjectId -> Bool
$c< :: ProjectId -> ProjectId -> Bool
compare :: ProjectId -> ProjectId -> Ordering
$ccompare :: ProjectId -> ProjectId -> Ordering
$cp1Ord :: Eq ProjectId
Ord, (forall x. ProjectId -> Rep ProjectId x)
-> (forall x. Rep ProjectId x -> ProjectId) -> Generic ProjectId
forall x. Rep ProjectId x -> ProjectId
forall x. ProjectId -> Rep ProjectId x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ProjectId x -> ProjectId
$cfrom :: forall x. ProjectId -> Rep ProjectId x
Generic, Eq ProjectId
Eq ProjectId
-> (Int -> ProjectId -> Int)
-> (ProjectId -> Int)
-> Hashable ProjectId
Int -> ProjectId -> Int
ProjectId -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: ProjectId -> Int
$chash :: ProjectId -> Int
hashWithSalt :: Int -> ProjectId -> Int
$chashWithSalt :: Int -> ProjectId -> Int
$cp1Hashable :: Eq ProjectId
Hashable, Get ProjectId
[ProjectId] -> Put
ProjectId -> Put
(ProjectId -> Put)
-> Get ProjectId -> ([ProjectId] -> Put) -> Binary ProjectId
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [ProjectId] -> Put
$cputList :: [ProjectId] -> Put
get :: Get ProjectId
$cget :: Get ProjectId
put :: ProjectId -> Put
$cput :: ProjectId -> Put
Binary, ProjectId -> ()
(ProjectId -> ()) -> NFData ProjectId
forall a. (a -> ()) -> NFData a
rnf :: ProjectId -> ()
$crnf :: ProjectId -> ()
NFData, b -> ProjectId -> ProjectId
NonEmpty ProjectId -> ProjectId
ProjectId -> ProjectId -> ProjectId
(ProjectId -> ProjectId -> ProjectId)
-> (NonEmpty ProjectId -> ProjectId)
-> (forall b. Integral b => b -> ProjectId -> ProjectId)
-> Semigroup ProjectId
forall b. Integral b => b -> ProjectId -> ProjectId
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> ProjectId -> ProjectId
$cstimes :: forall b. Integral b => b -> ProjectId -> ProjectId
sconcat :: NonEmpty ProjectId -> ProjectId
$csconcat :: NonEmpty ProjectId -> ProjectId
<> :: ProjectId -> ProjectId -> ProjectId
$c<> :: ProjectId -> ProjectId -> ProjectId
Semigroup, Semigroup ProjectId
ProjectId
Semigroup ProjectId
-> ProjectId
-> (ProjectId -> ProjectId -> ProjectId)
-> ([ProjectId] -> ProjectId)
-> Monoid ProjectId
[ProjectId] -> ProjectId
ProjectId -> ProjectId -> ProjectId
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [ProjectId] -> ProjectId
$cmconcat :: [ProjectId] -> ProjectId
mappend :: ProjectId -> ProjectId -> ProjectId
$cmappend :: ProjectId -> ProjectId -> ProjectId
mempty :: ProjectId
$cmempty :: ProjectId
$cp1Monoid :: Semigroup ProjectId
Monoid)

-- | Constructor function for project identifiers.
--
-- TODO: Figure out how to deal with the [] project.
mkProjectId :: [String] -> ProjectId
mkProjectId :: [String] -> ProjectId
mkProjectId = [String] -> ProjectId
ProjectId

-- | Accessor function for the underlying path of strings.
unProjectId :: ProjectId -> [String]
unProjectId :: ProjectId -> [String]
unProjectId (ProjectId [String]
str) = [String]
str

instance IsString ProjectId where
  fromString :: String -> ProjectId
fromString = String -> String -> ProjectId
forall input a.
(Stream input Identity Char, HasParser a) =>
String -> input -> a
parse String
"code stream"

instance Pretty ProjectId where
  pPrint :: ProjectId -> Doc
pPrint = [Doc] -> Doc
hcat ([Doc] -> Doc) -> (ProjectId -> [Doc]) -> ProjectId -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> [Doc] -> [Doc]
punctuate Doc
colon ([Doc] -> [Doc]) -> (ProjectId -> [Doc]) -> ProjectId -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Doc) -> [String] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map String -> Doc
text ([String] -> [Doc])
-> (ProjectId -> [String]) -> ProjectId -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProjectId -> [String]
unProjectId

instance HasParser ProjectId where
  parser :: ParsecT st input m ProjectId
parser = [String] -> ProjectId
mkProjectId ([String] -> ProjectId)
-> ParsecT st input m [String] -> ParsecT st input m ProjectId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT st input m String
-> ParsecT st input m Char -> ParsecT st input m [String]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
sepBy1 (ParsecT st input m Char -> ParsecT st input m String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (ParsecT st input m Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
alphaNum ParsecT st input m Char
-> ParsecT st input m Char -> ParsecT st input m Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> ParsecT st input m Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"_-")) (Char -> ParsecT st input m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
Parse.char Char
':')

instance FromJSON ProjectId where
  parseJSON :: Value -> Parser ProjectId
parseJSON = String -> (Text -> Parser ProjectId) -> Value -> Parser ProjectId
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"ProjectId" (String -> Text -> Parser ProjectId
forall (m :: * -> *) input a.
(MonadFail m, Stream input m Char, HasParser a) =>
String -> input -> m a
parseM String
"project id")

instance FromJSONKey ProjectId where
  fromJSONKey :: FromJSONKeyFunction ProjectId
fromJSONKey = (Text -> Parser ProjectId) -> FromJSONKeyFunction ProjectId
forall a. (Text -> Parser a) -> FromJSONKeyFunction a
FromJSONKeyTextParser (String -> Text -> Parser ProjectId
forall (m :: * -> *) input a.
(MonadFail m, Stream input m Char, HasParser a) =>
String -> input -> m a
parseM String
"project id")

instance ToJSON ProjectId where
  toJSON :: ProjectId -> Value
toJSON = String -> Value
forall a. IsString a => String -> a
fromString (String -> Value) -> (ProjectId -> String) -> ProjectId -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProjectId -> String
forall a. Pretty a => a -> String
prettyShow

instance ToJSONKey ProjectId where
  toJSONKey :: ToJSONKeyFunction ProjectId
toJSONKey = (ProjectId -> Text) -> ToJSONKeyFunction ProjectId
forall a. (a -> Text) -> ToJSONKeyFunction a
toJSONKeyText (String -> Text
forall a. IsString a => String -> a
fromString (String -> Text) -> (ProjectId -> String) -> ProjectId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProjectId -> String
forall a. Pretty a => a -> String
prettyShow)