Package com.dottydingo.hyperion.module.swagger

Source Code of com.dottydingo.hyperion.module.swagger.SwaggerSpecBuilder

package com.dottydingo.hyperion.module.swagger;

import com.dottydingo.hyperion.api.DeleteResponse;
import com.dottydingo.hyperion.api.EntityResponse;
import com.dottydingo.hyperion.api.HistoryResponse;
import com.dottydingo.hyperion.service.configuration.ApiVersionPlugin;
import com.dottydingo.hyperion.service.configuration.EntityPlugin;
import com.dottydingo.hyperion.service.configuration.HyperionEndpointConfiguration;
import com.dottydingo.hyperion.service.configuration.ServiceRegistry;
import com.dottydingo.hyperion.service.context.HttpMethod;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.types.ArraySchema;
import com.fasterxml.jackson.module.jsonSchema.types.ObjectSchema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.*;

/**
*/
public class SwaggerSpecBuilder
{
    private Logger logger = LoggerFactory.getLogger(SwaggerSpecBuilder.class);
    private ServiceRegistry serviceRegistry;
    private HyperionEndpointConfiguration endpointConfiguration;
    private String basePath;
    protected ObjectMapper objectMapper;
    private String resourceBundleBase = "com.dottydingo.hyperion.module.swagger.Messages";

    public void setServiceRegistry(ServiceRegistry serviceRegistry)
    {
        this.serviceRegistry = serviceRegistry;
    }

    public void setEndpointConfiguration(HyperionEndpointConfiguration endpointConfiguration)
    {
        this.endpointConfiguration = endpointConfiguration;
    }

    public void setBasePath(String basePath)
    {
        this.basePath = basePath;
    }

    public void setObjectMapper(ObjectMapper objectMapper)
    {
        this.objectMapper = objectMapper;
    }

    public void setResourceBundleBase(String resourceBundleBase)
    {
        this.resourceBundleBase = resourceBundleBase;
    }

    public ResourceListing buildResourceListing()
    {
        ResourceListing listing = new ResourceListing();
        listing.setApiVersion("1.0");
        listing.setSwaggerVersion("1.2");

        List<ApiResource> apiResources = new ArrayList<ApiResource>();
        for (EntityPlugin plugin : serviceRegistry.getEntityPlugins())
        {
            ApiResource apiResource = new ApiResource();
            apiResource.setDescription(plugin.getEndpointName());
            apiResource.setPath(String.format("/%s",plugin.getEndpointName()));
            apiResources.add(apiResource);
        }
        listing.setApis(apiResources);
        return listing;
    }

    public ApiDeclaration buildEndpoint(String endpoint)
    {
        EntityPlugin plugin = serviceRegistry.getPluginForName(endpoint);
        if(plugin == null)
            return null;

        ResourceBundle resourceBundle = getResourceBundle(plugin.getEndpointName());

        ApiDeclaration api = new ApiDeclaration();
        Map<String,Model> models = new HashMap<String, Model>();
        api.setModels(models);

        ApiVersionPlugin pluginVersion = plugin.getApiVersionRegistry().getPluginForVersion(null);

        api.setApiVersion(pluginVersion.getVersion().toString());
        api.setSwaggerVersion("1.2");
        api.setBasePath(basePath);
        api.setResourcePath(String.format("/%s",plugin.getEndpointName()));

        List<Api> apis = new ArrayList<Api>();
        if(plugin.isMethodAllowed(HttpMethod.GET) || plugin.isMethodAllowed(HttpMethod.PUT) ||
                plugin.isMethodAllowed(HttpMethod.DELETE))
        {
            apis.add(buildIdApi(plugin,resourceBundle));
        }

        if(plugin.isMethodAllowed(HttpMethod.GET) || plugin.isMethodAllowed(HttpMethod.POST))
            apis.add(buildApi(plugin,resourceBundle));

        TypeFactory typeFactory = objectMapper.getTypeFactory();

        if(plugin.isHistoryEnabled())
        {
            apis.add(buildHistory(plugin,resourceBundle));
            models.putAll(buildModels(String.format("%sHistoryResponse", plugin.getEndpointName()),
                    typeFactory.constructParametricType(HistoryResponse.class, Serializable.class, pluginVersion.getApiClass())));
        }

        api.setApis(apis);


        models.putAll(buildModels(endpoint, typeFactory.constructType(pluginVersion.getApiClass())));

        if(plugin.isMethodAllowed(HttpMethod.GET))
            models.putAll(buildModels(String.format("%sEntityResponse", plugin.getEndpointName()),
                    typeFactory.constructParametricType(EntityResponse.class, pluginVersion.getApiClass())));

        if(plugin.isMethodAllowed(HttpMethod.DELETE))
            models.putAll(buildModels(String.format("%sDeleteResponse", plugin.getEndpointName()),
                    typeFactory.constructType(DeleteResponse.class)));

        return api;
    }

    private Api buildHistory(EntityPlugin plugin,ResourceBundle resourceBundle)
    {


        Api api = new Api();
        api.setPath(String.format("/%s/history/{id}",plugin.getEndpointName()));
        api.setDescription(plugin.getEndpointName());
        List<Operation> operations = new ArrayList<Operation>();
        api.setOperations(operations);

        Operation operation = new Operation();
        operation.setMethod("GET");
        operation.setNickname(String.format("get%s", plugin.getEndpointName()));
        operation.setSummary(resourceBundle.getString("history.summary"));
        operation.setNotes(resourceBundle.getString("history.notes"));
        operation.setType(String.format("%sHistoryResponse", plugin.getEndpointName()));
        List<Parameter> parameters = new ArrayList<Parameter>();
        operation.setParameters(parameters);

        parameters.add(buildParameter("id",resourceBundle.getString("history.param.id.description"),
                "path",
                "string",
                true));
        parameters.add(buildParameter("start",resourceBundle.getString("history.param.start.description"),"query","string"));
        parameters.add(buildParameter("limit",resourceBundle.getString("history.param.limit.description"),"query","string"));
        if (endpointConfiguration.isAllowTrace())
            parameters.add(buildParameter(endpointConfiguration.getTraceParameterName(),
                    resourceBundle.getString("history.param.trace.description"),
                    "query",
                    "string"));

        operations.add(operation);

        return api;
    }

    private Api buildApi(EntityPlugin plugin,ResourceBundle resourceBundle)
    {
        Api api = new Api();
        api.setPath(String.format("/%s",plugin.getEndpointName()));
        api.setDescription(plugin.getEndpointName());
        List<Operation> operations = new ArrayList<Operation>();
        api.setOperations(operations);
        if(plugin.isMethodAllowed(HttpMethod.GET))
            operations.add(buildQueryOperation(plugin,resourceBundle));
        if(plugin.isMethodAllowed(HttpMethod.POST))
            operations.add(buildCreateOperation(plugin,resourceBundle));
        return api;
    }

    private Operation buildCreateOperation(EntityPlugin plugin,ResourceBundle resourceBundle)
    {
        Operation operation = new Operation();
        operation.setMethod("POST");
        operation.setNickname(String.format("create%s", plugin.getEndpointName()));
        operation.setSummary(resourceBundle.getString("create.summary"));
        operation.setNotes(resourceBundle.getString("create.notes"));
        operation.setType(plugin.getEndpointName());
        List<Parameter> parameters = new ArrayList<Parameter>();
        operation.setParameters(parameters);

        parameters.add(buildParameter("fields",resourceBundle.getString("create.param.fields.description"),"query","string"));
        parameters.add(buildParameter(endpointConfiguration.getVersionParameterName(),
                resourceBundle.getString("create.param.version.description"),
                "query",
                "string",
                endpointConfiguration.isRequireVersion()));
        parameters.add(buildParameter(null,resourceBundle.getString("create.param.body.description"),"body",plugin.getEndpointName()));
        if (endpointConfiguration.isAllowTrace())
            parameters.add(buildParameter(endpointConfiguration.getTraceParameterName(),
                    resourceBundle.getString("create.param.trace.description"),
                    "query",
                    "string"));
        return operation;
    }

