Skip to content

Commit 16168c1

Browse files
authored
Merge pull request #18 from homestar9/features/allof-inheritance
Add $allOf object inheritance
2 parents 9a721fd + c930524 commit 16168c1

File tree

1 file changed

+84
-10
lines changed

1 file changed

+84
-10
lines changed

models/OpenAPI/Parser.cfc

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)