class OpenApiGenerator implements APIGenerator {

    @Override
    @SuppressWarnings({"PMD.ExcessiveMethodLength"})
    public APIIntegration generateIntegration(final String specification, final ProvidedApiTemplate template) {

        final OpenApiModelInfo info = OpenApiModelParser.parse(specification, APIValidationContext.NONE);
        final OasDocument openApiDoc = info.getModel();

        final String name = Optional.ofNullable(openApiDoc.info)
            .flatMap(i -> Optional.ofNullable(i.title))
            .orElse("Untitled");

        final Integration.Builder integration = new Integration.Builder()
            .addTag("api-provider")
            .createdAt(System.currentTimeMillis())
            .name(name);

        switch (info.getApiVersion()) {
            case V2:
                oas20FlowGenerator.generateFlows(info.getV2Model(), integration, info, template);
                break;
            case V3:
                oas30FlowGenerator.generateFlows(info.getV3Model(), integration, info, template);
                break;
            default:
                throw new IllegalStateException(String.format("Unable to retrieve integration flow generator for OpenAPI document type '%s'", openApiDoc.getClass()));
        }

        // TODO: evaluate what can be shrunk (e.g. SpecificationOptimizer#minimizeForComponent)
        final byte[] updatedSpecification = Library.writeDocumentToJSONString(openApiDoc).getBytes(StandardCharsets.UTF_8);

        final String apiId = KeyGenerator.createKey();
        final OpenApi api = new OpenApi.Builder()
            .id(apiId)
            .name(name)
            .document(updatedSpecification)
            .putMetadata("Content-Type", getContentType(specification))
            .build();

        integration.addResource(new ResourceIdentifier.Builder()
            .id(apiId)
            .kind(Kind.OpenApi)
            .build());

        return new APIIntegration(integration.build(), api);
    }

}