harmony-0.1.0.0: src/Generation/ServiceGenerator.hs
-- | Generation of 'TC.Service' objects from the specification.
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
-- | Transforms an api specification to a service.
generateService :: AS.ApiSpec -- ^ The specification of the web service
-> (AS.Type -> String) -- ^ A mapping from internal types to target's types
-> TC.Service
generateService apiSpec fieldMapping =
TC.Service (AS.name apiSpec)
(AS.version apiSpec)
(AS.requiresAuth apiSpec)
$ map (generateSchema fieldMapping apiSpec . fst) $ AS.structs apiSpec
-- | Generates the information of a resource/struct.
generateSchema :: (AS.Type -> String) -- ^ A mapping from internal types to target's types
-> AS.ApiSpec -- ^ The specification of the web service
-> AS.Id -- ^ The name of the struct
-> 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
-- Leave empty if it doesn't exist
keyField = fromMaybe "" maybeKeyField
hasKeyField = isJust maybeKeyField
-- | Generates the information of the fields of a 'TC.Schema'.
generateVars :: (AS.Type -> String) -- ^ A mapping from internal types to target's types
-> AS.ApiSpec -- ^ The specification of the web service
-> AS.StructInfo -- ^ The information of the struct
-> [TC.SchemaVar] -- ^ The information of all the fields of the schema
generateVars fieldMapping apiSpec = map getVarFromField
where
getVarFromField :: AS.FieldInfo -> TC.SchemaVar
getVarFromField (AS.FI (n, t, modifs)) = generateSchemaVar n t modifs
-- TODO(6): implement custom fields
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