packages feed

ideas-0.7: src/Documentation/ServicePage.hs

{-# OPTIONS -XRankNTypes #-}
-----------------------------------------------------------------------------
-- Copyright 2010, 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 Documentation.DefaultPage
import Service.ExercisePackage
import Service.TypedExample
import Service.Types
import Service.DomainReasoner
import Service.State
import Text.HTML
import qualified Text.XML as XML
import Text.XML (XML)
import Control.Monad
import Common.Exercise
import Common.Utils (Some(..))

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 $ 
               XML.element "font" $ do
                  "color" XML..=. "red"
                  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 pkg = newState pkg "~(p /\\ ~q)"
   logic2 pkg = newState pkg "~~p /\\ T"
   
   lineq1, lineq2 :: Args
   lineq1 pkg = newState pkg "5*(x+1) == 11"
   lineq2 pkg = newState pkg "5*(x+1) == (x-1)/2"
   
   (f +++ g) pkg = f pkg ++ g pkg
   
   noCfg _    = [Nothing ::: maybeTp StrategyCfg]
   noArgs _   = []
   exArgs pkg = [pkg ::: ExercisePkg]

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 => ExercisePackage a -> String -> m (TypedValue a)
newState pkg s = do
   let ex = exercise pkg
   case parser ex s of
      Left msg -> fail ("newState: " ++ msg)
      Right a  -> return (emptyState pkg a ::: stateTp)
      
type Args = forall a . ExercisePackage a -> [TypedValue a]

makeExample :: String -> Args -> String -> DomainReasoner Example
makeExample pkgName f srvName = do
   let a = newId pkgName
   Some pkg <- findPackage a
   srv      <- findService srvName
   tr       <- typedExample pkg srv (f pkg)
   return (showId pkg, tr)