module Network.TableStorage.Request where
import Data.Time
import System.Locale
import Data.Maybe (fromMaybe)
import Data.List (intercalate)
import Text.XML.Light.Types (elAttribs)
import Text.XML.Light
import Network.TableStorage.Types
import Network.TableStorage.XML
import Network.TableStorage.Atom
import Network.TableStorage.Format
import Network.HTTP.Base
import Text.Printf (printf)
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 :: Account -> String -> EntityKey -> String
entityKeyResource acc tableName key = printf "/%s/%s(PartitionKey='%s',RowKey='%s')"
(accountName acc)
tableName
(ekPartitionKey key)
(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 $ printf "%f" val
printEntityColumn (EdmGuid (Just val)) = Just val
printEntityColumn (EdmInt32 (Just val)) = Just $ printf "%d" val
printEntityColumn (EdmInt64 (Just val)) = Just $ printf "%d" 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) = printf "(%s)" $ intercalate "%%20and%%20" $ map buildFilterString fs
buildFilterString (Or fs) = printf "(%s)" $ intercalate "%%20or%%20" $ map buildFilterString fs
buildFilterString (Not f) = "(not%%20" ++ buildFilterString f ++ ")"
buildFilterString (CompareBoolean prop val) = printf "%s%%20eq%%20%s" (urlEncode prop) (if val then "true" else "false")
buildFilterString (CompareDateTime prop cmp val) = printf "%s%%20%s%%20datetime'%s'" (urlEncode prop) (printComparisonType cmp) (formatTime defaultTimeLocale atomDateFormat val)
buildFilterString (CompareDouble prop cmp val) = printf "%s%%20%s%%20%f" (urlEncode prop) (printComparisonType cmp) val
buildFilterString (CompareGuid prop val) = printf "%s%%20eq%%20guid'%s'" (urlEncode prop) val
buildFilterString (CompareInt32 prop cmp val) = printf "%s%%20%s%%20%d" (urlEncode prop) (printComparisonType cmp) val
buildFilterString (CompareInt64 prop cmp val) = printf "%s%%20%s%%20%d" (urlEncode prop) (printComparisonType cmp) val
buildFilterString (CompareString prop cmp val) = printf "%s%%20%s%%20'%s'" (urlEncode prop) (printComparisonType cmp) (urlEncode val)
buildQueryString :: EntityQuery -> String
buildQueryString query = printf "$filter=%s&$top=%s"
(maybe "" buildFilterString $ eqFilter query)
(maybe "" show $ eqPageSize query)