public static void GenerateEntityFactory(JToken entities, string rootFilePath, Compilation compilation) { var entityFactory = new ClassContainer { Name = "FoundationFactory", Namespace = UsingKeys.FOUNDATION_FACTORY_CLASS, FilePath = $"{rootFilePath}/FoundationFactory.cs", DocString = "Foundation Factory", }; entityFactory.AddUsing(nameof(UsingKeys.SDK_COMMON), UsingKeys.SDK_COMMON); entityFactory.AddUsing(nameof(UsingKeys.FOUNDATION), UsingKeys.FOUNDATION); entityFactory.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityFactory.AddModifier(nameof(Modifiers.PARTIAL), Modifiers.PARTIAL); foreach (var entity in entities.Where(e => e["methods"].Any())) { var factoryMethod = new EntityFactoryMethodContainer { Name = $"{entity["_key"].GetStringValue().ToPascal()}Repository", Returns = $"{entity["_key"].GetStringValue().ToPascal()}Repository", MethodParams = new MethodParameterContainer(), }; factoryMethod.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityFactory.AddMethod(entity["_key"].GetStringValue(), factoryMethod); } compilation.AddClass(nameof(entityFactory), entityFactory); }
public static void GenerateRepository(JToken entity, string entityPascalName, string rootFilePath, string entityGroup, Compilation compilation) { var entityRepository = new ClassContainer(); // namespace entityRepository.Namespace = UsingKeys.FOUNDATION; // modifier entityRepository.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); // name entityRepository.Name = $"{entityPascalName}Repository"; // base type entityRepository.AddBaseType("BASE_ENTITY", "Repository"); entityRepository.AddUsing(nameof(UsingKeys.SDK_COMMON), UsingKeys.SDK_COMMON); // add interface entityRepository.AddBaseType("INTERFACE", $"I{entityRepository.Name}"); // doc (just use the name for now) entityRepository.DocString = entityRepository.Name; // set the filepath root/groupId/Class/Class.cs entityRepository.FilePath = $"{rootFilePath}/{entityGroup}/{entityPascalName}/"; entityRepository.FileName = $"{entityRepository.Name}.cs"; //default constructor var defaultConstructor = new ConstructorContainer { Name = entityRepository.Name, }; defaultConstructor.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityRepository.AddConstructor("DEFAULT", defaultConstructor); // config constructor var configConstructor = new DefaultConfigConstructorContainer { Name = entityRepository.Name }; configConstructor.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityRepository.AddConstructor("CONFIG", configConstructor); // get methods var methods = entity["methods"]; foreach (var method in methods) { // gather common info var methodName = method["_key"].GetStringValue().ToPascal(); // the http method var httpMethod = method["method"].GetStringValue()?.ToUpper() ?? "GET"; // if method return type is void var isVoid = httpMethod == "DELETE" ? true : false; // the path var path = method["path"].GetStringValue(); // is method paginated var isPaginated = method["pagination"].GetBoolValue(); // is method private var isPrivateMethod = method["private_method"] != null; // is method a custom call var isCustomMethodCall = method["custom_method"] != null; // does method return a foreing key var foreignKey = method["return_info"]["self"].GetBoolValue() == false && TypeHelpers.MapType(method["return_info"]["type"].GetStringValue()) == null; // return type var returns = TypeHelpers.MapType(method["return_info"]["type"].GetStringValue()) ?? method["return_info"]["type"].GetStringValue().ToPascal(); if (returns == "Void") { returns = entityPascalName; isVoid = true; } // name of custom method var customMethodName = method["custom_method"].GetStringValue().ToPascal(); if (isPaginated) { // add usings for paginated } if (foreignKey) { // add using for foreign key entityRepository.AddUsing("FOREIGN_KEY", UsingKeys.FOUNDATION); } var hasRequest = false; // gather internal parameters var pathParams = new List <MyParameterContainer>(); var queryParams = new List <MyParameterContainer>(); var bodyParams = new List <MyParameterContainer>(); var fileParams = new List <MyParameterContainer>(); var formParams = new List <MyParameterContainer>(); // does method need a request param if (method["fields"].Any(f => f["in"].GetStringValue() == "body")) { var requestParam = new MyParameterContainer { Key = "request", ParamType = returns ?? "string", External = true, Required = true, FieldName = "request", }; bodyParams.Add(requestParam); hasRequest = true; } foreach (var field in method["fields"]) { var _key = field["_key"].GetStringValue()?.ToPascal(); var _name = field["name"].GetStringValue(); var _api_fieldname = field["api_fieldname"].GetStringValue(); var _entity_fieldname = field["entity_fieldname"].GetStringValue()?.ToPascal(); var _parameter_fieldname = field["parameter_fieldname"].GetStringValue(); // TODO remove as soon as fixed in generator. Truly awful hack if (_name == "device_id" && entityPascalName == "Device") { _name = "id"; } // where is parameter? var paramIn = field["in"].GetStringValue(); // is it external? var external = field["external_param"].GetBoolValue(); // is it required? var required = field["required"].GetBoolValue(); // the type string type = null; // replace body with other type var replaceBody = field["__REPLACE_BODY"] != null; var defaultValue = field["minimum"].GetStringValue() ?? field["default"].GetStringValue(); var internalVal = field["items"] != null ? field["items"]["type"].GetStringValue() : null; type = TypeHelpers.GetAdditionalProperties(field) ?? TypeHelpers.MapType(field["type"].GetStringValue(), internalVal) ?? "string"; if (type == "Stream") { entityRepository.AddUsing(nameof(UsingKeys.SYSTEM_IO), UsingKeys.SYSTEM_IO); } if (paramIn == "path") { var param = new MyParameterContainer { Key = _entity_fieldname, ParamType = type, External = true, Required = required, FieldName = _name ?? _parameter_fieldname ?? _api_fieldname, DefaultValue = defaultValue, }; pathParams.Add(param); } if (paramIn == "query") { var param = new MyParameterContainer { Key = _entity_fieldname, ParamType = type, External = true, Required = required, FieldName = _name ?? _api_fieldname, DefaultValue = defaultValue, }; queryParams.Add(param); } if (paramIn == "body") { var param = new MyParameterContainer { Key = _name?.ToPascal() ?? _entity_fieldname, ParamType = type, External = external, Required = required, ReplaceBody = replaceBody, FieldName = _api_fieldname, CallContext = external ? null : "request", DefaultValue = defaultValue, }; bodyParams.Add(param); } if (paramIn == "stream") { if (field["type"].GetStringValue() == "file") { var param = new MyParameterContainer { Key = _entity_fieldname, ParamType = type, External = true, Required = required, FieldName = _name ?? _api_fieldname, DefaultValue = defaultValue, }; fileParams.Add(param); } else { var param = new MyParameterContainer { Key = _entity_fieldname, ParamType = type, External = true, Required = required, FieldName = _name ?? _api_fieldname, DefaultValue = defaultValue, }; formParams.Add(param); } } } var filter = method["x_filter"]; if (filter.Any()) { foreach (var filterValue in filter) { if (filterValue is JProperty filterValueProperty) { var filterValueName = filterValueProperty.Name; var apiFilterName = filterValueName; var correspondingField = entity["fields"].FirstOrDefault(f => f["_key"].GetStringValue() == filterValueName); if (correspondingField != null) { apiFilterName = correspondingField["api_fieldname"].GetStringValue(); } var filterOperators = filterValueProperty.Children().FirstOrDefault(); if (filterOperators != null) { filterOperators.Children().ToList().ForEach(f => { var filterOperator = f.GetStringValue(); var filterQueryKey = $"{apiFilterName}__{filterOperator}"; var filterParam = new MyParameterContainer { Key = $"Filter.GetEncodedValue(\"{filterValueName}\", \"${filterOperator}\")", ParamType = "string", Required = false, FieldName = filterQueryKey, External = false, }; queryParams.Add(filterParam); }); } } } } var methodParams = new MyMethodParameterContainer(pathParams, isPaginated ? new List <MyParameterContainer>() : queryParams, bodyParams, fileParams, formParams); // method is paginated, so create paginatedMethodContainer if (isPaginated == true) { var listOptionsName = CustomQueryOptionsGenerator.GenerateCustomQueryOptions(method, entity["fields"], entityPascalName, returns, rootFilePath, entityGroup, compilation); methodParams.Parameters.Insert(0, new MyParameterContainer { Key = "options", ParamType = $"I{listOptionsName}", Required = false, }); var paginatedMethodContainer = new PaginatedMethodContainer { EntityName = entityPascalName, Name = methodName, HttpMethod = httpMethod, Path = path, Paginated = isPaginated, Returns = returns, PathParams = pathParams, QueryParams = queryParams, BodyParams = bodyParams, FileParams = fileParams, FormParams = formParams, MethodParams = methodParams, CustomMethodCall = isCustomMethodCall, CustomMethodName = customMethodName, privateMethod = isPrivateMethod, ListOptionsName = $"I{listOptionsName}", }; paginatedMethodContainer.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityRepository.AddMethod(paginatedMethodContainer.Name, paginatedMethodContainer); } else if (isCustomMethodCall) { var customMethodParams = new MethodParameterContainer(); customMethodParams.Parameters = new List <ParameterContainer>() { new MyParameterContainer { Key = "model", ParamType = entityPascalName, Required = true, External = true, FieldName = "model", } }; // custom method call var customFunctionMethodContainer = new CustomFunctionMethodContainer { EntityName = entityPascalName, Name = methodName, Returns = returns, MethodParams = customMethodParams, CustomMethodCall = isCustomMethodCall, CustomMethodName = customMethodName, privateMethod = isPrivateMethod, IsAsync = true, }; customFunctionMethodContainer.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityRepository.AddMethod(customFunctionMethodContainer.Name, customFunctionMethodContainer); } else { var methodContainer = new DefaultMethodContainer() { EntityName = entityPascalName, Name = methodName, HttpMethod = httpMethod, Path = path, Paginated = isPaginated, Returns = returns, PathParams = pathParams, QueryParams = queryParams, BodyParams = bodyParams, FileParams = fileParams, FormParams = formParams, MethodParams = methodParams, CustomMethodCall = isCustomMethodCall, CustomMethodName = customMethodName, privateMethod = isPrivateMethod, IsAsync = true, HasRequest = hasRequest, IsVoidTask = isVoid, UseAnnonBody = ((methodName == "AddToGroup" || methodName == "RemoveFromGroup") && entityPascalName == "Device") }; if (isPrivateMethod) { methodContainer.AddModifier(nameof(Modifiers.INTERNAL), Modifiers.INTERNAL); } else { methodContainer.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); } entityRepository.AddMethod(methodContainer.Name, methodContainer); } } if (methods.Any()) { entityRepository.AddUsing(nameof(UsingKeys.ASYNC), UsingKeys.ASYNC); entityRepository.AddUsing(nameof(UsingKeys.EXCEPTIONS), UsingKeys.EXCEPTIONS); entityRepository.AddUsing(nameof(UsingKeys.GENERIC_COLLECTIONS), UsingKeys.GENERIC_COLLECTIONS); entityRepository.AddUsing(nameof(UsingKeys.SYSTEM), UsingKeys.SYSTEM); entityRepository.AddUsing(nameof(UsingKeys.CLIENT), UsingKeys.CLIENT); } compilation.AddClass(entityRepository.Name, entityRepository); var entityRepositoryInterface = entityRepository.Copy(); // entityRepositoryInterface.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityRepositoryInterface.Name = $"I{entityRepository.Name}"; entityRepositoryInterface.FilePath = $"{rootFilePath}/{entityGroup}/{entityPascalName}/"; entityRepositoryInterface.FileName = $"I{entityRepository.FileName}"; entityRepositoryInterface.BaseTypes.Clear(); entityRepositoryInterface.IsInterface = true; compilation.AddClass(entityRepositoryInterface.Name, entityRepositoryInterface); }
public static void GenerateEntityClass(JToken entity, string entityPascalName, string rootFilePath, string entityGroup, Compilation compilation) { var entityClass = new ClassContainer(); // namespace entityClass.Namespace = UsingKeys.FOUNDATION; // modifier (just public for now) entityClass.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); // name entityClass.Name = entityPascalName; // base type entityClass.AddBaseType("BASE_ENTITY", "Entity"); entityClass.AddUsing(nameof(UsingKeys.SDK_COMMON), UsingKeys.SDK_COMMON); // add interface entityClass.AddBaseType("Interface", $"I{entityClass.Name}"); // doc (just use the name for now) entityClass.DocString = entityClass.Name; // set the filepath root/groupId/Class/Class.cs entityClass.FilePath = $"{rootFilePath}/{entityGroup}/{entityClass.Name}/"; entityClass.FileName = $"{entityClass.Name}.cs"; // add rename dictionary if any if (entity["field_renames"].Count() > 0) { var renameContainer = new RenameContainer(); foreach (var rename in entity["field_renames"]) { var left = rename["_key"].GetStringValue().ToPascal(); var right = rename["api_fieldname"].GetStringValue(); renameContainer.AddRename(left, right); } entityClass.AddPrivateField("RENAMES", renameContainer); entityClass.AddUsing(nameof(UsingKeys.GENERIC_COLLECTIONS), UsingKeys.GENERIC_COLLECTIONS); } // get properties var properties = entity["fields"].Where(p => p["_key"].GetStringValue() != "id"); foreach (var property in properties) { // extract info from config var name = property["_key"].GetStringValue().ToPascal(); // docstring, fall back to name when no description is provided // TODO restore when multiline comment issue is solved // var docString = property["description"].GetStringValue() ?? property["_key"].GetStringValue(); var docString = property["_key"].GetStringValue(); var isReadOnly = property["readOnly"].GetBoolValue(); // get type var propertyType = TypeHelpers.GetPropertyType(property, entityClass); var customGetter = property["getter_custom_method"] != null; var customSetter = property["setter_custom_method"] != null; var isNullable = isNullableType(propertyType, property); if (customGetter || customSetter) { var overridePropContainer = new PropertyWithCustomGetterAndSetter { Name = name, DocString = docString, PropertyType = propertyType, GetAccessor = customGetter, SetAccessor = customSetter, CustomGetterName = property["getter_custom_method"].GetStringValue().ToPascal(), CustomSetterName = property["setter_custom_method"].GetStringValue().ToPascal(), IsNullable = isNullable, }; // can assume public overridePropContainer.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityClass.AddProperty(name, overridePropContainer); // need common for custom functions entityClass.AddUsing(nameof(UsingKeys.SDK_COMMON), UsingKeys.SDK_COMMON); entityClass.AddUsing(nameof(UsingKeys.JSON), UsingKeys.JSON); var backingField = new PrivateFieldContainer { Name = name.PascalToCamel(), FieldType = propertyType, }; backingField.AddModifier(nameof(Modifiers.INTERNAL), Modifiers.INTERNAL); entityClass.AddPrivateField($"{name}_BACKING_FIELD", backingField); } else if (propertyType == "DateTime") { var format = property["format"].GetStringValue(); var propContainer = new DateTimePropertyContainer() { Name = name, DocString = docString, PropertyType = propertyType, IsNullable = isNullable, SetAccessorModifier = isReadOnly ? Modifiers.INTERNAL : Modifiers.PUBLIC, DateFormat = format, }; propContainer.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityClass.AddProperty(name, propContainer); entityClass.AddUsing(nameof(UsingKeys.JSON), UsingKeys.JSON); } else { var propContainer = new PropertyWithSummaryContainer() { Name = name, DocString = docString, PropertyType = propertyType, IsNullable = isNullable, SetAccessorModifier = isReadOnly ? Modifiers.INTERNAL : Modifiers.PUBLIC, }; propContainer.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityClass.AddProperty(name, propContainer); } // add usings for foreign keys var foreignKey = property["items"] != null ? property["items"]["foreign_key"] : null; if (foreignKey != null) { var foreignKeyName = foreignKey["entity"].GetStringValue().ToPascal(); entityClass.AddUsing("FOREIGN_KEY", UsingKeys.FOUNDATION); } // add usings for date time if (propertyType == "DateTime") { entityClass.AddUsing(nameof(UsingKeys.SYSTEM), UsingKeys.SYSTEM); } // add usings for date time if (propertyType == "Filter") { entityClass.AddUsing(nameof(UsingKeys.FILTERS), UsingKeys.FILTERS); } // add usings for list if (propertyType.Contains("List<") || propertyType.Contains("Dictionary<")) { entityClass.AddUsing(nameof(UsingKeys.GENERIC_COLLECTIONS), UsingKeys.GENERIC_COLLECTIONS); } } compilation.AddClass(entityClass.Name, entityClass); var entityClassInterface = entityClass.Copy(); // entityRepositoryInterface.AddModifier(nameof(Modifiers.PUBLIC), Modifiers.PUBLIC); entityClassInterface.Name = $"I{entityClass.Name}"; entityClassInterface.FilePath = $"{rootFilePath}/{entityGroup}/{entityPascalName}/"; entityClassInterface.FileName = $"I{entityClass.FileName}"; entityClassInterface.BaseTypes.Clear(); entityClassInterface.IsInterface = true; compilation.AddClass(entityClassInterface.Name, entityClassInterface); }