Skip to content

Commit a12fcdb

Browse files
authored
Merge pull request #9 from MrMaydo/dev
Add java class generator
2 parents 5a62f87 + 14bbe09 commit a12fcdb

13 files changed

Lines changed: 413 additions & 133 deletions

src/class_generator.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from src.header_generator import set_package, set_imports, render_javadoc
2+
from src.java_method_generator import generate_fields_block, generate_getters_and_setters, generate_equals, \
3+
generate_hash_code
4+
from src.java_model import JavaClass
5+
6+
7+
def generate_java_class(java_class: JavaClass, package: str) -> str:
8+
if len(java_class.fields) == 0:
9+
return _empty_java_class(java_class, package)
10+
11+
body = [
12+
set_package(package),
13+
"",
14+
"",
15+
set_imports(java_class.fields),
16+
"",
17+
render_javadoc(java_class.description, indent_lvl=0),
18+
f"public class {java_class.name} {{",
19+
generate_fields_block(java_class.fields),
20+
"",
21+
generate_getters_and_setters(java_class.fields),
22+
"",
23+
generate_equals(java_class.name, java_class.fields),
24+
"",
25+
generate_hash_code(java_class.fields),
26+
"}",
27+
""
28+
]
29+
return "\n".join(body)
30+
31+
32+
def _empty_java_class(java_class: JavaClass, package: str) -> str:
33+
body = [
34+
set_package(package),
35+
"",
36+
render_javadoc(java_class.description, indent_lvl=0),
37+
f"public class {java_class.name} {{",
38+
"}",
39+
""
40+
]
41+
return "\n".join(body)

src/enum_generator.py

Lines changed: 57 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import re
22
from typing import List
33

4-
from src.java_model import EnumClass, indent_lvl1, indent_lvl2, indent_lvl3
5-
from src.header_generator import set_package
4+
from src.header_generator import set_package, render_javadoc
5+
from src.java_model import EnumClass, indent
66

77

88
def to_java_constant(value: str) -> str:
@@ -21,109 +21,89 @@ def generate_enum_class(enum_class: EnumClass, package: str) -> str:
2121
"",
2222
f"import java.util.HashMap;",
2323
f"import java.util.Map;",
24+
f"",
25+
render_javadoc(enum_class.description, indent_lvl=0),
26+
f"public enum {enum_class.name} {{",
27+
_get_constants(enum_class.values),
28+
f"",
29+
f"{indent(1)}private final static Map<String, {enum_class.name}> CONSTANTS = new HashMap<String, {enum_class.name}>();",
30+
_get_static_method(enum_class.name),
31+
f"",
32+
f"{indent(1)}private final String value;",
33+
_get_constructor(enum_class.name),
34+
_get_from_value_method(enum_class.name),
35+
_get_to_string_method(),
36+
_get_value_method(),
37+
"}",
2438
f""
2539
]
2640

27-
enum_body.extend(_get_javadoc(enum_class.description))
28-
29-
enum_body.append(f"public enum {enum_class.name} {{")
30-
enum_body.extend(_get_constants(enum_class.values))
31-
32-
enum_body.append(f"")
33-
enum_body.append(
34-
f"{indent_lvl1}private final static Map<String, {enum_class.name}> CONSTANTS = new HashMap<String, {enum_class.name}>();")
35-
enum_body.append(f"")
36-
enum_body.extend(_get_static_method(enum_class.name))
37-
38-
enum_body.append(f"")
39-
enum_body.append(f"{indent_lvl1}private final String value;")
40-
enum_body.append(f"")
41-
enum_body.extend(_get_constructor(enum_class.name))
42-
43-
enum_body.append(f"")
44-
enum_body.extend(_get_from_value_method(enum_class.name))
45-
46-
enum_body.append(f"")
47-
enum_body.extend(_get_to_string_method())
48-
49-
enum_body.append(f"")
50-
enum_body.extend(_get_value_method())
51-
enum_body.append("}")
52-
enum_body.append(f"")
53-
5441
return "\n".join(enum_body)
5542

5643

57-
def _get_javadoc(description: str) -> List[str]:
58-
javadoc = [""]
59-
if description is not None:
60-
javadoc = [
61-
"",
62-
"/**",
63-
f" * {description}",
64-
" */"
65-
]
66-
return javadoc
67-
68-
69-
def _get_constants(constants: List[str]) -> List[str]:
44+
def _get_constants(constants: List[str]) -> str:
7045
values = []
7146
for i, value in enumerate(constants):
7247
line_end = ";" if i == (len(constants) - 1) else ","
7348
values.append(
74-
f'{indent_lvl1}{to_java_constant(value)}("{value}"){line_end}'
49+
f'{indent(1)}{to_java_constant(value)}("{value}"){line_end}'
7550
)
76-
return values
51+
return "\n".join(values)
7752

7853

