2626import io .swagger .v3 .oas .models .media .Schema ;
2727import io .swagger .v3 .oas .models .parameters .Parameter ;
2828import io .swagger .v3 .oas .models .responses .ApiResponse ;
29+ import io .swagger .v3 .oas .models .security .SecurityRequirement ;
2930import j2html .rendering .FlatHtml ;
3031import j2html .tags .ContainerTag ;
3132import j2html .tags .specialized .DivTag ;
5051import org .openapitools .openapidiff .core .model .ChangedParameters ;
5152import org .openapitools .openapidiff .core .model .ChangedResponse ;
5253import org .openapitools .openapidiff .core .model .ChangedSchema ;
54+ import org .openapitools .openapidiff .core .model .ChangedSecurityRequirement ;
55+ import org .openapitools .openapidiff .core .model .ChangedSecurityRequirements ;
5356import org .openapitools .openapidiff .core .model .DiffContext ;
5457import org .openapitools .openapidiff .core .model .DiffResult ;
5558import org .openapitools .openapidiff .core .model .Endpoint ;
@@ -64,15 +67,27 @@ public class HtmlRender implements Render {
6467
6568 private final String title ;
6669 private final String linkCss ;
70+ private final boolean showAllChanges ;
6771 protected ChangedOpenApi diff ;
6872
6973 public HtmlRender () {
7074 this ("Api Change Log" , "http://deepoove.com/swagger-diff/stylesheets/demo.css" );
7175 }
7276
77+ public HtmlRender (boolean showAllChanges ) {
78+ this ("Api Change Log" , "http://deepoove.com/swagger-diff/stylesheets/demo.css" , showAllChanges );
79+ }
80+
7381 public HtmlRender (String title , String linkCss ) {
7482 this .title = title ;
7583 this .linkCss = linkCss ;
84+ this .showAllChanges = false ;
85+ }
86+
87+ public HtmlRender (String title , String linkCss , boolean showAllChanges ) {
88+ this .title = title ;
89+ this .linkCss = linkCss ;
90+ this .showAllChanges = showAllChanges ;
7691 }
7792
7893 public void render (ChangedOpenApi diff , OutputStreamWriter outputStreamWriter ) {
@@ -200,6 +215,11 @@ private OlTag ol_changed(List<ChangedOperation> changedOperations) {
200215 ul_detail .with (
201216 li ().with (h3 ("Response" )).with (ul_response (changedOperation .getApiResponses ())));
202217 }
218+ if (showAllChanges && changedOperation .resultSecurityRequirements ().isDifferent ()) {
219+ ul_detail .with (
220+ li ().with (h3 ("Security Requirements" ))
221+ .with (ul_securityRequirements (changedOperation .getSecurityRequirements ())));
222+ }
203223 ol .with (
204224 li ().with (span (method ).withClass (method ))
205225 .withText (pathUrl + " " )
@@ -209,6 +229,52 @@ private OlTag ol_changed(List<ChangedOperation> changedOperations) {
209229 return ol ;
210230 }
211231
232+ private UlTag ul_securityRequirements (ChangedSecurityRequirements changedSecurityRequirements ) {
233+ List <SecurityRequirement > addRequirements = changedSecurityRequirements .getIncreased ();
234+ List <SecurityRequirement > delRequirements = changedSecurityRequirements .getMissing ();
235+ List <ChangedSecurityRequirement > changedRequirements = changedSecurityRequirements .getChanged ();
236+ UlTag ul = ul ().withClass ("change security requirements" );
237+ if (addRequirements != null ) {
238+ for (SecurityRequirement addRequirement : addRequirements ) {
239+ ul .with (li_addSecurityRequirement (addRequirement ));
240+ }
241+ }
242+ if (delRequirements != null ) {
243+ for (SecurityRequirement delRequirement : delRequirements ) {
244+ ul .with (li_missingSecurityRequirement (delRequirement ));
245+ }
246+ }
247+ if (changedRequirements != null ) {
248+ for (ChangedSecurityRequirement changedRequirement : changedRequirements ) {
249+ ul .with (li_changedSecurityRequirement (changedRequirement ));
250+ }
251+ }
252+
253+ return ul ;
254+ }
255+
256+ private LiTag li_addSecurityRequirement (SecurityRequirement securityRequirement ) {
257+ return li ().withText ("New security requirement : " )
258+ .with (span (null == securityRequirement .toString () ? "" : (securityRequirement .toString ())));
259+ }
260+
261+ private LiTag li_missingSecurityRequirement (SecurityRequirement securityRequirement ) {
262+ return li ().withText ("Deleted security requirement : " )
263+ .with (span (null == securityRequirement .toString () ? "" : (securityRequirement .toString ())));
264+ }
265+
266+ private LiTag li_changedSecurityRequirement (
267+ ChangedSecurityRequirement changedSecurityRequirement ) {
268+ return li ().withText (String .format ("Changed security requirement : " ))
269+ .with (
270+ span (
271+ (null == changedSecurityRequirement .getNewSecurityRequirement ()
272+ || null
273+ == changedSecurityRequirement .getNewSecurityRequirement ().toString ())
274+ ? ""
275+ : (changedSecurityRequirement .getNewSecurityRequirement ().toString ())));
276+ }
277+
212278 private UlTag ul_response (ChangedApiResponse changedApiResponse ) {
213279 Map <String , ApiResponse > addResponses = changedApiResponse .getIncreased ();
214280 Map <String , ApiResponse > delResponses = changedApiResponse .getMissing ();
@@ -279,9 +345,12 @@ private LiTag li_changedRequest(String name, ChangedMediaType request) {
279345 LiTag li =
280346 li ().with (div_changedSchema (request .getSchema ()))
281347 .withText (String .format ("Changed body: '%s'" , name ));
282- if (request .isIncompatible ()) {
348+ if (request .isIncompatible () && ! showAllChanges ) {
283349 incompatibilities (li , request .getSchema ());
284350 }
351+ else if (showAllChanges ) {
352+ allChanges (li , request .getSchema ());
353+ }
285354 return li ;
286355 }
287356
@@ -291,6 +360,28 @@ private DivTag div_changedSchema(ChangedSchema schema) {
291360 return div ;
292361 }
293362
363+ private void allChanges (final LiTag output , final ChangedSchema schema ) {
364+ allChanges (output , "" , schema );
365+ }
366+
367+ private void allChanges (
368+ final ContainerTag <?> output , String propName , final ChangedSchema schema ) {
369+ String prefix = propName .isEmpty () ? "" : propName + "." ;
370+ properties (
371+ output , prefix , "Missing property" , schema .getMissingProperties (), schema .getContext ());
372+ properties (
373+ output , prefix , "Added property" , schema .getIncreasedProperties (), schema .getContext ());
374+
375+ propertiesChanged (
376+ output , prefix , "Changed property" , schema .getChangedProperties (), schema .getContext ());
377+ if (schema .getItems () != null ) {
378+ itemsAllChanges (output , propName , schema .getItems ());
379+ }
380+ schema
381+ .getChangedProperties ()
382+ .forEach ((name , property ) -> allChanges (output , prefix + name , property ));
383+ }
384+
294385 private void incompatibilities (final LiTag output , final ChangedSchema schema ) {
295386 incompatibilities (output , "" , schema );
296387 }
@@ -316,6 +407,10 @@ private void items(ContainerTag<?> output, String propName, ChangedSchema schema
316407 incompatibilities (output , propName + "[n]" , schema );
317408 }
318409
410+ private void itemsAllChanges (ContainerTag <?> output , String propName , ChangedSchema schema ) {
411+ allChanges (output , propName + "[n]" , schema );
412+ }
413+
319414 private void properties (
320415 ContainerTag <?> output ,
321416 String propPrefix ,
@@ -327,6 +422,17 @@ private void properties(
327422 }
328423 }
329424
425+ private void propertiesChanged (
426+ ContainerTag <?> output ,
427+ String propPrefix ,
428+ String title ,
429+ Map <String , ChangedSchema > properties ,
430+ DiffContext context ) {
431+ if (properties != null ) {
432+ properties .forEach ((key , value ) -> resolveProperty (output , propPrefix , key , value , title ));
433+ }
434+ }
435+
330436 private void resolveProperty (
331437 ContainerTag <?> output , String propPrefix , String key , Schema <?> value , String title ) {
332438 try {
@@ -336,6 +442,15 @@ private void resolveProperty(
336442 }
337443 }
338444
445+ private void resolveProperty (
446+ ContainerTag <?> output , String propPrefix , String key , ChangedSchema value , String title ) {
447+ try {
448+ property (output , propPrefix + key , title , resolve (value ));
449+ } catch (Exception e ) {
450+ property (output , propPrefix + key , title , type (value ));
451+ }
452+ }
453+
339454 protected void property (ContainerTag <?> output , String name , String title , Schema <?> schema ) {
340455 property (output , name , title , type (schema ));
341456 }
@@ -349,6 +464,13 @@ protected Schema<?> resolve(Schema<?> schema) {
349464 diff .getNewSpecOpenApi ().getComponents (), schema , schema .get$ref ());
350465 }
351466
467+ protected Schema <?> resolve (ChangedSchema schema ) {
468+ return refPointer .resolveRef (
469+ diff .getNewSpecOpenApi ().getComponents (),
470+ schema .getNewSchema (),
471+ schema .getNewSchema ().get$ref ());
472+ }
473+
352474 protected String type (Schema <?> schema ) {
353475 String result = "object" ;
354476 if (schema == null ) {
@@ -361,6 +483,10 @@ protected String type(Schema<?> schema) {
361483 return result ;
362484 }
363485
486+ protected String type (ChangedSchema schema ) {
487+ return type (schema .getNewSchema ());
488+ }
489+
364490 private UlTag ul_param (ChangedParameters changedParameters ) {
365491 List <Parameter > addParameters = changedParameters .getIncreased ();
366492 List <Parameter > delParameters = changedParameters .getMissing ();
0 commit comments