simcha-mappum 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/LICENSE +15 -0
- data/README +53 -0
- data/Rakefile +46 -0
- data/VERSION +1 -0
- data/bin/mapserver.rb +4 -0
- data/lib/mappum.rb +19 -0
- data/lib/mappum/dsl.rb +186 -0
- data/lib/mappum/map.rb +133 -0
- data/lib/mappum/mapserver/mapgraph.rb +193 -0
- data/lib/mappum/mapserver/mapserver.rb +197 -0
- data/lib/mappum/mapserver/views/transform-ws.wsdl.erb +50 -0
- data/lib/mappum/mapserver/views/ws-error.erb +10 -0
- data/lib/mappum/open_xml_object.rb +61 -0
- data/lib/mappum/ruby_transform.rb +129 -0
- data/lib/mappum/xml_transform.rb +298 -0
- data/mappum.gemspec +89 -0
- data/sample/address_fixture.xml +11 -0
- data/sample/crm.rb +9 -0
- data/sample/crm_client.xsd +28 -0
- data/sample/erp.rb +7 -0
- data/sample/erp_person.xsd +36 -0
- data/sample/example_map.rb +87 -0
- data/sample/example_notypes.rb +61 -0
- data/sample/person_fixture.xml +23 -0
- data/sample/person_fixture_any.xml +23 -0
- data/sample/server/map/example_any.rb +28 -0
- data/sample/server/map/example_soap4r.rb +59 -0
- data/sample/server/mapserver.sh +1 -0
- data/sample/server/schema/crm_client.xsd +29 -0
- data/sample/server/schema/erp/erp_person.xsd +38 -0
- data/test/test_example.rb +137 -0
- data/test/test_openstruct.rb +129 -0
- data/test/test_soap4r.rb +108 -0
- data/test/test_xml_any.rb +62 -0
- metadata +130 -0
@@ -0,0 +1,193 @@
|
|
1
|
+
module Mappum
|
2
|
+
module MapServer
|
3
|
+
class Graph
|
4
|
+
attr_reader :edge_maps
|
5
|
+
def initialize(map)
|
6
|
+
@map = map
|
7
|
+
@root = []
|
8
|
+
@struct_from = StrTree.new(nil,0,@root)
|
9
|
+
@struct_from.name = "struct1"
|
10
|
+
@struct_to = StrTree.new(nil,0,@root)
|
11
|
+
@struct_to.name = "struct2"
|
12
|
+
@edges = []
|
13
|
+
@edge_maps = {}
|
14
|
+
init(@map,@struct_from, @struct_to)
|
15
|
+
end
|
16
|
+
def getSvg
|
17
|
+
cmd = "dot"
|
18
|
+
format = "svg"
|
19
|
+
xCmd = "#{cmd} -T#{format}"
|
20
|
+
puts dot = getDot
|
21
|
+
f = IO.popen( xCmd ,"r+")
|
22
|
+
f.print(dot)
|
23
|
+
f.close_write
|
24
|
+
return f
|
25
|
+
end
|
26
|
+
def getPng
|
27
|
+
cmd = "dot"
|
28
|
+
format = "png"
|
29
|
+
xCmd = "#{cmd} -T#{format}"
|
30
|
+
dot = getDot
|
31
|
+
f = IO.popen( xCmd ,"r+")
|
32
|
+
f.print(dot)
|
33
|
+
f.close_write
|
34
|
+
return f
|
35
|
+
end
|
36
|
+
def getDot
|
37
|
+
str1 = makeStruct(@struct_from)
|
38
|
+
str2 = makeStruct(@struct_to)
|
39
|
+
edge = @edges.join
|
40
|
+
return <<DOT
|
41
|
+
digraph structs { node [shape=plaintext]; rankdir=LR; nodesep=0.1;
|
42
|
+
struct1 [
|
43
|
+
label=<
|
44
|
+
#{str1}
|
45
|
+
>
|
46
|
+
];
|
47
|
+
struct2 [
|
48
|
+
label=<
|
49
|
+
#{str2}
|
50
|
+
>
|
51
|
+
];
|
52
|
+
#{@root.collect { |struct| struct.line}}
|
53
|
+
#{edge}
|
54
|
+
|
55
|
+
}
|
56
|
+
DOT
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def makeStruct(struct_tree)
|
62
|
+
str = struct_tree.line || ""
|
63
|
+
unless struct_tree.children.nil? or struct_tree.children.empty?
|
64
|
+
str += "<TR><TD></TD> <TD CELLPADDING=\"1\">" unless struct_tree.parent.nil?
|
65
|
+
str += "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" BGCOLOR=\"cornsilk2\">\n"
|
66
|
+
st = struct_tree.children.collect { |child| makeStruct(child)}
|
67
|
+
st.uniq!
|
68
|
+
str += st.join + "</TABLE>"
|
69
|
+
str += "</TD></TR>\n" unless struct_tree.parent.nil?
|
70
|
+
end
|
71
|
+
return str
|
72
|
+
end
|
73
|
+
def init(map, struct_from, struct_to)
|
74
|
+
if map.normalized?
|
75
|
+
map_from, map_to = map.from, map.to
|
76
|
+
else
|
77
|
+
map_from, map_to = map.left, map.right
|
78
|
+
end
|
79
|
+
to_name, to_path, level_to = get_name_and_path(map_to)
|
80
|
+
from_name, from_path, level_from = get_name_and_path(map_from)
|
81
|
+
|
82
|
+
str_from = StrTree.new(struct_from,level_from, @root)
|
83
|
+
unless from_name.nil?
|
84
|
+
if level_from > -1
|
85
|
+
str_from.line = "<TR> <TD COLSPAN=\"2\" PORT=\"#{from_path}\">#{from_name}</TD></TR>\n"
|
86
|
+
else
|
87
|
+
str_from.line = "#{from_path} [ label = <\"#{from_name}\">];\n"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
str_to = StrTree.new(struct_to,level_to,@root)
|
91
|
+
unless to_name.nil?
|
92
|
+
if level_to > -1
|
93
|
+
str_to.line ="<TR> <TD COLSPAN=\"2\" PORT=\"#{to_path}\">#{to_name}</TD></TR>\n"
|
94
|
+
else
|
95
|
+
str_to.line = "#{to_path} [ label = <\"#{to_name}\">];\n"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
maps = []
|
99
|
+
if map.normalized?
|
100
|
+
maps = map.maps
|
101
|
+
else
|
102
|
+
maps = map.bidi_maps
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
unless maps.empty?
|
107
|
+
maps.each do |sub_map|
|
108
|
+
if(map.normalized? or sub_map.left.parent == map_from or
|
109
|
+
sub_map.right.parent == map_to)
|
110
|
+
|
111
|
+
init(sub_map, str_from, str_to)
|
112
|
+
else
|
113
|
+
init(sub_map, str_to, str_from)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
else
|
117
|
+
# as option? labelfloat=true
|
118
|
+
from_ref = "#{str_from.root.name}:#{from_path}" if level_from > -1
|
119
|
+
to_ref = "#{str_to.root.name}:#{to_path}" if level_to > -1
|
120
|
+
from_ref ||= from_path
|
121
|
+
to_ref ||= to_path
|
122
|
+
edge = "#{from_ref} -> #{to_ref} ["
|
123
|
+
if map.normalized?
|
124
|
+
edge += " arrowtail = none tooltip=\"#{from_name} >> #{to_name}\" "
|
125
|
+
else
|
126
|
+
edge += " arrowtail = vee tooltip=\"#{from_name} <=> #{to_name}\" "
|
127
|
+
end
|
128
|
+
edge += " arrowhead = vee URL=\"##{@edges.size+1}\" fontsize=10 "
|
129
|
+
unless map.simple?
|
130
|
+
edge += " label=\"#{@edges.size+1}\" labeltooltip = \"#{@edges.size+1}: #{from_name} >> #{to_name}\""
|
131
|
+
end
|
132
|
+
color = "black"
|
133
|
+
color = "blue" if level_to == -1 or level_from == -1
|
134
|
+
edge += " minlen=\"3\" color=\"#{color}\"];\n"
|
135
|
+
|
136
|
+
@edges << edge
|
137
|
+
unless map.simple?
|
138
|
+
@edge_maps[@edges.size] = map
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
def get_name_and_path(element, level = 0)
|
144
|
+
#on non filed elements
|
145
|
+
if element.kind_of?(Function)
|
146
|
+
return "Function", "c#{element.__id__.abs}", -1
|
147
|
+
end
|
148
|
+
if element.kind_of?(Constant)
|
149
|
+
return element.value.to_s, "c#{element.__id__.abs}", -1
|
150
|
+
end
|
151
|
+
|
152
|
+
name = element.name
|
153
|
+
if element.parent.nil?
|
154
|
+
#root element
|
155
|
+
name ||= element.clazz.to_s
|
156
|
+
else
|
157
|
+
level = level + 1 if name.nil?
|
158
|
+
pname, path, level = get_name_and_path(element.parent, level)
|
159
|
+
end
|
160
|
+
path = "#{path}v#{name}".gsub(":","vv") unless name.nil?
|
161
|
+
name = "#{name}[]" if not name.nil? and element.is_array
|
162
|
+
return name, path, level
|
163
|
+
end
|
164
|
+
end
|
165
|
+
class StrTree
|
166
|
+
attr_accessor :line, :parent,:children, :name
|
167
|
+
def initialize(parent, level, root)
|
168
|
+
@parent=parent if level > -1
|
169
|
+
root << self if level == -1
|
170
|
+
@parent.add(self, level) unless @parent.nil?
|
171
|
+
end
|
172
|
+
|
173
|
+
def add(child, level=0)
|
174
|
+
@children ||= []
|
175
|
+
if level == 0
|
176
|
+
@children << child unless @children.include?(child)
|
177
|
+
else
|
178
|
+
@parent.add(child, level - 1)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
def ==(other)
|
182
|
+
return false unless other.kind_of?(StrTree)
|
183
|
+
if @line == other.line and @parent == other.parent and @children == other.children
|
184
|
+
return true
|
185
|
+
end
|
186
|
+
end
|
187
|
+
def root
|
188
|
+
return parent.root unless parent.nil?
|
189
|
+
return self
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'soap4r'
|
3
|
+
require 'mappum/xml_transform'
|
4
|
+
require 'soap/marshal'
|
5
|
+
require 'mappum/mapserver/mapgraph'
|
6
|
+
require 'sinatra/base'
|
7
|
+
require 'erb'
|
8
|
+
|
9
|
+
module Mappum
|
10
|
+
class Mapserver < Sinatra::Default
|
11
|
+
set :views => File.join(File.dirname(__FILE__), 'views')
|
12
|
+
configure do
|
13
|
+
set :schema_dir => 'schema', :map_dir => 'map', :tmp_dir => nil
|
14
|
+
set :catalogue => nil
|
15
|
+
set :port => 9292
|
16
|
|
17
|
+
|
18
|
+
# FIXME make configurable
|
19
|
+
#wl = Mappum::WorkdirLoader.new(options.schema_dir, options.tmp_dir, options.map_dir)
|
20
|
+
@wl = Mappum::WorkdirLoader.new('schema', 'map')
|
21
|
+
@wl.generate_and_require
|
22
|
+
end
|
23
|
+
helpers do
|
24
|
+
def explain_func(element)
|
25
|
+
name = element.name.to_s
|
26
|
+
name ||= "self"
|
27
|
+
func = element.func.gsub(/^self/,name)
|
28
|
+
#replace [](1) with [1]
|
29
|
+
func = func.gsub(/\.\[\]\((.*)\)/,"[\\1]")
|
30
|
+
return "Simple function call: \"#{func}\"<br/>"
|
31
|
+
end
|
32
|
+
def explain(map)
|
33
|
+
str=""
|
34
|
+
if not map.right.nil? and not map.right.func.nil?
|
35
|
+
str+= explain_func(map.right)
|
36
|
+
elsif not map.from.nil? and not map.from.func.nil?
|
37
|
+
str+= explain_func(map.from)
|
38
|
+
end
|
39
|
+
unless map.func.nil?
|
40
|
+
str+= "Multiline function call (see source)<br/>"
|
41
|
+
end
|
42
|
+
unless map.dict.nil?
|
43
|
+
str+= "Dictionary mapping:<br/>"
|
44
|
+
str+= "<table border=\"1\">"
|
45
|
+
str+= "<tr><td>#{map.left.name}</td><td>#{map.right.name}</td></tr>"
|
46
|
+
map.dict.each do |k,v|
|
47
|
+
str+= "<tr><td>#{k}</td><td>#{v}</td></tr>"
|
48
|
+
end
|
49
|
+
str+= "</table>"
|
50
|
+
end
|
51
|
+
return str
|
52
|
+
end
|
53
|
+
def get_xmlns(namespace)
|
54
|
+
@namespaces ||= {}
|
55
|
+
@i ||= 0
|
56
|
+
@namespaces[namespace] = "ns#{@i+=1}" unless @namespaces.include?(namespace)
|
57
|
+
return @namespaces[namespace]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
#make get methods for xsd files
|
61
|
+
Dir.glob('schema'+'/**/*.xsd') do |filename|
|
62
|
+
get "/"+filename do
|
63
|
+
[200, {"Content-Type" => "text/xml"}, IO.read(filename)]
|
64
|
+
end
|
1
65
|
end
|
66
|
+
post "/transform" do
|
67
|
+
map_name = nil
|
68
|
+
map_name = params["map"] unless params["map"].nil? or params["map"] == "auto_select"
|
69
|
+
|
70
|
+
rt = Mappum::XmlTransform.new(options.catalogue)
|
71
|
+
|
72
|
+
xml = params["doc"]
|
73
|
+
content = rt.transform(xml,map_name)
|
74
|
+
|
75
|
+
[200, {"Content-Type" => "text/xml"}, [content]]
|
76
|
+
end
|
77
|
+
post "/transform-ws" do
|
78
|
+
map_name = env["HTTP_SOAPACTION"] unless env["HTTP_SOAPACTION"].nil? or env["HTTP_SOAPACTION"] == ""
|
79
|
+
#remove "" if present
|
80
|
+
map_name = map_name[1..-2] if map_name =~ /^".*"$/
|
81
|
+
|
82
|
+
rt = Mappum::XmlTransform.new(options.catalogue)
|
83
|
+
|
84
|
+
xml = env["rack.input"].read
|
85
|
+
begin
|
86
|
+
content = rt.transform(xml,map_name)
|
87
|
+
rescue Exception => e
|
88
|
+
@error = e
|
89
|
+
return [200, {"Content-Type" => "text/xml"}, [erb(:'ws-error')]]
|
90
|
+
end
|
91
|
+
return [200, {"Content-Type" => "text/xml"}, [content]]
|
92
|
+
end
|
93
|
+
get "/transform-ws.wsdl" do
|
94
|
+
|
95
|
+
@xml_imports = {}
|
96
|
+
Dir.glob('schema'+'/**/*.xsd') do |xsd_file|
|
97
|
+
namespace = XmlSupport.get_target_ns(xsd_file)
|
98
|
+
@xml_imports[xsd_file] = namespace unless namespace.nil?
|
99
|
+
#FIXME log warning
|
100
|
+
end
|
101
|
+
|
102
|
+
@xml_maps = []
|
103
|
+
@xml_elements = Set.new
|
104
|
+
Mappum.catalogue(options.catalogue).list_map_names.each do |mapname|
|
105
|
+
map = Mappum.catalogue(options.catalogue)[mapname]
|
106
|
+
|
107
|
+
from_qname = XSD::Mapping::Mapper.get_qname_from_class(map.from.clazz)
|
108
|
+
@xml_elements << from_qname unless from_qname.nil?
|
109
|
+
from_qname ||= XSD::QName.new(nil,"any")
|
110
|
+
|
111
|
+
|
112
|
+
to_qname = XSD::Mapping::Mapper.get_qname_from_class(map.to.clazz)
|
113
|
+
@xml_elements << to_qname unless to_qname.nil?
|
114
|
+
to_qname ||= XSD::QName.new(nil,"any")
|
115
|
+
|
116
|
+
@xml_maps << [mapname, from_qname, to_qname]
|
117
|
+
end
|
118
|
+
|
119
|
+
[200, {"Content-Type" => "text/xml"}, [erb(:'transform-ws.wsdl')]]
|
2
120
|
end
|
121
|
+
|
122
|
+
get "/svggraph" do
|
123
|
+
map_name = params["map"]
|
124
|
+
map = Mappum.catalogue(options.catalogue).get_bidi_map(map_name)
|
125
|
+
map ||= Mappum.catalogue(options.catalogue)[map_name]
|
126
|
+
return [404, {"Content-Type" => "text/html"}, ["No map " + map_name]] if map.nil?
|
127
|
+
graph = Mappum::MapServer::Graph.new(map)
|
128
|
+
[200, {"Content-Type" => "image/svg+xml"}, graph.getSvg]
|
129
|
+
|
130
|
+
end
|
131
|
+
get "/pnggraph" do
|
132
|
+
map_name = params["map"]
|
133
|
+
map = Mappum.catalogue(options.catalogue).get_bidi_map(map_name)
|
134
|
+
map ||= Mappum.catalogue(options.catalogue)[map_name]
|
135
|
+
return [404, {"Content-Type" => "text/html"}, ["No map '#{map_name}'"]] if map.nil?
|
136
|
+
graph = Mappum::MapServer::Graph.new(map)
|
137
|
+
[200, {"Content-Type" => "image/png"}, graph.getPng]
|
138
|
+
|
139
|
+
end
|
140
|
+
get "/doc" do
|
141
|
+
map_name = params["map"]
|
142
|
+
map = Mappum.catalogue(options.catalogue).get_bidi_map(map_name)
|
143
|
+
map ||= Mappum.catalogue(options.catalogue)[map_name]
|
144
|
+
return [404, {"Content-Type" => "text/html"}, ["No map " + map_name]] if map.nil?
|
145
|
+
graph = Mappum::MapServer::Graph.new(map)
|
146
|
+
text = <<HTML
|
147
|
+
<body>
|
148
|
+
<h1>#{map_name}</h1>
|
149
|
+
<p>
|
150
|
+
#{map.desc}
|
151
|
+
</p>
|
152
|
+
<object type="image/svg+xml" data="/svggraph?map=#{map_name}"><img src="/pnggraph?map=#{map_name}"></object>
|
153
|
+
<table border="1" cellspacing="0">
|
154
|
+
<tr><td>Number</td><td>Description</td><td>Technical explanation</td></tr>
|
155
|
+
#{graph.edge_maps.keys.sort.collect{|k| "<tr><td>#{k}</td><td>#{graph.edge_maps[k].desc} </td><td>#{explain(graph.edge_maps[k])} </td></tr>"}}
|
156
|
+
</table>
|
157
|
+
</body>
|
158
|
+
HTML
|
159
|
+
[200, {"Content-Type" => "text/html"}, [text]]
|
160
|
+
end
|
161
|
+
get "/" do
|
162
|
+
content404 = <<HTML
|
163
|
+
<body>
|
164
|
+
<FORM action="transform" method="post">
|
165
|
+
<P>
|
166
|
+
<select name="map">
|
167
|
+
<option value="auto_select" selected="true">auto select</option>
|
168
|
+
#{Mappum.catalogue(options.catalogue).list_map_names.collect{|mn| "<option value='#{mn}'>#{mn}</option>"}}
|
169
|
+
</select>
|
170
|
+
<br/>
|
171
|
+
<TEXTAREA name="doc" rows="20" cols="80"></TEXTAREA><br/>
|
172
|
+
<INPUT type="submit" value="Send"/><INPUT type="reset"/>
|
173
|
+
</P>
|
174
|
+
</FORM>
|
175
|
+
<BR/>
|
176
|
+
Bidirectional maps:<p>
|
177
|
+
#{Mappum.catalogue(options.catalogue).list_bidi_map_names.collect{|mn| "<a href='/doc?map=#{mn}'>#{mn}</a><br/>"}}
|
178
|
+
</p>
|
179
|
+
<BR/>
|
180
|
+
Unidirectional maps:<p>
|
181
|
+
#{Mappum.catalogue(options.catalogue).list_map_names.collect{|mn| "<a href='/doc?map=#{mn}'>#{mn}</a><br/>"}}
|
182
|
+
</p> </body>
|
183
|
+
HTML
|
184
|
+
[200, {"Content-Type" => "text/html"}, [content404]]
|
185
|
+
end
|
186
|
+
def self.parseopt
|
187
|
+
require 'optparse'
|
188
|
+
OptionParser.new { |op|
|
189
|
+
op.on('-x') { set :lock, true }
|
190
|
+
op.on('-e env') { |val| set :environment, val.to_sym }
|
191
|
+
op.on('-s server') { |val| set :server, val }
|
192
|
+
op.on('-p port') { |val| set :port, val.to_i }
|
193
|
+
}.parse!
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
if File.basename($0) == File.basename(__FILE__)
|
198
|
+
Mappum::Mapserver.parseopt
|
199
|
+
Mappum::Mapserver.run!
|
200
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<wsdl:definitions name="transfer-ws"
|
3
|
+
targetNamespace="http://mappum.ivmx.pl/transfer-ws/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
|
4
|
+
xmlns:tns="http://mappum.ivmx.pl/transfer-ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
5
|
+
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
6
|
+
<%@xml_imports.each do |file, namespace|%>
|
7
|
+
xmlns:<%=get_xmlns(namespace)%>="<%=namespace%>"
|
8
|
+
<%end%>>
|
9
|
+
|
10
|
+
<%@xml_imports.each do |file, namespace|%>
|
11
|
+
<wsdl:import namespace="<%=namespace%>"
|
12
|
+
location="<%=file%>"/>
|
13
|
+
<%end%>
|
14
|
+
<%@xml_elements.each do |qname|%>
|
15
|
+
<wsdl:message name="<%=qname.name%>">
|
16
|
+
<wsdl:part name="parameters" element="<%=get_xmlns(qname.namespace)%>:<%=qname.name%>"/>
|
17
|
+
</wsdl:message>
|
18
|
+
<%end%>
|
19
|
+
<wsdl:message name="any">
|
20
|
+
<wsdl:part name="parameters" type="xsd:anyType"/>
|
21
|
+
</wsdl:message>
|
22
|
+
<wsdl:portType name="default">
|
23
|
+
<%@xml_maps.each do |name, from, to|%>
|
24
|
+
<wsdl:operation name="<%=name%>">
|
25
|
+
<wsdl:input message="tns:<%=from.name%>"/>
|
26
|
+
<wsdl:output message="tns:<%=to.name%>"/>
|
27
|
+
</wsdl:operation>
|
28
|
+
<%end%>
|
29
|
+
</wsdl:portType>
|
30
|
+
<wsdl:binding name="binding" type="tns:default">
|
31
|
+
<soap:binding style="document"
|
32
|
+
transport="http://schemas.xmlsoap.org/soap/http" />
|
33
|
+
<%@xml_maps.each do |name, from, to|%>
|
34
|
+
<wsdl:operation name="<%=name%>">
|
35
|
+
<soap:operation soapAction="<%=name%>" />
|
36
|
+
<wsdl:input>
|
37
|
+
<soap:body use="literal" />
|
38
|
+
</wsdl:input>
|
39
|
+
<wsdl:output>
|
40
|
+
<soap:body use="literal" />
|
41
|
+
</wsdl:output>
|
42
|
+
</wsdl:operation>
|
43
|
+
<%end%>
|
44
|
+
</wsdl:binding>
|
45
|
+
<wsdl:service name="transfer">
|
46
|
+
<wsdl:port name="http" binding="tns:binding">
|
47
|
+
<soap:address location="http://localhost:9292/transform-ws" />
|
48
|
+
</wsdl:port>
|
49
|
+
</wsdl:service>
|
50
|
+
</wsdl:definitions>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
2
|
+
<env:Body>
|
3
|
+
<env:Fault>
|
4
|
+
<faultcode><%=ERB::Util.html_escape @error.class.to_s%></faultcode>
|
5
|
+
<faultstring><%=ERB::Util.html_escape @error.message%></faultstring>
|
6
|
+
<faultactor>Server</faultactor>
|
7
|
+
<detail><%=ERB::Util.html_escape @error.backtrace.join("\n")%></detail>
|
8
|
+
</env:Fault>
|
9
|
+
</env:Body>
|
10
|
+
</env:Envelope>
|