module EZCouch.Design where
import Prelude ()
import ClassyPrelude
import GHC.Generics
import EZCouch.Entity
import Data.Aeson
import qualified Network.HTTP.Types as HTTP
import qualified Network.HTTP.Conduit as HTTP
import qualified Data.Map as Map
import EZCouch.Action
import EZCouch.WriteAction
import EZCouch.Types
import EZCouch.Parsing
import EZCouch.Model.Design
import EZCouch.Model.View (View)
import qualified EZCouch.Model.View as View
readDesign :: (MonadAction m, Entity a) => m (Maybe (Persisted (Design a)))
readDesign = result
where
result = (flip catch) processException $
getAction ["_design", designName] [] ""
>>= runParser errorPersistedParser
>>= return . either (const Nothing) Just
where
designName = entityType $ (undefined :: m (Maybe (Persisted (Design a))) -> a) result
processException (HTTP.StatusCodeException (HTTP.Status 404 _) _) = return Nothing
processException e = throwIO e
createOrUpdateDesign :: (MonadAction m, Entity a) => Design a -> m (Persisted (Design a))
createOrUpdateDesign design =
createDesign design `catch` \e -> case e of
OperationException {} -> do
design' <- readDesign
case design' of
Just design'@(Persisted id rev design'') -> if design'' == design
then return design'
else updateEntity $ Persisted id rev design
Nothing -> throwIO e
_ -> throwIO e
createDesign :: (MonadAction m, Entity a) => Design a -> m (Persisted (Design a))
createDesign design = createIdentifiedEntity (id, design)
where
id = "_design/" ++ designName design
updateDesignView :: (MonadAction m, Entity a)
=> Persisted (Design a) -> Text -> View -> m (Persisted (Design a))
updateDesignView
design@(Persisted designId designRev (Design viewsMap))
viewName
view
| Just existingView <- lookup viewName viewsMap
= if existingView == view
then return design
else updateViewsMap $ Map.adjust (const $ view) viewName viewsMap
| otherwise
= updateViewsMap $ insert viewName view viewsMap
where
updateViewsMap = updateEntity . Persisted designId designRev . Design
createOrUpdateDesignView :: (MonadAction m, Entity a)
=> Text -> View -> m (Persisted (Design a))
createOrUpdateDesignView viewName view =
createDesign newDesign `catch` \e -> case e of
OperationException {} -> do
existingDesign <- readDesign
case existingDesign of
Just existingDesign -> updateDesignView existingDesign viewName view
Nothing -> throwIO e
_ -> throwIO e
where
newDesign = Design $ fromList [(viewName, view)]