Skip to content

Commit

Permalink
Swagger API methods are sorted, so that raml file will be the same on…
Browse files Browse the repository at this point in the history
… each generation
  • Loading branch information
mmatloka authored and rucek committed Aug 20, 2014
1 parent 72b4827 commit f0914d8
Show file tree
Hide file tree
Showing 9 changed files with 311 additions and 79 deletions.
40 changes: 6 additions & 34 deletions src/main/groovy/com/_8x8/cloud/swagger2raml/RamlGenerator.groovy
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com._8x8.cloud.swagger2raml

import com._8x8.cloud.swagger2raml.model.Api
import com._8x8.cloud.swagger2raml.model.Resource
import com._8x8.cloud.swagger2raml.reader.SwaggerApiReader
import com._8x8.cloud.swagger2raml.reader.SwaggerResourceReader
import com._8x8.cloud.swagger2raml.writer.ApiWriter

/**
Expand Down Expand Up @@ -31,44 +29,18 @@ class RamlGenerator {
static File generateFromSwaggerUrl(String url, String outputFileName) {
Api api = new SwaggerApiReader().readFromUrl(url)

SwaggerResourceReader swaggerResourceReader = new SwaggerResourceReader()
def actualResources = api.resources.collect { Resource resource ->
swaggerResourceReader.readFromUrl(url + resource.path).children
}

api.resources = flattenAndMerge(actualResources)

File outputFile = new File(outputFileName)
if (outputFile.exists()) {
outputFile.delete()
}
def outputFile = prepareOutputFile(outputFileName)

new ApiWriter(file: outputFile).writeApi(api)

return outputFile
}

private static Collection<Resource> flattenAndMerge(Collection<Collection<Resource>> resources) {
Collection<Resource> flattened = resources.flatten()
return merge(flattened)
}

private static Collection<Resource> merge(Collection<Resource> resources) {
Map<String, List<Resource>> resourcesByPath = resources.groupBy { it.path }

Collection<Resource> mergedResources = []
resourcesByPath.keySet().each { key ->
Resource mergedResource = new Resource(path: key)
resourcesByPath[key].each { resource ->
mergedResource.mergeWith(resource)
}
mergedResources.add(mergedResource)
}

mergedResources.each {
it.children = merge(it.children)
static File prepareOutputFile(String outputFileName) {
File outputFile = new File(outputFileName)
if (outputFile.exists()) {
outputFile.delete()
}

return mergedResources
return outputFile
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com._8x8.cloud.swagger2raml.model

import groovy.transform.Canonical
import groovy.transform.ToString

/**
* @author Jacek Kunicki
*/
@Canonical
@ToString(includePackage = false)
abstract class Method {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com._8x8.cloud.swagger2raml.model

import groovy.transform.Canonical
import groovy.transform.ToString

/**
* @author Jacek Kunicki
*/
@Canonical
@ToString(includePackage = false)
class QueryParameter {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com._8x8.cloud.swagger2raml.model

import groovy.transform.Canonical
import groovy.transform.ToString

/**
* @author Jacek Kunicki
*/
@Canonical
@ToString(includePackage = false)
class Resource {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@ class SwaggerApiReader extends SwaggerReader<Api> {
@Override
Api readFromUrl(String url) {
def json = jsonSlurper.parse(new URL(url))
return readFromJson(json)
Api api = readFromJson(json)

def swaggerResourceReader = new SwaggerResourceReader()
def actualResources = api.resources.collect { Resource resource ->
swaggerResourceReader.readFromUrl(url + resource.path).children
}

def flattenedResources = flattenAndMerge(actualResources)
api.resources = sortResources(flattenedResources)
return api;
}

@Override
Expand All @@ -21,10 +30,51 @@ class SwaggerApiReader extends SwaggerReader<Api> {
}

private static Api readFromJson(json) {
return new Api(
def api = new Api(
title: json.info.title,
version: json.apiVersion,
resources: json.apis.collect { new Resource(path: it.path) }
)

api.resources = sortResources(api.resources)

return api
}

private static Collection<Resource> sortResources(Collection<Resource> resources) {
def sortedResources = resources.sort { resource1, resource2 ->
resource1.path.compareTo(resource2.path)
}

sortedResources.each { resource ->
resource.children = sortResources(resource.children)
resource.methods.sort { method1, method2 -> method1.getClass().simpleName.compareTo(method2.getClass().simpleName) }
}

return sortedResources
}

private static Collection<Resource> flattenAndMerge(Collection<Collection<Resource>> resources) {
Collection<Resource> flattened = resources.flatten()
return merge(flattened)
}

private static Collection<Resource> merge(Collection<Resource> resources) {
Map<String, List<Resource>> resourcesByPath = resources.groupBy { it.path }

Collection<Resource> mergedResources = []
resourcesByPath.keySet().each { key ->
Resource mergedResource = new Resource(path: key)
resourcesByPath[key].each { resource ->
mergedResource.mergeWith(resource)
}
mergedResources.add(mergedResource)
}

mergedResources.each {
it.children = merge(it.children)
}

return mergedResources
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,31 @@ class ResourceSpec extends Specification {
where:
path << ['/foo', '/a/d', '/a/b/c']
}

def 'resources with same data should be equal'() {
setup:
def resource1 = new Resource(path: 'path')
def resource2 = new Resource(path: 'path')

expect:
resource1 == resource2
}

def 'resources with different paths should not be equal'() {
setup:
def resource1 = new Resource(path: 'path1')
def resource2 = new Resource(path: 'path2')

expect:
resource1 != resource2
}

def 'resources with different children order should not be equal'() {
setup:
def resource1 = new Resource(path: 'path', children: [new Resource(path: 'child1'), new Resource(path: 'child2')])
def resource2 = new Resource(path: 'path', children: [new Resource(path: 'child2'), new Resource(path: 'child1')])

expect:
resource1 != resource2
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package com._8x8.cloud.swagger2raml.reader

import com._8x8.cloud.swagger2raml.ResourceSpecBase
import com._8x8.cloud.swagger2raml.model.Api
import spock.lang.Specification
import com._8x8.cloud.swagger2raml.model.Delete
import com._8x8.cloud.swagger2raml.model.Get
import com._8x8.cloud.swagger2raml.model.Post
import com._8x8.cloud.swagger2raml.model.Put
import com._8x8.cloud.swagger2raml.model.Resource

/**
* @author Jacek Kunicki
*/
class SwaggerApiReaderSpec extends Specification {
class SwaggerApiReaderSpec extends ResourceSpecBase {

def 'should read API from file'() {
setup:
Expand All @@ -18,4 +23,44 @@ class SwaggerApiReaderSpec extends Specification {
then:
!api.resources?.empty
}

def 'should read the same API when swagger order is different'() {
setup:
File swaggerApiFile1 = new File('src/test/resources/swagger-api.json')
File swaggerApiFile2 = new File('src/test/resources/swagger-api-2.json')

when:
Api api1 = new SwaggerApiReader().readFromFile(swaggerApiFile1)
Api api2 = new SwaggerApiReader().readFromFile(swaggerApiFile2)

then:
api1.resources == api2.resources
}

def 'should merge resources by path recursively'() {
setup:
Collection<Resource> resources = [
new Resource(path: 'a', methods: [new Get()], children: [
new Resource(path: 'b', methods: [new Get()]),
new Resource(path: 'b', methods: [new Post()])
]),
new Resource(path: 'a', methods: [new Delete()], children: [
new Resource(path: 'b', methods: [new Put()])
]),
new Resource(path: 'c', methods: [new Get()])
]

when:
Collection<Resource> mergedResources = SwaggerApiReader.merge(resources)

then:
Resource resourceA = mergedResources.find { it.path == 'a' }
resourceA.hasChildren(1).hasMethods(Get, Delete)

and:
resourceA.childByPath('b').hasNoChildren().hasMethods(Get, Post, Put)

and:
mergedResources.find { it.path == 'c' }.hasNoChildren().hasMethods(Get)
}
}
Loading

0 comments on commit f0914d8

Please sign in to comment.