ideas-1.0: src/Documentation/ServicePage.hs
{-# LANGUAGE RankNTypes #-}
-----------------------------------------------------------------------------
-- Copyright 2011, Open Universiteit Nederland. This file is distributed
-- under the terms of the GNU General Public License. For more information,
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer : bastiaan.heeren@ou.nl
-- Stability : provisional
-- Portability : portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Documentation.ServicePage (makeServicePage) where
import Common.Exercise
import Common.Id
import Common.Utils (Some(..))
import Control.Monad
import Documentation.DefaultPage
import Service.DomainReasoner
import Service.State
import Service.TypedExample
import Service.Types
import Text.HTML
import Text.XML (XML)
makeServicePage :: String -> Service -> DomainReasoner ()
makeServicePage dir s = do
xs <- examplesFor (showId s)
generatePageAt 1 dir (servicePageFile s) (servicePage xs s)
servicePage :: [Example] -> Service -> HTMLBuilder
servicePage xs s = do
h1 (showId s)
para $ do
bold $ text "Signature:"
space
case serviceFunction s of
_ ::: t -> ttText (show t)
para $ do
bold $ text "Description: "
br
text $ description s
when (serviceDeprecated s) $
para $ bold $ text "Warning: this service is deprecated!"
unless (null xs) $ do
h2 $ "XML examples (" ++ show (length xs) ++ ")"
forM_ (zip [1::Int ..] xs) $
\(i, (msg, (xmlRequest, xmlReply, xmlTest))) -> do
h2 $ show i ++ ". " ++ msg
bold $ text "Request:"
highlightXML True xmlRequest
bold $ text "Reply:"
highlightXML True xmlReply
unless xmlTest $
spanClass "error" $
bold $ text "Error: invalid request/reply pair"
-----------------------------------------------------------------------
-- Examples
type Example = (String, (XML, XML, Bool))
examplesFor :: String -> DomainReasoner [Example]
examplesFor s = tryAll [ f t | (t, f) <- list, s == t ]
where
list =
[ ("derivation", makeExample "logic.dnf" (noCfg +++ logic1))
, ("derivation", makeExample "math.lineq" (noCfg +++ lineq1))
, ("allfirsts", makeExample "logic.dnf" logic2)
, ("allfirsts", makeExample "math.lineq" lineq2)
, ("onefirst", makeExample "logic.dnf" logic2)
, ("onefirst", makeExample "math.lineq" lineq2)
, ("rulesinfo", makeExample "math.lineq" noArgs)
, ("rulelist", makeExample "math.lineq" exArgs)
, ("strategyinfo", makeExample "math.lineq" exArgs)
, ("examples", makeExample "math.lineq" exArgs)
]
logic1, logic2 :: Args
logic1 ex = newState ex "~(p /\\ ~q)"
logic2 ex = newState ex "~~p /\\ T"
lineq1, lineq2 :: Args
lineq1 ex = newState ex "5*(x+1) == 11"
lineq2 ex = newState ex "5*(x+1) == (x-1)/2"
(f +++ g) ex = f ex ++ g ex
noCfg _ = [Nothing ::: maybeType StrategyCfg]
noArgs _ = []
exArgs ex = [ex ::: Exercise]
tryAll :: [DomainReasoner a] -> DomainReasoner [a]
tryAll xs =
let f m = liftM return m `catchError` const (return [])
in liftM concat (mapM f xs)
newState :: Monad m => Exercise a -> String -> m (TypedValue a)
newState ex s =
case parser ex s of
Left msg -> fail ("newState: " ++ msg)
Right a -> return (emptyState ex a ::: stateType)
type Args = forall a . Exercise a -> [TypedValue a]
makeExample :: String -> Args -> String -> DomainReasoner Example
makeExample exName f srvName = do
Some ex <- findExercise (newId exName)
srv <- findService srvName
tr <- typedExample ex srv (f ex)
return (showId ex, tr)