Skip to content

Commit 856b426

Browse files
committed
Avoid checking concrete classes (refactor)
Code inspired on MarkdownRender's implementation
1 parent fdf1072 commit 856b426

File tree

2 files changed

+121
-92
lines changed

2 files changed

+121
-92
lines changed

src/main/java/com/qdesrame/openapi/diff/output/ConsoleRender.java

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
import static com.qdesrame.openapi.diff.model.Changed.result;
44

55
import com.qdesrame.openapi.diff.model.*;
6+
import com.qdesrame.openapi.diff.utils.RefPointer;
7+
import com.qdesrame.openapi.diff.utils.RefType;
8+
import io.swagger.v3.oas.models.media.ArraySchema;
9+
import io.swagger.v3.oas.models.media.Schema;
610
import io.swagger.v3.oas.models.parameters.Parameter;
711
import io.swagger.v3.oas.models.responses.ApiResponse;
812
import java.util.List;
@@ -13,11 +17,14 @@
1317

1418
public class ConsoleRender implements Render {
1519
private static final int LINE_LENGTH = 74;
20+
protected static RefPointer<Schema> refPointer = new RefPointer<>(RefType.SCHEMAS);
21+
protected ChangedOpenApi diff;
1622

1723
private StringBuilder output;
1824

1925
@Override
2026
public String render(ChangedOpenApi diff) {
27+
this.diff = diff;
2128
output = new StringBuilder();
2229
if (diff.isUnchanged()) {
2330
output.append("No differences. Specifications are equivalents");
@@ -169,64 +176,70 @@ private String itemContent(
169176
.append(changedMediaType.isCompatible() ? "Backward compatible" : "Broken compatibility")
170177
.append(System.lineSeparator());
171178
if (!changedMediaType.isCompatible()) {
172-
incompatibility(sb, changedMediaType, "");
179+
sb.append(incompatibilities(changedMediaType.getSchema()));
173180
}
174181
return sb.toString();
175182
}
176183

177-
private void incompatibility(
178-
final StringBuilder output, final ComposedChanged changed, final String propPrefix) {
179-
if (changed.isCoreChanged() == DiffResult.INCOMPATIBLE) {
180-
if (changed instanceof ChangedSchema) {
181-
ChangedSchema cs = (ChangedSchema) changed;
182-
183-
cs.getMissingProperties().keySet().stream()
184-
.forEach(
185-
(propName) -> {
186-
output
187-
.append(StringUtils.repeat(' ', 10))
188-
.append("Missing property: ")
189-
.append(propPrefix)
190-
.append(propPrefix.isEmpty() ? "" : ".")
191-
.append(propName)
192-
.append(System.lineSeparator());
193-
});
194-
195-
if (cs.isChangedType()) {
196-
output
197-
.append(StringUtils.repeat(' ', 10))
198-
.append("Changed property type: ")
199-
.append(propPrefix)
200-
.append(System.lineSeparator());
201-
}
202-
}
184+
private String incompatibilities(final ChangedSchema schema) {
185+
return incompatibilities("", schema);
186+
}
187+
188+
private String incompatibilities(String propName, final ChangedSchema schema) {
189+
StringBuilder sb = new StringBuilder();
190+
if (schema.getItems() != null) {
191+
sb.append(items(propName, schema.getItems()));
192+
}
193+
if (schema.isCoreChanged() == DiffResult.INCOMPATIBLE && schema.isChangedType()) {
194+
String type = type(schema.getOldSchema()) + " -> " + type(schema.getNewSchema());
195+
sb.append(property(propName, "Changed property type", type));
203196
}
197+
String prefix = propName.isEmpty() ? "" : propName + ".";
198+
sb.append(
199+
properties(prefix, "Missing property", schema.getMissingProperties(), schema.getContext()));
200+
schema
201+
.getChangedProperties()
202+
.forEach((name, property) -> sb.append(incompatibilities(prefix + name, property)));
203+
return sb.toString();
204+
}
204205

205-
if (changed instanceof ChangedSchema) {
206-
ChangedSchema cs = (ChangedSchema) changed;
207-
208-
String description = null;
209-
if (!cs.getChangedProperties().isEmpty()) {
210-
cs.getChangedProperties().entrySet().stream()
211-
.forEach(
212-
(entry) -> {
213-
incompatibility(
214-
output,
215-
entry.getValue(),
216-
propPrefix + (propPrefix.isEmpty() ? "" : ".") + entry.getKey());
217-
});
218-
} else if (cs.getItems() != null) {
219-
incompatibility(output, cs.getItems(), propPrefix + "[n]");
220-
}
206+
private String items(String propName, ChangedSchema schema) {
207+
StringBuilder sb = new StringBuilder();
208+
sb.append(incompatibilities(propName + "[n]", schema));
209+
return sb.toString();
210+
}
221211

222-
return;
212+
private String properties(
213+
String propPrefix, String title, Map<String, Schema> properties, DiffContext context) {
214+
StringBuilder sb = new StringBuilder();
215+
if (properties != null) {
216+
properties.forEach(
217+
(key, value) -> sb.append(property(propPrefix + key, title, resolve(value))));
223218
}
219+
return sb.toString();
220+
}
224221

225-
for (Changed child : changed.getChangedElements()) {
226-
if (child instanceof ComposedChanged) {
227-
incompatibility(output, (ComposedChanged) child, "");
228-
}
222+
protected String property(String name, String title, Schema schema) {
223+
return property(name, title, type(schema));
224+
}
225+
226+
protected String property(String name, String title, String type) {
227+
return String.format("%s%s: %s (%s)\n", StringUtils.repeat(' ', 10), title, name, type);
228+
}
229+
230+
protected Schema resolve(Schema schema) {
231+
return refPointer.resolveRef(
232+
diff.getNewSpecOpenApi().getComponents(), schema, schema.get$ref());
233+
}
234+
235+
protected String type(Schema schema) {
236+
String result = "object";
237+
if (schema instanceof ArraySchema) {
238+
result = "array";
239+
} else if (schema.getType() != null) {
240+
result = schema.getType();
229241
}
242+
return result;
230243
}
231244

232245
private String ul_param(ChangedParameters changedParameters) {

src/main/java/com/qdesrame/openapi/diff/output/HtmlRender.java

Lines changed: 60 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
import static j2html.TagCreator.*;
55

66
import com.qdesrame.openapi.diff.model.*;
7+
import com.qdesrame.openapi.diff.utils.RefPointer;
8+
import com.qdesrame.openapi.diff.utils.RefType;
9+
import io.swagger.v3.oas.models.media.ArraySchema;
710
import io.swagger.v3.oas.models.media.MediaType;
11+
import io.swagger.v3.oas.models.media.Schema;
812
import io.swagger.v3.oas.models.parameters.Parameter;
913
import io.swagger.v3.oas.models.responses.ApiResponse;
1014
import j2html.tags.ContainerTag;
@@ -16,6 +20,8 @@ public class HtmlRender implements Render {
1620

1721
private String title;
1822
private String linkCss;
23+
protected static RefPointer<Schema> refPointer = new RefPointer<>(RefType.SCHEMAS);
24+
protected ChangedOpenApi diff;
1925

2026
public HtmlRender() {
2127
this("Api Change Log", "http://deepoove.com/swagger-diff/stylesheets/demo.css");
@@ -27,6 +33,8 @@ public HtmlRender(String title, String linkCss) {
2733
}
2834

2935
public String render(ChangedOpenApi diff) {
36+
this.diff = diff;
37+
3038
List<Endpoint> newEndpoints = diff.getNewEndpoints();
3139
ContainerTag ol_newEndpoint = ol_newEndpoint(newEndpoints);
3240

@@ -218,7 +226,7 @@ private ContainerTag li_changedRequest(String name, ChangedMediaType request) {
218226
li().with(div_changedSchema(request.getSchema()))
219227
.withText(String.format("Changed body: '%s'", name));
220228
if (request.isIncompatible()) {
221-
li = incompatibility(li, request, "");
229+
incompatibilities(li, request.getSchema());
222230
}
223231
return li;
224232
}
@@ -229,55 +237,63 @@ private ContainerTag div_changedSchema(ChangedSchema schema) {
229237
return div;
230238
}
231239

232-
private ContainerTag incompatibility(
233-
final ContainerTag output, final ComposedChanged changed, final String propPrefix) {
234-
if (changed.isCoreChanged() == DiffResult.INCOMPATIBLE) {
235-
if (changed instanceof ChangedSchema) {
236-
ChangedSchema cs = (ChangedSchema) changed;
237-
238-
cs.getMissingProperties().keySet().stream()
239-
.forEach(
240-
(propName) -> {
241-
output.with(
242-
p(String.format(
243-
"Missing property: %s%s%s",
244-
propPrefix, propPrefix.isEmpty() ? "" : ".", propName))
245-
.withClass("missing"));
246-
});
247-
248-
if (cs.isChangedType()) {
249-
output.with(p("Changed property type: " + propPrefix).withClass("missing"));
250-
}
251-
}
240+
private void incompatibilities(final ContainerTag output, final ChangedSchema schema) {
241+
incompatibilities(output, "", schema);
242+
}
243+
244+
private void incompatibilities(
245+
final ContainerTag output, String propName, final ChangedSchema schema) {
246+
if (schema.getItems() != null) {
247+
items(output, propName, schema.getItems());
248+
}
249+
if (schema.isCoreChanged() == DiffResult.INCOMPATIBLE && schema.isChangedType()) {
250+
String type = type(schema.getOldSchema()) + " -> " + type(schema.getNewSchema());
251+
property(output, propName, "Changed property type", type);
252252
}
253+
String prefix = propName.isEmpty() ? "" : propName + ".";
254+
properties(
255+
output, prefix, "Missing property", schema.getMissingProperties(), schema.getContext());
256+
schema
257+
.getChangedProperties()
258+
.forEach((name, property) -> incompatibilities(output, prefix + name, property));
259+
}
253260

254-
if (changed instanceof ChangedSchema) {
255-
ChangedSchema cs = (ChangedSchema) changed;
256-
257-
String description = null;
258-
if (!cs.getChangedProperties().isEmpty()) {
259-
cs.getChangedProperties().entrySet().stream()
260-
.forEach(
261-
(entry) -> {
262-
incompatibility(
263-
output,
264-
entry.getValue(),
265-
propPrefix + (propPrefix.isEmpty() ? "" : ".") + entry.getKey());
266-
});
267-
} else if (cs.getItems() != null) {
268-
incompatibility(output, cs.getItems(), propPrefix + "[n]");
269-
}
261+
private void items(ContainerTag output, String propName, ChangedSchema schema) {
262+
incompatibilities(output, propName + "[n]", schema);
263+
}
270264

271-
return output;
265+
private void properties(
266+
ContainerTag output,
267+
String propPrefix,
268+
String title,
269+
Map<String, Schema> properties,
270+
DiffContext context) {
271+
if (properties != null) {
272+
properties.forEach((key, value) -> property(output, propPrefix + key, title, resolve(value)));
272273
}
274+
}
273275

274-
for (Changed child : changed.getChangedElements()) {
275-
if (child instanceof ComposedChanged) {
276-
incompatibility(output, (ComposedChanged) child, "");
277-
}
278-
}
276+
protected void property(ContainerTag output, String name, String title, Schema schema) {
277+
property(output, name, title, type(schema));
278+
}
279+
280+
protected void property(ContainerTag output, String name, String title, String type) {
281+
output.with(p(String.format("%s: %s (%s)", title, name, type)).withClass("missing"));
282+
}
283+
284+
protected Schema resolve(Schema schema) {
285+
return refPointer.resolveRef(
286+
diff.getNewSpecOpenApi().getComponents(), schema, schema.get$ref());
287+
}
279288

280-
return output;
289+
protected String type(Schema schema) {
290+
String result = "object";
291+
if (schema instanceof ArraySchema) {
292+
result = "array";
293+
} else if (schema.getType() != null) {
294+
result = schema.getType();
295+
}
296+
return result;
281297
}
282298

283299
private ContainerTag ul_param(ChangedParameters changedParameters) {

0 commit comments

Comments
 (0)