-- | 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