module Generation.ServiceGenerator(generateService) where
import qualified Data.Map as M
import Data.Maybe (fromJust, fromMaybe, isJust)
import qualified Data.Set as S
import qualified Generation.TemplateCompiler as TC
import qualified TypeCheck.ApiSpec as AS
generateService :: AS.ApiSpec
-> (AS.Type -> String)
-> TC.Service
generateService apiSpec fieldMapping =
TC.Service (AS.name apiSpec)
(AS.version apiSpec)
(AS.requiresAuth apiSpec)
$ map (generateSchema fieldMapping apiSpec . fst) $ AS.structs apiSpec
generateSchema :: (AS.Type -> String)
-> AS.ApiSpec
-> AS.Id
-> TC.Schema
generateSchema fieldMapping apiSpec strId =
TC.Schema { TC.schemaName = strId
, TC.schemaRoute = schemaRoute'
, TC.writable = writable'
, TC.hasKeyField = hasKeyField
, TC.keyField = keyField
, TC.schemaVars = generateVars fieldMapping apiSpec structInfo }
where
(schemaRoute', writable') = maybe (Nothing, False) (\(r, w) -> (Just TC.StrValue { TC.value = r }, w)) (M.lookup strId $ AS.resources apiSpec)
structInfo = fromJust $ lookup strId $ AS.structs apiSpec
maybeKeyField = AS.getPrimaryKey structInfo
keyField = fromMaybe "" maybeKeyField
hasKeyField = isJust maybeKeyField
generateVars :: (AS.Type -> String)
-> AS.ApiSpec
-> AS.StructInfo
-> [TC.SchemaVar]
generateVars fieldMapping apiSpec = map getVarFromField
where
getVarFromField :: AS.FieldInfo -> TC.SchemaVar
getVarFromField (AS.FI (n, t, modifs)) = generateSchemaVar n t modifs
generateSchemaVar :: AS.Id -> AS.Type -> S.Set AS.Modifier -> TC.SchemaVar
generateSchemaVar name type' modifs =
TC.SchemaVar { TC.varName = name
, TC.varType = fieldMapping type'
, TC.isList = isList type'
, TC.isEnum = if isEnum type' then Just $ getValues type' else Nothing
, TC.isStruct = isStruct type'
, TC.isKey = AS.PrimaryKey `S.member` modifs
, TC.isRequired = AS.Required `S.member` modifs
, TC.isHidden = AS.Hidden `S.member` modifs
, TC.isUnique = AS.Unique `S.member` modifs || AS.PrimaryKey `S.member` modifs
, TC.isUserLogin = AS.UserLogin `S.member` modifs
}
where
getValues (AS.TEnum enumId) = TC.EnumValue $ map TC.StrValue (fromJust $ M.lookup enumId $ AS.enums apiSpec)
getValues (AS.TList t') = getValues t'
getValues other = error $ "getValues called on a non-enum type: " ++ show other
isEnum (AS.TEnum _) = True
isEnum (AS.TList t') = isEnum t'
isEnum _ = False
isList (AS.TList _) = True
isList _ = False
isStruct (AS.TStruct _) = True
isStruct (AS.TList t') = isStruct t'
isStruct _ = False