module Network.TableStorage.Request (
propertyList,
entityKeyResource,
columnToTypeString,
printEntityColumn,
printComparisonType,
buildFilterString,
buildQueryString
) where
import Data.Time ( formatTime )
import System.Locale ( defaultTimeLocale )
import Data.Maybe ( fromMaybe )
import Data.List ( intercalate )
import Text.XML.Light.Types ( elAttribs )
import Text.XML.Light
( Element(elContent, elName),
Content(Elem),
Attr(Attr),
blank_element )
import Network.TableStorage.Types
( EntityFilter(..),
ComparisonType(..),
EntityQuery(eqFilter, eqPageSize),
EntityColumn(..),
EntityKey(ekPartitionKey, ekRowKey) )
import Network.TableStorage.XML ( cDataText )
import Network.TableStorage.Atom
( qualifyDataServices, qualifyMetadata )
import Network.TableStorage.Format ( atomDateFormat )
import Network.HTTP.Base ( urlEncode )
propertyList :: [(String, EntityColumn)] -> Element
propertyList props =
blank_element { elName = qualifyMetadata "properties",
elContent = map property props } where
property (key, value) =
let stringValue = printEntityColumn value in
Elem blank_element { elName = qualifyDataServices key,
elAttribs = [ Attr (qualifyMetadata "type") $ columnToTypeString value,
Attr (qualifyMetadata "null") $ maybe "true" (const "false") stringValue ],
elContent = cDataText $ fromMaybe "" stringValue }
entityKeyResource :: String -> EntityKey -> String
entityKeyResource tableName key = "/" ++ tableName ++ "(PartitionKey='" ++ ekPartitionKey key ++ "',RowKey='" ++ ekRowKey key ++ "')"
columnToTypeString :: EntityColumn -> String
columnToTypeString (EdmBinary _) = "Edm.Binary"
columnToTypeString (EdmBoolean _) = "Edm.Boolean"
columnToTypeString (EdmDateTime _) = "Edm.DateTime"
columnToTypeString (EdmDouble _) = "Edm.Double"
columnToTypeString (EdmGuid _) = "Edm.EdmGuid"
columnToTypeString (EdmInt32 _) = "Edm.Int32"
columnToTypeString (EdmInt64 _) = "Edm.Int64"
columnToTypeString (EdmString _) = "Edm.String"
printEntityColumn :: EntityColumn -> Maybe String
printEntityColumn (EdmBinary (Just val)) = Just val
printEntityColumn (EdmBoolean (Just True)) = Just "true"
printEntityColumn (EdmBoolean (Just False)) = Just "false"
printEntityColumn (EdmDateTime (Just val)) = Just $ formatTime defaultTimeLocale atomDateFormat val
printEntityColumn (EdmDouble (Just val)) = Just $ show val
printEntityColumn (EdmGuid (Just val)) = Just val
printEntityColumn (EdmInt32 (Just val)) = Just $ show val
printEntityColumn (EdmInt64 (Just val)) = Just $ show val
printEntityColumn (EdmString (Just val)) = Just val
printEntityColumn _ = Nothing
printComparisonType :: ComparisonType -> String
printComparisonType Equal = "eq"
printComparisonType GreaterThan = "gt"
printComparisonType GreaterThanOrEqual = "ge"
printComparisonType LessThan = "lt"
printComparisonType LessThanOrEqual = "le"
printComparisonType NotEqual = "ne"
buildFilterString :: EntityFilter -> String
buildFilterString (And fs) = '(' : intercalate "%20and%20" (map buildFilterString fs) ++ ")"
buildFilterString (Or fs) = '(' : intercalate "%20or%20" (map buildFilterString fs) ++ ")"
buildFilterString (Not f) =
"(not%20"
++ buildFilterString f
++ ")"
buildFilterString (CompareBoolean prop val) =
urlEncode prop
++ "%20eq%20"
++ if val then "true" else "false"
buildFilterString (CompareDateTime prop cmp val) =
urlEncode prop
++ "%20"
++ printComparisonType cmp
++ "%20datetime'"
++ formatTime defaultTimeLocale atomDateFormat val
++ "'"
buildFilterString (CompareDouble prop cmp val) =
urlEncode prop
++ "%20"
++ printComparisonType cmp
++ "%20"
++ show val
buildFilterString (CompareGuid prop val) =
urlEncode prop
++ "%20eq%20guid'"
++ val
++ "'"
buildFilterString (CompareInt32 prop cmp val) =
urlEncode prop
++ "%20"
++ printComparisonType cmp
++ "%20"
++ show val
buildFilterString (CompareInt64 prop cmp val) =
urlEncode prop
++ "%20"
++ printComparisonType cmp
++ "%20"
++ show val
buildFilterString (CompareString prop cmp val) =
urlEncode prop
++ "%20"
++ printComparisonType cmp
++ "%20'"
++ urlEncode val
++ "'"
buildQueryString :: EntityQuery -> String
buildQueryString query =
"$filter="
++ maybe "" buildFilterString (eqFilter query)
++ "&$top="
++ maybe "" show (eqPageSize query)