changeset 5:782efee9766c

adapt bulletinboards for new Jungle
author Daichi TOMA <toma@cr.ie.u-ryukyu.ac.jp>
date Sun, 26 Jan 2014 21:24:06 +0900
parents 1363ce4186a7
children 0d12b5e49dfd
files App.hs RouteSetting.hs Routes.hs Types.hs
diffstat 4 files changed, 128 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- a/App.hs	Tue Jul 02 18:33:29 2013 +0900
+++ b/App.hs	Sun Jan 26 21:24:06 2014 +0900
@@ -1,24 +1,21 @@
-{-# LANGUAGE OverloadedStrings #-}
-
+import Jungle
 import Types
 import Routes
-import Network.Wai (Request, Response, pathInfo, queryString)
+import Network.Wai (Application, pathInfo, queryString)
 import Network.Wai.Parse (parseRequestBody, lbsBackEnd)
 import Network.Wai.Handler.Warp (run)
-import Control.Monad.Trans (lift, liftIO)
-import Data.Conduit (ResourceT)
-import Control.Concurrent.STM
-import qualified Jungle as J
+import Control.Monad.Trans (lift)
 
-application :: TJungle -> Request -> ResourceT IO Response
-application jungle request = do
-    let
+application :: Jungle -> Application
+application jungle request = do 
+    (params, _) <- parseRequestBody lbsBackEnd request
+    function jungle query params
+    where
       function = routes $ pathInfo request
       query    = queryString request
-    (params, _) <- parseRequestBody lbsBackEnd request
-    lift $ function jungle query params
 
-main = do 
+main = do
     putStrLn $ "Listening on port " ++ show 3000
-    jungle <- newJungle
+    jungle <- createJungle
+    createTree jungle treeName
     run 3000 $ application jungle
--- a/RouteSetting.hs	Tue Jul 02 18:33:29 2013 +0900
+++ b/RouteSetting.hs	Sun Jan 26 21:24:06 2014 +0900
@@ -1,167 +1,145 @@
 {-# LANGUAGE OverloadedStrings #-}
 
-module RouteSetting (routeSetting) where
+module RouteSetting
+( routeSetting
+) where
 
+import Jungle
 import Types
 import Network.Wai (Response, responseLBS)
 import Network.Wai.Parse (Param)
 import Network.HTTP.Types (status200)
 import Network.HTTP.Types.URI (Query)
-import Control.Concurrent.STM
-import Data.ByteString.Lazy.Char8 as B (ByteString, append, pack)
-import Data.ByteString.Lazy.UTF8 (fromString)
-import Data.ByteString.Char8 (unpack)
 import Data.Text (Text)
 import Data.Maybe (fromJust)
-import qualified Jungle as J
-import qualified Data.Map as Map
+import Data.ByteString.Lazy.Char8 as B (ByteString, append, pack)
+import Data.ByteString.Char8 as C (unpack)
 
-
-routeSetting :: [([Text],(TJungle -> Query -> [Param] -> IO Response))]
+routeSetting :: [([Text],(Jungle -> Query -> [Param] -> IO Response))]
 routeSetting = [([], showBoard),
                 (["createBoard"], createBoard),
-                (["showBoardMessage"],showBoardMessage),
-                (["createBoardMessage"],createBoardMessage),
-                (["editMessage"],editMessage)]
+                (["showBoardMessage"], showBoardMessage),
+                (["createBoardMessage"], createBoardMessage),
+                (["editMessage"], editMessage)]
 
+showBoard :: Jungle -> Query -> [Param] -> IO Response
 showBoard jungle query params = do
-    current_jungle <- readTVarIO jungle
-    let responseText = showBoardJungle current_jungle
-    return $ responseLBS status200 [("Content-type", "text/html")] $ responseText
+    node <- getRootNode jungle treeName
+    return $ responseLBS status200 [("Content-type", "text/html")] $ showBoardBy node
 
-showBoardJungle jungle = "<html><body><h1>BBS</h1>" `append` createBoardForm `append` listOfBoard jungle `append` "</body></html>"
-
+showBoardBy :: Node -> ByteString
+showBoardBy node = "<html><body><h1>BBS</h1>" `append` createBoardForm `append` listOfBoard node `append` "</body></html>"
+                 
+createBoardForm :: ByteString
 createBoardForm = "<form action='/createBoard' method='POST'><p>Create new board.</p><p>BoardName : <input type='text' name='bname'/><p>Author : <input type='text' name='author'/> EditKey : <input type='text' name='key'/></p><p>Message<br/> <input type='textarea' name='msg'/> </p><p><input type='submit' value='submit'/></p></form><hr/>"
 
-listOfBoard jungle = "<h2>list of boards</h2>" `append` getBoards jungle
+listOfBoard :: Node -> ByteString
+listOfBoard node = "<h2>list of boards</h2>" `append` getBoards node
 
-getBoards jungle = Map.foldr f "" (J.getMap $ J.getChildren $ J.getRootNode $ J.getTreeByName jungle "boards")
+getBoards :: Node -> ByteString
+getBoards node = foldr f "" (getChildren node [])
   where
     f a text = text `append` "<p><a href='/showBoardMessage?bname=" `append` (bname a) `append` "'>" `append` (bname a) `append` "</a></p>"
-    bname a = J.get (J.getAttributes a) "name"
+    bname a = fromJust $ getAttributes a [] "name"
 
-createBoard jungle query params = do
-    new_jungle <- createBoardJungle jungle params 
+createBoard :: Jungle -> Query -> [Param] -> IO Response
+createBoard jungle _ params = do
+    createBoardBy jungle params
     return $ responseLBS status200 [("Content-type", "text/html")] $ "createBoard"
 
-createBoardJungle :: TJungle -> [Param] -> IO J.Jungle
-createBoardJungle jungle [] = atomically $ readTVar jungle
-createBoardJungle jungle (bname:author:key:msg:xs) = atomically $ createBoardJungle' jungle (snd bname) (snd author) (snd key) (snd msg)
+createBoardBy :: Jungle -> [Param] -> IO ()
+createBoardBy jungle [] = return ()
+createBoardBy jungle (bname:author:key:msg:xs) = do
+    updateRootNodeWith (addBoardtoBoardList st_bname) jungle treeName
+    createTree jungle st_bname
+    updateRootNodeWith (createNewTree lb_author lb_key lb_msg) jungle st_bname
+    where
+      st_bname = C.unpack $ snd bname
+      lb_author = B.pack $ unpack $ snd author -- ByteString.Lazy
+      lb_key = B.pack $ unpack $ snd key
+      lb_msg = B.pack $ unpack $ snd msg
+      
 
-createBoardJungle' tv bname author key msg = do
-    jungle <- readTVar tv
-    let
-      jungle1 = addNewChild jungle "boards" [] J.createNode
-      jungle2 = putAttribute jungle1 "boards" [(Map.size $ J.getMap $ J.getChildren $ J.getRootNode $ J.getTreeByName jungle1 "boards")] "name" (B.pack $ unpack bname)
-      jungle3 = J.createTree jungle2 (unpack bname)
-      jungle4 = addNewChildAt jungle3 (unpack bname) [] 0 J.createNode 
-      jungle5 = putAttribute jungle4 (unpack bname) [0] "author" (B.pack $ unpack author)
-      jungle6 = putAttribute jungle5 (unpack bname) [0] "key" (B.pack $ unpack key)
-      jungle7 = putAttribute jungle6 (unpack bname) [0] "msg" (B.pack $ unpack msg)
-    writeTVar tv jungle7
-    readTVar tv
+addBoardtoBoardList :: String -> Node -> Node
+addBoardtoBoardList bname node = node -: addc -: (addca "name" (B.pack bname))
+  where
+    -- pathの最新の子にattributeを追加する
+    addca key value node = putAttribute node [(numOfChild node [])] key value
+    addc node = addNewChildAt node []
+    x -: f  = f x
 
+createNewTree :: ByteString -> ByteString -> ByteString -> Node -> Node
+createNewTree author key msg node = node -: addc -: (addca "author" author) -: (addca "key" key) -: (addca "msg" msg)
+  where
+    addca key value node = putAttribute node [(numOfChild node [])] key value
+    addc node = addNewChildAt node []
+    x -: f  = f x
+
+showBoardMessage :: Jungle -> Query -> [Param] -> IO Response
 showBoardMessage jungle query params = do
-    current_jungle <- readTVarIO jungle
-    let bname = fromJust $ fromJust $ lookup "bname" query
-    let responseText = showBoardMessageJungle current_jungle bname
-    return $ responseLBS status200 [("Content-type", "text/html")] $ responseText
+    node <- getRootNode jungle st_bname
+    return $ responseLBS status200 [("Content-type", "text/html")] $ showBoardMessageBy node (B.pack st_bname)
+    where
+      st_bname = C.unpack $ fromJust . fromJust $ lookup "bname" query
 
-showBoardMessageJungle jungle bname = "<html><body><h1>"`append` (B.pack $ unpack bname) `append` "</h1>" `append` (createBoardMessageForm (B.pack $ unpack bname)) `append` getMessages jungle bname `append` "</body></html>"
+showBoardMessageBy :: Node -> ByteString -> ByteString
+showBoardMessageBy node bname = "<html><body><h1>" `append` bname `append` "</h1>" `append` (createBoardMessageForm bname) `append` (getMessages node bname) `append` "</body></html>"
 
+createBoardMessageForm :: ByteString -> ByteString
 createBoardMessageForm bname = "<form action='/createBoardMessage' method='POST'><p>Author : <input type='text' name='author'/><input type='hidden' name='bname' value='" `append` bname `append` "'/> EditKey : <input type='text' name='key'/></p><p>Message<br/> <input type='textarea' name='msg'/> </p><p><input type='submit' value='submit'/></p></form>"
 
-getMessages jungle bname = Map.foldrWithKey f "" (J.getMap $ J.getChildren $ J.getRootNode $ J.getTreeByName jungle (unpack bname))
+getMessages :: Node -> ByteString -> ByteString
+getMessages node bname = foldr f "" (getChildrenWithKey node [])
   where
-    f k a text = text `append` "<hr/><p><b>" `append` author a `append` "</b></p><p>" `append` msg a `append` "</p><small><a href='/editMessage?bname=" `append` (B.pack $ unpack bname) `append` "&uuid=" `append` (B.pack $ show k) `append` "'>edit</a></small>"
-    author a = J.get (J.getAttributes a) "author"
-    msg a = J.get (J.getAttributes a) "msg"
+    f (id,node) text = text `append` "<hr/><p><b>" `append` (author node) `append` "</b></p><p>" `append` (msg node) `append` "</p><small><a href='/editMessage?bname=" `append` bname `append` "&uuid=" `append` (B.pack $ show id) `append` "'>edit</a></small>"
+    author node = fromJust $ getAttributes node [] "author"
+    msg node = fromJust $ getAttributes node [] "msg"
 
+createBoardMessage :: Jungle -> Query -> [Param] -> IO Response
 createBoardMessage jungle query params = do
-    new_jungle <- createBoardMessageJungle jungle params 
+    createBoardMessageBy jungle params
     return $ responseLBS status200 [("Content-type", "text/html")] $ "createBoardMessage"
 
-createBoardMassageJungle :: TJungle -> [Param] -> IO J.Jungle
-createBoardMassageJungle jungle [] = atomically $ readTVar jungle
-createBoardMessageJungle jungle (author:bname:key:msg:xs) = atomically $ createBoardMessageJungle' jungle (snd bname) (snd author) (snd key) (snd msg)
-
-createBoardMessageJungle' tv bname author key msg = do
-    jungle <- readTVar tv
-    let
-      jungle1 = addNewChild jungle (unpack bname) [] J.createNode 
-      size = Map.size $ J.getMap $ J.getChildren $ J.getRootNode $ J.getTreeByName jungle1 (unpack bname)
-      jungle2 = putAttribute jungle1 (unpack bname) [size] "author" (B.pack $ unpack author)
-      jungle3 = putAttribute jungle2 (unpack bname) [size] "key" (B.pack $ unpack key)
-      jungle4 = putAttribute jungle3 (unpack bname) [size] "msg" (B.pack $ unpack msg)
-    writeTVar tv jungle4
-    readTVar tv
-    return $ responseLBS status200 [("Content-type", "text/html")] $ "createBoardMessage"
-
-editMessage jungle query params = do
-    new_jungle <- editMessageJungle jungle params
-    let bname = fromJust $ fromJust $ lookup "bname" query
-    let uuid = fromJust $ fromJust $ lookup "uuid" query
-    let responseText = editMessageForm bname uuid
-    return $ responseLBS status200 [("Content-type", "text/html")] $ responseText
-
-editMessageJungle jungle [] = atomically $ readTVar jungle
-editMessageJungle jungle (author:bname:uuid:key:msg:xs) = atomically $ editMessageJungle' jungle (snd bname) (snd author) (snd key) (snd msg) (snd uuid)
-
-editMessageJungle' tv bname author key msg uuid = do
-    jungle <- readTVar tv
-    let
-      x = read $ unpack uuid
-      jungle1 = putAttribute jungle (unpack bname) [x] "author" (B.pack $ unpack author)
-      jungle2 = putAttribute jungle1 (unpack bname) [x] "key" (B.pack $ unpack key)
-      jungle3 = putAttribute jungle2 (unpack bname) [x] "msg" (B.pack $ unpack msg)
-    writeTVar tv jungle3
-    readTVar tv
-
-editMessageForm bname uuid = "<html><body><h1>edit message</h1><form method='POST'><p>Author : <input type='text' name='author'/><input type='hidden' name='bname' value='" `append` (B.pack $ unpack bname) `append` "'/><input type='hidden' name='uuid' value='" `append` (B.pack $ unpack uuid) `append` "'/> EditKey : <input type='text' name='key'/></p><p>Message<br/> <input type='textarea' name='msg'/> </p><p><input type='submit' value='submit'/></p></form></body></html>"
-
+createBoardMessageBy :: Jungle -> [Param] -> IO ()
+createBoardMessageBy jungle [] = return ()
+createBoardMessageBy jungle (author:bname:key:msg:xs) = do
+    updateRootNodeWith (addNewMessage lb_author lb_key lb_msg) jungle st_bname
+    where
+      st_bname = C.unpack $ snd bname
+      lb_author = B.pack $ unpack $ snd author -- ByteString.Lazy
+      lb_key = B.pack $ unpack $ snd key
+      lb_msg = B.pack $ unpack $ snd msg
 
-showBoard' jungle query params = do
-    new_jungle <- modifyJungle' jungle params
-    let responseText = makeResponseText new_jungle
-    return $ responseLBS status200 [("Content-type", "text/html")] $ responseText
-
-makeResponseText :: (Show a) => a -> B.ByteString
-makeResponseText s = form `append` "<h1>Hello " `append` (toByteString s) `append` "</h1>\n"
-    where 
-      form = "<form method=\"POST\" action=\"#\"><input name=\"key\" type=\"text\"><input name=\"value\" type=\"text\"><input type=\"submit\"></form>"
-
-toByteString :: (Show a) => a -> B.ByteString
-toByteString s = fromString $ show s
-
-modifyJungle' :: TJungle -> [Param] -> IO J.Jungle
-modifyJungle' jungle [] = atomically $ readTVar jungle
-modifyJungle' jungle (key:value:xs) = atomically $ test jungle (unpack $ snd key) (unpack $ snd value)
+addNewMessage :: ByteString -> ByteString -> ByteString -> Node -> Node
+addNewMessage author key msg node = node -: addc -: (addca "author" author) -: (addca "key" key) -: (addca "msg" msg)
+  where
+    addca key value node = putAttribute node [(numOfChild node [])] key value
+    addc node = addNewChildAt node []
+    x -: f  = f x
+      
+editMessage :: Jungle -> Query -> [Param] -> IO Response
+editMessage jungle query params = do
+    editMessageBy jungle params
+    return $ responseLBS status200 [("Content-type", "text/html")] $ editMessageForm lb_bname lb_uuid
+    where
+      lb_bname = B.pack $ C.unpack $ fromJust . fromJust $ lookup "bname" query
+      lb_uuid = B.pack $ C.unpack $ fromJust . fromJust $ lookup "uuid" query
 
-add :: TJungle -> String -> String -> STM ()
-add tv key value = do
-    jungle <- readTVar tv
-    let
-      new_jungle = putAttribute jungle "boards" [] key (B.pack value)
-    writeTVar tv new_jungle
+editMessageBy :: Jungle -> [Param] -> IO ()
+editMessageBy jungle [] = return ()
+editMessageBy jungle (author:bname:uuid:key:msg:xs) = do
+    updateRootNodeWith (editMessage' id lb_author lb_key lb_msg) jungle st_bname
+    where
+      st_bname = C.unpack $ snd bname
+      id = read $ C.unpack $ snd uuid
+      lb_author = B.pack $ unpack $ snd author -- ByteString.Lazy
+      lb_key = B.pack $ unpack $ snd key
+      lb_msg = B.pack $ unpack $ snd msg
 
-test jungle key value = do
-    add jungle key value
-    readTVar jungle
-
-putAttribute :: J.Jungle -> String -> J.Path -> String -> B.ByteString -> J.Jungle
-putAttribute jungle tree_name path key value = new_jungle jungle
+editMessage' :: Int -> ByteString -> ByteString -> ByteString -> Node -> Node
+editMessage' id author key msg node = node -: (addca "author" author) -: (addca "key" key) -: (addca "msg" msg)
   where
-    new_tree jungle = J.putAttribute (J.getTreeByName jungle tree_name) path key value
-    new_jungle jungle = J.updateTree jungle (new_tree jungle)
+    addca key value node = putAttribute node [id] key value
+    x -: f  = f x
 
-addNewChildAt :: J.Jungle -> String -> J.Path -> Int -> J.Node -> J.Jungle
-addNewChildAt jungle tree_name path pos node = new_jungle jungle
-  where
-    new_tree jungle = J.addNewChildAt (J.getTreeByName jungle tree_name) path pos node
-    new_jungle jungle = J.updateTree jungle (new_tree jungle)
-
-addNewChild :: J.Jungle -> String -> J.Path -> J.Node -> J.Jungle
-addNewChild jungle tree_name path node = new_jungle jungle
-  where
-    new_tree jungle = J.addNewChildAt (J.getTreeByName jungle tree_name) path ((Map.size $ J.getMap $ J.getChildren $ J.getRootNode $ J.getTreeByName jungle tree_name) + 1) node
-    new_jungle jungle = J.updateTree jungle (new_tree jungle)
+editMessageForm bname uuid = "<html><body><h1>edit message</h1><form method='POST'><p>Author : <input type='text' name='author'/><input type='hidden' name='bname' value='" `append` bname `append` "'/><input type='hidden' name='uuid' value='" `append` uuid `append` "'/> EditKey : <input type='text' name='key'/></p><p>Message<br/> <input type='textarea' name='msg'/> </p><p><input type='submit' value='submit'/></p></form></body></html>"
--- a/Routes.hs	Tue Jul 02 18:33:29 2013 +0900
+++ b/Routes.hs	Sun Jan 26 21:24:06 2014 +0900
@@ -1,16 +1,20 @@
 {-# LANGUAGE OverloadedStrings #-}
 
-module Routes (routes) where
+module Routes
+( routes
+) where
 
+import Jungle
 import Types
 import RouteSetting
 import Network.Wai (Response, responseLBS)
+import Network.Wai.Parse (Param)
 import Network.HTTP.Types (status404)
 import Network.HTTP.Types.URI (Query)
-import Network.Wai.Parse (Param)
 import Data.Text (Text)
 
-routes :: [Text] -> (TJungle -> Query -> [Param] -> IO Response)
+
+routes :: [Text] -> (Jungle -> Query -> [Param] -> IO Response)
 routes path = findRoute path routeSetting
 
 findRoute path [] = notFound
@@ -18,8 +22,6 @@
     | path == p = f
     | otherwise = findRoute path xs
 
-notFound _ _ _ = do
+notFound :: Jungle -> Query -> [Param] -> IO Response
+notFound _ _ _ = 
     return $ responseLBS status404 [("Content-type", "text/html")] $ "404 - File Not Found"
-
-
-
--- a/Types.hs	Tue Jul 02 18:33:29 2013 +0900
+++ b/Types.hs	Sun Jan 26 21:24:06 2014 +0900
@@ -1,18 +1,8 @@
 module Types
-( TJungle
-, newJungle
+( treeName
 ) where
 
-import Control.Concurrent.STM (TVar, newTVarIO)
-import qualified Jungle as J
-
-import Data.ByteString.Lazy.Char8 (pack)
-
-type TJungle = TVar J.Jungle
+import Jungle
 
-newJungle :: IO TJungle
-newJungle = do
-    let
-      jungle = J.createTree J.createJungle "boards"
-    tv <- newTVarIO jungle
-    return tv
+treeName :: String
+treeName = "boards"