{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-} module Data.STAR.Path((./), (/<>), (->//) ,starBlocks ,filterP ,blocksByName ,entriesByName ,entryValue ,allEntriesByName ,flattenEntries) where import Prelude hiding(String) import Data.STAR.Type -- ^ This module presents a convenient, compositional interface for filtering -- Example use: -- > test1 :: STAR -> [String] -- > test1 = blocksByName "" ./ entriesByName "chemical_shifts" ./ entryValue -- Another example: -- > test2 :: STAR -> [String] -- > test2 = starBlocks ./ entries ./ entryValue -- | Path separator - serves as general function composition operator. infixr 3 ./ (./) :: (a -> [a1]) -> (a1 -> [b]) -> a -> [b] f ./ g = concatMap g . f -- | Path predicate operator - serves as general function composition operator. (/<>) :: (a -> b) -> (b -> Bool) -> a -> [b] f /<> g = filterP g . f infixl 1 ->// -- | Applies a path to a set of elements (not just a document, or single entry.) elts ->// path = concatMap path elts starBlocks :: STAR -> [STARBlock] starBlocks (STAR blocks) = blocks filterP :: (t -> Bool) -> t -> [t] f `filterP` x = [x | f x] -- STAR selectors are typed, and always return a list of results -- (in order to be conveniently used with concatMap and composition.) -- | Selects all block matching a given name or GLOBAL block for empty string. -- TODO: Regex for names? blocksByName :: String -> STAR -> [STAREntry] blocksByName name = starBlocks ./ filterP matches ./ entries where matches (Global _) = name =="" matches (Data { dataKey = key }) = key == name -- | Filter entries with a given name. Expand loops if necessary. entriesByName :: String -> STAREntry -> [STAREntry] entriesByName name es = matches es where matches (Loop table) = concatMap (concatMap matches) table matches e = [e | key e == name] -- | Extracts a string value from a flat entry. entryValue :: STAREntry -> [String] entryValue (Loop _) = [] entryValue (Frame _ _) = [] entryValue e = [value e] -- | Expands a possibly complex entry into a list of flat entries. flattenEntries :: STAREntry -> [STAREntry] flattenEntries (Loop l) = concat l flattenEntries (Frame _ l) = l flattenEntries e = [e] -- | Find all flat entries with a given name, and return their values. allEntriesByName name = starBlocks ./ entries ./ flattenEntries ./ entriesByName name ./ entryValue