module Database.Persist.Zookeeper.Internal
where
import Control.Monad.IO.Class (MonadIO (..))
import Data.Monoid
import Data.Maybe
import qualified Data.Aeson as A
import qualified Data.Text as T
import Database.Persist.Types
import Database.Persist.Class
import Database.Persist.Zookeeper.Binary
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as BL
import qualified Data.ByteString.Base64.URL as B64
import qualified Data.Map as M
txtToKey :: (PersistEntity val) => String -> Key val
txtToKey txt =
case (keyFromValues [PersistText (T.pack txt)]) of
Right v -> v
Left _v ->
case B64.decode $ B.pack txt of
Left v -> error $ v
Right v' ->
case A.decode $ BL.fromStrict v' of
Just values ->
case (keyFromValues values) of
Right v -> v
Left v -> error $ T.unpack v
Nothing -> error "failed"
keyToTxt :: (PersistEntity val) => Key val -> String
keyToTxt key =
case keyToValues key of
[PersistText txt] -> T.unpack txt
v -> B.unpack $ B64.encode $ BL.toStrict $ A.encode $ v
dummyFromKey :: Key v -> Maybe v
dummyFromKey _ = Nothing
dummyFromFList :: [Filter v] -> v
dummyFromFList _ = error "huga"
dummyFromUnique :: Unique v -> Maybe v
dummyFromUnique _ = Nothing
val2table :: (PersistEntity val) => val -> T.Text
val2table = unDBName . entityDB . entityDef . Just
uniqkey2key :: (PersistEntity val) => Unique val -> Key val
uniqkey2key uniqkey = txtToKey $ (B.unpack $ B64.encode $ BL.toStrict $ A.encode $ persistUniqueToValues uniqkey)
val2uniqkey :: (MonadIO m, PersistEntity val) => val -> m (Maybe (Unique val))
val2uniqkey val = do
case persistUniqueKeys val of
(uniqkey:_) -> return $ Just uniqkey
[] -> return Nothing
entity2bin :: (PersistEntity val) => val -> B.ByteString
entity2bin val = toValue (map toPersistValue (toPersistFields val))
bin2entity :: (PersistEntity val) => B.ByteString -> Maybe val
bin2entity bin =
case fromPersistValues (fromValue bin) of
Right body -> Just $ body
Left s -> error $ T.unpack s
entity2path :: (PersistEntity val) => val -> String
entity2path val = "/" <> (T.unpack $ val2table val)
key2path :: (PersistEntity val) => Key val -> String
key2path key = entity2path $ fromJust $ dummyFromKey key
filter2path :: (PersistEntity val) => [Filter val] -> String
filter2path filterList = entity2path $ dummyFromFList filterList
getMap :: PersistEntity val => val -> M.Map T.Text PersistValue
getMap val = M.fromList $ getList val
getList :: PersistEntity val => val -> [(T.Text,PersistValue)]
getList val =
let fields = fmap toPersistValue (toPersistFields val)
in zip (getFieldsName val) fields
getFieldsName :: (PersistEntity val) => val -> [T.Text]
getFieldsName val = fmap (unDBName.fieldDB) $ entityFields $ entityDef $ Just val
getFieldName :: (PersistEntity val) => EntityField val typ -> T.Text
getFieldName field = unDBName $ fieldDB $ persistFieldDef $ field
fieldval :: (PersistEntity val) => EntityField val typ -> val -> PersistValue
fieldval field val = (getMap val) M.! (getFieldName field)
updateEntity :: PersistEntity val => val -> [Update val] -> Either T.Text val
updateEntity val upds =
fromPersistValues $ map snd $ foldl updateVals (getList val) upds
updateVals :: PersistEntity val => [(T.Text,PersistValue)] -> Update val -> [(T.Text,PersistValue)]
updateVals [] _ = []
updateVals ((k,v):xs) u@(Update field _ _) =
if getFieldName field == k
then (k,updateVal v u):xs
else (k,v):updateVals xs u
updateVals a _ = error $"not supported vals:" ++ show a
updateVal :: PersistEntity val => PersistValue -> Update val -> PersistValue
updateVal _org (BackendUpdate _) = error $ "BackendUpdate is not supported."
updateVal org (Update _ val upd) =
case upd of
Assign -> pval
Add -> numAdd org pval
Subtract -> numSub org pval
Multiply -> numMul org pval
Divide -> numDiv org pval
BackendSpecificUpdate _ -> error $ "BackendSpecificUpdate is not supported."
where
pval = toPersistValue val
numAdd (PersistInt64 l) (PersistInt64 r) = (PersistInt64 (l + r))
numAdd (PersistNull) (PersistInt64 r) = (PersistInt64 r)
numAdd (PersistDouble l) (PersistDouble r) = (PersistDouble (l + r))
numAdd (PersistNull) (PersistDouble r) = (PersistDouble r)
numAdd o _ = error $ "not support : " ++ show o
numSub (PersistInt64 l) (PersistInt64 r) = (PersistInt64 (l r))
numSub (PersistNull) (PersistInt64 r) = (PersistInt64 (0 r))
numSub (PersistDouble l) (PersistDouble r) = (PersistDouble (l r))
numSub (PersistNull) (PersistDouble r) = (PersistDouble (0 r))
numSub _ _ = error "not support"
numMul (PersistInt64 l) (PersistInt64 r) = (PersistInt64 (l * r))
numMul (PersistNull) (PersistInt64 r) = (PersistInt64 (0 * r))
numMul (PersistDouble l) (PersistDouble r) = (PersistDouble (l * r))
numMul (PersistNull) (PersistDouble r) = (PersistDouble (0 * r))
numMul _ _ = error "not support"
numDiv (PersistInt64 l) (PersistInt64 r) = (PersistInt64 (l `div` r))
numDiv (PersistNull) (PersistInt64 r) = (PersistInt64 (0 `div` r))
numDiv (PersistDouble l) (PersistDouble r) = (PersistDouble (l / r))
numDiv (PersistNull) (PersistDouble r) = (PersistDouble (0 / r))
numDiv _ _ = error "not support"