Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions src/class_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from src.header_generator import set_package, set_imports, render_javadoc
from src.java_method_generator import generate_fields_block, generate_getters_and_setters, generate_equals, \
generate_hash_code
from src.java_model import JavaClass


def generate_java_class(java_class: JavaClass, package: str) -> str:
if len(java_class.fields) == 0:
return _empty_java_class(java_class, package)

body = [
set_package(package),
"",
"",
set_imports(java_class.fields),
"",
render_javadoc(java_class.description, indent_lvl=0),
f"public class {java_class.name} {{",
generate_fields_block(java_class.fields),
"",
generate_getters_and_setters(java_class.fields),
"",
generate_equals(java_class.name, java_class.fields),
"",
generate_hash_code(java_class.fields),
"}",
""
]
return "\n".join(body)


def _empty_java_class(java_class: JavaClass, package: str) -> str:
body = [
set_package(package),
"",
render_javadoc(java_class.description, indent_lvl=0),
f"public class {java_class.name} {{",
"}",
""
]
return "\n".join(body)
134 changes: 57 additions & 77 deletions src/enum_generator.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from typing import List

from src.java_model import EnumClass, indent_lvl1, indent_lvl2, indent_lvl3
from src.header_generator import set_package
from src.header_generator import set_package, render_javadoc
from src.java_model import EnumClass, indent


def to_java_constant(value: str) -> str:
Expand All @@ -21,109 +21,89 @@ def generate_enum_class(enum_class: EnumClass, package: str) -> str:
"",
f"import java.util.HashMap;",
f"import java.util.Map;",
f"",
render_javadoc(enum_class.description, indent_lvl=0),
f"public enum {enum_class.name} {{",
_get_constants(enum_class.values),
f"",
f"{indent(1)}private final static Map<String, {enum_class.name}> CONSTANTS = new HashMap<String, {enum_class.name}>();",
_get_static_method(enum_class.name),
f"",
f"{indent(1)}private final String value;",
_get_constructor(enum_class.name),
_get_from_value_method(enum_class.name),
_get_to_string_method(),
_get_value_method(),
"}",
f""
]

enum_body.extend(_get_javadoc(enum_class.description))

enum_body.append(f"public enum {enum_class.name} {{")
enum_body.extend(_get_constants(enum_class.values))

enum_body.append(f"")
enum_body.append(
f"{indent_lvl1}private final static Map<String, {enum_class.name}> CONSTANTS = new HashMap<String, {enum_class.name}>();")
enum_body.append(f"")
enum_body.extend(_get_static_method(enum_class.name))

enum_body.append(f"")
enum_body.append(f"{indent_lvl1}private final String value;")
enum_body.append(f"")
enum_body.extend(_get_constructor(enum_class.name))

enum_body.append(f"")
enum_body.extend(_get_from_value_method(enum_class.name))

enum_body.append(f"")
enum_body.extend(_get_to_string_method())

enum_body.append(f"")
enum_body.extend(_get_value_method())
enum_body.append("}")
enum_body.append(f"")

return "\n".join(enum_body)


def _get_javadoc(description: str) -> List[str]:
javadoc = [""]
if description is not None:
javadoc = [
"",
"/**",
f" * {description}",
" */"
]
return javadoc


def _get_constants(constants: List[str]) -> List[str]:
def _get_constants(constants: List[str]) -> str:
values = []
for i, value in enumerate(constants):
line_end = ";" if i == (len(constants) - 1) else ","
values.append(
f'{indent_lvl1}{to_java_constant(value)}("{value}"){line_end}'
f'{indent(1)}{to_java_constant(value)}("{value}"){line_end}'
)
return values
return "\n".join(values)


def _get_static_method(class_name: str) -> List[str]:
def _get_static_method(class_name: str) -> str:
body = [
f"{indent_lvl1}static {{",
f"{indent_lvl2}for ({class_name} c : values()) {{",
f"{indent_lvl3}CONSTANTS.put(c.value, c);",
f"{indent_lvl2}}}",
f"{indent_lvl1}}}"
"",
f"{indent(1)}static {{",
f"{indent(2)}for ({class_name} c : values()) {{",
f"{indent(3)}CONSTANTS.put(c.value, c);",
f"{indent(2)}}}",
f"{indent(1)}}}"
]
return body
return "\n".join(body)


