• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

torand / openapi2java / 22519240185

28 Feb 2026 10:47AM UTC coverage: 84.535% (+0.1%) from 84.425%
22519240185

push

github

torand
chore: prepare release

572 of 795 branches covered (71.95%)

Branch coverage included in aggregate %.

1702 of 1895 relevant lines covered (89.82%)

5.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.3
/src/main/java/io/github/torand/openapi2java/writers/java/JavaPojoWriter.java
1
/*
2
 * Copyright (c) 2024-2026 Tore Eide Andersen
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package io.github.torand.openapi2java.writers.java;
17

18
import io.github.torand.openapi2java.generators.Options;
19
import io.github.torand.openapi2java.model.AnnotatedTypeName;
20
import io.github.torand.openapi2java.model.PojoInfo;
21
import io.github.torand.openapi2java.model.PropertyInfo;
22
import io.github.torand.openapi2java.utils.PackageUtils;
23
import io.github.torand.openapi2java.writers.BaseWriter;
24
import io.github.torand.openapi2java.writers.PojoWriter;
25

26
import java.io.Writer;
27
import java.util.List;
28
import java.util.concurrent.atomic.AtomicInteger;
29
import java.util.function.Predicate;
30

31
import static io.github.torand.javacommons.collection.CollectionHelper.nonEmpty;
32
import static io.github.torand.openapi2java.utils.PackageUtils.isFqnInPackage;
33
import static java.util.function.Predicate.not;
34
import static java.util.stream.Collectors.joining;
35

36
/**
37
 * Writes Java code for a pojo.
38
 */
39
public class JavaPojoWriter extends BaseWriter implements PojoWriter {
40

41
    public JavaPojoWriter(Writer writer, Options opts) {
42
        super(writer, opts);
4✔
43
    }
1✔
44

45
    @Override
46
    public void write(PojoInfo pojoInfo) {
47
        writeLine("package %s;", opts.getModelPackage(pojoInfo.modelSubpackage()));
13✔
48
        writeNewLine();
2✔
49

50
        writeNonJavaImports(pojoInfo);
3✔
51
        writeJavaImports(pojoInfo);
3✔
52

53
        if (pojoInfo.isDeprecated()) {
3!
54
            writeLine("/// @deprecated %s".formatted(pojoInfo.deprecationMessage()));
×
55
            writeLine("@Deprecated");
×
56
        }
57

58
        pojoInfo.annotations().forEach(a -> writeLine(a.annotation()));
12✔
59

60
        if (opts.pojosAsRecords()) {
4✔
61
            writeLine("public record %s (".formatted(pojoInfo.name()));
14✔
62
        } else {
63
            writeLine("public class %s {".formatted(pojoInfo.name()));
13✔
64
        }
65

66
        AtomicInteger propNo = new AtomicInteger(1);
5✔
67
        pojoInfo.properties().forEach(propInfo -> {
7✔
68
            writeNewLine();
2✔
69
            writePropertyAnnotationLines(propInfo);
3✔
70
            writePropertyTypeAndNameLines(propInfo);
3✔
71

72
            if (opts.pojosAsRecords()) {
4✔
73
                if (propNo.getAndIncrement() < pojoInfo.properties().size()) {
6✔
74
                    writeLine(",");
6✔
75
                } else {
76
                    writeNewLine();
3✔
77
                }
78
            } else {
79
                writeLine(";");
5✔
80
            }
81
        });
1✔
82

83
        if (opts.pojosAsRecords()) {
4✔
84
            writeLine(") {");
5✔
85
            writeNewLine();
2✔
86
            writeLine("}");
6✔
87
        } else {
88
            writeNewLine();
2✔
89
            writeNoArgConstructor(pojoInfo.name());
4✔
90
            if (nonEmpty(pojoInfo.properties())) {
4✔
91
                writeNewLine();
2✔
92
                writeParameterizedConstructor(pojoInfo.name(), pojoInfo.properties());
6✔
93
            }
94
            writeLine("}");
5✔
95
        }
96
    }
1✔
97

98
    private void writeJavaImports(PojoInfo pojoInfo) {
99
        List<String> imports = pojoInfo.aggregatedNormalImports().stream()
4✔
100
            .filter(PackageUtils::isJavaPackage)
2✔
101
            .filter(not(PackageUtils::isFundamentalJavaClass))
4✔
102
            .map("import %s;"::formatted)
10✔
103
            .toList();
2✔
104

105
        if (nonEmpty(imports)) {
3✔
106
            imports.forEach(this::writeLine);
10✔
107
            writeNewLine();
2✔
108
        }
109
    }
1✔
110

111
    private void writeNonJavaImports(PojoInfo pojoInfo) {
112
        Predicate<String> isInSamePackage = fqn -> isFqnInPackage(fqn, opts.getModelPackage(pojoInfo.modelSubpackage()));
12✔
113

114
        List<String> imports = pojoInfo.aggregatedNormalImports().stream()
4✔
115
            .filter(not(PackageUtils::isJavaPackage))
3✔
116
            .filter(not(isInSamePackage))
4✔
117
            .map("import %s;"::formatted)
10✔
118
            .toList();
2✔
119

120
        if (nonEmpty(imports)) {
3!
121
            imports.forEach(this::writeLine);
10✔
122
            writeNewLine();
2✔
123
        }
124
    }
1✔
125

126
    private void writeNoArgConstructor(String name) {
127
        writeIndent(1);
3✔
128
        writeLine("public %s() {", name);
9✔
129
        writeIndent(1);
3✔
130
        writeLine("}");
5✔
131
    }
1✔
132

133
    private void writeParameterizedConstructor(String name, List<PropertyInfo> props) {
134
        writeIndent(1);
3✔
135
        writeLine("public %s(%s) {", name, props.stream().map(p -> p.type().getFullName() + " " + p.name()).collect(joining(", ")));
26✔
136
        props.forEach(p -> {
4✔
137
            writeIndent(2);
3✔
138
            writeLine("this.%s = %s;", p.name(), p.name());
15✔
139
        });
1✔
140
        writeIndent(1);
3✔
141
        writeLine("}");
5✔
142
    }
1✔
143

144
    private void writePropertyAnnotationLines(PropertyInfo propInfo) {
145
        if (propInfo.isDeprecated()) {
3✔
146
            writeIndent(1);
3✔
147
            writeLine("/// @deprecated %s".formatted(propInfo.deprecationMessage()));
13✔
148
            writeIndent(1);
3✔
149
            writeLine("@Deprecated");
5✔
150
        }
151
        propInfo.annotations().forEach(a -> {
5✔
152
            writeIndent(1);
3✔
153
            writeLine(a.annotation());
6✔
154
        });
1✔
155
    }
1✔
156

157
    private void writePropertyTypeAndNameLines(PropertyInfo propInfo) {
158
        AnnotatedTypeName annotatedTypeName = propInfo.type().getAnnotatedFullName();
4✔
159

160
        annotatedTypeName.annotations().forEach(a -> {
5✔
161
            writeIndent(1);
3✔
162
            writeLine(a);
5✔
163
        });
1✔
164

165
        writeIndent(1);
3✔
166
        if (opts.pojosAsRecords()) {
4✔
167
            write("%s %s".formatted(annotatedTypeName.typeName(), propInfo.name()));
19✔
168
        } else {
169
            write("public %s %s".formatted(annotatedTypeName.typeName(), propInfo.name()));
18✔
170
        }
171
    }
1✔
172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc