Ejemplo n.º 1
0
def _write_logic_class(writer: IndentedWriter, message: Message) -> None:
    writer.write("public")
    if writer.indent > 0:
        writer.append(" static")

    writer.appendln(f" class {message.name} extends {message.name}Entity {{")
    writer.newline()

    indented_writer = writer.indented()

    constructor_parameters, super_import_list = _get_super_constructor_parameters(
        message)
    constructor_parameters_string = []
    super_arguments_string = []

    for constructor_parameter in constructor_parameters:
        name = constructor_parameter[0]
        type = constructor_parameter[1]

        constructor_parameters_string.append(f'@NonNull {type} {name}')
        super_arguments_string.append(f'{name}')

    indented_writer.writeln(
        f'public {message.name}({", ".join(constructor_parameters_string)}) {{'
    )
    indented_writer.indented().writeln(
        f'super({", ".join(super_arguments_string)});')
    indented_writer.writeln("}")

    for submessage in message.messages:
        name = submessage.name

        if submessage.is_array:
            if submessage.extends is None or submessage.properties or submessage.messages:
                _write_logic_class(indented_writer, submessage)
        else:
            if submessage.extends is None or submessage.is_non_empty:
                _write_logic_class(indented_writer, submessage)

    writer.writeln(f"}}")
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
def _write_logic_class(writer: IndentedWriter,
                       message: Message,
                       shared_interface: SharedInterface = None) -> None:
    if shared_interface:
        writer.write(f"open class {shared_interface.name}{message.name}")
    else:
        writer.write(f"open class {message.name}")

    super_nonnull_variables = _get_variables(message, "", True)[0]
    super_nullable_variables = _get_variables(message, "", True)[1]
    shared_interface_super_nonnull_variables = []
    shared_interface_super_nullable_variables = []
    if shared_interface:
        for parent in shared_interface.parents:
            shared_interface_super_nonnull_variables += _get_variables(
                parent.root, "")[0]
            shared_interface_super_nullable_variables += _get_variables(
                parent.root, "")[1]

    indented_writer = writer.indented()

    writer.appendln("(")
    if (super_nonnull_variables or shared_interface_super_nonnull_variables
            or shared_interface_super_nullable_variables):
        for constructor_parameter in super_nonnull_variables:
            name = constructor_parameter.name
            type = constructor_parameter.type
            indented_writer.writeln(f'{name}: {type},')
        if shared_interface:
            for variable in shared_interface.variables:
                if variable not in super_nonnull_variables:
                    indented_writer.writeln(
                        f'{variable.name}: {variable.type},')
        if shared_interface_super_nonnull_variables:
            for variable in shared_interface_super_nonnull_variables:
                if variable not in super_nonnull_variables:
                    indented_writer.writeln(
                        f'{variable.name}: {variable.type},')
        # if shared_interface_super_nullable_variables:
        #     for variable in shared_interface_super_nullable_variables:
        #         if variable not in super_nullable_variables:
        #             indented_writer.writeln(f'{variable.name}: {variable.type},')

        if shared_interface:
            writer.writeln(f") : {shared_interface.name}{message.name}Entity(")
        else:
            writer.writeln(f") : {message.name}Entity(")
        for constructor_parameter in super_nonnull_variables:
            name = constructor_parameter.name
            if debug:
                indented_writer.writeln('/* super variable */ ')
            indented_writer.writeln(f'{name},')
        if shared_interface:
            for variable in shared_interface.variables:
                if variable not in super_nonnull_variables:
                    if debug:
                        indented_writer.writeln(
                            '/* shared interface variable */ ')
                    indented_writer.writeln(f'{variable.name},')
        if shared_interface_super_nonnull_variables:
            for variable in shared_interface_super_nonnull_variables:
                if variable not in super_nonnull_variables:
                    if debug:
                        indented_writer.writeln(
                            '/* shared interface super nonnull variable */ ')
                    indented_writer.writeln(f'{variable.name},')
        # if shared_interface_super_nullable_variables:
        #     for variable in shared_interface_super_nullable_variables:
        #         if variable not in super_nullable_variables:
        #             if debug:
        #                 indented_writer.writeln('/* shared interface super nullable variable */ ')
        #             indented_writer.writeln(f'{variable.name},')
        writer.write(f")")
    else:
        if shared_interface:
            writer.writeln(
                f") : {shared_interface.name}{message.name}Entity()")
        else:
            writer.writeln(f") : {message.name}Entity()")
    hasId = False
    if not shared_interface:
        for variable in super_nonnull_variables:
            if variable.network_name == "Id" and variable.type == "String" and not variable.nullable:
                hasId = True

    if hasId or message.messages:
        hasSubClass = False
        for submessage in message.messages:
            name = submessage.name

            if submessage.is_array:
                if len(submessage.extends
                       ) != 1 or submessage.properties or submessage.messages:
                    if not hasSubClass:
                        writer.appendln(" {")
                        hasSubClass = True
                    _write_logic_inner(indented_writer, submessage)
            else:
                if len(submessage.extends
                       ) != 1 or submessage.properties or submessage.messages:
                    if not hasSubClass:
                        writer.appendln(" {")
                        hasSubClass = True
                    _write_logic_inner(indented_writer, submessage)
        if hasId:
            if not hasSubClass:
                writer.appendln(" {")
                hasSubClass = True
            indented_writer.newline()
            indented_writer.writeln("companion object {")
            indented_writer.indented().write("fun create(")
            for constructor_parameter in super_nonnull_variables:
                name = constructor_parameter.name
                type = constructor_parameter.type
                if name != 'id':
                    indented_writer.append(f'{name}: {type}, ')
            indented_writer.append(") = " + message.name + "(INSERT_ID")
            for constructor_parameter in super_nonnull_variables:
                name = constructor_parameter.name
                type = constructor_parameter.type
                if name != 'id':
                    indented_writer.append(f', {name}')
            indented_writer.appendln(")")
            indented_writer.writeln("}")
        if hasSubClass:
            writer.writeln("}")
        else:
            writer.newline()
    else:
        writer.newline()

    if (shared_interface and
        (super_nonnull_variables or shared_interface_super_nonnull_variables
         or shared_interface_super_nullable_variables)):
        constructor_writer = indented_writer.indented()
        writer.writeln("{")

        indented_writer.writeln("constructor(")
        constructor_writer.writeln(
            f"{camelcase(message.name)}: {message.name},")
        for constructor_parameter in shared_interface_super_nonnull_variables:
            if constructor_parameter not in super_nonnull_variables:
                constructor_writer.writeln(
                    f'{constructor_parameter[1]}: {constructor_parameter[2]},'
                )  #last one without comma
        # for constructor_parameter in shared_interface_super_nullable_variables:
        #     if constructor_parameter not in super_nullable_variables:
        #         constructor_writer.writeln(f'{constructor_parameter[1]}: {constructor_parameter[2]},') #last one without comma
        for variable in shared_interface.variables:
            if variable not in super_nonnull_variables:
                constructor_writer.writeln(
                    f"{variable.name}: {variable.type},")
        indented_writer.writeln(") : this(")
        for constructor_parameter in super_nonnull_variables:
            name = constructor_parameter.name
            constructor_writer.writeln(
                f'{camelcase(message.name)}.{name},')  #last one without comma
        for constructor_parameter in shared_interface_super_nonnull_variables:
            if constructor_parameter not in super_nonnull_variables:
                name = constructor_parameter.name
                constructor_writer.writeln(f'{name},')  #last one without comma
        # for constructor_parameter in shared_interface_super_nullable_variables:
        #     name = constructor_parameter[1]
        #     if constructor_parameter not in super_nullable_variables:
        #         constructor_writer.writeln(f'{name},') #last one without comma
        for variable in shared_interface.variables:
            if variable not in super_nonnull_variables:
                constructor_writer.writeln(f'{variable.name},')
        indented_writer.writeln(") {")
        indented_writer.indented().writeln(
            f"copyNullableVariables({camelcase(message.name)})")
        indented_writer.writeln("}")
        writer.writeln("}")
