/*
* JBoss, Home of Professional Open Source
* Copyright 2008-11, Red Hat Middleware LLC, and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.savara.switchyard.bpel.generator;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import org.savara.common.util.XMLUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class SwitchyardBPELGenerator {
private static final Logger logger=Logger.getLogger(SwitchyardBPELGenerator.class.getName());
public SwitchyardBPELGenerator() {
}
public org.w3c.dom.Element createSwitchyardDescriptor(String name,
org.w3c.dom.Element descriptor,
java.util.Map<String,javax.wsdl.Definition> wsdls)
throws Exception {
return (createSwitchyardDescriptor(name, descriptor, null, wsdls));
}
public org.w3c.dom.Element createSwitchyardDescriptor(String name,
org.w3c.dom.Element descriptor, javax.wsdl.Definition serviceWsdl,
java.util.Map<String,javax.wsdl.Definition> wsdls)
throws Exception {
org.w3c.dom.Element ret=null;
String targetNamespace=null;
if (serviceWsdl != null) {
targetNamespace = serviceWsdl.getTargetNamespace();
}
StringBuffer composite=new StringBuffer();
composite.append("<switchyard xmlns=\"urn:switchyard-config:switchyard:1.0\"\r\n");
NamedNodeMap attrs=descriptor.getAttributes();
// Initialize namespaces
java.util.Map<String, String> namespaces=new java.util.HashMap<String,String>();
for (int i=0; i < attrs.getLength(); i++) {
Attr attr=(Attr)attrs.item(i);
if (attr.getName().startsWith("xmlns:")) {
namespaces.put(attr.getName().substring(6), attr.getValue());
composite.append("\t\t"+attr.getName()+"=\""+attr.getValue()+"\"\r\n");
}
}
if (targetNamespace != null) {
composite.append("\t\ttargetNamespace=\""+targetNamespace+"\"\r\n");
}
composite.append("\t\tname=\""+name+"\" >\r\n");
composite.append("\t<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200912\" name=\""+name+
"\"");
if (targetNamespace != null) {
composite.append(" targetNamespace=\""+targetNamespace+"\"");
}
composite.append(" >\r\n");
NodeList nl=descriptor.getChildNodes();
for (int i=0; i < nl.getLength(); i++) {
Node n=nl.item(i);
if (n instanceof Element && XMLUtils.getLocalname(n.getNodeName()).equals("process")) {
Element process=(Element)n;
composite.append(generateServices(name, process, wsdls, namespaces));
composite.append(generateReferences(name, process, wsdls, namespaces));
composite.append(generateComponent(name, process, wsdls, namespaces));
// TODO: Generate references for any 'invoke' entry that is not
// satisfied by a service (process) provided by this deployment
// descriptor
}
}
composite.append("\t</composite>\r\n");
composite.append("</switchyard>\r\n");
ret = (org.w3c.dom.Element)XMLUtils.getNode(composite.toString());
return(ret);
}
/**
* This method generates a service element.
*
* @param compositeName The composite name
* @param process The process details
* @param wsdls The set of wsdls
* @param namespaces The namespaces
* @param port The port number
* @return The service element
*/
protected String generateServices(String compositeName, Element process,
java.util.Map<String,javax.wsdl.Definition> wsdls,
java.util.Map<String, String> namespaces) {
StringBuffer ret=new StringBuffer();
NodeList nl=process.getElementsByTagName("provide");
java.util.List<String> wsdlPaths=new java.util.Vector<String>();
for (int i=0; i < nl.getLength(); i++) {
Node n=nl.item(i);
if (n instanceof Element) {
NodeList services=((Element)n).getElementsByTagName("service");
if (services.getLength() == 1 && services.item(0) instanceof Element) {
Element service=(Element)services.item(0);
String name=getComponentName(compositeName);
String servName=getServiceName(service);
ret.append("\t\t<service name=\""+servName+"\" promote=\""+name+"/"+servName+"\">\r\n");
String wsdlInterface=getInterfaceDetails(service, wsdls, namespaces);
ret.append("\t\t\t<interface.wsdl interface=\""+wsdlInterface+"\"/>\r\n");
ret.append("\t\t\t<binding.soap xmlns=\"urn:switchyard-component-soap:config:1.0\" >\r\n");
String wsdlInterfacePath=getInterfacePath(service, wsdls, namespaces);
if (!wsdlPaths.contains(wsdlInterfacePath)) {
ret.append("\t\t\t\t<wsdl>"+wsdlInterfacePath+"</wsdl>\r\n");
wsdlPaths.add(wsdlInterfacePath);
}
ret.append("\t\t\t\t<socketAddr>:18001</socketAddr>\r\n");
ret.append("\t\t\t</binding.soap>\r\n");
ret.append("\t\t</service>\r\n");
}
}
}
return(ret.toString());
}
/**
* This method generates a reference element.
*
* @param compositeName The composite name
* @param process The process details
* @param wsdls The set of wsdls
* @param namespaces The namespaces
* @param port The port number
* @return The reference element
*/
protected String generateReferences(String compositeName, Element process,
java.util.Map<String,javax.wsdl.Definition> wsdls,
java.util.Map<String, String> namespaces) {
StringBuffer ret=new StringBuffer();
org.w3c.dom.NodeList nl = process.getElementsByTagName("invoke");
for (int i=0; i < nl.getLength(); i++) {
Node n=nl.item(i);
if (n instanceof Element) {
NodeList services=((Element)n).getElementsByTagName("service");
if (services.getLength() == 1 && services.item(0) instanceof Element) {
Element service=(Element)services.item(0);
// TODO: Need to access wsdl details for the service
String wsdlInterface=getInterfaceDetails(service, wsdls, namespaces);
String name=getComponentName(compositeName);
String servName=getServiceName(service);
ret.append("\t\t<reference name=\""+servName+"\" promote=\""+
name+"/"+servName+"\" multiplicity=\"1..1\" >\r\n");
ret.append("\t\t\t<interface.wsdl interface=\""+wsdlInterface+"\"/>\r\n");
ret.append("\t\t\t<binding.soap xmlns=\"urn:switchyard-component-soap:config:1.0\" >\r\n");
String wsdlInterfacePath=getInterfacePath(service, wsdls, namespaces);
ret.append("\t\t\t\t<wsdl>"+wsdlInterfacePath+"</wsdl>\r\n");
ret.append("\t\t\t\t<socketAddr>:18001</socketAddr>\r\n");
ret.append("\t\t\t</binding.soap>\r\n");
ret.append("\t\t</reference>\r\n");
}
}
}
return(ret.toString());
}
/**
* This method generates the component element.
*
* @param compositeName The composite name
* @param process The process details
* @param wsdls The wsdls
* @param namespaces The namespaces
* @return The component element
*/
protected String generateComponent(String compositeName, Element process,
java.util.Map<String,javax.wsdl.Definition> wsdls,
java.util.Map<String, String> namespaces) {
StringBuffer ret=new StringBuffer();
String name=getComponentName(compositeName);
ret.append("\t\t<component name=\""+name+"\">\r\n");
ret.append("\t\t\t<implementation.bpel xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" process=\""+
process.getAttribute("name")+"\" />\r\n");
NodeList nl=process.getElementsByTagName("provide");
for (int i=0; i < nl.getLength(); i++) {
Node n=nl.item(i);
if (n instanceof Element) {
NodeList services=((Element)n).getElementsByTagName("service");
if (services.getLength() == 1 && services.item(0) instanceof Element) {
Element service=(Element)services.item(0);
// TODO: Need to access wsdl details for the service
String wsdlInterface=getInterfaceDetails(service, wsdls, namespaces);
ret.append("\t\t\t<service name=\""+getServiceName(service)+"\" >\r\n");
ret.append("\t\t\t\t<interface.wsdl interface=\""+wsdlInterface+"\"/>\r\n");
ret.append("\t\t\t</service>\r\n");
}
}
}
nl = process.getElementsByTagName("invoke");
for (int i=0; i < nl.getLength(); i++) {
Node n=nl.item(i);
if (n instanceof Element) {
NodeList services=((Element)n).getElementsByTagName("service");
if (services.getLength() == 1 && services.item(0) instanceof Element) {
Element service=(Element)services.item(0);
// TODO: Need to access wsdl details for the service
String wsdlInterface=getInterfaceDetails(service, wsdls, namespaces);
ret.append("\t\t\t<reference name=\""+getServiceName(service)+"\" >\r\n");
ret.append("\t\t\t\t<interface.wsdl interface=\""+wsdlInterface+"\"/>\r\n");
ret.append("\t\t\t</reference>\r\n");
}
}
}
ret.append("\t\t</component>\r\n");
return(ret.toString());
}
/**
* The interface details associated with a wsdl interface.
*
* @param service The service element
* @param wsdls The wsdls
* @param namespaces The namespaces
* @return The interface details
*/
protected String getInterfaceDetails(Element service,
java.util.Map<String,javax.wsdl.Definition> wsdls,
java.util.Map<String, String> namespaces) {
String ret=null;
// Identify the namespace and local part
String namespace=null;
String localPart=service.getAttribute("name");
int index=localPart.indexOf(':');
if (index != -1) {
namespace = namespaces.get(localPart.substring(0, index));
localPart = localPart.substring(index+1);
}
QName qname=new QName(namespace, localPart);
for (String path : wsdls.keySet()) {
javax.wsdl.Definition wsdl=wsdls.get(path);
javax.wsdl.Service serv=wsdl.getService(qname);
if (serv != null) {
// Use port type associated with first port found
javax.wsdl.Port port=(javax.wsdl.Port)
serv.getPorts().values().iterator().next();
if (port != null) {
String portType=port.getBinding().getPortType().getQName().getLocalPart();
ret = path+"#wsdl.porttype("+portType+")";
} else {
logger.severe("Unable to find port type associated with service '"+qname+"'");
}
break;
}
}
return(ret);
}
/**
* This method returns the path to the wsdl definition associated
* with the supplied service.
*
* @param service The service
* @param wsdls The wsdls
* @param namespaces The namespaces
* @return The wsdl definition path
*/
protected String getInterfacePath(Element service,
java.util.Map<String,javax.wsdl.Definition> wsdls,
java.util.Map<String, String> namespaces) {
String ret=null;
// Identify the namespace and local part
String namespace=null;
String localPart=service.getAttribute("name");
int index=localPart.indexOf(':');
if (index != -1) {
namespace = namespaces.get(localPart.substring(0, index));
localPart = localPart.substring(index+1);
}
QName qname=new QName(namespace, localPart);
for (String path : wsdls.keySet()) {
javax.wsdl.Definition wsdl=wsdls.get(path);
javax.wsdl.Service serv=wsdl.getService(qname);
if (serv != null) {
ret = path;
break;
}
}
return(ret);
}
/**
* This method returns the name of the component associated with the
* composite.
*
* @param name The composite name
* @return The component name
*/
protected String getComponentName(String name) {
return (name+"Component");
}
/**
* This method returns the name of the service associated with the
* BPEL process.
*
* @param process The BPEL process
* @return The service name
*/
protected String getServiceName(Element service) {
String ret=service.getAttribute("name");
int index=ret.indexOf(':');
if (index != -1) {
ret = ret.substring(index+1);
}
return (ret);
}
}