79-
def _get_static_method(class_name: str) -> List[str]:
54+
def _get_static_method(class_name: str) -> str:
8055
body = [
81-
f"{indent_lvl1}static {{",
82-
f"{indent_lvl2}for ({class_name} c : values()) {{",
83-
f"{indent_lvl3}CONSTANTS.put(c.value, c);",
84-
f"{indent_lvl2}}}",
85-
f"{indent_lvl1}}}"
56+
"",
57+
f"{indent(1)}static {{",
58+
f"{indent(2)}for ({class_name} c : values()) {{",
59+
f"{indent(3)}CONSTANTS.put(c.value, c);",
60+
f"{indent(2)}}}",
61+
f"{indent(1)}}}"
8662
]
87-
return body
63+
return "\n".join(body)
8864

8965

90-
def _get_constructor(class_name: str) -> List[str]:
66+
def _get_constructor(class_name: str) -> str:
9167
body = [
92-
f"{indent_lvl1}{class_name}(String value) {{",
93-
f"{indent_lvl2}this.value = value;",
94-
f"{indent_lvl1}}}"
68+
"",
69+
f"{indent(1)}{class_name}(String value) {{",
70+
f"{indent(2)}this.value = value;",
71+
f"{indent(1)}}}"
9572
]
96-
return body
73+
return "\n".join(body)
9774

9875

99-
def _get_from_value_method(class_name: str) -> List[str]:
76+
def _get_from_value_method(class_name: str) -> str:
10077
body = [
101-
f"{indent_lvl1}public static {class_name} fromValue(String value) {{",
102-
f"{indent_lvl2}{class_name} constant = CONSTANTS.get(value);",
103-
f"{indent_lvl2}if (constant == null) {{",
104-
f"{indent_lvl3}throw new IllegalArgumentException(value);",
105-
f"{indent_lvl2}}} else {{",
106-
f"{indent_lvl3}return constant;",
107-
f"{indent_lvl2}}}",
108-
f"{indent_lvl1}}}"
78+
"",
79+
f"{indent(1)}public static {class_name} fromValue(String value) {{",
80+
f"{indent(2)}{class_name} constant = CONSTANTS.get(value);",
81+
f"{indent(2)}if (constant == null) {{",
82+
f"{indent(3)}throw new IllegalArgumentException(value);",
83+
f"{indent(2)}}} else {{",
84+
f"{indent(3)}return constant;",
85+
f"{indent(2)}}}",
86+
f"{indent(1)}}}"
10987
]
110-
return body
88+
return "\n".join(body)
11189

11290

113-
def _get_to_string_method() -> List[str]:
91+
def _get_to_string_method() -> str:
11492
body = [
115-
f"{indent_lvl1}@Override",
116-
f"{indent_lvl1}public String toString() {{",
117-
f"{indent_lvl2}return this.value;",
118-
f"{indent_lvl1}}}"
93+
"",
94+
f"{indent(1)}@Override",
95+
f"{indent(1)}public String toString() {{",
96+
f"{indent(2)}return this.value;",
97+
f"{indent(1)}}}"
11998
]
120-
return body
99+
return "\n".join(body)
121100

122101

123-
def _get_value_method() -> List[str]:
102+
def _get_value_method() -> str:
124103
body = [
125-
f"{indent_lvl1}public String value() {{",
126-
f"{indent_lvl2}return this.value;",
127-
f"{indent_lvl1}}}"
104+
"",
105+
f"{indent(1)}public String value() {{",
106+
f"{indent(2)}return this.value;",
107+
f"{indent(1)}}}"
128108
]
129-
return body
109+
return "\n".join(body)

src/header_generator.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,39 @@
11
import re
2+
from typing import List, Union
3+
4+
from src.java_model import Field, indent
25

36

47
def set_package(package: str) -> str:
58
PACKAGE_REGEX = r"^(?:[A-Za-z_][A-Za-z0-9_]*)(?:\.(?:[A-Za-z_][A-Za-z0-9_]*))*$"
69
if not re.match(PACKAGE_REGEX, package):
710
raise ValueError(f"Invalid package: '{package}'")
811
return f"package {package};"
12+
13+
14+
def set_imports(fields: List[Field]) -> str:
15+
imports = [_imports["Objects"]]
16+
for field in fields:
17+
if field.type in _imports.keys():
18+
imports.append(_imports[field.type])
19+
imports.sort()
20+
return "\n".join(imports)
21+
22+
23+
def render_javadoc(description: Union[str, None], indent_lvl: int) -> str:
24+
if not description:
25+
return ""
26+
27+
return "\n".join([
28+
"",
29+
f"{indent(indent_lvl)}/**",
30+
f"{indent(indent_lvl)} * {description}",
31+
f"{indent(indent_lvl)} */"
32+
])
33+
34+
35+
_imports = {
36+
"Date": "import java.util.Date;",
37+
"List": "import java.util.List;",
38+
"Objects": "import java.util.Objects;",
39+
}

src/java_method_generator.py

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import re
22
from typing import List
33

