{-# LANGUAGE RecordWildCards #-}
module Data.Aeson.JSONPath.Query.Query
  ( qQuery
  , qQueryLocated
  )
  where

import Control.Monad                   (join)
import Data.Aeson                      (Value)
import Data.Vector                     (Vector)

import qualified Data.Vector           as V

import Data.Aeson.JSONPath.Types
import Data.Aeson.JSONPath.Query.Segment

import Prelude

-- | Runs the JSONPath Query
qQuery :: Query -> QueryState -> Vector Value
qQuery :: Query -> QueryState -> Vector Value
qQuery Query{[QuerySegment Query]
QueryType
queryType :: QueryType
querySegments :: [QuerySegment Query]
queryType :: Query -> QueryType
querySegments :: Query -> [QuerySegment Query]
..} qS :: QueryState
qS@QueryState{Value
Query -> QueryState -> Vector Value
rootVal :: Value
curVal :: Value
executeQuery :: Query -> QueryState -> Vector Value
rootVal :: QueryState -> Value
curVal :: QueryState -> Value
executeQuery :: QueryState -> Query -> QueryState -> Vector Value
..} = case QueryType
queryType of
  QueryType
Root    -> (Vector Value -> QuerySegment Query -> Vector Value)
-> Vector Value -> [QuerySegment Query] -> Vector Value
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Vector Value -> QuerySegment Query -> Vector Value
applySegment (Value -> Vector Value
forall a. a -> Vector a
V.singleton Value
rootVal) [QuerySegment Query]
querySegments
  QueryType
Current -> (Vector Value -> QuerySegment Query -> Vector Value)
-> Vector Value -> [QuerySegment Query] -> Vector Value
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Vector Value -> QuerySegment Query -> Vector Value
applySegment (Value -> Vector Value
forall a. a -> Vector a
V.singleton Value
curVal) [QuerySegment Query]
querySegments
  where
    applySegment :: Vector Value -> QuerySegment Query -> Vector Value
    applySegment :: Vector Value -> QuerySegment Query -> Vector Value
applySegment Vector Value
vec QuerySegment Query
seg = Vector (Vector Value) -> Vector Value
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Vector (Vector Value) -> Vector Value)
-> Vector (Vector Value) -> Vector Value
forall a b. (a -> b) -> a -> b
$ (Value -> Vector Value) -> Vector Value -> Vector (Vector Value)
forall a b. (a -> b) -> Vector a -> Vector b
V.map (\Value
x -> QuerySegment Query -> QueryState -> Vector Value
qQuerySegment QuerySegment Query
seg QueryState
qS{ curVal :: Value
curVal = Value
x }) Vector Value
vec

-- | Runs the JSONPath Query also returning node locations
qQueryLocated :: Query -> QueryState -> String -> Vector (String,Value)
qQueryLocated :: Query -> QueryState -> String -> Vector (String, Value)
qQueryLocated Query{[QuerySegment Query]
QueryType
queryType :: Query -> QueryType
querySegments :: Query -> [QuerySegment Query]
queryType :: QueryType
querySegments :: [QuerySegment Query]
..} qS :: QueryState
qS@QueryState{Value
Query -> QueryState -> Vector Value
rootVal :: QueryState -> Value
curVal :: QueryState -> Value
executeQuery :: QueryState -> Query -> QueryState -> Vector Value
rootVal :: Value
curVal :: Value
executeQuery :: Query -> QueryState -> Vector Value
..} String
loc = case QueryType
queryType of
  QueryType
Root    -> (Vector (String, Value)
 -> QuerySegment Query -> Vector (String, Value))
-> Vector (String, Value)
-> [QuerySegment Query]
-> Vector (String, Value)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Vector (String, Value)
-> QuerySegment Query -> Vector (String, Value)
applySegment ((String, Value) -> Vector (String, Value)
forall a. a -> Vector a
V.singleton (String
loc,Value
rootVal)) [QuerySegment Query]
querySegments
  QueryType
Current -> (Vector (String, Value)
 -> QuerySegment Query -> Vector (String, Value))
-> Vector (String, Value)
-> [QuerySegment Query]
-> Vector (String, Value)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Vector (String, Value)
-> QuerySegment Query -> Vector (String, Value)
applySegment ((String, Value) -> Vector (String, Value)
forall a. a -> Vector a
V.singleton (String
loc,Value
curVal)) [QuerySegment Query]
querySegments
  where
    applySegment :: Vector (String,Value) -> QuerySegment Query -> Vector (String,Value)
    applySegment :: Vector (String, Value)
-> QuerySegment Query -> Vector (String, Value)
applySegment Vector (String, Value)
vec QuerySegment Query
seg = Vector (Vector (String, Value)) -> Vector (String, Value)
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Vector (Vector (String, Value)) -> Vector (String, Value))
-> Vector (Vector (String, Value)) -> Vector (String, Value)
forall a b. (a -> b) -> a -> b
$ ((String, Value) -> Vector (String, Value))
-> Vector (String, Value) -> Vector (Vector (String, Value))
forall a b. (a -> b) -> Vector a -> Vector b
V.map (\(String
location,Value
cur) -> QuerySegment Query
-> QueryState -> String -> Vector (String, Value)
qQuerySegmentLocated QuerySegment Query
seg QueryState
qS{ curVal :: Value
curVal = Value
cur } String
location) Vector (String, Value)
vec