/*
* JBoss, Home of Professional Open Source
* Copyright 2008, 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.bpel.util;
import javax.xml.namespace.QName;
import org.savara.bpel.model.TPartnerLink;
import org.savara.bpel.model.TProcess;
import org.savara.common.logging.FeedbackHandler;
import org.savara.common.util.XMLUtils;
import org.savara.contract.model.Contract;
import org.savara.contract.model.Interface;
import org.savara.protocol.contract.generator.ContractGenerator;
import org.savara.protocol.contract.generator.ContractGeneratorFactory;
import org.savara.wsdl.util.WSDLGeneratorUtil;
import org.scribble.protocol.model.ProtocolModel;
import org.scribble.protocol.model.Role;
/**
* This class contains utility functions associated with the BPEL generator.
*/
public class BPELGeneratorUtil {
private static final String USE_PEER2_PEER = "usePeer2Peer";
private static final String XMLNS_PREFIX = "xmlns:";
private static final String SERVICE_LABEL = "service";
private static final String PROVIDE_LABEL = "provide";
private static final String PARTNER_LINK_LABEL = "partnerLink";
private static final String INVOKE_LABEL = "invoke";
private static final String ACTIVE_LABEL = "active";
private static final String PROCESS_LABEL = "process";
private static final String DEPLOY_LABEL = "deploy";
private static final String APACHE_ODE_NAMESPACE = "http://www.apache.org/ode/schemas/dd/2007/03";
private static final String NAME_LABEL = "name";
private static final String PROCESS_EVENTS_LABEL = "process-events";
private static final String PORT_TYPE_LABEL = "portType";
private static final String PLNK_PREFIX = "plnk";
private static final String PLNK_ROLE = PLNK_PREFIX+":role";
private static final String PARTNER_LINK_TYPE = "partnerLinkType";
private static final String PLNK_PARTNER_LINK_TYPE = PLNK_PREFIX+":"+PARTNER_LINK_TYPE;
private static final String WSDL_DEFINITIONS = "wsdl:definitions";
private static final String WSDL_NS = "http://schemas.xmlsoap.org/wsdl/";
private static final String PLNKTYPE_NS = "http://docs.oasis-open.org/wsbpel/2.0/plnktype";
private static final String XMLNS_WSDL = "xmlns:wsdl";
private static final String XMLNS_PLNK = "xmlns:plnk";
private static final String WSDL_IMPORT = "wsdl:import";
private static final String TARGET_NAMESPACE_LABEL = "targetNamespace";
/**
* This method creates a WSDL document containing the partner link
* types.
*
* @param model The global protocol model
* @param role The role of the process
* @param localcm The local protocol model
* @param bpelProcess The BPEL process
* @param journal The feedback handler
* @return The WSDL document containing the partner link types
* @throws Exception Failed to generate the partner link types
*/
public static org.w3c.dom.Document generatePartnerLinkTypes(ProtocolModel model, Role role,
ProtocolModel localcm, TProcess bpelProcess, FeedbackHandler journal) throws Exception {
org.w3c.dom.Document doc=javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
org.w3c.dom.Element defn=doc.createElement(WSDL_DEFINITIONS);
doc.appendChild(defn);
defn.setAttribute(XMLNS_PLNK, PLNKTYPE_NS);
defn.setAttribute(XMLNS_WSDL, WSDL_NS);
defn.setAttribute(NAME_LABEL, localcm.getProtocol().getName());
defn.setAttribute(TARGET_NAMESPACE_LABEL, bpelProcess.getTargetNamespace());
ContractGenerator cg=ContractGeneratorFactory.getContractGenerator();
// Add import to associated wsdl
String wsdlName=WSDLGeneratorUtil.getWSDLFileName(role, localcm.getProtocol().getName(), "");
org.w3c.dom.Element imp=doc.createElement(WSDL_IMPORT);
imp.setAttribute("namespace", bpelProcess.getTargetNamespace());
imp.setAttribute("location", wsdlName);
defn.appendChild(imp);
// Add imports for associated roles
java.util.ListIterator<Role> roles=localcm.getProtocol().getRoles().listIterator();
while (roles.hasNext()) {
Role r=roles.next();
// Check if role is a client parameter - if so,
// don't include an import for it
if (localcm.getProtocol().getParameterDefinition(r.getName()) != null) {
continue;
}
Contract contract=null;
if (cg != null) {
contract=cg.generate(model.getProtocol(), null, r, journal);
}
if (contract != null) {
boolean gen=false;
java.util.Iterator<Interface> iter=contract.getInterfaces().iterator();
while (gen == false && iter.hasNext()) {
Interface intf=iter.next();
if (intf.getMessageExchangePatterns().size() > 0) {
gen = true;
}
}
if (gen) {
wsdlName = WSDLGeneratorUtil.getWSDLFileName(r, localcm.getProtocol().getName(), "");
imp = doc.createElement(WSDL_IMPORT);
imp.setAttribute("namespace", contract.getNamespace());
imp.setAttribute("location", wsdlName);
defn.appendChild(imp);
}
}
}
// Create partner link types
java.util.Map<String, String> nsMap=new java.util.HashMap<String, String>();
for (TPartnerLink pl : bpelProcess.getPartnerLinks().getPartnerLink()) {
org.w3c.dom.Element plt=doc.createElement(PLNK_PARTNER_LINK_TYPE);
plt.setAttribute(NAME_LABEL, pl.getPartnerLinkType().getLocalPart());
if (pl.getPartnerRole() != null && pl.getPartnerRole().trim().length() > 0) {
org.w3c.dom.Element plRole=doc.createElement(PLNK_ROLE);
plt.appendChild(plRole);
plRole.setAttribute(NAME_LABEL, pl.getPartnerRole());
Role useRole=null;
for (int i=0; useRole == null &&
i < localcm.getProtocol().getRoles().size(); i++) {
if (pl.getPartnerRole().startsWith(localcm.getProtocol().getRoles().get(i).getName())) {
useRole = localcm.getProtocol().getRoles().get(i);
}
}
Contract contract=null;
if (cg != null && useRole != null) {
contract=cg.generate(model.getProtocol(), null, useRole, journal);
}
if (contract != null) {
Interface intf=null;
if (pl.getMyRole() != null) {
intf = contract.getInterface(null, pl.getMyRole());
}
if (intf == null && contract.getInterfaces().size() > 0) {
intf = contract.getInterfaces().iterator().next();
}
if (intf != null) {
String prefix=null;
String portType=intf.getName();
if (intf.getNamespace() != null) {
prefix = XMLUtils.getPrefixForNamespace(intf.getNamespace(), nsMap);
portType = prefix+":"+portType;
}
plRole.setAttribute(PORT_TYPE_LABEL, portType);
}
}
}
if (pl.getMyRole() != null && pl.getMyRole().trim().length() > 0) {
org.w3c.dom.Element plRole=doc.createElement(PLNK_ROLE);
plt.appendChild(plRole);
plRole.setAttribute(NAME_LABEL, pl.getMyRole());
Contract contract=null;
if (cg != null) {
String linkName=pl.getPartnerLinkType().getLocalPart();
int pos=linkName.indexOf("To");
if (pos != -1) {
java.util.Set<Role> clientRoles=new java.util.HashSet<Role>();
clientRoles.add(new Role(linkName.substring(0, pos)));
contract=cg.generate(model.getProtocol(), clientRoles, role, journal);
} else {
contract=cg.generate(model.getProtocol(), null, role, journal);
}
}
if (contract != null) {
Interface intf=null;
if (pl.getMyRole() != null) {
intf = contract.getInterface(null, pl.getMyRole());
}
if (intf == null && contract.getInterfaces().size() > 0) {
intf = contract.getInterfaces().iterator().next();
}
if (intf != null) {
String prefix=null;
String portType=intf.getName();
if (intf.getNamespace() != null) {
prefix = XMLUtils.getPrefixForNamespace(intf.getNamespace(), nsMap);
portType = prefix+":"+portType;
}
plRole.setAttribute(PORT_TYPE_LABEL, portType);
}
}
}
defn.appendChild(plt);
}
// Create remaining namespace/prefix mappings
java.util.Iterator<String> iter=nsMap.keySet().iterator();
while (iter.hasNext()) {
String ns=iter.next();
String prefix=nsMap.get(ns);
defn.setAttribute(XMLNS_PREFIX+prefix, ns);
}
return (doc);
}
/**
* This method generates the BPEL deployment descriptor.
*
* @param model The global protocol model
* @param role The role being generated
* @param localcm The local protocol model
* @param bpelProcess The BPEL process
* @param wsdls The list of relevant WSDL definitions
* @param partnerLinkTypes The partner link types for this role
* @param journal The feedback handler
* @return The deployment descriptor
* @throws Exception Failed to generate the BPEL deployment descriptor
*/
public static org.w3c.dom.Document generateDeploymentDescriptor(ProtocolModel model, Role role, ProtocolModel localcm,
TProcess bpelProcess, java.util.Collection<javax.wsdl.Definition> wsdls,
org.w3c.dom.Element partnerLinkTypes,
FeedbackHandler journal) throws Exception {
org.w3c.dom.Document doc=javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
org.w3c.dom.Element defn=doc.createElementNS(APACHE_ODE_NAMESPACE,
DEPLOY_LABEL);
doc.appendChild(defn);
java.util.Map<String, String> nsMap=new java.util.HashMap<String, String>();
// Create process element
org.w3c.dom.Element proc=doc.createElement(PROCESS_LABEL);
defn.appendChild(proc);
String name=bpelProcess.getName();
if (bpelProcess.getTargetNamespace() != null) {
String prefix=XMLUtils.getPrefixForNamespace(bpelProcess.getTargetNamespace(), nsMap);
name = prefix+":"+name;
}
proc.setAttribute(NAME_LABEL, name);
org.w3c.dom.Element active=doc.createElement(ACTIVE_LABEL);
proc.appendChild(active);
org.w3c.dom.Text activeText=doc.createTextNode(Boolean.TRUE.toString());
active.appendChild(activeText);
org.w3c.dom.Element processEvents=doc.createElement(PROCESS_EVENTS_LABEL);
processEvents.setAttribute("generate", "all");
proc.appendChild(processEvents);
// TODO: Need more info - possibly Contract should have interfaces based on
// the relationship between two roles, as this may provide the necessary
// information - but this requires the ability to have multiple interfaces
// per role, which some other parts of the BPEL generation would currently
// not handle.
// Work through partner links for now
for (TPartnerLink pl : bpelProcess.getPartnerLinks().getPartnerLink()) {
if (pl.getMyRole() != null && pl.getMyRole().trim().length() > 0) {
org.w3c.dom.Element provide=doc.createElement(PROVIDE_LABEL);
provide.setAttribute(PARTNER_LINK_LABEL, XMLUtils.getLocalname(pl.getName()));
org.w3c.dom.Element service=doc.createElement(SERVICE_LABEL);
// Find service for partner link
initializeService(service, bpelProcess,pl, wsdls, partnerLinkTypes, nsMap);
provide.appendChild(service);
proc.appendChild(provide);
}
}
for (TPartnerLink pl : bpelProcess.getPartnerLinks().getPartnerLink()) {
if (pl.getPartnerRole() != null && pl.getPartnerRole().trim().length() > 0) {
org.w3c.dom.Element invoke=doc.createElement(INVOKE_LABEL);
invoke.setAttribute(PARTNER_LINK_LABEL, XMLUtils.getLocalname(pl.getName()));
invoke.setAttribute(USE_PEER2_PEER, Boolean.FALSE.toString());
org.w3c.dom.Element service=doc.createElement(SERVICE_LABEL);
// Find service for partner link
initializeService(service, bpelProcess, pl, wsdls, partnerLinkTypes, nsMap);
invoke.appendChild(service);
proc.appendChild(invoke);
}
}
// Create remaining namespace/prefix mappings
java.util.Iterator<String> iter=nsMap.keySet().iterator();
while (iter.hasNext()) {
String ns=iter.next();
String prefix=nsMap.get(ns);
defn.setAttribute(XMLNS_PREFIX+prefix, ns);
}
return (doc);
}
protected static void initializeService(org.w3c.dom.Element service, TProcess bpelProcess,
TPartnerLink pl, java.util.Collection<javax.wsdl.Definition> wsdls,
org.w3c.dom.Element partnerLinkTypes,
java.util.Map<String,String> nsMap) {
QName serviceName=null;
String servicePort=null;
// Get partner link type details
QName partnerLinkType=pl.getPartnerLinkType();
org.w3c.dom.NodeList nl=partnerLinkTypes.getChildNodes();
String portType=null;
for (int i=0; portType == null && i < nl.getLength(); i++) {
org.w3c.dom.Node n=nl.item(i);
if (n instanceof org.w3c.dom.Element
&& XMLUtils.getLocalname(n.getNodeName()).equals(PARTNER_LINK_TYPE)) {
org.w3c.dom.Element plt=(org.w3c.dom.Element)nl.item(i);
String name=plt.getAttribute("name");
if (name != null && name.equals(partnerLinkType.getLocalPart())) {
org.w3c.dom.NodeList nl2=plt.getChildNodes();
for (int j=0; portType == null && j < nl2.getLength(); j++) {
org.w3c.dom.Node n2=nl2.item(j);
if (n2 instanceof org.w3c.dom.Element
&& XMLUtils.getLocalname(n2.getNodeName()).equals("role")) {
org.w3c.dom.Element role=(org.w3c.dom.Element)n2;
String roleName=role.getAttribute("name");
if ((pl.getMyRole() != null && pl.getMyRole().equals(roleName))
|| (pl.getPartnerRole() != null && pl.getPartnerRole().equals(roleName))) {
portType = role.getAttribute("portType");
String ptprefix=XMLUtils.getPrefix(portType);
String ptns=partnerLinkTypes.getAttribute("xmlns:"+ptprefix);
String newprefix=XMLUtils.getPrefixForNamespace(ptns, nsMap);
portType = newprefix+":"+XMLUtils.getLocalname(portType);
}
}
}
}
}
}
if (portType != null) {
String portTypePrefix=XMLUtils.getPrefix(portType);
String portTypeNS=XMLUtils.getNamespaceForPrefix(portTypePrefix, nsMap);
QName ptQName=new QName(portTypeNS, XMLUtils.getLocalname(portType));
for (javax.wsdl.Definition wsdl : wsdls) {
if (wsdl.getTargetNamespace().equals(portTypeNS)) {
@SuppressWarnings("unchecked")
java.util.Collection<javax.wsdl.Service> services=
wsdl.getServices().values();
for (javax.wsdl.Service s : services) {
@SuppressWarnings("unchecked")
java.util.Collection<javax.wsdl.Port> ports=
s.getPorts().values();
for (javax.wsdl.Port p : ports) {
if (p.getBinding() != null
&& p.getBinding().getPortType() != null
&& p.getBinding().getPortType().getQName().equals(ptQName)) {
serviceName = s.getQName();
servicePort = p.getName();
}
}
}
}
}
if (serviceName != null) {
String prefix=XMLUtils.getPrefixForNamespace(serviceName.getNamespaceURI(), nsMap);
service.setAttribute("name", prefix+":"+serviceName.getLocalPart());
}
if (servicePort != null) {
service.setAttribute("port", servicePort);
}
}
}
}