X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Rakka%2FStorage%2FDefaultPage.hs;h=b5648cf49b64c6c69b7d8cf2ba8b5b06b8313092;hb=98e508613bb7a50a1f65998ce87f065df957b736;hp=8770ef05264a2f18ece8047b0f1b4861da9967d7;hpb=484e15845d9c06d0fa62044d3b6b3ff8c78a6e04;p=Rakka.git diff --git a/Rakka/Storage/DefaultPage.hs b/Rakka/Storage/DefaultPage.hs index 8770ef0..b5648cf 100644 --- a/Rakka/Storage/DefaultPage.hs +++ b/Rakka/Storage/DefaultPage.hs @@ -1,16 +1,26 @@ module Rakka.Storage.DefaultPage - ( loadDefaultPage + ( findAllDefaultPages + , loadDefaultPage ) where -import qualified Codec.Binary.Base64.String as B64 +import qualified Codec.Binary.Base64 as B64 import Control.Arrow +import Control.Arrow.ArrowIO import Control.Arrow.ArrowList -import qualified Data.ByteString.Lazy.Char8 as L8 +import qualified Data.ByteString.Lazy as L +import Data.Encoding +import Data.Encoding.UTF8 +import qualified Data.Map as M +import Data.Set (Set) +import qualified Data.Set as S import Paths_Rakka -- Cabal が用意する。 import Rakka.Page import Rakka.Utils +import System.FilePath +import System.FilePath.Find import System.Directory +import System.Time import Text.XML.HXT.Arrow.ReadDocument import Text.XML.HXT.Arrow.XmlArrow import Text.XML.HXT.Arrow.XmlIOStateArrow @@ -19,25 +29,54 @@ import Text.XML.HXT.DOM.TypeDefs import Text.XML.HXT.DOM.XmlKeywords +doesLocalDirExist :: IO Bool +doesLocalDirExist = doesDirectoryExist "defaultPages" + + +findAllDefaultPages :: IO (Set PageName) +findAllDefaultPages + -- ./defaultPages が存在するなら、その中を探す。無ければ Cabal で + -- defaultPages を探す。 + = do localDirExists <- doesLocalDirExist + if localDirExists then + findAllIn "defaultPages" + else + -- FIXME: この getDataFileName の使ひ方は undocumented + findAllIn =<< getDataFileName "defaultPages" + where + findAllIn :: FilePath -> IO (Set PageName) + findAllIn dirPath + = find always (fileType ==? RegularFile) dirPath + >>= + return . S.fromList . map (decodePageName . makeRelative dirPath) + + loadDefaultPage :: PageName -> IO (Maybe Page) loadDefaultPage pageName - -- ./data/Foo を探した後、Cabal で defaultPages/Foo を探す。 - = do let pagePath = encodePageName pageName - isInDataDir <- doesFileExist ("./data/" ++ pagePath) - if isInDataDir then - return . Just =<< loadPageFile pageName ("./data/" ++ pagePath) + -- ./defaultPages が存在するなら、./defaultPages/Foo を探す。無けれ + -- ば Cabal で defaultPages/Foo を探す。 + = do let pagePath = "defaultPages/" ++ encodePageName pageName + + localDirExists <- doesLocalDirExist + if localDirExists then + tryLoad pagePath else - do fpath <- getDataFileName ("defaultPages/" ++ pagePath) - isInstalled <- doesFileExist fpath - if isInstalled then - return . Just =<< loadPageFile pageName fpath - else - return Nothing + tryLoad =<< getDataFileName pagePath + where + tryLoad :: FilePath -> IO (Maybe Page) + tryLoad fpath + = do exists <- doesFileExist fpath + if exists then + return . Just =<< loadPageFile pageName fpath + else + return Nothing loadPageFile :: PageName -> FilePath -> IO Page loadPageFile name path - = do [page] <- runX ( constA (name, path) + = do [page] <- runX ( setErrorMsgHandler False fail + >>> + constA (name, path) >>> loadPageFileA ) @@ -47,30 +86,43 @@ loadPageFile name path loadPageFileA :: IOStateArrow s (PageName, FilePath) Page loadPageFileA = proc (name, fpath) -> - do tree <- readFromDocument [ (a_validate , v_0) - , (a_check_namespaces , v_1) - , (a_remove_whitespace, v_1) - ] -< fpath - parsePage -< (name, tree) + do tree <- readFromDocument [ (a_validate , v_0) + , (a_check_namespaces , v_1) + , (a_remove_whitespace, v_1) + ] -< fpath + lastMod <- arrIO (\ x -> getModificationTime x >>= toCalendarTime) -< fpath + parsePage -< (name, lastMod, tree) -parsePage :: (ArrowXml a, ArrowChoice a) => a (PageName, XmlTree) Page -parsePage - = proc (name, tree) +parsePage :: (ArrowXml a, ArrowChoice a) => a (PageName, CalendarTime, XmlTree) Page +parsePage + = proc (name, lastMod, tree) + -> do redirect <- maybeA (getXPathTreesInDoc "/page/@redirect/text()" >>> getText) -< tree + case redirect of + Nothing -> parseEntity -< (name, lastMod, tree) + Just dest -> returnA -< (Redirection { + redirName = name + , redirDest = dest + , redirRevision = Nothing + , redirLastMod = lastMod + }) + + +parseEntity :: (ArrowXml a, ArrowChoice a) => a (PageName, CalendarTime, XmlTree) Page +parseEntity + = proc (name, lastMod, tree) -> do mimeType <- (getXPathTreesInDoc "/page/@type/text()" >>> getText >>> arr read) -< tree - isTheme <- (maybeA (getXPathTreesInDoc "/page/@type/text()" >>> getText) - >>> defaultTo "no" + lang <- maybeA (getXPathTreesInDoc "/page/@lang/text()" >>> getText) -< tree + + isTheme <- (withDefault (getXPathTreesInDoc "/page/@isTheme/text()" >>> getText) "no" >>> parseYesOrNo) -< tree - isFeed <- (maybeA (getXPathTreesInDoc "/page/@isFeed/text()" >>> getText) - >>> defaultTo "no" + isFeed <- (withDefault (getXPathTreesInDoc "/page/@isFeed/text()" >>> getText) "no" >>> parseYesOrNo) -< tree - isLocked <- (maybeA (getXPathTreesInDoc "/page/@isLocked/text()" >>> getText) - >>> defaultTo "no" + isLocked <- (withDefault (getXPathTreesInDoc "/page/@isLocked/text()" >>> getText) "no" >>> parseYesOrNo) -< tree - isBoring <- (maybeA (getXPathTreesInDoc "/page/@isBoring/text()" >>> getText) - >>> defaultTo "no" + isBoring <- (withDefault (getXPathTreesInDoc "/page/@isBoring/text()" >>> getText) "no" >>> parseYesOrNo) -< tree summary <- (maybeA (getXPathTreesInDoc "/page/summary/text()" @@ -83,22 +135,26 @@ parsePage &&& getAttrValue0 "page")) -< tree - textData <- maybeA (getXPathTreesInDoc "/page/textData" >>> getText) -< tree - binaryData <- maybeA (getXPathTreesInDoc "/page/binaryData" >>> getText) -< tree + textData <- maybeA (getXPathTreesInDoc "/page/textData/text()" >>> getText) -< tree + binaryData <- maybeA (getXPathTreesInDoc "/page/binaryData/text()" >>> getText) -< tree - let content = case (textData, binaryData) of - (Just text, _ ) -> L8.pack text - (_ , Just binary) -> L8.pack $ B64.decode binary + let (isBinary, content) + = case (textData, binaryData) of + (Just text, _ ) -> (False, encodeLazy UTF8 text ) + (_ , Just binary) -> (True , L.pack $ B64.decode binary) - returnA -< Page { + returnA -< Entity { pageName = name , pageType = mimeType + , pageLanguage = lang , pageIsTheme = isTheme , pageIsFeed = isFeed , pageIsLocked = isLocked , pageIsBoring = isBoring - , pageRevision = Nothing + , pageIsBinary = isBinary + , pageRevision = 0 + , pageLastMod = lastMod , pageSummary = summary - , pageOtherLang = otherLang + , pageOtherLang = M.fromList otherLang , pageContent = content } \ No newline at end of file