def _get_constructor(class_name: str) -> List[str]:
def _get_constructor(class_name: str) -> str:
body = [
f"{indent_lvl1}{class_name}(String value) {{",
f"{indent_lvl2}this.value = value;",
f"{indent_lvl1}}}"
"",
f"{indent(1)}{class_name}(String value) {{",
f"{indent(2)}this.value = value;",
f"{indent(1)}}}"
]
return body
return "\n".join(body)


def _get_from_value_method(class_name: str) -> List[str]:
def _get_from_value_method(class_name: str) -> str:
body = [
f"{indent_lvl1}public static {class_name} fromValue(String value) {{",
f"{indent_lvl2}{class_name} constant = CONSTANTS.get(value);",
f"{indent_lvl2}if (constant == null) {{",
f"{indent_lvl3}throw new IllegalArgumentException(value);",
f"{indent_lvl2}}} else {{",
f"{indent_lvl3}return constant;",
f"{indent_lvl2}}}",
f"{indent_lvl1}}}"
"",
f"{indent(1)}public static {class_name} fromValue(String value) {{",
f"{indent(2)}{class_name} constant = CONSTANTS.get(value);",
f"{indent(2)}if (constant == null) {{",
f"{indent(3)}throw new IllegalArgumentException(value);",
f"{indent(2)}}} else {{",
f"{indent(3)}return constant;",
f"{indent(2)}}}",
f"{indent(1)}}}"
]
return body
return "\n".join(body)


def _get_to_string_method() -> List[str]:
def _get_to_string_method() -> str:
body = [
f"{indent_lvl1}@Override",
f"{indent_lvl1}public String toString() {{",
f"{indent_lvl2}return this.value;",
f"{indent_lvl1}}}"
"",
f"{indent(1)}@Override",
f"{indent(1)}public String toString() {{",
f"{indent(2)}return this.value;",
f"{indent(1)}}}"
]
return body
return "\n".join(body)


def _get_value_method() -> List[str]:
def _get_value_method() -> str:
body = [
f"{indent_lvl1}public String value() {{",
f"{indent_lvl2}return this.value;",
f"{indent_lvl1}}}"
"",
f"{indent(1)}public String value() {{",
f"{indent(2)}return this.value;",
f"{indent(1)}}}"
]
return body
return "\n".join(body)
31 changes: 31 additions & 0 deletions src/header_generator.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,39 @@
import re
from typing import List, Union

from src.java_model import Field, indent


def set_package(package: str) -> str:
PACKAGE_REGEX = r"^(?:[A-Za-z_][A-Za-z0-9_]*)(?:\.(?:[A-Za-z_][A-Za-z0-9_]*))*$"
if not re.match(PACKAGE_REGEX, package):
raise ValueError(f"Invalid package: '{package}'")
return f"package {package};"


def set_imports(fields: List[Field]) -> str:
imports = [_imports["Objects"]]
for field in fields:
if field.type in _imports.keys():
imports.append(_imports[field.type])
imports.sort()
return "\n".join(imports)


def render_javadoc(description: Union[str, None], indent_lvl: int) -> str:
if not description:
return ""

return "\n".join([
"",
f"{indent(indent_lvl)}/**",
f"{indent(indent_lvl)} * {description}",
f"{indent(indent_lvl)} */"
])


_imports = {
"Date": "import java.util.Date;",
"List": "import java.util.List;",
"Objects": "import java.util.Objects;",
}
67 changes: 28 additions & 39 deletions src/java_method_generator.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from typing import List

from src.java_model import JAVA_KEYWORDS, JAVA_BUILTIN_TYPES, JAVA_LITERALS, indent_lvl1, indent_lvl2, indent_lvl3, \
return_indent, Field
from src.header_generator import render_javadoc
from src.java_model import JAVA_KEYWORDS, JAVA_BUILTIN_TYPES, JAVA_LITERALS, Field, indent


def generate_fields_block(fields: List[Field]) -> str:
Expand All @@ -17,24 +17,12 @@ def generate_field_declaration(field: Field) -> str:
_validate_java_field_name(field.name)

declaration = [
_render_javadoc(field),
f"{indent_lvl1}private {field.type} {field.name};"
render_javadoc(field.description, indent_lvl=1),
f"{indent(1)}private {field.type} {field.name};"
]
return "\n".join(declaration)


def _render_javadoc(field: Field) -> str:
if field.description is None:
return ""