4-
from src.java_model import JAVA_KEYWORDS, JAVA_BUILTIN_TYPES, JAVA_LITERALS, indent_lvl1, indent_lvl2, indent_lvl3, \
5-
return_indent, Field
4+
from src.header_generator import render_javadoc
5+
from src.java_model import JAVA_KEYWORDS, JAVA_BUILTIN_TYPES, JAVA_LITERALS, Field, indent
66

77

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

1919
declaration = [
20-
_render_javadoc(field),
21-
f"{indent_lvl1}private {field.type} {field.name};"
20+
render_javadoc(field.description, indent_lvl=1),
21+
f"{indent(1)}private {field.type} {field.name};"
2222
]
2323
return "\n".join(declaration)
2424

2525

26-
def _render_javadoc(field: Field) -> str:
27-
if field.description is None:
28-
return ""
29-
30-
return "\n".join([
31-
"",
32-
f"{indent_lvl1}/**",
33-
f"{indent_lvl1} * {field.description}",
34-
f"{indent_lvl1} */"
35-
])
36-
37-
3826
def generate_getters_and_setters(fields: List[Field]) -> str:
3927
methods = []
4028
for field in fields:
@@ -49,9 +37,9 @@ def generate_getter(field: Field) -> str:
4937

5038
getter = [
5139
"",
52-
f"{indent_lvl1}public {field.type} {getter_name}() {{",
53-
f"{indent_lvl2}return {field.name};",
54-
f"{indent_lvl1}}}"
40+
f"{indent(1)}public {field.type} {getter_name}() {{",
41+
f"{indent(2)}return {field.name};",
42+
f"{indent(1)}}}"
5543
]
5644
return "\n".join(getter)
5745

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

6250
setter = [
6351
"",
64-
f"{indent_lvl1}public void {setter_name}({field.type} {field.name}) {{",
65-
f"{indent_lvl2}this.{field.name} = {field.name};",
66-
f"{indent_lvl1}}}"
52+
f"{indent(1)}public void {setter_name}({field.type} {field.name}) {{",
53+
f"{indent(2)}this.{field.name} = {field.name};",
54+
f"{indent(1)}}}"
6755
]
6856
return "\n".join(setter)
6957

7058

7159
def generate_equals(class_name: str, fields: List[Field]) -> str:
7260
equals = [
7361
"",
74-
f"{indent_lvl1}@Override",
75-
f"{indent_lvl1}public boolean equals(Object obj) {{",
62+
f"{indent(1)}@Override",
63+
f"{indent(1)}public boolean equals(Object obj) {{",
7664

77-
f"{indent_lvl2}if (this == obj)",
78-
f"{indent_lvl3}return true;",
65+
f"{indent(2)}if (this == obj)",
66+
f"{indent(3)}return true;",
7967

80-
f"{indent_lvl2}if (!(obj instanceof {class_name}))",
81-
f"{indent_lvl3}return false;",
68+
f"{indent(2)}if (!(obj instanceof {class_name}))",
69+
f"{indent(3)}return false;",
8270

83-
f"{indent_lvl2}{class_name} that = ({class_name}) obj;",
71+
f"{indent(2)}{class_name} that = ({class_name}) obj;",
8472

8573
_render_equals_return_statement(fields),
86-
f"{indent_lvl1}}}"
74+
f"{indent(1)}}}"
8775
]
8876

8977
return "\n".join(equals)
@@ -95,20 +83,21 @@ def _render_equals_return_statement(fields: List[Field]) -> str:
9583
getter_name = _build_getter_name(field.name)
9684
end_line = ";" if i == (len(fields) - 1) else ""
9785
if i == 0:
98-
return_statement.append(f"{indent_lvl2}return Objects.equals({getter_name}(), that.{getter_name}()){end_line}")
86+
return_statement.append(
87+
f"{indent(2)}return Objects.equals({getter_name}(), that.{getter_name}()){end_line}")
9988
else:
10089
return_statement.append(
101-
f"{indent_lvl2}{return_indent}&& Objects.equals({getter_name}(), that.{getter_name}()){end_line}")
90+
f"{indent(4)}&& Objects.equals({getter_name}(), that.{getter_name}()){end_line}")
10291
return "\n".join(return_statement)
10392

10493

10594
def generate_hash_code(fields: List[Field]) -> str:
10695
hash_code = [
10796
"",
108-
f"{indent_lvl1}@Override",
109-
f"{indent_lvl1}public int hashCode() {{",
97+
f"{indent(1)}@Override",
98+
f"{indent(1)}public int hashCode() {{",
11099
_render_hashcode_return_statement(fields),
111-
f"{indent_lvl1}}}"
100+
f"{indent(1)}}}"
112101
]
113102

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

129118

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

137-
return_statement.append(f"{indent_lvl2});")
126+
return_statement.append(f"{indent(2)});")
138127

139128
return "\n".join(return_statement)
140129

0 commit comments

Comments
 (0)