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.
- data/.gitignore +4 -0
- data/LICENSE +15 -0
- data/README +53 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/bin/mapserver.rb +4 -0
- data/java-api/pom.xml +63 -0
- data/java-api/src/main/java/pl/ivmx/mappum/JavaTransform.java +12 -0
- data/java-api/src/main/java/pl/ivmx/mappum/MappumApi.java +83 -0
- data/java-api/src/main/java/pl/ivmx/mappum/TreeElement.java +23 -0
- data/java-api/src/main/java/pl/ivmx/mappum/WorkdirLoader.java +12 -0
- data/java-api/src/test/java/iv/Client.java +237 -0
- data/java-api/src/test/java/iv/Person.java +261 -0
- data/java-api/src/test/java/pl/ivmx/mappum/MappumTest.java +122 -0
- data/java-api/src/test/resources/map/example_map.rb +88 -0
- data/lib/mappum.rb +46 -0
- data/lib/mappum/autoconv_catalogue.rb +43 -0
- data/lib/mappum/dsl.rb +255 -0
- data/lib/mappum/java_transform.rb +107 -0
- data/lib/mappum/map.rb +194 -0
- data/lib/mappum/mapserver/mapgraph.rb +192 -0
- data/lib/mappum/mapserver/mapserver.rb +213 -0
- data/lib/mappum/mapserver/maptable.rb +80 -0
- data/lib/mappum/mapserver/views/doc.erb +15 -0
- data/lib/mappum/mapserver/views/main.erb +39 -0
- data/lib/mappum/mapserver/views/maptable.erb +16 -0
- data/lib/mappum/mapserver/views/rubysource.erb +25 -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 +68 -0
- data/lib/mappum/ruby_transform.rb +199 -0
- data/lib/mappum/xml_transform.rb +382 -0
- data/mappum.gemspec +117 -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 +44 -0
- data/sample/example_conversions.rb +12 -0
- data/sample/example_map.rb +92 -0
- data/sample/example_notypes.rb +77 -0
- data/sample/example_when.rb +13 -0
- data/sample/person_fixture.xml +23 -0
- data/sample/person_fixture_any.xml +26 -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_conversions.rb +24 -0
- data/test/test_example.rb +175 -0
- data/test/test_openstruct.rb +129 -0
- data/test/test_soap4r.rb +108 -0
- data/test/test_when.rb +35 -0
- data/test/test_xml_any.rb +62 -0
- 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
|