simcha-mappum 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|