#!/usr/bin/ruby require 'rubygems' require 'xml/smart' class BPEL_Transform def initialize(fname) @base = ::File.dirname(fname) @doc = XML::Smart.open(fname) @doc.namespaces = { 'bpel' => 'http://docs.oasis-open.org/wsbpel/2.0/process/executable', 'bpws' => 'http://schemas.xmlsoap.org/ws/2003/03/business-process/', 'ext' => 'http://www.activebpel.org/2006/09/bpel/extension/query_handling', 'xsd' => 'http://www.w3.org/2001/XMLSchema' } @acounter = 0 @MULTI = 2 @vars = {} end def transform_dsl # {{{ @acounter = 0 @vars = {} extract_vars spaces = 0 result = '' @doc.find("/bpel:process/bpel:sequence").each do |e| result << print_elements(e,spaces) end result end # }}} def extract_vars # {{{ @doc.find("//bpel:variables/bpel:variable").each do |v| @vars[v.attributes['name']] = extract_ns_plus v.attributes['messageType'] end end # }}} def transform_data # {{{ result = "\n" @doc.find("//bpel:variables/bpel:variable").each do |v| result << print_spaces(@MULTI) result << "<" + v.attributes['name'] + "/>\n" end result << '' result end # }}} def transform_endpoints # {{{ result = XML::Smart.string('') result.namespaces = { 'xsd' => 'http://www.w3.org/2001/XMLSchema', } @doc.find("//bpel:invoke").each do |e| op = e.attributes['operation'] plnk_name = e.attributes['partnerLink'] @doc.find("/bpel:process/bpel:partnerLinks/bpel:partnerLink[@name=\"#{plnk_name}\"]").each do |f| plnk_role = f.attributes['partnerRole'] plnk_type = remove_ns f.attributes['partnerLinkType'] @doc.find("/bpel:process/bpel:import[@importType=\"http://www.w3.org/ns/wsdl\"]").each do |g| XML::Smart.open(@base + "/" + g.attributes['location']) do |w| w.namespaces = { 'wsdl' => 'http://www.w3.org/ns/wsdl', 'plnk' => 'http://schemas.xmlsoap.org/ws/2003/05/partner-link/', 'std' => g.attributes['namespace'], 'xsd' => 'http://www.w3.org/2001/XMLSchema', 'whttp' => 'http://www.w3.org/ns/wsdl/http' } w.find("/wsdl:description/plnk:partnerLinkType[@name='#{plnk_type}']/plnk:role[@name='#{plnk_role}']").each do |h| interface = remove_ns h.attributes['portType'] method = w.find("string(/wsdl:description/wsdl:binding[@interface='#{interface}']/wsdl:operation[@ref='#{op}']/@whttp:method)") method = method == '' ? 'SOAP' : method n1 = result.root.add("#{plnk_name}.#{op}") w.find("/wsdl:description/wsdl:interface[@name='#{interface}']/wsdl:operation[@name='#{op}']/wsdl:*").each do |i| schema_nsn = extract_ns i.attributes['element'] schema_root = remove_ns i.attributes['element'] schema_ns = w.root.namespaces[schema_nsn] w.find("/wsdl:description/wsdl:types/xsd:schema[@targetNamespace='#{schema_ns}']").each do |s| n2 = n1.add(i.name.to_s, 'method' => method, 'targetNamespace' => w.root.attributes['targetNamespace']) n2.add(s) n2.find("xsd:schema/xsd:element[@name!='#{schema_root}']").delete_all! end end end end end end end result.to_s end # }}} def transform_invocation # {{{ result = XML::Smart.string('') @doc.find("/bpel:process/bpel:sequence/bpel:receive[@createInstance='yes']").each do |e| op = e.attributes['operation'] plnk_name = e.attributes['partnerLink'] @doc.find("/bpel:process/bpel:partnerLinks/bpel:partnerLink[@name=\"#{plnk_name}\"]").each do |f| plnk_role = f.attributes['myRole'] plnk_type = remove_ns f.attributes['partnerLinkType'] @doc.find("/bpel:process/bpel:import[@importType=\"http://www.w3.org/ns/wsdl\"]").each do |g| XML::Smart.open(@base + "/" + g.attributes['location']) do |w| w.namespaces = { 'wsdl' => 'http://www.w3.org/ns/wsdl', 'plnk' => 'http://schemas.xmlsoap.org/ws/2003/05/partner-link/', 'std' => g.attributes['namespace'], 'xsd' => 'http://www.w3.org/2001/XMLSchema', 'whttp' => 'http://www.w3.org/ns/wsdl/http' } w.find("/wsdl:description/plnk:partnerLinkType[@name='#{plnk_type}']/plnk:role[@name='#{plnk_role}']").each do |h| interface = remove_ns h.attributes['portType'] method = w.find("string(/wsdl:description/wsdl:binding[@interface='#{interface}']/wsdl:operation[@ref='#{op}']/@whttp:method)") method = method == '' ? 'SOAP' : method w.find("/wsdl:description/wsdl:interface[@name='#{interface}']/wsdl:operation[@name='#{op}']/wsdl:input").each do |i| schema_nsn = extract_ns i.attributes['element'] schema_root = remove_ns i.attributes['element'] schema_ns = w.root.namespaces[schema_nsn] w.find("/wsdl:description/wsdl:types/xsd:schema[@targetNamespace='#{schema_ns}']/xsd:element[@name!='#{schema_root}']").delete_all! w.find("/wsdl:description/wsdl:types/xsd:schema[@targetNamespace='#{schema_ns}']").each do |s| node = result.root.add('invocation', 'plnk_name' => plnk_name, 'plnk_role' => plnk_role, 'plnk_type' => plnk_type, 'interface' => interface, 'method' => method, 'targetNamespace' => w.root.attributes['targetNamespace']) node.add(s) end end end end end end end result.to_s end # }}} def print_elements(e,spaces) # {{{ result = '' e.find("*[not(@createInstance) or @createInstance='no']").each do |e| result << print_element(e,spaces) end result end # }}} def print_element(e,spaces) # {{{ result = '' case e.name.name when 'invoke' result << print_activity_plain(spaces) result << print_activity_call(e,spaces) when 'receive' result << print_activity_plain(spaces) result << print_activity_call(e) result << print_activity_end(spaces) when 'reply' result << print_reply(e,spaces) when 'forEach' result << print_foreach(e,spaces) when 'pick' when 'sequence' result << print_elements(e,spaces) when 'pick' when 'scope' when 'wait' when 'assign' result << print_activity_plain(spaces) result << print_activity_manipulate(e) result << print_activity_assign(e,spaces+@MULTI) result << print_activity_end(spaces) when 'if' result << print_choose(e,spaces) when 'while' result << print_while(e,spaces) when 'flow' result << print_parallel(e,spaces) end result end # }}} def print_activity_plain(spaces) # {{{ @acounter += 1 result = print_spaces(spaces) result << 'activity :a' result << @acounter.to_s end # }}} def print_activity_manipulate(e) # {{{ result = ", :manipulate do\n" end # }}} def print_activity_assign(e,spaces) # {{{ result = '' e.find('bpel:copy').each do |c| result << print_spaces(spaces) result << bpel_copy_x(c,'bpel:to','set') result << ' = ' result << bpel_copy_x(c,'bpel:from','evaluate') result << "\n" end result end # }}} def print_activity_end(spaces) # {{{ result = print_spaces(spaces) result << "end\n" end # }}} def bpel_copy_x(c,what,op) # {{{ result = '' c.find(what).each do |to| text = if to.attributes['variable'] if to.attributes['part'] temp = "$#{to.attributes['variable']}" temp << '/' + @vars[to.attributes['variable']].to_s + to.attributes['part'] result << transform_bpel_xpath(temp,op) else result << "data.#{to.attributes['variable']}" end temp else result << transform_bpel_xpath(to.text,op) end end result end # }}} def print_choose(e,spaces) # {{{ result = '' result << print_spaces(spaces) << "choose do\n" result << print_alternative(e,'alternative',spaces+@MULTI) e.find('bpel:elseif').each do |ei| result << print_alternative(ei,'alternative',spaces+@MULTI) end e.find('bpel:else').each do |ei| result << print_alternative(ei,'otherwise',spaces+@MULTI) end result << print_spaces(spaces) << "end\n" result end # }}} def print_alternative(e,word,spaces) # {{{ result = '' result << print_spaces(spaces) case word when 'alternative' result << word + " " result << transform_bpel_xpath(e.find('string(bpel:condition)'),'evaluate') when 'otherwise' result << word end result << " do\n" result << print_elements(e,spaces+@MULTI) result << print_spaces(spaces) << "end\n" result end # }}} def print_while(e,spaces) # {{{ result = '' result << print_spaces(spaces) result << "loop pre_test{" result << transform_bpel_xpath(e.find('string(bpel:condition)'),'evaluate') result << "} do\n" result << print_elements(e,spaces+@MULTI) result << print_spaces(spaces) << "end\n" result end # }}} def print_foreach(e,spaces) # {{{ result = '' cname = e.find('string(@counterName)') parallel = e.find('boolean(@parallel[.="yes"])') sps = spaces if parallel result << print_spaces(sps) << "parallel(:wait) do\n" sps += @MULTI end result << print_spaces(sps) << "#{cname} = " << e.find('string(bpel:startCounterValue)') << "\n" result << print_spaces(sps) << "loop pre_test{" result << "#{cname} <= " << transform_bpel_xpath(e.find('string(bpel:finalCounterValue)'),'evaluate') result << "} do\n" if parallel sps += @MULTI result << print_spaces(sps) << "parallel_branch(#{cname}) do |#{cname}|\n" end e.find("*[name()='bpel:scope']").each do |f| result << print_elements(f,sps+@MULTI) end if parallel result << print_spaces(sps) << "end\n" sps -= @MULTI end result << print_spaces(sps+@MULTI) << "#{cname} += 1\n" result << print_spaces(sps) << "end\n" if parallel result << print_spaces(spaces) << "end\n" end result end # }}} def print_reply(e,spaces) # {{{ result = '' result << print_spaces(spaces) result << "status.update(1,\"#{e.attributes['partnerLink']}.#{e.attributes['operation']};#{e.attributes['variable']}\")" result end # }}} def print_parallel(e,spaces) # {{{ result = '' result << print_spaces(spaces) result << "parallel do\n" result << print_spaces(spaces+@MULTI) result << "links = {}\n" e.find("*[name()!='bpel:links']").each do |e| result << print_spaces(spaces+@MULTI) result << "parallel_branch do\n" e.find('bpel:targets/bpel:target').each do |l| result << print_spaces(spaces+@MULTI+@MULTI) result << "links[\"" + l.attributes['linkName'] + "\"] = Thread.current\n" result << print_spaces(spaces+@MULTI+@MULTI) result << "Thread.current.stop\n" end result << print_element(e,spaces+@MULTI+@MULTI) e.find('bpel:sources/bpel:source').each do |s| result << print_spaces(spaces+@MULTI+@MULTI) result << "until links.include?(\"" + s.attributes["linkName"] + "\") && links[\"" + s.attributes["linkName"] + "\"].stop?\n" result << print_spaces(spaces+@MULTI+@MULTI+@MULTI) result << "Thread.current.pass\n" result << print_spaces(spaces+@MULTI+@MULTI) << "end\n" result << print_spaces(spaces+@MULTI+@MULTI) result << "links[\"" + s.attributes["linkName"] + "\"].run\n" end result << print_spaces(spaces+@MULTI) << "end\n" end result << print_spaces(spaces) << "end\n" result end # }}} def print_activity_call(e,spaces) # {{{ result = ", :call, :\"#{e.attributes['partnerLink']}.#{e.attributes['operation']}\", data.#{e.attributes['inputVariable']}" if e.attributes['outputVariable'] result << " do |result|\n" result << print_spaces(spaces+@MULTI) result << "data.#{e.attributes['outputVariable']} = result\n" result << print_activity_end(spaces) else result << "\n" end end # }}} def print_spaces(spaces) # {{{ ' ' * spaces end # }}} def transform_bpel_xpath(text,op) # {{{ text.gsub!(/\$([a-z][a-zA-Z0-9]+)\.Document/,'/helper/\1') text.gsub!(/\$([a-z][a-zA-Z0-9]+)\.([a-z][a-zA-Z0-9]+)/) do t1,t2 = $1,$2 "/helper/#{t1}/" + @vars[t1] + t2 end text.gsub!(/\$([a-z][a-zA-Z0-9]+)/,'/helper/\1') "XPATHHelper.#{op}(\"" + text.strip + "\")" end # }}} private def remove_ns(str) # {{{ str.gsub(/[a-zA_Z][a-zA_Z0-9]*:/,'') end # }}} def extract_ns(str) # {{{ str.nil? ? '' : str.match(/^([a-zA_Z][a-zA_Z0-9]*):/)[1].to_s end # }}} def extract_ns_plus(str) # {{{ str.nil? ? '' : str.match(/^[a-zA_Z][a-zA_Z0-9]*:/).to_s end # }}} end