{-# 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
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
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
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
Ord, 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
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
Hashable, Get ProjectId
[ProjectId] -> Put
ProjectId -> Put
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 -> ()
forall a. (a -> ()) -> NFData a
rnf :: ProjectId -> ()
$crnf :: ProjectId -> ()
NFData, NonEmpty ProjectId -> ProjectId
ProjectId -> ProjectId -> 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 :: forall b. Integral b => 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
[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
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 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> [Doc] -> [Doc]
punctuate Doc
colon forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map String -> Doc
text forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProjectId -> [String]
unProjectId

instance HasParser ProjectId where
  parser :: forall st input (m :: * -> *). CharParser st input m ProjectId
parser = [String] -> ProjectId
mkProjectId forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> 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 (forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
alphaNum forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"_-")) (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 = forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"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 = forall a. (Text -> Parser a) -> FromJSONKeyFunction a
FromJSONKeyTextParser (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 = forall a. IsString a => String -> a
fromString forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Pretty a => a -> String
prettyShow

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