mappum 0.2.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.
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.rb ADDED
@@ -0,0 +1,46 @@
1
+ # TODO docs
2
+ require 'set'
3
+ require 'mappum/dsl'
4
+ require 'mappum/map'
5
+
6
+ module Mappum
7
+ #
8
+ # Add mapinng in DSL to the catalogue.
9
+ #
10
+ def self.catalogue_add(name = "ROOT", &block)
11
+ @catalogue ||= {}
12
+ @catalogue_src ||= {}
13
+ @catalogue[name] ||= RootMap.new(name)
14
+ definition = DSL::RootMap.new(name, @source).make_definition(&block)
15
+ definition.maps.each{|m| @catalogue[name].add(m)}
16
+ definition.bidi_maps.each{|m| @catalogue[name].add(m)}
17
+ end
18
+ #
19
+ # Get root map.
20
+ #
21
+ def self.catalogue(name = "ROOT")
22
+ name = "ROOT" if name.nil?
23
+ if @catalogue.nil?
24
+ throw RuntimeError.new("No maps where loaded remember to put some moaps in 'map' folder and load them.\n"+
25
+ "To load in ruby just require files or use WorkdirLoader.generate_and_require.\n"+
26
+ "To load in java run:\nMappumApi mp = new MappumApi();\nmp.loadMaps();")
27
+ end
28
+ @catalogue[name]
29
+ end
30
+ def self.catalogues
31
+ return @catalogue.keys
32
+ end
33
+ #
34
+ # Empty catalogues
35
+ #
36
+ def self.drop_all
37
+ @catalogue = {}
38
+ @catalogue_src = {}
39
+ end
40
+ #
41
+ #Set source file from which definitions are read
42
+ #
43
+ def self.source=(src)
44
+ @source = src
45
+ end
46
+ end
@@ -0,0 +1,43 @@
1
+ require 'date'
2
+ require 'time'
3
+
4
+ Mappum.catalogue_add "MAPPUM_AUTOCONV" do
5
+ map Date, String do |a,b|
6
+ map a.self << b.self do |b1|
7
+ Date.parse(b1)
8
+ end
9
+
10
+ map a.self >> b.self do |a1|
11
+ a1.to_s
12
+ end
13
+ end
14
+ map Time, String do |a,b|
15
+ map a.self << b.self do |b1|
16
+ Time.parse(b1)
17
+ end
18
+
19
+ map a.self >> b.self do |a1|
20
+ a1.rfc2822
21
+ end
22
+ end
23
+ map Fixnum, String do |a,b|
24
+ map a.self << b.self do |b1|
25
+ b1.to_i
26
+ end
27
+
28
+ map a.self >> b.self do |a1|
29
+ a1.to_s
30
+ end
31
+ end
32
+ map Float, String do |a,b|
33
+ map a.self << b.self do |b1|
34
+ b1.to_f
35
+ end
36
+
37
+ map a.self >> b.self do |a1|
38
+ a1.to_s
39
+ end
40
+ end
41
+
42
+
43
+ end
data/lib/mappum/dsl.rb ADDED
@@ -0,0 +1,255 @@
1
+ require 'facets/kernel/instance_exec'
2
+ class Object
3
+ def >> field
4
+ return {Mappum::DSL::Constant.new(self) => field} if field.kind_of?(Mappum::DSL::Field)
5
+ throw "Constant can be mapped to field only"
6
+ end
7
+ end
8
+ module Mappum
9
+ module DSL
10
+ class Map
11
+ attr_accessor :def
12
+ def initialize
13
+ @def = Mappum::Map.new
14
+ end
15
+ def map(*attr, &block)
16
+ mapa = FieldMap.new(attr)
17
+ mapa.def.source = @def.source
18
+
19
+ mapa.def.desc = @comment
20
+ @comment = nil
21
+
22
+ if (not mapa.def.normalized?) && block_given?
23
+ eval_right = mapa.mpun_right.clone
24
+ eval_right.mpun_definition.is_root = true
25
+ eval_left = mapa.mpun_left.clone
26
+ eval_left.mpun_definition.is_root = true
27
+ mapa.instance_exec(eval_left, eval_right, &block)
28
+ elsif block_given?
29
+ mapa.def.func = block
30
+ mapa.def.func_on_nil = true if mapa.mpun_left.kind_of?(Function)
31
+ end
32
+ @def.maps += mapa.def.normalize
33
+ @def.bidi_maps << mapa.def
34
+ return mapa.def
35
+ end
36
+ #
37
+ # Define condition evaluated before this mapping is applyed.
38
+ # First argument is a label
39
+ # :> - left to right map
40
+ # :< - right to left map
41
+ # Second argument is a block and from elemnt is pased to the block.
42
+ #
43
+ def map_when(label,&condition)
44
+ case label
45
+ when :>, '>'
46
+ @def.when_l2r = condition
47
+ when :<, '<'
48
+ @def.when_r2l = condition
49
+ end
50
+ end
51
+ #
52
+ # Add comment to mapping.
53
+ #
54
+ def `(str)
55
+ @comment ||= ""
56
+ @comment += str
57
+ end
58
+
59
+ # Add prefix to auto map names
60
+ def name_map_prefix(name)
61
+ name_map(:prefix, name)
62
+ end
63
+ #
64
+ # Give name to a map where map is:
65
+ # :<=> - bidirectional map name
66
+ # :> - left to right map name
67
+ # :< - right to left map name
68
+ # :prefix - add prefix to auto generated names
69
+ #
70
+ def name_map(map, name)
71
+ case map
72
+ when :<=>, '<=>'
73
+ @def.name = name.to_s
74
+ when :>, '>'
75
+ @def.l2r_name = name.to_s
76
+ when :<, '<'
77
+ @def.r2l_name = name.to_s
78
+ when :prefix, 'prefix'
79
+ if name.to_s[-1..-1]=='_'
80
+ @def.name_prefix = name.to_s
81
+ else
82
+ @def.name_prefix = "#{name.to_s}_"
83
+ end
84
+ end
85
+ end
86
+ def func
87
+ Mappum::DSL::Function.new
88
+ end
89
+ def tree(clazz)
90
+ return Field.new(nil, nil, clazz)
91
+ end
92
+ end
93
+ class RootMap < Map
94
+ def initialize(name,source=nil)
95
+ @def = Mappum::RootMap.new(name)
96
+ @def.source = source
97
+ end
98
+ def make_definition &block
99
+ instance_eval(&block)
100
+ @def
101
+ end
102
+ end
103
+ class FieldMap < Map
104
+ attr_accessor :mpun_left, :mpun_right
105
+ def mpun_left=(left_map_dsl)
106
+ @mpun_left=left_map_dsl
107
+ @def.left=left_map_dsl.mpun_definition
108
+ end
109
+ def mpun_right=(right_map_dsl)
110
+ @mpun_right=right_map_dsl
111
+ @def.right=right_map_dsl.mpun_definition
112
+ end
113
+ def initialize(*attr)
114
+ @def = Mappum::FieldMap.new
115
+ type_size = 1
116
+ if attr == [[nil]]
117
+ raise """Can't make map for [[nil]] arguments.
118
+ Can be that You define top level class mapping with \"<=>\" please use \",\" instead (we know its a Bug). """
119
+ end
120
+ mapped = attr[0][0]
121
+ if attr[0][0].instance_of?(Class) or attr[0][0].instance_of?(Symbol) and
122
+ attr[0][1].instance_of?(Class) or attr[0][1].instance_of?(Symbol)
123
+ mapped = [attr[0][0], attr[0][1]]
124
+ type_size = 2
125
+ end
126
+
127
+ if mapped.instance_of?(Array) then
128
+ if(mapped[0]).instance_of?(Class) or (mapped[0]).instance_of?(Symbol)
129
+ @def.strip_empty = false
130
+ self.mpun_left = Field.new(nil,nil,mapped[0])
131
+ else
132
+ self.mpun_left = mapped[0]
133
+ end
134
+ if(mapped[1]).instance_of?(Class) or (mapped[1]).instance_of?(Symbol)
135
+ @def.strip_empty = false
136
+ self.mpun_right = Field.new(nil,nil,mapped[1])
137
+ else
138
+ self.mpun_right = mapped[1]
139
+ end
140
+ end
141
+ if mapped.instance_of?(Hash) then
142
+ self.mpun_left = mapped.keys[0]
143
+ self.mpun_right = mapped.values[0]
144
+ end
145
+
146
+ if mapped.instance_of?(Hash) then
147
+ @def.from = @def.left
148
+ @def.to = @def.right
149
+ end
150
+
151
+ @def.dict = attr[0][1][:dict] if attr[0].size > type_size
152
+ @def.desc = attr[0][1][:desc] if attr[0].size > type_size
153
+ @def.map_when = attr[0][1][:when] if attr[0].size > type_size
154
+ @def.when_r2l = attr[0][1][:when_r2l] if attr[0].size > type_size
155
+ @def.when_l2r = attr[0][1][:when_l2r] if attr[0].size > type_size
156
+ if @def.normalized? and not (@def.when_r2l.nil? and @def.when_l2r.nil?)
157
+ raise "r2l and l2r :when functions can be set only on bidirectional maps"
158
+ end
159
+ if not @def.normalized? and not @def.map_when.nil?
160
+ raise ":when function can be set only on unidirectional maps use :when_r2l and :when_l2r or map_when function"
161
+ end
162
+
163
+ @def.submap_alias = attr[0][1][:map] if attr[0].size > type_size
164
+
165
+ end
166
+ end
167
+ #Base class for all mapped elements eg. fields, constants
168
+ class Mappet
169
+ def mpun_definition
170
+ @def
171
+ end
172
+ def <=> field
173
+ [self, field]
174
+ end
175
+
176
+ def << field
177
+ return {field => self} if field.kind_of?(Mappum::DSL::Mappet)
178
+ return {Constant.new(field) => self}
179
+ end
180
+
181
+ def >> field
182
+ return {self => field} if field.kind_of?(Mappum::DSL::Mappet)
183
+ throw "Must map to a field"
184
+ end
185
+ end
186
+ class Constant < Mappet
187
+ def initialize(value)
188
+ @def = Mappum::Constant.new
189
+ @def.value = value
190
+ end
191
+ end
192
+
193
+ class Function < Mappet
194
+ def initialize
195
+ @def = Mappum::Function.new
196
+ end
197
+ end
198
+
199
+ class Field < Mappet
200
+ def initialize(parent, name, clazz, placeholder = false)
201
+ @def = Mappum::Field.new
202
+ @def.parent = parent
203
+ @def.name = name
204
+ @def.clazz = clazz
205
+ @def.is_array = false
206
+ @def.is_root = false
207
+ @def.is_root = false
208
+ @def.is_placeholder = placeholder
209
+ end
210
+
211
+ def type(*attr)
212
+ method_missing(:type, *attr)
213
+ end
214
+ def id(*attr)
215
+ method_missing(:id, *attr)
216
+ end
217
+
218
+ def method_missing(symbol, *args, &block)
219
+ if @def.is_root
220
+ if(symbol == :self)
221
+ return Field.new(@def, nil, args[0], true)
222
+ end
223
+ return Field.new(@def, symbol, args[0])
224
+ end
225
+
226
+ if symbol == :[]
227
+ #empty [] is just indication that field is an array not function
228
+ if args.size == 0
229
+ @def.is_array = true
230
+ return self
231
+ end
232
+ #[n] indicates both mapping function and array
233
+ if args.size == 1 and args[0].instance_of?(Fixnum)
234
+ @def.is_array = true
235
+ end
236
+ end
237
+ #this functions also indicate Array -> element
238
+ if symbol == :find or symbol == :detect
239
+ @def.is_array = true
240
+ end
241
+ arguments = args.clone
242
+ unless block.nil?
243
+ arguments << "&mappum_block"
244
+ @def.block = block
245
+ end
246
+ if @def.func.nil?
247
+ @def.func = "self.#{symbol}(#{arguments.join(", ")})"
248
+ else
249
+ @def.func += ".#{symbol}(#{arguments.join(", ")})"
250
+ end
251
+ return self
252
+ end
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,107 @@
1
+ require 'mappum/ruby_transform'
2
+ require 'mappum/xml_transform'
3
+ require 'java'
4
+
5
+ module Mappum
6
+ #
7
+ # Java Pojo to Pojo transforming class. Requires JRuby to work correctly.
8
+ #
9
+ class JavaTransform < RubyTransform
10
+ def initialize(*args)
11
+ super(*args)
12
+ end
13
+
14
+ protected
15
+
16
+ def convert_to (to, field_def)
17
+ if to.kind_of? Array then
18
+ jtype = field_def.clazz
19
+ jtype ||= "String"
20
+ return to.to_java(jtype)
21
+ else
22
+ return to
23
+ end
24
+ end
25
+ def convert_from (from, field_def)
26
+ if from.kind_of? ArrayJavaProxy then
27
+ return from.to_ary
28
+ else
29
+ return from
30
+ end
31
+ end
32
+ end
33
+ class JavaApi < Java::pl.ivmx.mappum.MappumApi
34
+ def initialize
35
+ super(false)
36
+ end
37
+ def getWorkdirLoader(schema_path="schema", map_dir="map", basedir=nil)
38
+ return WorkdirLoader.new(schema_path, map_dir, basedir)
39
+ end
40
+ def getJavaTransform(catalogueName=nil)
41
+ catalogue = Mappum.catalogue(catalogueName)
42
+ return JavaTransform.new(catalogue)
43
+ end
44
+ def loadMaps(dir="map",reload=true)
45
+ Mappum.drop_all
46
+ JavaSupport.list_maps_on_cp(dir).each do |map_file|
47
+ Mappum.source = map_file
48
+ load map_file
49
+ Mappum.source = nil
50
+ end
51
+ end
52
+ def startServer
53
+ require 'webrick'
54
+ load 'mappum/mapserver/mapserver.rb'
55
+ Mappum::Mapserver.parseopt
56
+ Mappum::Mapserver.run!
57
+
58
+ end
59
+ end
60
+
61
+ #
62
+ # Utility class providing some usefull methods in java.
63
+ #
64
+ class JavaSupport
65
+ #
66
+ # List map files on classpath.
67
+ #
68
+ def self.list_maps_on_cp(dir="map")
69
+ dir="map" if dir.nil?
70
+ thread = java.lang.Thread.new
71
+ class_loader = thread.context_class_loader
72
+ container_urls = class_loader.find_resources(dir).to_a
73
+ maplist = []
74
+ container_urls.each do |url|
75
+ if url.protocol == "file"
76
+ filelist = Dir.glob(File.join(url.path,"*.rb"))
77
+ #make paths relative again
78
+ maplist += filelist.collect{|f| f[(url.path.size-dir.size)..-1]}
79
+ elsif url.protocol == "vfsfile"
80
+ filelist = Dir.glob(File.join(url.path,"*.rb"))
81
+ #make paths relative again
82
+ maplist += filelist.collect{|f| f[(url.path.size-dir.size-1)..-1]}
83
+ elsif url.protocol == "jar"
84
+ #beware nestet url
85
+ path = URI.new(url.path).path
86
+ path = path[0..(path.rindex("!")-1)]
87
+ zip = java.util.zip.ZipFile.new(path)
88
+ names = zip.entries.to_a.collect{|ze| ze.name}
89
+ maplist += names.select{|nm| nm.index("map") == 0 and nm[-3..-1] == ".rb"}
90
+ else
91
+ #ups
92
+ puts "WARN: Unknown protocol #{url.protocol} on the classpath. When looking for #{dir} in #{__FILE__}"
93
+ end
94
+ end
95
+ return maplist
96
+ end
97
+ end
98
+ class JavaTransform
99
+ include Java::pl.ivmx.mappum.JavaTransform
100
+ end
101
+ class WorkdirLoader
102
+ include Java::pl.ivmx.mappum.WorkdirLoader
103
+ end
104
+ class TreeElement
105
+ include Java::pl.ivmx.mappum.TreeElement
106
+ end
107
+ end