Dynamic.hs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-|
  3. Module : Codec.ActivityStream.Dynamic
  4. Description : A (more dynamic) interface to Activity Streams
  5. Copyright : (c) Getty Ritter, 2014
  6. Maintainer : gdritter@galois.com
  7. This is an interface to ActivityStreams that simply wraps an underlying
  8. @aeson@ Object, and exposes a set of (convenient) lenses to access the
  9. values inside. If an @aeson@ object is wrapped in the respective wrapper,
  10. it will contain the obligatory values for that type (e.g. an @Activity@
  11. is guaranteed to have a @published@ date.)
  12. -}
  13. module Codec.ActivityStream.Dynamic
  14. ( Lens'
  15. -- * MediaLink
  16. , MediaLink
  17. , mlDuration
  18. , mlHeight
  19. , mlWidth
  20. , mlURL
  21. , mlRest
  22. , makeMediaLink
  23. -- * Object
  24. , Object
  25. , oAttachments
  26. , oAuthor
  27. , oContent
  28. , oDisplayName
  29. , oDownstreamDuplicates
  30. , oId
  31. , oImage
  32. , oObjectType
  33. , oPublished
  34. , oSummary
  35. , oUpdated
  36. , oUpstreamDuplicates
  37. , oURL
  38. , oRest
  39. , emptyObject
  40. -- * Activity
  41. , Activity
  42. , acActor
  43. , acContent
  44. , acGenerator
  45. , acIcon
  46. , acId
  47. , acObject
  48. , acPublished
  49. , acProvider
  50. , acTarget
  51. , acTitle
  52. , acUpdated
  53. , acURL
  54. , acVerb
  55. , acRest
  56. , makeActivity
  57. -- * Collection
  58. , Collection
  59. , cTotalItems
  60. , cItems
  61. , cURL
  62. , cRest
  63. , makeCollection
  64. ) where
  65. import Data.Aeson ( FromJSON(..)
  66. , ToJSON(..)
  67. , Result(..)
  68. , fromJSON
  69. )
  70. import qualified Data.Aeson as A
  71. import Data.DateTime (DateTime)
  72. import qualified Data.HashMap.Strict as HM
  73. import Data.Text (Text)
  74. import Codec.ActivityStream.LensInternal ( Lens'
  75. , makeLens
  76. , makeAesonLens
  77. , makeAesonLensMb
  78. )
  79. data MediaLink = MediaLink { fromMediaLink :: A.Object } deriving (Eq, Show)
  80. instance FromJSON MediaLink where
  81. parseJSON (A.Object o) | HM.member "url" o = return (MediaLink o)
  82. | otherwise = fail "..."
  83. parseJSON _ = fail "..."
  84. instance ToJSON MediaLink where
  85. toJSON (MediaLink o) = A.Object o
  86. mlRest :: Lens' MediaLink A.Object
  87. mlRest = makeLens fromMediaLink (\ o' m -> m { fromMediaLink = o' })
  88. mlDuration :: Lens' MediaLink (Maybe Int)
  89. mlDuration = makeAesonLensMb "duration" mlRest
  90. mlHeight :: Lens' MediaLink (Maybe Int)
  91. mlHeight = makeAesonLensMb "height" mlRest
  92. mlWidth :: Lens' MediaLink (Maybe Int)
  93. mlWidth = makeAesonLensMb "width" mlRest
  94. mlURL :: Lens' MediaLink Text
  95. mlURL = makeAesonLens "url" mlRest
  96. -- | Create a @MediaLink@ with just a @url@ property.
  97. makeMediaLink :: Text -> MediaLink
  98. makeMediaLink url = MediaLink (HM.insert "url" (toJSON url) HM.empty)
  99. -- | Object
  100. data Object = Object { fromObject :: A.Object } deriving (Eq, Show)
  101. instance FromJSON Object where
  102. parseJSON (A.Object o) = return (Object o)
  103. parseJSON _ = fail "..."
  104. instance ToJSON Object where
  105. toJSON (Object o) = A.Object o
  106. oRest :: Lens' Object A.Object
  107. oRest = makeLens fromObject (\ o' m -> m { fromObject = o' })
  108. oAttachments :: Lens' Object (Maybe [Object])
  109. oAttachments = makeAesonLensMb "attachments" oRest
  110. oAuthor :: Lens' Object (Maybe Object)
  111. oAuthor = makeAesonLensMb "author" oRest
  112. oContent :: Lens' Object (Maybe Text)
  113. oContent = makeAesonLensMb "content" oRest
  114. oDisplayName :: Lens' Object (Maybe Text)
  115. oDisplayName = makeAesonLensMb "displayName" oRest
  116. oDownstreamDuplicates :: Lens' Object (Maybe [Text])
  117. oDownstreamDuplicates = makeAesonLensMb "downstreamDuplicates" oRest
  118. oId :: Lens' Object (Maybe Text)
  119. oId = makeAesonLensMb "id" oRest
  120. oImage :: Lens' Object (Maybe MediaLink)
  121. oImage = makeAesonLensMb "image" oRest
  122. oObjectType :: (FromJSON o, ToJSON o) => Lens' Object (Maybe o)
  123. oObjectType = makeAesonLensMb "objectType" oRest
  124. oPublished :: Lens' Object (Maybe DateTime)
  125. oPublished = makeAesonLensMb "published" oRest
  126. oSummary :: Lens' Object (Maybe Text)
  127. oSummary = makeAesonLensMb "summary" oRest
  128. oUpdated :: Lens' Object (Maybe DateTime)
  129. oUpdated = makeAesonLensMb "updated" oRest
  130. oUpstreamDuplicates :: Lens' Object (Maybe [Text])
  131. oUpstreamDuplicates = makeAesonLensMb "upstreamDuplicates" oRest
  132. oURL :: Lens' Object (Maybe Text)
  133. oURL = makeAesonLensMb "url" oRest
  134. -- | Create an @Object@ with no fields.
  135. emptyObject :: Object
  136. emptyObject = Object HM.empty
  137. -- | Activity
  138. data Activity = Activity { fromActivity :: A.Object } deriving (Eq, Show)
  139. instance FromJSON Activity where
  140. parseJSON (A.Object o)
  141. | HM.member "published" o && HM.member "provider" o = return (Activity o)
  142. | otherwise = fail "..."
  143. parseJSON _ = fail "..."
  144. instance ToJSON Activity where
  145. toJSON (Activity o) = A.Object o
  146. acRest :: Lens' Activity A.Object
  147. acRest = makeLens fromActivity (\ o' m -> m { fromActivity = o' })
  148. acActor :: Lens' Activity Object
  149. acActor = makeAesonLens "actor" acRest
  150. acContent :: Lens' Activity (Maybe Text)
  151. acContent = makeAesonLensMb "content" acRest
  152. acGenerator :: Lens' Activity (Maybe Object)
  153. acGenerator = makeAesonLens "generator" acRest
  154. acIcon :: Lens' Activity (Maybe MediaLink)
  155. acIcon = makeAesonLensMb "icon" acRest
  156. acId :: Lens' Activity (Maybe Text)
  157. acId = makeAesonLensMb "id" acRest
  158. acObject :: Lens' Activity (Maybe Object)
  159. acObject = makeAesonLensMb "object" acRest
  160. acPublished :: Lens' Activity DateTime
  161. acPublished = makeAesonLens "published" acRest
  162. acProvider :: Lens' Activity (Maybe Object)
  163. acProvider = makeAesonLensMb "provider" acRest
  164. acTarget :: Lens' Activity (Maybe Object)
  165. acTarget = makeAesonLensMb "target" acRest
  166. acTitle :: Lens' Activity (Maybe Text)
  167. acTitle = makeAesonLensMb "title" acRest
  168. acUpdated :: Lens' Activity (Maybe DateTime)
  169. acUpdated = makeAesonLensMb "updated" acRest
  170. acURL :: Lens' Activity (Maybe Text)
  171. acURL = makeAesonLensMb "url" acRest
  172. acVerb :: (FromJSON v, ToJSON v) => Lens' Activity (Maybe v)
  173. acVerb = makeAesonLensMb "verb" acRest
  174. -- | Create an @Activity@ with an @actor@, @published@, and
  175. -- @provider@ property.
  176. makeActivity :: Object -> DateTime -> Activity
  177. makeActivity actor published = Activity
  178. $ HM.insert "actor" (toJSON actor)
  179. $ HM.insert "published" (toJSON published)
  180. $ HM.empty
  181. -- | Collection
  182. data Collection = Collection { fromCollection :: A.Object } deriving (Eq, Show)
  183. instance FromJSON Collection where
  184. parseJSON (A.Object o) = return (Collection o)
  185. parseJSON _ = fail "..."
  186. instance ToJSON Collection where
  187. toJSON (Collection o) = A.Object o
  188. cRest :: Lens' Collection A.Object
  189. cRest = makeLens fromCollection (\ o' m -> m { fromCollection = o' })
  190. cTotalItems :: Lens' Collection (Maybe Int)
  191. cTotalItems = makeAesonLensMb "totalItems" cRest
  192. cItems :: Lens' Collection (Maybe [Object])
  193. cItems = makeAesonLensMb "items" cRest
  194. cURL :: Lens' Collection (Maybe Text)
  195. cURL = makeAesonLensMb "url" cRest
  196. -- | Create a @Collection@ with an @items@ and a @url@ property
  197. -- and fill in the corresponding @totalItems@ field with the
  198. -- length of the @items@ array.
  199. makeCollection :: [Object] -> Text -> Collection
  200. makeCollection objs url = Collection
  201. $ HM.insert "totalItems" (toJSON (length objs))
  202. $ HM.insert "items" (toJSON objs)
  203. $ HM.insert "url" (toJSON url)
  204. $ HM.empty