return "\n".join([
"",
f"{indent_lvl1}/**",
f"{indent_lvl1} * {field.description}",
f"{indent_lvl1} */"
])


def generate_getters_and_setters(fields: List[Field]) -> str:
methods = []
for field in fields:
Expand All @@ -49,9 +37,9 @@ def generate_getter(field: Field) -> str:

getter = [
"",
f"{indent_lvl1}public {field.type} {getter_name}() {{",
f"{indent_lvl2}return {field.name};",
f"{indent_lvl1}}}"
f"{indent(1)}public {field.type} {getter_name}() {{",
f"{indent(2)}return {field.name};",
f"{indent(1)}}}"
]
return "\n".join(getter)

Expand All @@ -61,29 +49,29 @@ def generate_setter(field: Field) -> str:

setter = [
"",
f"{indent_lvl1}public void {setter_name}({field.type} {field.name}) {{",
f"{indent_lvl2}this.{field.name} = {field.name};",
f"{indent_lvl1}}}"
f"{indent(1)}public void {setter_name}({field.type} {field.name}) {{",
f"{indent(2)}this.{field.name} = {field.name};",
f"{indent(1)}}}"
]
return "\n".join(setter)


def generate_equals(class_name: str, fields: List[Field]) -> str:
equals = [
"",
f"{indent_lvl1}@Override",
f"{indent_lvl1}public boolean equals(Object obj) {{",
f"{indent(1)}@Override",
f"{indent(1)}public boolean equals(Object obj) {{",

f"{indent_lvl2}if (this == obj)",
f"{indent_lvl3}return true;",
f"{indent(2)}if (this == obj)",
f"{indent(3)}return true;",

f"{indent_lvl2}if (!(obj instanceof {class_name}))",
f"{indent_lvl3}return false;",
f"{indent(2)}if (!(obj instanceof {class_name}))",
f"{indent(3)}return false;",

f"{indent_lvl2}{class_name} that = ({class_name}) obj;",
f"{indent(2)}{class_name} that = ({class_name}) obj;",

_render_equals_return_statement(fields),
f"{indent_lvl1}}}"
f"{indent(1)}}}"
]

return "\n".join(equals)
Expand All @@ -95,20 +83,21 @@ def _render_equals_return_statement(fields: List[Field]) -> str:
getter_name = _build_getter_name(field.name)
end_line = ";" if i == (len(fields) - 1) else ""
if i == 0:
return_statement.append(f"{indent_lvl2}return Objects.equals({getter_name}(), that.{getter_name}()){end_line}")
return_statement.append(
f"{indent(2)}return Objects.equals({getter_name}(), that.{getter_name}()){end_line}")
else:
return_statement.append(
f"{indent_lvl2}{return_indent}&& Objects.equals({getter_name}(), that.{getter_name}()){end_line}")
f"{indent(4)}&& Objects.equals({getter_name}(), that.{getter_name}()){end_line}")
return "\n".join(return_statement)


def generate_hash_code(fields: List[Field]) -> str:
hash_code = [
"",
f"{indent_lvl1}@Override",
f"{indent_lvl1}public int hashCode() {{",
f"{indent(1)}@Override",
f"{indent(1)}public int hashCode() {{",
_render_hashcode_return_statement(fields),
f"{indent_lvl1}}}"
f"{indent(1)}}}"
]

return "\n".join(hash_code)
Expand All @@ -124,17 +113,17 @@ def _render_hashcode_return_statement(fields: List[Field]) -> str:
def _render_hashcode_return_statement_single_field(fields: List[Field]) -> str:
field_name = fields[0].name
getter_name = _build_getter_name(field_name)
return f"{indent_lvl2}return Objects.hash({getter_name}());"
return f"{indent(2)}return Objects.hash({getter_name}());"


def _render_hashcode_return_statement_multiple_field(fields: List[Field]) -> str:
return_statement = [f"{indent_lvl2}return Objects.hash("]
return_statement = [f"{indent(2)}return Objects.hash("]
for index, field in enumerate(fields):
getter_name = _build_getter_name(field.name)
comma = "," if index < (len(fields) - 1) else ""
return_statement.append(f"{indent_lvl2}{return_indent}{getter_name}(){comma}")
return_statement.append(f"{indent(4)}{getter_name}(){comma}")

return_statement.append(f"{indent_lvl2});")
return_statement.append(f"{indent(2)});")

return "\n".join(return_statement)

Expand Down
Loading