module Text.HJson.Query
(
Jsons
,JFilter
,emptyObj
,(-->)
,(<>)
,(<.>)
,merges
,mergesRec
,isObj
,isArr
,isStr
,isStrBy
,isNum
,isNumBy
,isBool
,isNull
,isPrimitive
,getFromKeys
,getFromObj
,getFromArr
,getFromIndex
,getFromIndexes
,getChildern
,getFromKey
,(>>>)
,(<+>)
,orElse
,when
,guards
,deepObj
,deepArr
,deep
)
where
import qualified Data.Map as M (empty, singleton, unionWith, elems, union, lookup)
import qualified Data.Maybe as Mb (catMaybes)
import qualified Data.List as L (nub)
import qualified Text.HJson.Pretty as PP (toString)
import Text.HJson
type Jsons = [Json]
type JFilter = Json -> Jsons
infixl 1 >>>
infixr 2 <+>
infixr 3 <>
infixr 3 <.>
infixr 4 -->
emptyObj :: Json
emptyObj = JObject (M.empty)
(-->) :: String -> Json -> Json
key --> val = JObject (M.singleton key val)
(<>) :: Json -> Json -> Json
(JObject x ) <> (JObject y) = JObject $ M.union x y
(<>) _ _ = emptyObj
(<.>) :: Json -> Json -> Json
(JObject x) <.> (JObject y) = JObject $ M.unionWith (\m n -> m <.> n) x y
(<.>) _ _ = emptyObj
merges :: [Json] -> Json
merges [] = emptyObj
merges js = foldl1 (<>) js
mergesRec :: [Json] -> Json
mergesRec js = foldl (<.>) emptyObj js
isObj :: JFilter
isObj (JObject o) = [JObject o]
isObj _ = []
isArr :: JFilter
isArr (JArray a) = [JArray a]
isArr _ = []
isStr :: JFilter
isStr (JString s) = [JString s]
isStr _ = []
isStrBy :: (String -> Bool) -> JFilter
isStrBy p (JString s) = if p s then [JString s] else []
isStrBy _ _ = []
isNum :: JFilter
isNum (JNumber n) = [JNumber n]
isNum _ = []
isNumBy :: Fractional a => (a -> Bool) -> JFilter
isNumBy p (JNumber n) = if p (fromRational n) then [JNumber n] else []
isNumBy _ _ = []
isBool :: JFilter
isBool (JBool p) = [JBool p]
isBool _ = []
isNull :: JFilter
isNull JNull = [JNull]
isNull _ = []
isPrimitive :: JFilter
isPrimitive (JString s) = [JString s]
isPrimitive (JNumber n) = [JNumber n]
isPrimitive (JBool p) = [JBool p]
isPrimitive JNull = [JNull]
isPrimitive _ = []
getFromKey :: String -> JFilter
getFromKey k (JObject m) = Mb.catMaybes [(M.lookup k m)]
getFromKey _ _ = []
getFromKeys :: [String] -> JFilter
getFromKeys ks (JObject m) = Mb.catMaybes $ map (\k -> (M.lookup k m)) (L.nub ks)
getFromKeys _ _ = []
getFromObj :: JFilter
getFromObj (JObject o) = M.elems o
getFromObj _ = []
getFromArr :: JFilter
getFromArr (JArray a) = a
getFromArr _ = []
getFromIndex :: Int -> JFilter
getFromIndex i (JArray a) = if i < length a then [a !! i] else []
getFromIndex _ _ = []
getFromIndexes :: [Int] -> JFilter
getFromIndexes is ja = concat [getFromIndex i ja | i <- is]
getChildern :: JFilter
getChildern (JObject o) = M.elems o
getChildern (JArray a) = a
getChildern _ = []
(>>>) :: JFilter -> JFilter -> JFilter
(f >>> g) t = concat [g t' | t' <- f t]
(<+>) :: JFilter -> JFilter -> JFilter
(f <+> g) t = f t ++ g t
orElse :: JFilter -> JFilter -> JFilter
orElse f g t
| null res1 = g t
| otherwise = res1
where
res1 = f t
when :: JFilter -> JFilter -> JFilter
when f g t
| null (g t) = [t]
| otherwise = f t
guards :: JFilter -> JFilter -> JFilter
guards g f t
| null (g t) = []
| otherwise = f t
deepObj :: JFilter -> JFilter
deepObj f = f `orElse` (getFromObj >>> deepObj f)
deepArr :: JFilter -> JFilter
deepArr f = f `orElse` (getFromArr >>> deepArr f)
deep :: JFilter -> JFilter
deep f = f `orElse` (getChildern >>> deep f)