def _get_super_constructor_parameters(message: Message): constructor_parameters: List[Tuple[str, str]] = [] import_list = set() if message.extends is not None: super_constructor_parameters, super_import_list = _get_super_constructor_parameters( message.extends.root) constructor_parameters += super_constructor_parameters import_list.update(super_import_list) for property in message.properties: type = property.type name = property.name method = property.method variable_name = camelcase(name) variable_type = _java_type(type) nullable = property.nullable if property.enum is not None and len(property.enum): variable_type = name if not nullable and method != "request": constructor_parameters.append((variable_name, variable_type)) for message in message.messages: name = message.name nullable = message.nullable # special case for array messages if message.is_array: if message.extends is None or message.is_non_empty: variable_type = f"List<{name}>" else: variable_type = f"List<{message.extends.name}>" variable_name = camelcase(name) + "List" import_list.add("java.util.List") else: if message.extends is None or message.is_non_empty: variable_type = name else: variable_type = message.extends.name variable_name = camelcase(name) if not nullable: constructor_parameters.append((variable_name, variable_type)) return constructor_parameters, import_list
def _write_service(writer: IndentedWriter, entity: Entity, package: str) -> None: writer.writeln(f"package {package}.{_package(entity.package)}.service;") writer.newline() dependencies: List[str] = [] if entity.key_ids: dependencies.append("retrofit2.http.Query") import_non_null = False import_nullable = False for key_id in entity.key_ids: for key_property in entity.key_properties(key_id): if key_property.nullable: import_nullable = True else: import_non_null = True if "GET" in entity.methods or "PUT" in entity.methods or "POST" in entity.methods or "DELETE" in entity.methods: dependencies.append("io.reactivex.Single") if entity.version != -1: dependencies.append("retrofit2.http.Headers") if "PUT" in entity.methods or "POST" in entity.methods: import_non_null = True dependencies.append("retrofit2.http.Body") for method in entity.methods: dependencies.append(f"retrofit2.http.{method}") if "GET" in entity.methods or "PUT" in entity.methods or "POST" in entity.methods: dependencies.append( f"{package}.{_package(entity.package)}.logic.{entity.name}") if import_non_null: dependencies.append("androidx.annotation.NonNull") if import_nullable: dependencies.append("androidx.annotation.Nullable") previous_dependency = None for dependency in sorted(dependencies): if previous_dependency is not None and previous_dependency.split( ".")[0] != dependency.split(".")[0]: writer.newline() writer.writeln(f"import {dependency};") previous_dependency = dependency writer.newline() writer.writeln(f"public interface {entity.name}Service {{") writer.newline() for method in entity.methods: indented_writer = writer.indented() for key_id in entity.key_ids: parameter_list = [] for key_property in entity.key_properties(key_id): variable_name = camelcase(key_property.name) variable_type = _java_type(key_property.type) nullable = '@NonNull' if key_property.nullable: nullable = '@Nullable' parameter_list.append( f'{nullable} @Query("{key_property.name}") {variable_type} {variable_name}' ) parameters = ', '.join(parameter_list) if entity.version != -1: indented_writer.writeln( f'@Headers("X-Navajo-Version: {entity.version}")') indented_writer.writeln( f'@{method}("{entity.path}?v={entity.version}")') else: indented_writer.writeln(f'@{method}("{entity.path}")') if method == "GET": indented_writer.writeln( f'Single<{entity.name}> get{entity.name}({parameters});') if method == "PUT": indented_writer.writeln( f'Single<{entity.name}> update{entity.name}({parameters}, @NonNull @Body {entity.name} {entity.name[0].lower() + entity.name[1:]});' ) if method == "DELETE": indented_writer.writeln( f'Single<{entity.name}> remove{entity.name}({parameters});' ) if method == "POST": indented_writer.writeln( f'Single<{entity.name}> insert{entity.name}({parameters}, @NonNull @Body {entity.name} {entity.name[0].lower() + entity.name[1:]});' ) indented_writer.newline() if not len(entity.key_ids): if entity.version != -1: indented_writer.writeln( f'@Headers("X-Navajo-Version: {entity.version}")') indented_writer.writeln( f'@{method}("{entity.path}?v={entity.version}")') else: indented_writer.writeln(f'@{method}("{entity.path}")') if method == "GET": indented_writer.writeln( f'Single<{entity.name}> get{entity.name}();') if method == "PUT": indented_writer.writeln( f'Single<{entity.name}> update{entity.name}(@NonNull @Body {entity.name} {entity.name[0].lower() + entity.name[1:]});' ) if method == "DELETE": indented_writer.writeln( f'Single<{entity.name}> remove{entity.name}();') if method == "POST": indented_writer.writeln( f'Single<{entity.name}> insert{entity.name}(@NonNull @Body {entity.name} {entity.name[0].lower() + entity.name[1:]});' ) indented_writer.newline() writer.writeln("}") writer.newline()
def _write_datamodel_class(writer: IndentedWriter, message: Message, import_list: Set, prefix: str = '') -> None: writer.write("public") if prefix != '': writer.append(" static") writer.append(f" class {message.name}Entity") if message.extends is not None: writer.append(f" extends {message.extends.name}") writer.appendln(" implements Serializable {") writer.newline() prefix += message.name + "." indented_writer = writer.indented() constructor_parameters = [] for property in message.properties: if property.method == "request": continue type = property.type name = property.name variable_name = camelcase(name) variable_type = _java_type(type) nullable = property.nullable if property.enum is not None and len(property.enum): indented_writer.writeln(f'public enum {name} {{') for enum_value in property.enum: enum_writer = indented_writer.indented() enum_writer.writeln(f'{enum_value},') indented_writer.writeln('}') indented_writer.newline() variable_type = name if nullable: indented_writer.writeln(f'@Nullable') import_list.add("androidx.annotation.Nullable") else: constructor_parameters.append((variable_name, variable_type)) indented_writer.writeln(f'@NonNull') import_list.add("androidx.annotation.NonNull") indented_writer.writeln(f'@SerializedName("{name}")') import_list.add("com.google.gson.annotations.SerializedName") indented_writer.writeln(f"public {variable_type} {variable_name};") indented_writer.newline() for submessage in message.messages: name = submessage.name nullable = submessage.nullable if submessage.is_array: if submessage.extends is None or submessage.is_non_empty: import_list.update( _write_datamodel_class(indented_writer, submessage, import_list, prefix)) variable_type = "List<" + prefix + name + ">" else: variable_type = "List<" + submessage.extends.name + ">" variable_name = camelcase(name) + "List" import_list.add("java.util.List") else: if submessage.extends is None or submessage.is_non_empty: import_list.update( _write_datamodel_class(indented_writer, submessage, import_list, prefix)) variable_type = prefix + name else: variable_type = submessage.extends.name variable_name = camelcase(name) if nullable: indented_writer.writeln('@Nullable') import_list.add("androidx.annotation.Nullable") else: constructor_parameters.append((variable_name, variable_type)) indented_writer.writeln('@NonNull') import_list.add("androidx.annotation.NonNull") indented_writer.writeln(f'@SerializedName("{name}")') import_list.add("com.google.gson.annotations.SerializedName") indented_writer.writeln(f'public {variable_type} {variable_name};') indented_writer.newline() super_constructor_parameters = [] constructor_parameters_string = [] if message.extends is not None: super_constructor_parameters, super_import_list = _get_super_constructor_parameters( message.extends.root) import_list.update(super_import_list) for constructor_parameter in super_constructor_parameters: name = constructor_parameter[0] type = constructor_parameter[1] constructor_parameters_string.append(f'@NonNull {type} {name}') import_list.add("androidx.annotation.NonNull") for constructor_parameter in constructor_parameters: name = constructor_parameter[0] type = constructor_parameter[1] constructor_parameters_string.append(f'@NonNull {type} {name}') import_list.add("androidx.annotation.NonNull") indented_writer.writeln( f'public {message.name}Entity({", ".join(constructor_parameters_string)}) {{' ) super_arguments_string = [] for constructor_parameter in super_constructor_parameters: name = constructor_parameter[0] super_arguments_string.append(name) body_writer = indented_writer.indented() body_writer.writeln(f'super({", ".join(super_arguments_string)});') for constructor_parameter in constructor_parameters: name = constructor_parameter[0] body_writer.writeln(f'this.{name} = {name};') indented_writer.writeln('}') indented_writer.newline() writer.writeln("}") writer.newline() return import_list
def _get_variables(message: Message, prefix: str, recursive: bool = False): nonnull_variables = [] nullable_variables = [] enums = [] inner_classes = [] for property in message.properties: if property.method == "request": continue type = property.type name = property.name variable_name = camelcase(name) variable_type = _kotlin_type(type) variable_type_primitive = True nullable = property.nullable if property.enum: enum_options = [] for enum_value in property.enum: enum_options.append(enum_value) enums.append((name, enum_options)) variable_type = name if nullable: variable_type += "?" nullable_variables.append( Variable(name, variable_name, variable_type, variable_type_primitive, nullable)) else: nonnull_variables.append( Variable(name, variable_name, variable_type, variable_type_primitive, nullable)) for submessage in message.messages: name = submessage.name nullable = submessage.nullable variable_type_primitive = False if submessage.is_array: if not submessage.extends or (len(submessage.extends) == 1 and (submessage.properties or submessage.messages)): # inner class inner_classes.append((submessage, prefix)) variable_type = "MutableList<" + prefix + name + ">" elif len(submessage.extends) == 1: # external class variable_type = "MutableList<" + submessage.extends[ 0].name + ">" else: inner_classes.append((submessage, prefix)) variable_type = "MutableList<" + prefix + submessage.name + ">" variable_name = camelcase(name) + "List" else: if not submessage.extends or (len(submessage.extends) == 1 and (submessage.properties or submessage.messages)): inner_classes.append((submessage, prefix)) variable_type = prefix + name elif len(submessage.extends) == 1: variable_type = submessage.extends[0].name else: inner_classes.append((submessage, prefix)) variable_type = prefix + submessage.name variable_name = camelcase(name) if nullable: variable_type += "?" nullable_variables.append( Variable(name, variable_name, variable_type, variable_type_primitive, nullable)) else: nonnull_variables.append( Variable(name, variable_name, variable_type, variable_type_primitive, nullable)) if recursive: if len(message.extends) == 1: result = _get_variables(message.extends[0].root, prefix, recursive) nonnull_variables = result[0] + nonnull_variables nullable_variables += result[1] + nullable_variables enums += result[2] inner_classes += result[3] return nonnull_variables, nullable_variables, enums, inner_classes
def _write_service(writer: IndentedWriter, entity: Entity, package: str) -> None: writer.writeln(f"package {package}.{_package(entity.package)}.service") writer.newline() dependencies = set() dependencies.update([ "retrofit2.http.Query", "com.google.gson.TypeAdapterFactory", f"com.sendrato.app.sdk.gson.RuntimeTypeAdapterFactory" ]) if "GET" in entity.methods or "PUT" in entity.methods or "POST" in entity.methods or "DELETE" in entity.methods: dependencies.add("io.reactivex.Single") if entity.version != -1: dependencies.add("retrofit2.http.Headers") if "PUT" in entity.methods or "POST" in entity.methods: dependencies.add("retrofit2.http.Body") for method in entity.methods: dependencies.add(f"retrofit2.http.{method}") if "GET" in entity.methods or "PUT" in entity.methods or "POST" in entity.methods or "DELETE" in entity.methods: dependencies.add( f"{package}.{_package(entity.package)}.logic.{entity.name}") for dependency in _get_dependencies(entity): dependencies.add(f"{package}.{_package(dependency.package)}.logic." + dependency.name) for dependency in sorted(dependencies): writer.writeln(f"import {dependency}") writer.newline() writer.writeln(f"interface {entity.name}Service {{") writer.newline() indented_writer = writer.indented() for method in entity.methods: for key_id in entity.key_ids: parameter_list = [] for key_property in entity.key_properties(key_id): variable_name = camelcase(key_property.name) variable_type = _kotlin_type(key_property.type) if key_property.nullable: variable_type += '?' parameter_list.append( f'@Query("{key_property.name}") {variable_name}: {variable_type}' ) parameters = ', '.join(parameter_list) if entity.version != -1: indented_writer.writeln( f'@Headers("X-Navajo-Version: {entity.version}")') indented_writer.writeln( f'@{method}("{entity.path}?v={entity.version}")') else: indented_writer.writeln(f'@{method}("{entity.path}")') if method == "GET": indented_writer.writeln( f'fun {entity.name[0].lower() + entity.name[1:]}({parameters}): Single<{entity.name}>' ) if method == "PUT": indented_writer.writeln( f'fun update{entity.name}({parameters}, @Body {entity.name[0].lower() + entity.name[1:]}: {entity.name}): Single<{entity.name}>' ) if method == "DELETE": indented_writer.writeln( f'fun remove{entity.name}({parameters}): Single<{entity.name}>' ) if method == "POST": indented_writer.writeln( f'fun insert{entity.name}({parameters}, @Body {entity.name[0].lower() + entity.name[1:]}: {entity.name}): Single<{entity.name}>' ) indented_writer.newline() if not entity.key_ids: if entity.version != -1: indented_writer.writeln( f'@Headers("X-Navajo-Version: {entity.version}")') indented_writer.writeln( f'@{method}("{entity.path}?v={entity.version}")') else: indented_writer.writeln(f'@{method}("{entity.path}")') if method == "GET": indented_writer.writeln( f'fun {entity.name[0].lower() + entity.name[1:]}(): Single<{entity.name}> ' ) if method == "PUT": indented_writer.writeln( f'fun update{entity.name}(@Body {entity.name[0].lower() + entity.name[1:]}: {entity.name}): Single<{entity.name}>' ) if method == "DELETE": indented_writer.writeln( f'fun remove{entity.name}(): Single<{entity.name}>') if method == "POST": indented_writer.writeln( f'fun insert{entity.name}(@Body {entity.name[0].lower() + entity.name[1:]}: {entity.name}): Single<{entity.name}>' ) indented_writer.newline() indented_writer.writeln("companion object {") companion_writer = indented_writer.indented() companion_writer.writeln( "var typeFactoryAdapterList = listOf<TypeAdapterFactory>(") _write_service_typeadapterfactories(companion_writer, entity.root, "") companion_writer.writeln(")") indented_writer.writeln("}") writer.writeln("}") writer.newline()
def _get_shared_interface(message: Message) -> SharedInterface: variables = [] enums = [] for property in message.properties: if property.method == "request": continue type = property.type name = property.name variable_name = camelcase(name) variable_type = _kotlin_type(type) nullable = property.nullable if property.enum: variable_type = message.name + "Entity." + name enum_options = [] for enum_value in property.enum: enum_options.append(enum_value) enums.append((name, enum_options)) # assert False, "This is not supported, because of Swift :-(" if nullable: variable_type += "?" variables.append( Variable(name, variable_name, variable_type, True, nullable)) for submessage in message.messages: name = submessage.name nullable = submessage.nullable if submessage.is_array: if not submessage.extends or (len(submessage.extends) == 1 and (submessage.properties or submessage.messages)): # assert False, "This is not supported, because of Swift :-(" variable_type = "MutableList<" + submessage.name + ">" elif len(submessage.extends) == 1: variable_type = "MutableList<" + submessage.extends[ 0].name + ">" else: variable_type = "MutableList<" + submessage.name + ">" # assert False, "This is not supported, because of Swift :-(" variable_name = camelcase(name) + "List" else: if not submessage.extends or (len(submessage.extends) == 1 and (submessage.properties or submessage.messages)): variable_type = submessage.name # assert False, f"This is not supported, because of Swift :-(" elif len(submessage.extends) == 1: variable_type = submessage.extends[0].name else: variable_type = submessage.name # assert False, "This is not supported, because of Swift :-(" variable_name = camelcase(name) if nullable: variable_type += "?" variables.append( Variable(name, variable_name, variable_type, False, nullable)) return SharedInterface(message.name, variables, [], enums)