@@ -95,7 +95,7 @@ component name="OpenAPIParser" accessors="true" {
9595 public function parse ( required struct APIDoc , required string XPath = " " ){
9696 setDocumentObject ( getWirebox ().getInstance ( " OpenAPIDocument@SwaggerSDK" ).init ( arguments .APIDoc , arguments .XPath ) );
9797
98- parseDocumentReferences ( getDocumentObject ().getRootDocument ( ) );
98+ parseDocumentInheritance ( parseDocumentReferences ( getDocumentObject ().getDocument () ) );
9999
100100 return this ;
101101 }
@@ -131,12 +131,13 @@ component name="OpenAPIParser" accessors="true" {
131131 DocItem [ i ] = parseDocumentReferences ( DocItem [ i ] );
132132 }
133133 } else if ( isStruct ( DocItem ) ) {
134- // handle top-level values, if they exist
135- if ( structKeyExists ( DocItem , " $ref" ) ) return fetchDocumentReference (DocItem [ " $ref" ]);
134+
135+ // handle top-level values, if they exist
136+ if ( structKeyExists ( DocItem , " $ref" ) ) return fetchDocumentReference ( DocItem [ " $ref" ] );
136137
137138 for ( var key in DocItem ){
138139
139- if (
140+ if (
140141 isStruct ( DocItem [ key ] )
141142 &&
142143 structKeyExists ( DocItem [ key ], " $ref" )
@@ -157,6 +158,79 @@ component name="OpenAPIParser" accessors="true" {
157158
158159 }
159160
161+
162+ /**
163+ * Parses API Document $allOf notations recursively
164+ *
165+ * @param APIDoc The struct representation of the API Document
166+ * @param [XPath] The XPath to zoom the parsed document to during recursion
167+ **/
168+ public function parseDocumentInheritance ( required any DocItem ){
169+
170+ if ( isArray ( DocItem ) ) {
171+ for ( var i = 1 ; i <= arrayLen ( DocItem ); i ++ ){
172+ DocItem [ i ] = parseDocumentInheritance ( DocItem [ i ] );
173+ }
174+ } else if ( isStruct ( DocItem ) ) {
175+
176+ // handle top-level extension
177+ if (
178+ structKeyExists ( DocItem , " $allOf" ) &&
179+ isArray ( DocItem [ " $allOf" ] )
180+ ) {
181+ return extendObject ( DocItem [ " $allOf" ] );
182+ }
183+
184+ for ( var key in DocItem ){
185+
186+ if (
187+ isStruct ( DocItem [ key ] ) &&
188+ structKeyExists ( DocItem [ key ], " $allOf" ) &&
189+ isArray ( DocItem [ key ][ " $allOf" ] )
190+ ) {
191+ DocItem [ key ] = extendObject ( DocItem [ key ][ " $allOf" ] );
192+ } else if ( isStruct ( DocItem [ key ] ) || isArray ( DocItem [ key ] ) ){
193+ DocItem [ key ] = parseDocumentInheritance ( DocItem [ key ] );
194+ }
195+
196+ }
197+ }
198+
199+ return DocItem ;
200+
201+ }
202+
203+
204+ /**
205+ * Extends schema definitions based on the passed array of schema objects
206+ * Note: Ignores CFML objects (non-structs) because sometimes the parser gets passed in here for some reason
207+ *
208+ * @objects
209+ */
210+ function extendObject ( array objects ) {
211+ var output = {
212+ " type" : " object"
213+ };
214+ objects .each ( function ( item , index ) {
215+ if ( isStruct ( item ) ) {
216+ item .each ( function ( key , value ) {
217+
218+ if (
219+ output .keyExists ( key ) &&
220+ isStruct ( output [ key ] )
221+ ) {
222+ output [ key ].append ( value , true );
223+ } else {
224+ output [ key ] = value
225+ }
226+
227+ } );
228+ }
229+ } );
230+
231+ return output ;
232+ }
233+
160234 /**
161235 * Retrieves the value from a nested struct when given an XPath argument
162236 *
@@ -202,23 +276,23 @@ component name="OpenAPIParser" accessors="true" {
202276 // Files receive a parser reference
203277 if ( left ( FilePath , 4 ) == ' http' ){
204278
205- var ReferenceDocument = Wirebox .getInstance ( " OpenAPIParser@SwaggerSDK" ).init ( $ref );
279+ ReferenceDocument = Wirebox .getInstance ( " OpenAPIParser@SwaggerSDK" ).init ( $ref );
206280
207281 } else if ( len ( FilePath ) && fileExists ( getDirectoryFromPath ( getBaseDocumentPath () ) & FilePath )){
208282
209- var ReferenceDocument = Wirebox .getInstance ( " OpenAPIParser@SwaggerSDK" ).init ( getDirectoryFromPath ( getBaseDocumentPath () ) & $ ref );
283+ ReferenceDocument = Wirebox .getInstance ( " OpenAPIParser@SwaggerSDK" ).init ( getDirectoryFromPath ( getBaseDocumentPath () ) & FilePath );
210284
211285 } else if ( len ( FilePath ) && fileExists ( expandPath ( FilePath ) ) ) {
212286
213- var ReferenceDocument = Wirebox .getInstance ( " OpenAPIParser@SwaggerSDK" ).init ( expandPath ( FilePath ) & ( ! isNull ( xPath ) ? " ## " & xPath : " " ) );
287+ ReferenceDocument = Wirebox .getInstance ( " OpenAPIParser@SwaggerSDK" ).init ( expandPath ( FilePath ) & ( ! isNull ( xPath ) ? " ## " & xPath : " " ) );
214288
215289 } else if ( len ( FilePath ) && ! fileExists ( getDirectoryFromPath ( getBaseDocumentPath () ) & FilePath )) {
216290
217291 throw ( type = " SwaggerSDK.ParserException" , message = " File #( getDirectoryFromPath ( getBaseDocumentPath () ) & FilePath ) # does not exist" );
218292
219293 } else if ( ! isNull ( XPath ) && len ( XPath ) ) {
220294
221- var ReferenceDocument = getInternalXPath ( XPath );
295+ ReferenceDocument = getInternalXPath ( XPath );
222296
223297 } else {
224298
@@ -235,7 +309,7 @@ component name="OpenAPIParser" accessors="true" {
235309
236310 }
237311
238- return ReferenceDocument ;
312+ return ReferenceDocument . getNormalizedDocument () ;
239313 }
240314
241315 /**
@@ -248,4 +322,4 @@ component name="OpenAPIParser" accessors="true" {
248322
249323 }
250324
251- }
325+ }
0 commit comments