    private Operation buildQueryOperation(EntityPlugin plugin,ResourceBundle resourceBundle)
    {
        Operation operation = new Operation();
        operation.setMethod("GET");
        operation.setNickname(String.format("get%s", plugin.getEndpointName()));
        operation.setSummary(resourceBundle.getString("query.summary"));
        operation.setNotes(resourceBundle.getString("query.notes"));
        operation.setType(String.format("%sEntityResponse", plugin.getEndpointName()));
        List<Parameter> parameters = new ArrayList<Parameter>();
        operation.setParameters(parameters);

        parameters.add(buildParameter("fields", resourceBundle.getString("query.param.fields.description"), "query", "string"));
        parameters.add(buildParameter("sort", resourceBundle.getString("query.param.sort.description"),"query","string"));
        parameters.add(buildParameter("start", resourceBundle.getString("query.param.start.description"),"query","string"));
        parameters.add(buildParameter("limit", resourceBundle.getString("query.param.limit.description"),"query","string"));
        parameters.add(buildParameter("query", resourceBundle.getString("query.param.query.description"),"query","string"));
        parameters.add(buildParameter(endpointConfiguration.getVersionParameterName(),
                resourceBundle.getString("query.param.version.description"),
                "query",
                "string",
                endpointConfiguration.isRequireVersion()));
        if (endpointConfiguration.isAllowTrace())
            parameters.add(buildParameter(endpointConfiguration.getTraceParameterName(),
                    resourceBundle.getString("query.param.trace.description"),
                    "query",
                    "string"));
        return operation;
    }

    private Api buildIdApi(EntityPlugin plugin,ResourceBundle resourceBundle)
    {
        Api api = new Api();
        api.setPath(String.format("/%s/{id}",plugin.getEndpointName()));
        api.setDescription(plugin.getEndpointName());
        List<Operation> operations = new ArrayList<Operation>();
        api.setOperations(operations);
        if(plugin.isMethodAllowed(HttpMethod.GET))
            operations.add(buildGetOperation(plugin,resourceBundle));
        if(plugin.isMethodAllowed(HttpMethod.DELETE))
            operations.add(buildDeleteOperation(plugin,resourceBundle));
        if(plugin.isMethodAllowed(HttpMethod.PUT))
            operations.add(buildUpdateOperation(plugin,resourceBundle));

        return api;
    }

    private Operation buildUpdateOperation(EntityPlugin plugin,ResourceBundle resourceBundle)
    {
        Operation operation = new Operation();
        operation.setMethod("PUT");
        operation.setNickname(String.format("update%s", plugin.getEndpointName()));
        operation.setSummary(resourceBundle.getString("update.summary"));
        operation.setNotes(resourceBundle.getString("update.notes"));
        operation.setType(plugin.getEndpointName());
        List<Parameter> parameters = new ArrayList<Parameter>();
        operation.setParameters(parameters);

        parameters.add(buildParameter("id",
                resourceBundle.getString("update.param.id.description"),
                "path",
                "string",
                true));
        parameters.add(buildParameter("fields",resourceBundle.getString("update.param.fields.description"),"query","string"));
        parameters.add(buildParameter(endpointConfiguration.getVersionParameterName(),
                resourceBundle.getString("update.param.version.description"),
                "query",
                "string",
                endpointConfiguration.isRequireVersion()));
        parameters.add(buildParameter(null,resourceBundle.getString("update.param.body.description"),"body",plugin.getEndpointName()));
        if (endpointConfiguration.isAllowTrace())
            parameters.add(buildParameter(endpointConfiguration.getTraceParameterName(),
                    resourceBundle.getString("update.param.trace.description"),
                    "query",
                    "string"));
        return operation;
    }

    private Operation buildDeleteOperation(EntityPlugin plugin,ResourceBundle resourceBundle)
    {
        Operation operation = new Operation();
        operation.setMethod("DELETE");
        operation.setNickname(String.format("delete%s",plugin.getEndpointName()));
        operation.setSummary(resourceBundle.getString("delete.summary"));
        operation.setNotes(resourceBundle.getString("delete.notes"));
        operation.setType(String.format("%sDeleteResponse",plugin.getEndpointName()));
        List<Parameter> parameters = new ArrayList<Parameter>();
        operation.setParameters(parameters);

        parameters.add(buildParameter("id",
                resourceBundle.getString("delete.param.id.description"),
                "path",
                "string",
                true));
        if (endpointConfiguration.isAllowTrace())
            parameters.add(buildParameter(endpointConfiguration.getTraceParameterName(),
                    resourceBundle.getString("delete.param.trace.description"),
                    "query",
                    "string"));
        return operation;
    }