Ejemplo n.º 4
0
def _write_datamodel_class(writer: IndentedWriter,
                           message: Message,
                           prefix: str = '') -> None:
    writer.write(f"export interface {message.name}")
    if message.extends is not None:
        writer.append(f" extends {message.extends.name}")

    variables: Set[str] = set()

    for property in message.properties:
        if property.method == "request":
            continue

        name = property.name

        if property.enum is not None:
            type = name
        else:
            type = _type(property.type)

        variable = name
        variable += f": {type}"
        if property.nullable:
            variable += " | null"
        variable += ";"

        variables.add(variable)

    interfaces: List[Message] = []

    for sub_message in message.messages:
        name = sub_message.name
        type = sub_message.name

        if sub_message.is_array:
            if sub_message.extends is None or len(sub_message.messages) or len(
                    sub_message.properties):
                interfaces.append(sub_message)
                type = f"{name}[]"
            else:
                type = f"{sub_message.extends.name}[]"
        else:
            if sub_message.extends is None or len(sub_message.messages) or len(
                    sub_message.properties):
                interfaces.append(sub_message)
            else:
                type = sub_message.extends.name

        variable = name
        variable += f": {type}"
        if sub_message.nullable:
            variable += " | null"
        variable += ";"

        variables.add(variable)

    # When there are no variables, then just render an empty interface, but with {} on 1 line
    if variables:
        writer.appendln(" {")
        for variable in sorted(variables, key=lambda x: x.split(":")[0]):
            writer.indented().writeln(variable)

        writer.appendln("}")
    else:
        writer.appendln(" {}")

    if interfaces:
        writer.newline()

        for interface in interfaces:
            _write_datamodel_class(writer, interface)
Ejemplo n.º 5
0
def _write_datamodel_class(writer: IndentedWriter,
                           message: Message,
                           import_list: Set,
                           prefix: str = '',
                           shared_interface: SharedInterface = None) -> Set:
    if shared_interface is None:
        writer.write(f"open class {message.name}Entity")
    else:
        writer.write(f"open class {shared_interface.name}{message.name}Entity")

    if not shared_interface:
        prefix += message.name + "."

    variables = _get_variables(message, prefix)
    nonnull_variables = variables[0]
    nullable_variables = variables[1]
    enums = variables[2]
    inner_classes = variables[3]
    super_variables = []
    super_interface_nonnull_variables = []
    super_interface_nullable_variables = []
    shared_interface_super_nonnull_variables = []
    shared_interface_super_nullable_variables = []

    constructor_vars = []
    member_vars = []

    if len(message.extends) == 1:
        super_variables = _get_variables(message.extends[0].root,
                                         message.extends[0].root.name + ".",
                                         True)[0]
    if shared_interface:
        for parent in shared_interface.parents:
            shared_interface_super_nonnull_variables += _get_variables(
                parent.root, prefix)[0]
            shared_interface_super_nullable_variables += _get_variables(
                parent.root, prefix)[1]

    indented_writer = writer.indented()

    if (super_variables or nonnull_variables
            or super_interface_nonnull_variables or shared_interface
            or shared_interface_super_nonnull_variables
            or shared_interface_super_nullable_variables):
        writer.appendln("(")

        if (super_variables):
            for variable in super_variables:
                if debug:
                    indented_writer.writeln('/* super variable */ ')
                indented_writer.writeln(f'{variable.name}: {variable.type},')
                constructor_vars.append(variable)

        if (super_interface_nonnull_variables):
            for variable in super_interface_nonnull_variables:
                if variable in shared_interface_super_nonnull_variables + nonnull_variables:
                    continue
                if shared_interface:
                    if debug:
                        indented_writer.writeln(
                            '/* super interface non null shared variable */ ')
                    indented_writer.writeln(
                        f'override var {variable.name}: {variable.type},')
                else:
                    import_list.add(
                        "com.google.gson.annotations.SerializedName")
                    if debug:
                        indented_writer.writeln(
                            '/* super interface non null variable */ ')
                    indented_writer.writeln(
                        f'@SerializedName("{variable.network_name}") override var {variable.name}: {variable.type},'
                    )
                constructor_vars.append(variable)

        if (nonnull_variables):
            for variable in nonnull_variables:
                import_list.add("com.google.gson.annotations.SerializedName")
                if shared_interface:
                    if variable in super_interface_nonnull_variables:
                        if debug:
                            indented_writer.writeln(
                                '/* non null shared override variable */ ')
                        indented_writer.writeln(
                            f'{variable.name}: {variable.type},')
                    else:
                        if debug:
                            indented_writer.writeln(
                                '/* non null shared variable */ ')
                        indented_writer.writeln(
                            f'{variable.name}: {variable.type},')
                else:
                    if variable in super_interface_nonnull_variables:
                        if debug:
                            indented_writer.writeln(
                                '/* non null override variable */ ')
                        indented_writer.writeln(
                            f'@SerializedName("{variable.network_name}") override var {variable.name}: {variable.type},'
                        )
                    else:
                        if debug:
                            indented_writer.writeln('/* non null variable */ ')
                        indented_writer.writeln(
                            f'@SerializedName("{variable.network_name}") open var {variable.name}: {variable.type},'
                        )

                constructor_vars.append(variable)

        if (shared_interface):
            for variable in shared_interface.variables:
                import_list.add("com.google.gson.annotations.SerializedName")
                if debug:
                    indented_writer.writeln('/* shared interface variable */ ')
                indented_writer.writeln(
                    f'@SerializedName("{variable.network_name}") override var {variable.name}: {variable.type},'
                )
                constructor_vars.append(variable)

        if (shared_interface_super_nonnull_variables):
            for variable in shared_interface_super_nonnull_variables:
                if variable in nonnull_variables:
                    continue
                if debug:
                    indented_writer.writeln(
                        '/* shared interface super nonnull variable */ ')
                indented_writer.writeln(
                    f'@SerializedName("{variable.network_name}") override var {variable.name}: {variable.type},'
                )
                constructor_vars.append(variable)

        writer.write(")")
    if shared_interface:
        writer.append(f" : {message.name}")
        if super_variables or super_interface_nonnull_variables or nonnull_variables:
            vars = []
            if super_variables:
                for variable in super_variables:
                    vars.append(f'{variable.name}')
            if (super_interface_nonnull_variables):
                for variable in super_interface_nonnull_variables:
                    if variable in nonnull_variables:
                        continue
                    vars.append(f'{variable.name} /* super interface */')
            if nonnull_variables:
                for variable in nonnull_variables:
                    vars.append(f'{variable.name}')
            writer.append(f'({", ".join(vars)})')

        if shared_interface.is_inner:
            writer.append(f", {prefix + shared_interface.name}")
        else:
            writer.append(f", {shared_interface.name}")
        # if shared_interface.variables:
        # writer.append("(")
        # for variable in shared_interface.variables:
        #     writer.append(f'{variable.name}, ')
        # writer.append(")")
        writer.append(", Serializable, Entity")
    elif not message.extends:
        writer.append(" : Serializable, Entity")
    else:
        writer.append(f" : {message.extends[0].name}")
        if super_variables:
            writer.appendln("(")
            for variable, has_more in lookahead(super_variables):
                indented_writer.write(f'{variable.name}')
                if has_more:
                    writer.appendln(',')
                else:
                    writer.appendln('')
            writer.write(")")
        writer.append(", Serializable, Entity")

    hasId = False
    if not shared_interface:
        for variable in nonnull_variables:
            if variable.network_name == "Id" and variable.type == "String" and not variable.nullable:
                hasId = True

    writer.appendln(" {")
    writer.newline()

    if (shared_interface_super_nullable_variables):
        for variable in shared_interface_super_nullable_variables:
            if variable in nullable_variables:
                continue
            else:
                if debug:
                    indented_writer.writeln(
                        '/* shared interface super nullable variable */ ')
                indented_writer.writeln(
                    f'@SerializedName("{variable.network_name}") override var {variable.name}: {variable.type} = null'
                )
                member_vars.append(variable)

    for inner_class in inner_classes:
        import_list.update(
            _write_datamodel_inner(indented_writer, inner_class[0],
                                   import_list, inner_class[1]))

    for enum in enums:
        indented_writer.writeln(f"enum class {enum[0]} {{")
        indented_writer.indented().writeln(f'{", ".join(enum[1])}')
        indented_writer.writeln(f"}}")
        writer.newline()

    if not shared_interface:
        for variable in nullable_variables:
            import_list.add("com.google.gson.annotations.SerializedName")
            indented_writer.writeln(
                f'@SerializedName("{variable.network_name}")')
            indented_writer.writeln(
                f"open var {variable.name}: {variable.type} = null")
            member_vars.append(variable)
            writer.newline()

        for variable in super_interface_nullable_variables:
            import_list.add("com.google.gson.annotations.SerializedName")
            indented_writer.writeln(
                f'@SerializedName("{variable.network_name}")')
            indented_writer.writeln(
                f"override var {variable.name}: {variable.type} = null")
            member_vars.append(variable)
            writer.newline()

    if hasId:
        indented_writer.writeln("override fun hashCode(): Int {")
        indented_writer.indented().writeln("return id.hashCode()")
        indented_writer.writeln("}")
        indented_writer.newline()
        indented_writer.writeln("override fun equals(other: Any?): Boolean {")
        indented_writer.indented().writeln(
            f"if (other is {message.name}Entity) {{")
        indented_writer.indented().indented().writeln(
            "return this === other || (id == other.id && id != INSERT_ID)")
        indented_writer.indented().writeln("}")
        indented_writer.indented().writeln("return super.equals(other)")
        indented_writer.writeln("}")
        indented_writer.newline()
        indented_writer.writeln("companion object {")
        indented_writer.indented().writeln('const val INSERT_ID = "insert"')
        indented_writer.writeln("}")
        indented_writer.newline()

    logic_type = f"{prefix}{shared_interface.name}{message.name}" if shared_interface else f"{prefix[:-1]}"
    indented_writer.writeln("@Transient")
    indented_writer.writeln(f"private lateinit var original: {logic_type}")
    indented_writer.newline()
    indented_writer.writeln("override fun saveOriginal() {")
    indented_writer.indented().writeln(f"original = copy()")
    indented_writer.writeln("}")
    indented_writer.newline()

    indented_writer.writeln(f"override fun copy(): {logic_type} {{")
    indented_writer.indented().write(f"val copy = {logic_type}(")
    for variable in constructor_vars:
        indented_writer.append(
            f"{variable.name}{'.map { it.copy() }.map { it as ' + variable.type[12:-1] + ' }.toMutableList()' if variable.name.endswith('List') else ''}{'' if variable.primitive or variable.name.endswith('List') else ('.copy() as ' + variable.type)}, "
        )
    indented_writer.appendln(")")
    indented_writer.indented().writeln(
        f"copy.copyNullableVariables(this as {logic_type})")
    indented_writer.indented().writeln(f"return copy")
    indented_writer.writeln("}")
    indented_writer.newline()
    indented_writer.writeln(
        f"fun copyNullableVariables(from: {logic_type}) {{")
    if message.extends or shared_interface:
        indented_writer.indented().writeln(
            f"super.copyNullableVariables(from)")
    for variable in member_vars:
        if variable.primitive:
            indented_writer.indented().writeln(
                f"{variable.name} = from.{variable.name}")
        else:
            if variable.name.endswith("List"):
                if variable.nullable:
                    indented_writer.indented().writeln(
                        f"{variable.name} = from.{variable.name}?.map {{ it.copy() }}?.map {{ it as {variable.type[12:-2]} }}?.toMutableList()"
                    )
                else:
                    indented_writer.indented().writeln(
                        f"{variable.name} = from.{variable.name}.map {{ it.copy() }}.map {{ it as {variable.type[12:-1]} }}.toMutableList()"
                    )
            else:
                indented_writer.indented().writeln(
                    f"{variable.name} = from.{variable.name}{'?' if variable.nullable else ''}.copy() as {variable.type}"
                )
    indented_writer.writeln("}")
    indented_writer.newline()

    indented_writer.writeln(
        f"override fun deepEquals(other: Any?): Boolean {{")

    if message.extends:
        indented_writer.indented().writeln(f"if (!super.deepEquals(other)) {{")
        indented_writer.indented().indented().writeln("return false")
        indented_writer.indented().writeln("}")
    indented_writer.indented().writeln(f"return other is {logic_type}")
    for variable in (constructor_vars + member_vars):
        if variable.primitive:
            indented_writer.indented().indented().writeln(
                f"&& {variable.name} == other.{variable.name}")
        else:
            if variable.name.endswith("List"):
                indented_writer.indented().indented().writeln(
                    f"&& {f'if ({variable.name} == null || other.{variable.name} == null) {variable.name} == other.{variable.name} else' if variable.nullable else ''} {variable.name}!!.size == other.{variable.name}!!.size && {variable.name}!!.zip(other.{variable.name}!!) {{ a, b -> a.deepEquals(b) }}.fold(true) {{ x, y -> x && y}}"
                )
            else:
                indented_writer.indented().indented().writeln(
                    f"&& {f'if ({variable.name} == null) other.{variable.name} == null else {variable.name}?' if variable.nullable else variable.name}.deepEquals(other.{variable.name}){' == true' if variable.nullable else ''}"
                )

    indented_writer.writeln("}")
    indented_writer.newline()
    if message.extends or shared_interface:
        indented_writer.write("override ")
    else:
        indented_writer.write("open ")
    indented_writer.appendln(f"fun hasChanged(): Boolean {{")
    indented_writer.indented().writeln(f"return !deepEquals(original)")
    indented_writer.writeln("}")

    indented_writer.newline()
    indented_writer.writeln(f"override fun toOriginal() : {logic_type} {{")
    indented_writer.indented().writeln(f"val result = original")
    indented_writer.indented().writeln(f"original.saveOriginal()")
    indented_writer.indented().writeln(f"return result")
    indented_writer.writeln("}")

    writer.writeln("}")

    return import_list