All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.reprezen.genflow.openapi.diagram.swagger.SwaggerDiagramData.xtend Maven / Gradle / Ivy

/*******************************************************************************
 * i * Copyright © 2013, 2016 Modelsolv, Inc.
 * All Rights Reserved.
 * 
 * NOTICE: All information contained herein is, and remains the property
 * of ModelSolv, Inc. See the file license.html in the root directory of
 * this project for further information.
 *******************************************************************************/
package com.reprezen.genflow.openapi.diagram.swagger

import com.reprezen.genflow.common.services.MethodServices
import io.swagger.models.HttpMethod
import io.swagger.models.Operation
import io.swagger.models.Path
import io.swagger.models.Response
import io.swagger.models.Swagger
import io.swagger.models.parameters.BodyParameter
import io.swagger.models.parameters.FormParameter
import io.swagger.models.parameters.Parameter
import io.swagger.models.properties.Property
import java.util.HashMap

import static org.apache.commons.text.StringEscapeUtils.*

class SwaggerDiagramData {
	val static StatusCodeComparator STATUS_CODE_COMPARATOR = new StatusCodeComparator
	val static int DEFAULT_RESPONSE_CODE = -1;

	extension XtendHelper = new XtendHelper
	extension Anchors = new Anchors

	val SwaggerDiagramTypes typesProvider
	val Swagger swagger

	new(Swagger model) {
		swagger = model
		typesProvider = new SwaggerDiagramTypes(model)
	}

	def String generateDiagramData() {
		val String result = generateJSON(swagger)
		return result
	}

	def String generateJSON(Swagger swagger) {
		'''
			{
				"ResourceAPI": {
					"objecttype": "ResourceAPI",
					"name": "«escapeEcmaScript(swagger.info?.title)»",
					"anchorId": "«htmlLink(swagger)»",
					"baseURI": "«escapeEcmaScript(swagger.host+swagger.basePath)»",
					"resources": [
					«swagger.paths.safe.entrySet.joinedMap(',',
				[ e, idx |
					generateResource(e.key, e.value, idx)
				])»
					]
				}
			}
		'''
	}

	def String generateResource(String uri, Path path, int pathIdx) {
		'''
			{
			    "objecttype": "ObjectResource",
			    "name": "«uri»",
			    "anchorId": "«htmlLink(path)»",
			    "id": "«uri»",
			    "URI": {
					"name": [ 
					{
				"objecttype": "URISegment", 
				"label": "", 
				"id": "«uri».URI.«pathIdx»"
				}
				],
				"parameters": [
				]
				},
				"methods": [
				«FOR entry : path.operationMap.safe.sorted.entrySet SEPARATOR ','»
					«generateMethod(path, entry.key, entry.value)»
				«ENDFOR»
				],
				"mediaTypes" : [
				]
			}
		'''
	}

	def String generateMethod(Path path, HttpMethod httpMethod, Operation operation) {
		'''
			{
				"objecttype": "Method",
				"name": "«escapeEcmaScript(operation.operationId)»",
				"anchorId": "«htmlLink(operation)»",
				"type": "«httpMethod»",
				«generateRequestWithTrailingComma(path, operation)»
				"responses": [
				«FOR entry : operation.responses.safe.sortedWith(STATUS_CODE_COMPARATOR).entrySet SEPARATOR ','»
					«generateResponse(entry.key, entry.value)»
				«ENDFOR»
				]
			}
		'''
	}

	def generateRequestWithTrailingComma(Path path, Operation operation) {
		val name2param = new HashMap()
		operation.parameters.safe.forEach[name2param.put(it.name, it)]
		path.parameters.safe.forEach[name2param.put(it.name, it)]

		'''
			"request": {
			    "objecttype": "Request",
			    "resource_type": "«operation.requestType»",
			    "name": "(empty request)",
			    "parameters":  [
			    «FOR next : name2param.values SEPARATOR ','»
			    	«generateRequestParameter(next)»
			    «ENDFOR»
			    ]
			},
		'''
	}

	def generateRequestParameter(Parameter parameter) {
		'''
			{
			    "objecttype": "«escapeEcmaScript(parameter.parameterObjectType)»",
			    "name": "«escapeEcmaScript(parameter.parameterLabel)»",
			    "isProperty": false,
			    "propertyId": "",
			    "required": «parameter.required»
			}
		'''
	}

	def generateResponseHeader(String headerName, Property header) {
		'''
			{
			    "objecttype": "HeaderParameter",
			    "name": "«escapeEcmaScript(headerName)»",
			    "isProperty": false,
			    "propertyId": "",
			    "required": «header.required»
			}
		'''
	}

	def generateResponse(String code, Response response) {
		val intCode = StatusCodeComparator.safeParse(code, DEFAULT_RESPONSE_CODE)

		// the next line is according to spec but I don't think it is good 
		// val defaultPrefix = if(intCode == DEFAULT_RESPONSE_CODE) "(default response) :" else ""
		// val defaultPrefix = ""
		'''
			{
			    "objecttype": "Response",
			    "resource_type": "«response.responseType»",
			    "statusCode": "«intCode.responseStatusCode»",
			    "statusCodeGroup": "«getResponseStatusCodeGroup(intCode)»",
			    "parameters":  [
			    «FOR entry : response.headers.safe.sorted.entrySet SEPARATOR ','»
			    	«generateResponseHeader(entry.key, entry.value)»
			    «ENDFOR»
			    ]
			}
		'''
	}

	def static private getResponseStatusCode(int statusCode) {
		if (statusCode == DEFAULT_RESPONSE_CODE) {
			return "(default response)"
		}
		val desc = MethodServices.getResponseStatusCodeDescription(statusCode)
		statusCode + (if(!desc.empty) ' - ' + desc else '')
	}

	def static private getResponseStatusCodeGroup(int code) {

		// this string constants are use in JS: 
		// @see: chart-flow-jquery.js: function image(type, obj)
		switch code {
			case DEFAULT_RESPONSE_CODE: 'Default'
			case code >= 100 && code < 200: 'Informational'
			case code >= 200 && code < 300: 'Success'
			case code >= 300 && code < 400: 'Redirection'
			case code >= 400 && code < 500: 'Client Error'
			case code >= 500 && code < 600: 'Server Error'
			default: ''
		}
	}

	def getParameterObjectType(Parameter parameter) {
		switch (parameter.in ?: "") {
			case "query": return 'QueryParameter'
			case "header": return 'HeaderParameter'
			case "path": return 'RequestParameter'
			case "formData": return 'Request'
			case "body": return 'Request'
			default: 'Request'
		}
	}

	def getParameterLabel(Parameter parameter) {
		typesProvider.parameterLabel(parameter)
	}

	def String getResponseType(Response response) {
		val schema = response.responseSchema
		return typesProvider.propertyTypeLabel("Response", schema)
	}

	def String getRequestType(Operation operation) {
		var bodyParams = operation.parameters.filter(BodyParameter)
		if (!bodyParams.empty) {
			return typesProvider.computeType(bodyParams.head)
		}
		var formParams = operation.parameters.filter(FormParameter)
		if (!formParams.empty) {
			return '''Form Data'''
		}
		''''''
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy