mappum 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +4 -0
  2. data/LICENSE +15 -0
  3. data/README +53 -0
  4. data/Rakefile +48 -0
  5. data/VERSION +1 -0
  6. data/bin/mapserver.rb +4 -0
  7. data/java-api/pom.xml +63 -0
  8. data/java-api/src/main/java/pl/ivmx/mappum/JavaTransform.java +12 -0
  9. data/java-api/src/main/java/pl/ivmx/mappum/MappumApi.java +83 -0
  10. data/java-api/src/main/java/pl/ivmx/mappum/TreeElement.java +23 -0
  11. data/java-api/src/main/java/pl/ivmx/mappum/WorkdirLoader.java +12 -0
  12. data/java-api/src/test/java/iv/Client.java +237 -0
  13. data/java-api/src/test/java/iv/Person.java +261 -0
  14. data/java-api/src/test/java/pl/ivmx/mappum/MappumTest.java +122 -0
  15. data/java-api/src/test/resources/map/example_map.rb +88 -0
  16. data/lib/mappum.rb +46 -0
  17. data/lib/mappum/autoconv_catalogue.rb +43 -0
  18. data/lib/mappum/dsl.rb +255 -0
  19. data/lib/mappum/java_transform.rb +107 -0
  20. data/lib/mappum/map.rb +194 -0
  21. data/lib/mappum/mapserver/mapgraph.rb +192 -0
  22. data/lib/mappum/mapserver/mapserver.rb +213 -0
  23. data/lib/mappum/mapserver/maptable.rb +80 -0
  24. data/lib/mappum/mapserver/views/doc.erb +15 -0
  25. data/lib/mappum/mapserver/views/main.erb +39 -0
  26. data/lib/mappum/mapserver/views/maptable.erb +16 -0
  27. data/lib/mappum/mapserver/views/rubysource.erb +25 -0
  28. data/lib/mappum/mapserver/views/transform-ws.wsdl.erb +50 -0
  29. data/lib/mappum/mapserver/views/ws-error.erb +10 -0
  30. data/lib/mappum/open_xml_object.rb +68 -0
  31. data/lib/mappum/ruby_transform.rb +199 -0
  32. data/lib/mappum/xml_transform.rb +382 -0
  33. data/mappum.gemspec +117 -0
  34. data/sample/address_fixture.xml +11 -0
  35. data/sample/crm.rb +9 -0
  36. data/sample/crm_client.xsd +28 -0
  37. data/sample/erp.rb +7 -0
  38. data/sample/erp_person.xsd +44 -0
  39. data/sample/example_conversions.rb +12 -0
  40. data/sample/example_map.rb +92 -0
  41. data/sample/example_notypes.rb +77 -0
  42. data/sample/example_when.rb +13 -0
  43. data/sample/person_fixture.xml +23 -0
  44. data/sample/person_fixture_any.xml +26 -0
  45. data/sample/server/map/example_any.rb +28 -0
  46. data/sample/server/map/example_soap4r.rb +59 -0
  47. data/sample/server/mapserver.sh +1 -0
  48. data/sample/server/schema/crm_client.xsd +29 -0
  49. data/sample/server/schema/erp/erp_person.xsd +38 -0
  50. data/test/test_conversions.rb +24 -0
  51. data/test/test_example.rb +175 -0
  52. data/test/test_openstruct.rb +129 -0
  53. data/test/test_soap4r.rb +108 -0
  54. data/test/test_when.rb +35 -0
  55. data/test/test_xml_any.rb +62 -0
  56. metadata +164 -0
data/lib/mappum/map.rb ADDED
@@ -0,0 +1,194 @@
1
+ module Mappum
2
+ # Base Map class representing mapping betwean two or more types, properties etc.
3
+ class Map
4
+
5
+ attr_accessor :maps, :bidi_maps, :strip_empty, :source
6
+
7
+ def initialize
8
+ @maps = []
9
+ @bidi_maps =[]
10
+ @strip_empty = true
11
+ end
12
+ # When value of mapped property is null remove property.
13
+ def strip_empty?
14
+ @strip_empty
15
+ end
16
+ end
17
+
18
+
19
+ class RootMap < Map
20
+ attr_accessor :name
21
+ def initialize(name)
22
+ super()
23
+ @name = name
24
+ @strip_empty = false
25
+ @maps_by_name, @maps_by_from = {},{}
26
+ @maps_by_from_to = {}
27
+ @bidi_maps_by_name, @bidi_maps_by_class = {},{}
28
+ end
29
+ def [](arg1, to_class=nil)
30
+ from_class = arg1
31
+ unless to_class.nil?
32
+ key = [from_class.to_s, to_class.to_s]
33
+ return @maps_by_from_to[key]
34
+ end
35
+ mpa = @maps_by_from[from_class.to_s]
36
+ return mpa unless mpa.nil?
37
+ return @maps_by_name[arg1.to_s]
38
+ end
39
+ def get_bidi_map(name)
40
+ mpa = @bidi_maps_by_class[name.to_s]
41
+ return mpa unless mpa.nil?
42
+
43
+ return @bidi_maps_by_name[name.to_s]
44
+ end
45
+ def list_map_names(full_list = false)
46
+ list = []
47
+ list += @maps_by_name.collect{|k,v| k}
48
+ list += @maps_by_from.collect{|k,v| k} if full_list
49
+ return list
50
+ end
51
+ def list_bidi_map_names
52
+ list = []
53
+ list += @bidi_maps_by_name.collect{|k, v| k}
54
+ return list
55
+ end
56
+ #
57
+ # Add array of maps to catalogue.
58
+ # Makes name index for map search.
59
+ # Map names will be used and no 2 names can be the same in the catalogue/
60
+ # Class names will be used for maps that are unique in regard to mapping from and to classes.
61
+ #
62
+ def add(map)
63
+ if map.normalized?
64
+ raise "Duplicate map name #{map.name}" if @maps_by_name.include?(map.name)
65
+ @maps_by_name[map.name] = map
66
+ #When there are 2 maps from same class to other classes non will be found by default
67
+ add_to_index(@maps_by_from, map.from.clazz.to_s, map)
68
+
69
+ #When there are 2 maps from same class to same class non will be found by default
70
+ from_to_key = [map.from.clazz.to_s, map.to.clazz.to_s]
71
+ add_to_index(@maps_by_from_to, from_to_key, map)
72
+ else
73
+ raise "Duplicate map name #{map.name}" if @bidi_maps_by_name.include?(map.name)
74
+ @bidi_maps_by_name[map.name] = map
75
+
76
+ add_to_index(@bidi_maps_by_class, map.left.clazz.to_s, map)
77
+ add_to_index(@bidi_maps_by_class, map.right.clazz.to_s, map)
78
+ end
79
+ end
80
+ #
81
+ # Add value to index in key position unless there is a value for such a key
82
+ # in such a case put nil in the index to mark position invalid
83
+ #
84
+ private
85
+ def add_to_index(index, key, map)
86
+ if index.include?(key)
87
+ index[key] = nil
88
+ else
89
+ index[key] = map
90
+ end
91
+ end
92
+ end
93
+
94
+ class FieldMap < Map
95
+ attr_accessor :dict, :desc, :left, :right, :func, :block, :to, :from, :func_on_nil, :submap_alias
96
+ attr_accessor :name, :l2r_name, :r2l_name, :name_prefix, :map_when, :when_r2l, :when_l2r
97
+ # True if map is unidirectional. Map is unidirectional
98
+ # when maps one way only.
99
+ def normalized?
100
+ not @from.nil?
101
+ end
102
+ def name
103
+ return @name unless @name.nil?
104
+ if normalized?
105
+ @name = "#{@name_prefix}#{@from.clazz}_to_#{@to.clazz}"
106
+ else
107
+ @name = "#{@name_prefix}#{@left.clazz}_to_from-#{@right.clazz}"
108
+ end
109
+ return @name
110
+ end
111
+ def normalize
112
+ #if bidirectional
113
+ if not normalized?
114
+ map_r2l = self.clone
115
+ map_r2l.to = self.left
116
+ map_r2l.from = self.right
117
+ map_r2l.name = self.r2l_name
118
+ map_r2l.r2l_name, map_r2l.l2r_name = nil, nil
119
+ map_r2l.map_when = self.when_r2l
120
+ map_r2l.when_r2l, map_r2l.when_l2r = nil, nil
121
+ map_r2l.maps = self.maps.select do |m|
122
+ m.to.parent == map_r2l.to
123
+ end
124
+
125
+ map_r2l.dict = self.dict.invert unless self.dict.nil?
126
+
127
+ map_l2r = self.clone
128
+ map_l2r.to = self.right
129
+ map_l2r.from = self.left
130
+ map_l2r.name = self.l2r_name
131
+ map_l2r.r2l_name, map_l2r.l2r_name = nil, nil
132
+ map_l2r.map_when = self.when_l2r
133
+ map_l2r.when_r2l, map_l2r.when_l2r = nil, nil
134
+ map_l2r.maps = self.maps.select do |m|
135
+ m.to.parent == map_l2r.to
136
+ end
137
+
138
+ [map_r2l, map_l2r]
139
+ else
140
+ [self]
141
+ end
142
+ end
143
+ def simple?
144
+ @func.nil? && @dict.nil? && @desc.nil? &&
145
+ @maps.empty? && @bidi_maps.empty? && @right.func.nil? && @left.func.nil?
146
+ end
147
+ def func_on_nil?
148
+ @func_on_nil
149
+ end
150
+ end
151
+ class Tree
152
+ attr_accessor :parent
153
+
154
+ def initialize(parent)
155
+ @parent = parent
156
+ end
157
+ def method_missing(symbol, *args)
158
+ return Field.new(@parent, symbol, args[0])
159
+ end
160
+ end
161
+ class Field < Struct.new(:name, :clazz, :parent, :func, :block, :is_root, :is_array, :is_placeholder)
162
+ def array?
163
+ is_array
164
+ end
165
+ def placeholder?
166
+ is_placeholder
167
+ end
168
+ end
169
+ class Constant < Struct.new(:value)
170
+ def parent
171
+ nil
172
+ end
173
+ def is_array
174
+ @value.kind_of?(Array)
175
+ end
176
+ def func
177
+ nil
178
+ end
179
+ end
180
+ class Function
181
+ def parent
182
+ nil
183
+ end
184
+ def array?
185
+ false
186
+ end
187
+ def func
188
+ nil
189
+ end
190
+ def value
191
+ nil
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,192 @@
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
+ 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
+ def makeStruct(struct_tree)
61
+ str = struct_tree.line || ""
62
+ unless struct_tree.children.nil? or struct_tree.children.empty?
63
+ str += "<TR><TD></TD> <TD CELLPADDING=\"1\">" unless struct_tree.parent.nil?
64
+ str += "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" BGCOLOR=\"cornsilk2\">\n"
65
+ st = struct_tree.children.collect { |child| makeStruct(child)}
66
+ st.uniq!
67
+ str += st.join + "</TABLE>"
68
+ str += "</TD></TR>\n" unless struct_tree.parent.nil?
69
+ end
70
+ return str
71
+ end
72
+ def init(map, struct_from, struct_to)
73
+ if map.normalized?
74
+ map_from, map_to = map.from, map.to
75
+ else
76
+ map_from, map_to = map.left, map.right
77
+ end
78
+ to_name, to_path, level_to = get_name_and_path(map_to)
79
+ from_name, from_path, level_from = get_name_and_path(map_from)
80
+
81
+ str_from = StrTree.new(struct_from,level_from, @root)
82
+ unless from_name.nil?
83
+ if level_from > -1
84
+ str_from.line = "<TR> <TD COLSPAN=\"2\" PORT=\"#{from_path}\">#{from_name}</TD></TR>\n"
85
+ else
86
+ str_from.line = "#{from_path} [ label = <\"#{from_name}\">];\n"
87
+ end
88
+ end
89
+ str_to = StrTree.new(struct_to,level_to,@root)
90
+ unless to_name.nil?
91
+ if level_to > -1
92
+ str_to.line ="<TR> <TD COLSPAN=\"2\" PORT=\"#{to_path}\">#{to_name}</TD></TR>\n"
93
+ else
94
+ str_to.line = "#{to_path} [ label = <\"#{to_name}\">];\n"
95
+ end
96
+ end
97
+ maps = []
98
+ if map.normalized?
99
+ maps = map.maps
100
+ else
101
+ maps = map.bidi_maps
102
+ end
103
+
104
+
105
+ unless maps.empty?
106
+ maps.each do |sub_map|
107
+ if(map.normalized? or sub_map.left.parent == map_from or
108
+ sub_map.right.parent == map_to)
109
+
110
+ init(sub_map, str_from, str_to)
111
+ else
112
+ init(sub_map, str_to, str_from)
113
+ end
114
+ end
115
+ else
116
+ # as option? labelfloat=true
117
+ from_ref = "#{str_from.root.name}:#{from_path}" if level_from > -1
118
+ to_ref = "#{str_to.root.name}:#{to_path}" if level_to > -1
119
+ from_ref ||= from_path
120
+ to_ref ||= to_path
121
+ edge = "#{from_ref} -> #{to_ref} ["
122
+ if map.normalized?
123
+ edge += " arrowtail = none tooltip=\"#{from_name} >> #{to_name}\" "
124
+ else
125
+ edge += " arrowtail = vee tooltip=\"#{from_name} <=> #{to_name}\" "
126
+ end
127
+ edge += " arrowhead = vee URL=\"##{@edges.size+1}\" fontsize=10 "
128
+ unless map.simple?
129
+ edge += " label=\"#{@edges.size+1}\" labeltooltip = \"#{@edges.size+1}: #{from_name} >> #{to_name}\""
130
+ end
131
+ color = "black"
132
+ color = "blue" if level_to == -1 or level_from == -1
133
+ edge += " minlen=\"3\" color=\"#{color}\"];\n"
134
+
135
+ @edges << edge
136
+ unless map.simple?
137
+ @edge_maps[@edges.size] = map
138
+ end
139
+ end
140
+
141
+ end
142
+ def get_name_and_path(element, level = 0)
143
+ #on non filed elements
144
+ if element.kind_of?(Function)
145
+ return "Function", "c#{element.__id__.abs}", -1
146
+ end
147
+ if element.kind_of?(Constant)
148
+ return element.value.to_s, "c#{element.__id__.abs}", -1
149
+ end
150
+
151
+ name = element.name
152
+ if element.parent.nil?
153
+ #root element
154
+ name ||= element.clazz.to_s
155
+ else
156
+ level = level + 1 if name.nil?
157
+ pname, path, level = get_name_and_path(element.parent, level)
158
+ end
159
+ path = "#{path}v#{name}".gsub(":","vv") unless name.nil?
160
+ name = "#{name}[]" if not name.nil? and element.is_array
161
+ return name, path, level
162
+ end
163
+ end
164
+ class StrTree
165
+ attr_accessor :line, :parent,:children, :name
166
+ def initialize(parent, level, root)
167
+ @parent=parent if level > -1
168
+ root << self if level == -1
169
+ @parent.add(self, level) unless @parent.nil?
170
+ end
171
+
172
+ def add(child, level=0)
173
+ @children ||= []
174
+ if level == 0
175
+ @children << child unless @children.include?(child)
176
+ else
177
+ @parent.add(child, level - 1)
178
+ end
179
+ end
180
+ def ==(other)
181
+ return false unless other.kind_of?(StrTree)
182
+ if @line == other.line and @parent == other.parent and @children == other.children
183
+ return true
184
+ end
185
+ end
186
+ def root
187
+ return parent.root unless parent.nil?
188
+ return self
189
+ end
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,213 @@
1
+ require 'rubygems'
2
+ gem 'soap4r'
3
+ require 'mappum/xml_transform'
4
+ require 'soap/marshal'
5
+ require 'mappum/mapserver/mapgraph'
6
+ require 'mappum/mapserver/maptable'
7
+ require 'syntax/convertors/html'
8
+ require 'sinatra/base'
9
+ require 'erb'
10
+
11
+ module Mappum
12
+ class Mapserver < Sinatra::Default
13
+ set :views => File.join(File.dirname(__FILE__), 'views')
14
+ set :public => File.join(File.dirname(__FILE__), 'public')
15
+ configure do
16
+ set :schema_dir => 'schema', :map_dir => 'map', :tmp_dir => nil
17
+ set :catalogue => nil
18
+ set :port => 9292
19
+
20
+ # FIXME make configurable
21
+ #wl = Mappum::WorkdirLoader.new(options.schema_dir, options.tmp_dir, options.map_dir)
22
+ @wl = Mappum::WorkdirLoader.new('schema', 'map')
23
+ @wl.generate_and_require
24
+ end
25
+ helpers do
26
+ def explain_func(element)
27
+ name = element.name.to_s
28
+ name ||= "self"
29
+ func = element.func.gsub(/^self/,name)
30
+ #replace [](1) with [1]
31
+ func = func.gsub(/\.\[\]\((.*)\)/,"[\\1]")
32
+ return "Simple function call: \"#{func}\"<br/>"
33
+ end
34
+ def explain(map)
35
+ str=""
36
+ if not map.right.nil? and not map.right.func.nil?
37
+ str+= explain_func(map.right)
38
+ elsif not map.from.nil? and not map.from.func.nil?
39
+ str+= explain_func(map.from)
40
+ end
41
+ unless map.func.nil?
42
+ str+= "Multiline function call (see source)<br/>"
43
+ end
44
+ unless map.dict.nil?
45
+ str+= "Dictionary mapping:<br/>"
46
+ str+= "<table border=\"1\">"
47
+ str+= "<tr><td>#{map.left.name}</td><td>#{map.right.name}</td></tr>"
48
+ map.dict.each do |k,v|
49
+ str+= "<tr><td>#{k}</td><td>#{v}</td></tr>"
50
+ end
51
+ str+= "</table>"
52
+ end
53
+ return str
54
+ end
55
+ def get_xmlns(namespace)
56
+ @namespaces ||= {}
57
+ @i ||= 0
58
+ @namespaces[namespace] = "ns#{@i+=1}" unless @namespaces.include?(namespace)
59
+ return @namespaces[namespace]
60
+ end
61
+ end
62
+ #make get methods for xsd files
63
+ Dir.glob('schema'+'/**/*.xsd') do |filename1|
64
+ get "/"+filename1 do
65
+ [200, {"Content-Type" => "text/xml"}, IO.read(filename1)]
66
+ end
67
+ #make get methods for map files
68
+ Dir.glob('map'+'/**/*.rb') do |filename|
69
+ get "/"+filename do
70
+ convertor = Syntax::Convertors::HTML.for_syntax "ruby"
71
+ @body = convertor.convert( IO.read(filename) )
72
+
73
+ [200, {"Content-Type" => "text/html"}, erb(:rubysource)]
74
+ end
75
+ end
76
+ end
77
+ post "*/transform" do
78
+ @catalogue = params[:splat][0] || "ROOT"
79
+ @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
80
+
81
+ map_name = nil
82
+ map_name = params["map"] unless params["map"].nil? or params["map"] == "auto_select"
83
+ force_openstruct = false
84
+ force_openstruct = params["ignore"] unless params["map"].nil?
85
+
86
+ rt = Mappum::XmlTransform.new(@catalogue, force_openstruct)
87
+
88
+ xml = params["doc"]
89
+ content = rt.transform(xml,map_name)
90
+
91
+ [200, {"Content-Type" => "text/xml"}, [content]]
92
+ end
93
+ post "*/transform-ws" do
94
+ @catalogue = params[:splat][0] || "ROOT"
95
+ @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
96
+
97
+ map_name = env["HTTP_SOAPACTION"] unless env["HTTP_SOAPACTION"].nil? or env["HTTP_SOAPACTION"] == ""
98
+ #remove "" if present
99
+ map_name = map_name[1..-2] if map_name =~ /^".*"$/
100
+
101
+ rt = Mappum::XmlTransform.new(@catalogue)
102
+
103
+ xml = env["rack.input"].read
104
+ begin
105
+ content = rt.transform(xml,map_name)
106
+ rescue Exception => e
107
+ @error = e
108
+ return [200, {"Content-Type" => "text/xml"}, [erb(:'ws-error')]]
109
+ end
110
+ return [200, {"Content-Type" => "text/xml"}, [content]]
111
+ end
112
+ get "*/transform-ws.wsdl" do
113
+ @catalogue = params[:splat][0] || "ROOT"
114
+ @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
115
+
116
+ @xml_imports = {}
117
+ Dir.glob('schema'+'/**/*.xsd') do |xsd_file|
118
+ namespace = XmlSupport.get_target_ns(xsd_file)
119
+ @xml_imports[xsd_file] = namespace unless namespace.nil?
120
+ #FIXME log warning
121
+ end
122
+
123
+ @xml_maps = []
124
+ @xml_elements = Set.new
125
+ Mappum.catalogue(@catalogue).list_map_names.each do |mapname|
126
+ map = Mappum.catalogue(@catalogue)[mapname]
127
+
128
+ from_qname = XSD::Mapping::Mapper.get_qname_from_class(map.from.clazz)
129
+ @xml_elements << from_qname unless from_qname.nil?
130
+ from_qname ||= XSD::QName.new(nil,"any")
131
+
132
+
133
+ to_qname = XSD::Mapping::Mapper.get_qname_from_class(map.to.clazz)
134
+ @xml_elements << to_qname unless to_qname.nil?
135
+ to_qname ||= XSD::QName.new(nil,"any")
136
+
137
+ @xml_maps << [mapname, from_qname, to_qname]
138
+ end
139
+
140
+ [200, {"Content-Type" => "text/xml"}, [erb(:'transform-ws.wsdl')]]
141
  end
