class OpenApiModelParser {

    public static OpenApiModelInfo parse(final String specification, final APIValidationContext validationContext) {
        final OpenApiModelInfo.Builder resultBuilder = new OpenApiModelInfo.Builder();

        final String resolvedSpecification;
        try {
            resolvedSpecification = resolve(specification);
            resultBuilder.resolvedSpecification(resolvedSpecification);
        } catch (final Exception e) {
            LOG.debug("Unable to resolve OpenAPI document\n{}\n", specification, e);
            return resultBuilder
                .addError(new Violation.Builder().error("error").property("").message("Unable to resolve OpenAPI document from: "
                    + ofNullable(specification).map(s -> StringUtils.abbreviate(s, 100)).orElse("")).build())
                .build();
        }

        final JsonNode tree;
        try {
            tree = JsonUtils.reader().readTree(resolvedSpecification);
        } catch (final IOException e) {
            return new OpenApiModelInfo.Builder()
                .addError(new Violation.Builder()
                    .property("")
                    .error("unreadable-document")
                    .message("Unable to read OpenAPI document: " + e.getMessage())
                    .build())
                .build();
        }

        OpenApiVersion openApiVersion = getOpenApiVersion(tree);
        if (openApiVersion == null) {
            return new OpenApiModelInfo.Builder()
                .addError(new Violation.Builder()
                    .property("")
                    .error("unsupported-version")
                    .message(String.format("This document cannot be uploaded. " +
                        "Provide an OpenAPI document (supported versions are %s).", OpenApiVersion.getSupportedVersions()))
                    .build())
                .build();
        }

        final Document parsed = Library.readDocumentFromJSONString(resolvedSpecification);
        if (!(parsed instanceof OasDocument)) {
            LOG.debug("Unable to read OpenAPI document\n{}\n", specification);
            return resultBuilder
                .addError(new Violation.Builder()
                    .error("error")
                    .property("")
                    .message("Unable to read OpenAPI document from: '" + StringUtils.abbreviate(resolvedSpecification, 100)).build())
                .build();
        }

        resultBuilder.model((OasDocument) parsed);
        if (validationContext != APIValidationContext.NONE) {
            try {
                validateJsonSchema(convertToJson(resolvedSpecification), resultBuilder, openApiVersion, parsed.getClass());
            } catch (IOException e) {
                return resultBuilder
                    .addError(new Violation.Builder()
                        .error("error")
                        .property("")
                        .message("Unable to read OpenAPI document from: '" + StringUtils.abbreviate(resolvedSpecification, 100)).build())
                    .build();
            }
            return applyValidationRules(validationContext, resultBuilder.build(), openApiVersion);
        }
        return resultBuilder.build();
    }

    private  OpenApiModelParser();

}