    private Operation buildGetOperation(EntityPlugin plugin,ResourceBundle resourceBundle)
    {
        Operation operation = new Operation();
        operation.setMethod("GET");
        operation.setNickname(String.format("get%s",plugin.getEndpointName()));
        operation.setSummary(resourceBundle.getString("get.summary"));
        operation.setNotes(resourceBundle.getString("get.notes"));
        operation.setType(String.format("%sEntityResponse",plugin.getEndpointName()));
        List<Parameter> parameters = new ArrayList<Parameter>();
        operation.setParameters(parameters);

        parameters.add(buildParameter("id",
                resourceBundle.getString("get.param.id.description"),
                "path",
                "string",
                true));
        parameters.add(buildParameter("fields",resourceBundle.getString("get.param.fields.description"),"query","string"));
        parameters.add(buildParameter(endpointConfiguration.getVersionParameterName(),
                resourceBundle.getString("get.param.version.description"),
                "query",
                "string",
                endpointConfiguration.isRequireVersion()));
        if (endpointConfiguration.isAllowTrace())
            parameters.add(buildParameter(endpointConfiguration.getTraceParameterName(),
                    resourceBundle.getString("get.param.trace.description"),
                    "query",
                    "string"));
        return operation;
    }


    private Parameter buildParameter(String name,String description,String paramType,String dataType)
    {
        return buildParameter(name, description, paramType, dataType,false);
    }

    private Parameter buildParameter(String name,String description,String paramType,String dataType,boolean required)
    {
        Parameter parameter = new Parameter();
        parameter.setName(name);
        parameter.setDescription(description);
        parameter.setParamType(paramType);
        parameter.setDataType(dataType);
        parameter.setRequired(required);
        return parameter;
    }

    protected ResourceBundle getResourceBundle(String endpoint)
    {
        return ResourceBundle.getBundle(resourceBundleBase,new Locale(endpoint));
    }

    protected Map<String,Model> buildModels(String name,JavaType type)
    {
        ObjectSchema schema = buildSchema(type);
        if(schema != null)
            return buildModels(name, schema);
        return Collections.emptyMap();
    }

    protected ObjectSchema buildSchema(JavaType type)
    {
        try
        {
            TypeIdSchemaFactoryWrapper visitor = new TypeIdSchemaFactoryWrapper();
            objectMapper.acceptJsonFormatVisitor(type, visitor);
            JsonSchema jsonSchema = visitor.finalSchema();

            return jsonSchema.asObjectSchema();
        }
        catch (JsonMappingException e)
        {
            logger.warn("Error generating model for type {}",type);
        }
        return null;
    }


    protected Map<String,Model> buildModels(String name, ObjectSchema objectSchema)
    {
        Map<String,Model> modelMap = new HashMap<String, Model>();
        Map<String,JsonSchema> properties = new LinkedHashMap<String, JsonSchema>();

        for (Map.Entry<String, JsonSchema> entry : objectSchema.getProperties().entrySet())
        {
            JsonSchema schema = entry.getValue();
            if(schema.isObjectSchema())
            {
                JsonSchema temp = new ReferenceSchema();
                temp.set$ref(schema.getId());
                properties.put(entry.getKey(),temp);
                modelMap.putAll(buildModels(schema.getId(),schema.asObjectSchema()));
            }
            else if(schema.isArraySchema() && schema.asArraySchema().getItems().isSingleItems() && schema.asArraySchema().getItems().asSingleItems().getSchema().isObjectSchema())
            {
                ObjectSchema entrySchema = (ObjectSchema) schema.asArraySchema().getItems().asSingleItems().getSchema();

                ArraySchema arraySchema = new ArraySchema();
                JsonSchema temp = new ReferenceSchema();
                temp.set$ref(entrySchema.getId());
                arraySchema.setItemsSchema(temp);
                properties.put(entry.getKey(),arraySchema);

                modelMap.putAll(buildModels(entrySchema.getId(), entrySchema));
            }
            else
            {
                properties.put(entry.getKey(),entry.getValue());
            }
        }

        Model model = new Model();
        model.setId(name);
        model.setProperties(properties);
        modelMap.put(name,model);

        return modelMap;
    }

}
TOP

Related Classes of com.dottydingo.hyperion.module.swagger.SwaggerSpecBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.