142
+
143
+ get "*/svggraph" do
144
+ @catalogue = params[:splat][0] || "ROOT"
145
+ @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
146
+
147
+ map_name = params["map"]
148
+ map = Mappum.catalogue(@catalogue).get_bidi_map(map_name)
149
+ map ||= Mappum.catalogue(@catalogue)[map_name]
150
+ return [404, {"Content-Type" => "text/html"}, ["No map " + map_name]] if map.nil?
151
+ graph = Mappum::MapServer::Graph.new(map)
152
+ [200, {"Content-Type" => "image/svg+xml"}, graph.getSvg]
153
+
154
+ end
155
+ get "*/maptable" do
156
+ @catalogue = params[:splat][0] || "ROOT"
157
+ @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
158
+
159
+ @map_name = params["map"]
160
+ @map = Mappum.catalogue(@catalogue)[@map_name]
161
+ return [404, {"Content-Type" => "text/html"}, ["No map " + @map_name]] if @map.nil?
162
+ @maptable = Mappum::MapServer::MapTable.new(@map)
163
+ @edge_maps = @maptable.edge_maps.keys.sort.collect{|k| [k, @maptable.edge_maps[k], explain(@maptable.edge_maps[k])]}
164
+
165
+ [200, {"Content-Type" => "text/html"}, [erb(:maptable)]]
166
+
167
+ end
168
+
169
+ get "*/pnggraph" do
170
+ @catalogue = params[:splat][0] || "ROOT"
171
+ @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
172
+
173
+ map_name = params["map"]
174
+ map = Mappum.catalogue(@catalogue).get_bidi_map(map_name)
175
+ map ||= Mappum.catalogue(@catalogue)[map_name]
176
+ return [404, {"Content-Type" => "text/html"}, ["No map '#{map_name}'"]] if map.nil?
177
+ graph = Mappum::MapServer::Graph.new(map)
178
+ [200, {"Content-Type" => "image/png"}, graph.getPng]
179
+
180
+ end
181
+ get "*/doc" do
182
+ @catalogue = params[:splat][0] || "ROOT"
183
+ @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
184
+
185
+ @map_name = params["map"]
186
+ @map = Mappum.catalogue(@catalogue).get_bidi_map(@map_name)
187
+ @map ||= Mappum.catalogue(@catalogue)[@map_name]
188
+ return [404, {"Content-Type" => "text/html"}, ["No map " + @map_name]] if @map.nil?
189
+ graph = Mappum::MapServer::Graph.new(@map)
190
+ @edge_maps = graph.edge_maps.keys.sort.collect{|k| [k, graph.edge_maps[k], explain(graph.edge_maps[k])]}
191
+ [200, {"Content-Type" => "text/html"}, [erb(:doc)]]
192
+ end
193
+ get "/" do
194
+ @catalogue = params["catalogue"] || "ROOT"
195
+ @catalogues = Mappum.catalogues
196
+ @bidi_maps_name_source = Mappum.catalogue(@catalogue).list_bidi_map_names.collect{|mn| [mn, Mappum.catalogue(@catalogue).get_bidi_map(mn).source] }
197
+ @maps_name_source = Mappum.catalogue(@catalogue).list_map_names.collect{|mn| [mn, Mappum.catalogue(@catalogue)[mn].source]}
198
+ [200, {"Content-Type" => "text/html"}, [erb(:main)]]
199
+ end
200
+ def self.parseopt
201
+ require 'optparse'
202
+ OptionParser.new { |op|
203
+ op.on('-x') { set :lock, true }
204
+ op.on('-e env') { |val| set :environment, val.to_sym }
205
+ op.on('-s server') { |val| set :server, val }
206
+ op.on('-p port') { |val| set :port, val.to_i }
207
+ }.parse!
208
+ end
209
+ end
210
+ end
211
+ if File.basename($0) == File.basename(__FILE__)
212
+ Mappum::Mapserver.parseopt
213
+ Mappum::Mapserver.run!
214
+ end