11package it .imolainformatica .openapi2jsonschema4j .impl ;
22
33import java .io .File ;
4- import java .util .HashMap ;
5- import java .util .Iterator ;
6- import java .util .Map ;
4+ import java .util .*;
75
86import com .fasterxml .jackson .annotation .JsonInclude .Include ;
97import com .fasterxml .jackson .databind .JsonNode ;
1412import com .fasterxml .jackson .databind .ser .FilterProvider ;
1513import com .fasterxml .jackson .databind .ser .impl .SimpleBeanPropertyFilter ;
1614import com .fasterxml .jackson .databind .ser .impl .SimpleFilterProvider ;
15+ import com .fasterxml .jackson .databind .ser .std .NullSerializer ;
1716import com .github .fge .jsonschema .core .report .ProcessingReport ;
1817import com .github .fge .jsonschema .main .JsonSchemaFactory ;
1918import com .github .fge .jsonschema .processors .syntax .SyntaxValidator ;
2019
21- import io .swagger .models .AbstractModel ;
22- import io .swagger .models .ArrayModel ;
23- import io .swagger .models .Model ;
24- import io .swagger .models .ModelImpl ;
25- import io .swagger .models .Swagger ;
20+ import io .swagger .models .*;
21+ import io .swagger .models .properties .*;
2622import it .imolainformatica .openapi2jsonschema4j .base .BaseJsonSchemaGenerator ;
2723import it .imolainformatica .openapi2jsonschema4j .base .IJsonSchemaGenerator ;
2824import lombok .extern .slf4j .Slf4j ;
@@ -39,14 +35,13 @@ public DraftV4JsonSchemaGenerator(boolean strict) {
3935 private Map <String , JsonNode > generateForObjects () throws Exception {
4036 for (String ref : getMessageObjects ()) {
4137 String title = ref .replace (DEFINITIONS2 , "" );
42- log .info ("title={}" , title );
4338 Map <String , Object > defs = (Map <String , Object >) ((HashMap <String , Model >) getObjectsDefinitions ()).clone ();
4439 AbstractModel ob = (AbstractModel ) defs .get (title );
4540 defs .remove (title );
4641 Map <String , Object > res = new HashMap <String , Object >();
4742 res .put (DEFINITIONS , defs );
4843 res .put (TITLE2 , title );
49-
44+ log . info ( "Generating json schema for object '{}' of type {}" , title , ob . getClass ());
5045 if (ob instanceof ModelImpl ) {
5146 res .put (TYPE , ((ModelImpl ) ob ).getType ());
5247 res .put (PROPERTIES , ob .getProperties ());
@@ -65,12 +60,100 @@ private Map<String, JsonNode> generateForObjects() throws Exception {
6560 res .put (MAX_ITEMS , ((ArrayModel ) ob ).getMaxItems ());
6661 }
6762 res .put ($SCHEMA , HTTP_JSON_SCHEMA_ORG_DRAFT_04_SCHEMA );
63+ removeUnusedObject (res ,ob );
6864 getGeneratedObjects ().put (title , postprocess (res ));
6965 }
7066 return getGeneratedObjects ();
7167
7268 }
7369
70+ private void removeUnusedObject (Map <String , Object > res , AbstractModel ob ) {
71+ log .info ("Removing unused definition for '{}'" ,res .get (TITLE2 ));
72+ List <String > usedDefinition = new ArrayList <>();
73+ navigateModel ((String )res .get (TITLE2 ),usedDefinition ,res ,ob );
74+ log .info ("Used Object = {}" ,usedDefinition );
75+ List <String > tbdeleted = new ArrayList <>();
76+ for (String key : ((Map <String ,Object >)res .get (DEFINITIONS )).keySet ()) {
77+ if (!usedDefinition .contains (key )){
78+ log .debug ("Removing definition for object {}" ,key );
79+ tbdeleted .add (key );
80+ } else {
81+ log .debug ("Object {} is used!" ,key );
82+ }
83+ }
84+ for (String del : tbdeleted ){
85+ ((Map <String ,Object >)res .get (DEFINITIONS )).remove (del );
86+ }
87+ }
88+
89+ private void navigateModel (String originalRef , List <String > usedDefinition , Map <String , Object > res , Object ob ) {
90+ log .debug ("Analyzing ref {} object={}" ,originalRef ,ob );
91+ String objectName =originalRef .replace (DEFINITIONS2 ,"" );
92+ if (ob ==null ){
93+ ob = ((Map ) res .get (DEFINITIONS )).get (objectName );
94+ }
95+ log .debug ("Analyzing object {} {}" ,ob ,originalRef );
96+ if (usedDefinition .contains (objectName )){
97+ log .info ("Found circular reference for object {}!" ,objectName );
98+ return ;
99+ }
100+ usedDefinition .add (objectName );
101+ if (ob instanceof ModelImpl ) {
102+ ModelImpl mi = (ModelImpl )ob ;
103+ Map <String , Property > m = mi .getProperties ();
104+ log .debug ("properties={}" ,m );
105+ if (m !=null ) {
106+ for (String name : m .keySet ()) {
107+ navigateProperty (name , m .get (name ), usedDefinition , res );
108+ }
109+ }
110+ } else if (ob instanceof ArrayModel ) {
111+ log .debug ("array model={}" ,res .get (ITEMS ));
112+ if (res .get (ITEMS ) instanceof RefProperty ) {
113+ navigateModel (((RefProperty )((RefProperty )res .get (ITEMS ))).getOriginalRef (),usedDefinition ,res ,null );
114+ }
115+ } else if (ob instanceof ComposedModel ) {
116+ ComposedModel cm = (ComposedModel )ob ;
117+ for (Model m : cm .getAllOf ()) {
118+ navigateModel (m .getReference (), usedDefinition ,res ,null );
119+ }
120+
121+ } else if (ob instanceof RefModel ) {
122+ RefModel rm = (RefModel )ob ;
123+ Map <String , Property > m = rm .getProperties ();
124+ log .debug ("properties={}" ,m );
125+ if (m !=null ) {
126+ for (String name : m .keySet ()) {
127+ navigateProperty (name , m .get (name ), usedDefinition , res );
128+ }
129+ }
130+
131+ } else {
132+ throw new RuntimeException (ob .getClass ()+" not handled!" );
133+ }
134+ }
135+
136+ private void navigateProperty (String propertyName , Property p ,List <String > usedDefinition ,Map <String , Object > res ){
137+ log .debug ("property name '{}' of type {}" ,propertyName ,p );
138+ if (p instanceof RefProperty ) {
139+ navigateModel (((RefProperty )((RefProperty ) p )).getOriginalRef (),usedDefinition ,res ,null );
140+ } else if (p instanceof ArrayProperty ) {
141+ ArrayProperty ap = (ArrayProperty ) p ;
142+ log .debug ("Array property={} items={}" ,ap ,ap .getItems ());
143+ navigateProperty ("items" ,ap .getItems (),usedDefinition ,res );
144+ } else if (p instanceof ObjectProperty ){
145+ ObjectProperty op = (ObjectProperty ) p ;
146+ for (String name : op .getProperties ().keySet ()){
147+ navigateProperty (name ,op .getProperties ().get (name ),usedDefinition ,res );
148+ }
149+ } else if (p instanceof MapProperty ) {
150+ MapProperty mp = (MapProperty )p ;
151+ navigateProperty (mp .getName (),mp .getAdditionalProperties (),usedDefinition ,res );
152+ } else {
153+ log .debug (p .getClass () + " - nothing to do!" );
154+ }
155+ }
156+
74157 private JsonNode postprocess (Map <String , Object > res ) throws Exception {
75158 ObjectMapper mapper = new ObjectMapper ();
76159 mapper .setSerializationInclusion (Include .NON_NULL );
0 commit comments