44import static j2html .TagCreator .*;
55
66import 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 ;
710import io .swagger .v3 .oas .models .media .MediaType ;
11+ import io .swagger .v3 .oas .models .media .Schema ;
812import io .swagger .v3 .oas .models .parameters .Parameter ;
913import io .swagger .v3 .oas .models .responses .ApiResponse ;
1014import 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
@@ -214,16 +222,80 @@ private ContainerTag li_missingRequest(String name, MediaType request) {
214222 }
215223
216224 private ContainerTag li_changedRequest (String name , ChangedMediaType request ) {
217- return li ().withText (String .format ("Changed body: '%s'" , name ))
218- .with (div_changedSchema (request .getSchema ()));
225+ ContainerTag li =
226+ li ().with (div_changedSchema (request .getSchema ()))
227+ .withText (String .format ("Changed body: '%s'" , name ));
228+ if (request .isIncompatible ()) {
229+ incompatibilities (li , request .getSchema ());
230+ }
231+ return li ;
219232 }
220233
221234 private ContainerTag div_changedSchema (ChangedSchema schema ) {
222235 ContainerTag div = div ();
223- div .with (h3 ("Schema" ));
236+ div .with (h3 ("Schema" + ( schema . isIncompatible () ? " incompatible" : "" ) ));
224237 return div ;
225238 }
226239
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 );
252+ }
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+ }
260+
261+ private void items (ContainerTag output , String propName , ChangedSchema schema ) {
262+ incompatibilities (output , propName + "[n]" , schema );
263+ }
264+
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 )));
273+ }
274+ }
275+
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+ }
288+
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 ;
297+ }
298+
227299 private ContainerTag ul_param (ChangedParameters changedParameters ) {
228300 List <Parameter > addParameters = changedParameters .getIncreased ();
229301 List <Parameter > delParameters = changedParameters .getMissing ();
0 commit comments