packages feed

hxt-7.1: examples/arrows/RelaxTestSuite/ReadDir.hs

{- |
   Read a complete directory hierarchy and return it as a tree.
   Copied and modified from Peter Simons (<http://cryp.to/>).

   $Id: ReadDir.hs,v 1.1 2005/09/02 17:09:38 hxml Exp $
   
-}

module ReadDir
    ( Entry(..)
    , readDir
    )

where

import System.Directory
  ( getDirectoryContents
  , doesDirectoryExist
  )
import Data.List
  ( find
  , isSuffixOf
  )
import Maybe
  ( fromMaybe )


data Entry = Dir [Entry] -- ^ Directory with a list of subdirectories and files
           | DirContent FilePath [FilePath] -- ^ Relax NG schema and list of XML documents
     deriving Show


-- ------------------------------------------------------------

-- |
-- Read the complete directory hierarchy starting at the FilePath given by the first 
-- parameter and return a tree representing it. Directories contain their
-- sub-entries in alphabetic order.
--
-- Each 'DirContent' represents a Relax NG schema and all XML Documents
-- in the directory.
--
-- The function may throw exceptions when IO fails.

readDir :: FilePath -> FilePath -> IO Entry
readDir pre p
  = do 
    dir     <- getDirectoryContents $ pre ++ "/" ++ p
    entries <- getEntries $ clean [".", "..", "CVS"] dir
    return $ Dir entries
  where
  getEntries :: [FilePath] -> IO [Entry]
  getEntries xs
    = do
      dirs     <- mapM toEntryDir xs
      files    <- mapM toEntryFiles xs
      xmlfiles <- return $ [ f | f <- files, ".xml" `isSuffixOf` f]
      rngfile  <- return $ fromMaybe "" $ find (".rng" `isSuffixOf`) files
      return $ if rngfile /= ""
              then (DirContent rngfile xmlfiles):dirs
              else dirs
  
  toEntryDir :: FilePath -> IO Entry
  toEntryDir x = do
              isDir <- doesDirectoryExist $ path ++ "/" ++ x
              if isDir then readDir path x else return $ Dir []
              where path = pre ++ "/" ++ p              
  
  toEntryFiles :: FilePath -> IO FilePath
  toEntryFiles x = do
                  isDir <- doesDirectoryExist path
                  return $ if isDir then "" else path 
              where path = pre ++ p ++ "/" ++ x              
  
  clean :: [String] -> [FilePath] -> [FilePath]
  clean ver xs = [ x | x <- xs, not $ elem x ver]

-- ------------------------------------------------------------