simcha-mappum 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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}&nbsp;</td><td>#{explain(graph.edge_maps[k])}&nbsp;</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>