/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* Copyright (c) 2013, MPL CodeInside http://codeinside.ru
*/
package ru.codeinside.gws.wsdl;
import org.ow2.easywsdl.schema.api.Element;
import org.ow2.easywsdl.schema.api.Import;
import org.ow2.easywsdl.schema.api.Include;
import org.ow2.easywsdl.schema.api.Schema;
import org.ow2.easywsdl.schema.api.Type;
import org.ow2.easywsdl.schema.api.extensions.NamespaceMapperImpl;
import org.ow2.easywsdl.wsdl.api.Binding;
import org.ow2.easywsdl.wsdl.api.BindingOperation;
import org.ow2.easywsdl.wsdl.api.Description;
import org.ow2.easywsdl.wsdl.api.Endpoint;
import org.ow2.easywsdl.wsdl.api.Operation;
import org.ow2.easywsdl.wsdl.api.Part;
import org.ow2.easywsdl.wsdl.api.Service;
import org.ow2.easywsdl.wsdl.api.Types;
import org.ow2.easywsdl.wsdl.api.WSDLException;
import org.ow2.easywsdl.wsdl.api.abstractItf.AbsItfBinding;
import org.ow2.easywsdl.wsdl.api.abstractItf.AbsItfParam;
import org.ow2.easywsdl.wsdl.api.binding.BindingProtocol;
import org.ow2.easywsdl.wsdl.impl.generic.WSDLReaderImpl;
import ru.codeinside.gws.api.ServiceDefinition;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
final public class ServiceDefinitionParser implements ru.codeinside.gws.api.ServiceDefinitionParser {
final private Logger log = Logger.getLogger(getClass().getName());
@Override
public ServiceDefinition parseServiceDefinition(URL wsdlUrl) {
final Description description = parse(wsdlUrl);
final ServiceDefinition definition = new ServiceDefinition();
definition.resources = getImportsAndIncludes(description);
definition.namespaces = getAllNamespaces(description);
definition.services = new LinkedHashMap<QName, ServiceDefinition.Service>();
for (Service service : description.getServices()) {
final QName serviceQName = service.getQName();
ServiceDefinition.Service tService = new ServiceDefinition.Service();
tService.ports = new LinkedHashMap<QName, ServiceDefinition.Port>();
for (Endpoint endpoint : service.getEndpoints()) {
if (endpoint.getHttpAuthenticationRealm() != null
|| endpoint.getHttpAuthenticationScheme() != null) {
log.warning("HttpAuthentication not supported!");
continue;
}
ServiceDefinition.Port port = new ServiceDefinition.Port();
port.operations = new LinkedHashMap<QName, ServiceDefinition.Operation>();
port.soapAddress = endpoint.getAddress();
Binding binding = endpoint.getBinding();
if (AbsItfBinding.BindingConstants.SOAP11_BINDING4WSDL11 != binding.getTypeOfBinding()) {
log.warning("binding type:" + binding.getTypeOfBinding());
continue;
}
final AbsItfBinding.StyleConstant bindingStyle = binding.getStyle();
if (bindingStyle != null) {
if (AbsItfBinding.StyleConstant.DOCUMENT != bindingStyle) {
log.warning("binding style:" + bindingStyle);
continue;
}
}
if (!"1.1".equals(binding.getVersion())) {
log.warning("binding version:" + binding.getVersion());
continue;
}
if (!"http://schemas.xmlsoap.org/soap/http".equals(binding.getTransportProtocol())) {
log.warning("binding transport:" + binding.getTransportProtocol());
continue;
}
port.binding = binding.getQName();
port.port = binding.getInterface().getQName();
final List<BindingOperation> operations = binding.getBindingOperations();
for (BindingOperation bop : operations) {
if (bop.getMEP() != BindingProtocol.SOAPMEPConstants.REQUEST_RESPONSE) {
log.warning("soap MEP: " + bop.getMEP());
continue;
}
if (bop.getStyle() != AbsItfBinding.StyleConstant.DOCUMENT) {
log.warning("style: " + bop.getStyle());
continue;
}
ServiceDefinition.Operation sOp = new ServiceDefinition.Operation();
sOp.soapAction = bop.getSoapAction();
sOp.in = new ServiceDefinition.Arg();
sOp.out = new ServiceDefinition.Arg();
port.operations.put(bop.getQName(), sOp);
final Operation op = bop.getOperation();
sOp.in = parseParam(op.getInput());
sOp.out = parseParam(op.getOutput());
}
tService.ports.put(new QName(port.port.getNamespaceURI(), endpoint.getName()), port);
}
definition.services.put(serviceQName, tService);
}
return definition;
}
private Set<URI> getImportsAndIncludes(Description description) {
final Set<URI> uris = new LinkedHashSet<URI>();
for (final Schema schema : description.getTypes().getSchemas()) {
collectImportsAndIncludes(uris, schema);
}
return uris;
}
private void collectImportsAndIncludes(Set<URI> uris, Schema schema) {
// Схемы может вообще не быть!
if (schema != null) {
for (final Include i : schema.getIncludes()) {
if (uris.add(i.getLocationURI())) {
collectImportsAndIncludes(uris, i.getSchema());
}
}
for (final Import i : schema.getImports()) {
if (uris.add(i.getLocationURI())) {
collectImportsAndIncludes(uris, i.getSchema());
}
}
}
}
private ServiceDefinition.Arg parseParam(AbsItfParam input) {
ServiceDefinition.Arg arg = new ServiceDefinition.Arg();
arg.message = input.getMessageName();
arg.name = input.getName();
arg.parts = new LinkedHashMap<String, QName>();
for (Part part : input.getParts()) {
final String partName = part.getPartQName().getLocalPart();
final Element el = part.getElement();
if (el != null) {
arg.parts.put(partName, el.getQName());
} else {
final Type type = part.getType();
if (type != null) {
arg.parts.put(partName, type.getQName());
}
}
}
return arg;
}
private Set<String> getAllNamespaces(final Description description) {
final Set<String> allNamespaces = new LinkedHashSet<String>();
final NamespaceMapperImpl namespaces = description.getNamespaces();
for (final Map.Entry<String, String> e : namespaces.getNamespaces().entrySet()) {
final String ns = e.getValue();
if (log.isLoggable(Level.FINE)) {
String p = e.getKey();
log.fine("NS: " + p + ":" + ns);
}
allNamespaces.add(ns);
}
Types types = description.getTypes();
for (final Schema schema : types.getSchemas()) {
if (log.isLoggable(Level.FINE) && !schema.getElements().isEmpty()) {
log.fine("elements: " + schema.getElements());
}
for (final Type type : schema.getTypes()) {
boolean isNew = allNamespaces.add(type.getQName().getNamespaceURI());
if (isNew && log.isLoggable(Level.FINE)) {
log.fine("T: " + type.getQName());
}
}
}
return allNamespaces;
}
private Description parse(URL wsdlUrl) {
try {
return new WSDLReaderImpl().read(wsdlUrl);
} catch (WSDLException e) {
throw new RuntimeException(e);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}