concrete-haskell-0.1.0.13: src/Data/Concrete/Utils.hs
{-# LANGUAGE DeriveGeneric, OverloadedStrings, FlexibleInstances #-}
module Data.Concrete.Utils
(
getUUID
, createAnnotationMetadata
, writeCommunication
, showCommunication
, commToString
, incrementUUID
, stringToComm
) where
import GHC.Generics
import Path.IO (resolveFile')
import Data.Concrete.Autogen.Communication_Types (Communication(..), default_Communication, read_Communication, write_Communication)
import Data.Concrete.Autogen.Structure_Types (Section(..))
import Data.Concrete.Autogen.Uuid_Types (UUID(..))
import Data.Concrete.Autogen.Metadata_Types (AnnotationMetadata(..), default_AnnotationMetadata)
import Data.Concrete.Autogen.Spans_Types (TextSpan(..))
import Data.Concrete.Autogen.Service_Iface (Service_Iface(about, alive))
import Data.Concrete.Autogen.Services_Types (ServiceInfo(..))
import Data.Concrete.Autogen.Access_Types (FetchResult(..), default_FetchResult)
import Data.Concrete.Autogen.StoreCommunicationService_Iface (StoreCommunicationService_Iface(store))
import Data.Concrete.Autogen.FetchCommunicationService_Iface (FetchCommunicationService_Iface(fetch))
import qualified Data.Concrete.Autogen.StoreCommunicationService as StoreCommunicationService
import Data.Text
import Data.Either (rights)
import Data.Maybe (fromJust, maybeToList, fromMaybe)
import Data.ByteString.Lazy
import Data.Map
import Data.UUID.V4 (nextRandom)
import Data.UUID (toString, toWords, fromWords, fromString, nil)
import qualified Data.UUID as U
import qualified Data.Text.Lazy as T
import Thrift
import Thrift.Transport.Handle hiding (HandleSource)
import Thrift.Transport.Framed
import Thrift.Transport.Empty
import Thrift.Protocol.Compact
import Thrift.Protocol
import Thrift.Transport.IOBuffer
import Thrift.Transport
import Thrift.Server (runThreadedServer)
import qualified Data.List as L
import qualified Data.Map as Map
import qualified Data.ByteString as BSS
import qualified Data.ByteString.Lazy as BS
import qualified Codec.Compression.GZip as GZip
import qualified Codec.Compression.BZip as BZip
import qualified Codec.Archive.Tar as Tar
import qualified Codec.Archive.Zip as Zip
import qualified Codec.Archive.Tar.Entry as Tar
import qualified Codec.Archive.Tar.Index as Tar
import Data.Time
import Data.Time.Clock.POSIX
import System.FilePath (takeFileName, (</>), (<.>))
import Data.Either (rights)
import Control.Monad (liftM, join)
import Data.Foldable (foldr)
import System.IO (Handle)
import qualified Data.Vector as V
import qualified Data.Binary.Get as G
import qualified Control.Monad.Extra as E
getUUID :: IO UUID
getUUID = do
uuid <- (T.pack . toString) <$> nextRandom
return $ UUID uuid
incrementUUID :: UUID -> UUID
incrementUUID (UUID u) = case toWords (fromMaybe nil $ fromString (T.unpack u)) of
(a, b, c, d) -> UUID $ (T.pack . toString) (fromWords a b c (d + 1))
writeCommunication :: Handle -> Communication -> IO ()
writeCommunication out c = do
t <- commToString c
BS.hPutStr out t
entryToString :: Tar.EntryContent -> BS.ByteString
entryToString (Tar.NormalFile s _) = s
data TString = TString ReadBuffer WriteBuffer
getWrite :: TString -> WriteBuffer
getWrite (TString r w) = w
getRead :: TString -> ReadBuffer
getRead (TString r w) = r
newTString = do
w <- newWriteBuffer
r <- newReadBuffer
return $ TString r w
instance Transport TString where
tIsOpen (TString r w) = do
p <- peekBuf r
case p of
Nothing -> return False
_ -> return True
tClose (TString r w) = case peekBuf r of
_ -> return ()
tRead (TString r w) i = readBuf r i
tPeek (TString r w) = peekBuf r
tWrite (TString r w) bs = writeBuf w bs
tFlush (TString r w) = flushBuf w >> return ()
commToString :: Communication -> IO BS.ByteString
commToString c = do
otransport <- newTString
let oproto = CompactProtocol otransport
write_Communication oproto c
flushBuf (getWrite otransport)
stringToComm :: BS.ByteString -> IO Communication
stringToComm s = do
otransport@(TString r w) <- newTString
fillBuf r s
let oproto = CompactProtocol otransport
read_Communication oproto
createAnnotationMetadata :: String -> IO AnnotationMetadata
createAnnotationMetadata s = do
time <- round `fmap` getPOSIXTime
return default_AnnotationMetadata { annotationMetadata_tool=T.pack s
, annotationMetadata_timestamp=time
}
showSection :: T.Text -> Section -> T.Text
showSection t s = T.concat [" ", ((fromMaybe "*NO LABEL*" . section_label) s), " == ", t']
where
TextSpan s' e' = (fromJust . section_textSpan) s
k = section_kind s
t' = substr t (fromIntegral s') (fromIntegral e')
substr :: T.Text -> Int -> Int -> T.Text
substr t s e = res
where
(_, start) = T.splitAt (fromIntegral s) t
res = T.take (fromIntegral $ e - s) start
showCommunication :: Communication -> T.Text
showCommunication c = T.concat [communication_id c, " ", communication_type c, "\n Content sections:\n", T.intercalate "\n" contentSects, "\n ", metadataText]
where
ss = L.concat $ L.map V.toList (maybeToList (communication_sectionList c))
t = (fromJust . communication_text) c
contentSects = L.map (showSection t) ((L.filter (\x -> section_kind x == "content")) ss)
metadataSects = L.map (fromMaybe "?" . section_label) ((L.filter (\x -> section_kind x /= "content")) ss)
--metadataText = T.intercalate ", " metadataSects
metadataText = T.concat [(T.pack . show) (L.length metadataSects), " metadata sections"]