class SoapApiModelParser {

    public static SoapApiModelInfo parseSoapAPI(final String specification, final String wsdlURL) {
        SoapApiModelInfo.Builder builder = new SoapApiModelInfo.Builder();

        try {
            // check if WSDL specification is a URL
            final String resolvedSpecification;
            final Optional<String> resolvedWsdlURL;
            final boolean isHttpUrl = specification.toLowerCase(Locale.US).startsWith("http");
            if (isHttpUrl) {

                final URL httpURL = new URL(specification);
                resolvedWsdlURL = Optional.of(httpURL.toString());
                final HttpURLConnection connection = (HttpURLConnection) httpURL.openConnection();
                connection.setRequestMethod("GET");

                if (connection.getResponseCode() > 299) {
                    throw new IOException(connection.getResponseMessage());
                }

                resolvedSpecification = IOStreams.readText(connection.getInputStream());

            } else {
                resolvedSpecification = specification;
                resolvedWsdlURL = Optional.ofNullable(wsdlURL);
            }

            // set WSDL URL, either resolved from specification or provided by caller
            builder.wsdlURL(resolvedWsdlURL);

            // get concise WSDL representation without extra spaces
            final String condensedSpecification = condenseWSDL(resolvedSpecification);
            builder.resolvedSpecification(condensedSpecification);

            // parse WSDL to get model Definition
            final InputSource inputSource = new InputSource(new StringReader(condensedSpecification));
            final Definition definition = getWsdlReader().readWSDL(resolvedWsdlURL.orElse(null), inputSource);

            builder.model(definition);
            validateModel(definition, builder);

            // set default service, port and address if present
            final SoapApiModelInfo localBuild = builder.build();
            if (localBuild.getServices().size() == 1) {

                final QName defaultService = localBuild.getServices().get(0);
                builder.defaultService(defaultService);

                final List<String> ports = localBuild.getPorts().get(defaultService);
                if (ports.size() == 1) {
                    final String defaultPort = ports.get(0);
                    builder.defaultPort(defaultPort);

                    // set default address
                    String locationURI = getAddress(definition, defaultService, defaultPort);
                    if (locationURI != null) {
                        builder.defaultAddress(locationURI);
                    }
                }
            }

        } catch (IOException e) {
            addError(builder, "Error reading WSDL: " + e.getMessage(), e);
        } catch (WSDLException | BusException e) {
            addError(builder, "Error parsing WSDL: " + e.getMessage(), e);
        } catch (TransformerException e) {
            addError(builder, "Error condensing WSDL: " + e.getMessage(), e);
        }

        return builder.build();
    }

    private  SoapApiModelParser();

}