mappum 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,10 +19,10 @@ module Mappum
19
19
  def self.parse_caller(at)
20
20
  if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
21
21
  file = Regexp.last_match[1]
22
- line = Regexp.last_match[2].to_i
23
- method = Regexp.last_match[3]
24
- [file, line, method]
25
- end
22
+ line = Regexp.last_match[2].to_i
23
+ method = Regexp.last_match[3]
24
+ [file, line, method]
25
+ end
26
26
  end
27
27
  class Map
28
28
  attr_accessor :def
@@ -91,7 +91,7 @@ module Mappum
91
91
  #
92
92
  # Add comment to mapping.
93
93
  #
94
- def `(str)
94
+ def `(str) #for bad colorizers add:```
95
95
  @comment ||= ""
96
96
  @comment += str
97
97
  end
@@ -126,8 +126,15 @@ module Mappum
126
126
  def func
127
127
  Mappum::DSL::Function.new
128
128
  end
129
+ def const(cst)
130
+ Mappum::DSL::Constant.new(cst)
131
+ end
129
132
  def tree(clazz)
130
- return Field.new(nil, nil, clazz)
133
+ return Mappum::DSL::Field.new(nil, nil, clazz)
134
+ end
135
+ def context
136
+ fld = Mappum::DSL::Context.new
137
+ return fld
131
138
  end
132
139
  end
133
140
  class RootMap < Map
@@ -205,7 +212,7 @@ module Mappum
205
212
  end
206
213
  @def.submap_alias = attr[0][1][:map] if attr[0].size > type_size
207
214
 
208
- end
215
+ end
209
216
  end
210
217
  #Base class for all mapped elements eg. fields, constants
211
218
  class Mappet
@@ -241,12 +248,10 @@ module Mappum
241
248
 
242
249
  class Field < Mappet
243
250
  def initialize(parent, name, clazz, placeholder = false, src_ref = nil)
244
- @def = Mappum::Field.new
251
+ @def ||= Mappum::Field.new
245
252
  @def.parent = parent
246
253
  @def.name = name
247
254
  @def.clazz = clazz
248
- @def.is_array = false
249
- @def.is_root = false
250
255
  @def.is_root = false
251
256
  @def.is_placeholder = placeholder
252
257
  @def.src_ref = src_ref
@@ -279,19 +284,28 @@ module Mappum
279
284
  if symbol == :[]
280
285
  #empty [] is just indication that field is an array not function
281
286
  if args.size == 0
282
- @def.is_array = true
287
+ @def.enum_type = Array
283
288
  return self
284
289
  end
285
- #[n] indicates both mapping function and array
286
- if args.size == 1 and args[0].instance_of?(Fixnum)
287
- @def.is_array = true
290
+ #[n] indicates both mapping function and Hash
291
+ if args.size == 1
292
+ @def.enum_type = Hash
288
293
  end
289
294
  end
290
- #this functions also indicate Array -> element
295
+ #this functions also indicate enumerable -> element
291
296
  if symbol == :find or symbol == :detect or symbol == :select
292
- @def.is_array = true
297
+ @def.enum_type = Array
298
+ end
299
+ arguments = args.clone.collect do |a|
300
+ ret = nil
301
+ if a.kind_of? Symbol
302
+ ret = ":'#{a}'"
303
+ elsif a.kind_of? String
304
+ ret = "'#{a}'"
305
+ else
306
+ ret = a
307
+ end
293
308
  end
294
- arguments = args.clone
295
309
  unless block.nil?
296
310
  arguments << "&mappum_block"
297
311
  @def.block = block
@@ -304,5 +318,11 @@ module Mappum
304
318
  return self
305
319
  end
306
320
  end
321
+ class Context < Field
322
+ def initialize
323
+ @def = Mappum::Context.new
324
+ @def.is_root
325
+ end
326
+ end
307
327
  end
308
328
  end
@@ -10,25 +10,78 @@ module Mappum
10
10
  def initialize(*args)
11
11
  super(*args)
12
12
  end
13
-
13
+ def transform(from, map=nil, to=nil, options={})
14
+ begin
15
+ if map.kind_of?(Java::JavaUtil::Map)
16
+ options = map
17
+ map = nil
18
+ end
19
+ super(from, map, to, options)
20
+ rescue MappumException => me
21
+ jme = Java::pl::ivmx::mappum::JavaMappumException.new(me)
22
+ jme.from_name = me.from_name
23
+ jme.to_name = me.to_name
24
+ jme.from = me.from
25
+ jme.to = me.to
26
+ jme.from_root = me.from_root
27
+ jme.to_root = me.to_root
28
+ jme.mappum_backtrace = me.mappum_backtrace
29
+
30
+ raise jme
31
+ end
32
+ end
14
33
  protected
34
+ def is_array?(obj)
35
+ return (obj.kind_of?(Array) or obj.kind_of?(ArrayJavaProxy) or obj.kind_of?(Set) or obj.kind_of?(Java::JavaUtil::Set))
36
+ end
15
37
 
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
38
+ def convert_to (to, field_def, parent)
39
+ if to.kind_of? Array or to.kind_of? Hash or to.kind_of? Set then
40
+ param_type = nil
41
+ unless parent.nil?
42
+ jclass = parent.java_class
43
+ unless jclass.nil?
44
+ jmethod = jclass.declared_method_smart "set#{classify(field_def.name.to_s)}".to_sym
45
+ param_type = jmethod.parameter_types[0]
46
+ end
47
+ end
48
+ if (param_type.nil? and to.kind_of? Array) or (not param_type.nil? and param_type.array?)
49
+ jtype = field_def.clazz
50
+ jtype ||= "String"
51
+ return to.to_java(jtype)
52
+ elsif (param_type.nil? and to.kind_of? Set) or (not param_type.nil? and param_type <= java.util.Set.java_class)
53
+ jset = java.util.LinkedHashSet.new to
54
+ unless param_type.class.kind_of? Module
55
+ jset = param_type.new to
56
+ end
57
+ return jset
58
+ elsif (param_type.nil? and to.kind_of? Hash) or (not param_type.nil? and param_type <= java.util.Map.java_class)
59
+ jmap = java.util.LinkedHashMap.new
60
+ unless param_type.class.kind_of? Module
61
+ jmap = param_type.new
62
+ end
63
+ jmap.put_all to
64
+ return jmap
65
+ else
66
+ raise "#{param_type} of enumerable not supported"
67
+ end
68
+ else
22
69
  return to
23
70
  end
24
71
  end
25
72
  def convert_from (from, field_def)
26
- if from.kind_of? ArrayJavaProxy then
73
+ if from.kind_of?(ArrayJavaProxy) then
27
74
  return from.to_ary
28
- else
75
+ elsif from.kind_of?(Java::JavaUtil::Set) then
76
+ return from.to_a
77
+ else
29
78
  return from
30
79
  end
31
80
  end
81
+ private
82
+ def classify(string)
83
+ return string.gsub(/(^|_)(.)/) { $2.upcase }
84
+ end
32
85
  end
33
86
  class JavaApi < Java::pl.ivmx.mappum.MappumApi
34
87
  def initialize
@@ -121,9 +121,7 @@ module Mappum
121
121
  map_r2l.when_r2l, map_r2l.when_l2r = nil, nil
122
122
  map_r2l.to_array_take = self.to_array_take_r2l
123
123
  map_r2l.to_array_take_r2l, map_r2l.to_array_take_l2r = nil, nil
124
- map_r2l.maps = self.maps.select do |m|
125
- m.to.parent == map_r2l.to
126
- end
124
+
127
125
 
128
126
  map_r2l.dict = self.dict.invert unless self.dict.nil?
129
127
 
@@ -136,14 +134,18 @@ module Mappum
136
134
  map_l2r.when_r2l, map_l2r.when_l2r = nil, nil
137
135
  map_l2r.to_array_take = self.to_array_take_l2r
138
136
  map_l2r.to_array_take_r2l, map_l2r.to_array_take_l2r = nil, nil
137
+
138
+ map_r2l.maps = self.maps.select do |m|
139
+ m.to.parent == map_r2l.to or m.to.parent.kind_of? Context
140
+ end
139
141
  map_l2r.maps = self.maps.select do |m|
140
- m.to.parent == map_l2r.to
142
+ m.to.parent == map_l2r.to or m.to.parent.kind_of? Context
141
143
  end
142
144
 
143
145
  [map_r2l, map_l2r]
144
146
  else
145
147
  [self]
146
- end
148
+ end
147
149
  end
148
150
  def simple?
149
151
  @func.nil? && @dict.nil? && @desc.nil? &&
@@ -164,15 +166,20 @@ module Mappum
164
166
  end
165
167
  end
166
168
  class Field < Struct.new(:name, :clazz, :parent, :func, :block, :is_root, :is_placeholder, :src_ref)
167
- #define is_array separetly to exclude it from equals
168
- attr_accessor :is_array
169
+ #define enum_type separetly to exclude it from equals
170
+ attr_accessor :enum_type
169
171
  def array?
170
- is_array
172
+ not enum_type.nil?
171
173
  end
172
174
  def placeholder?
173
175
  is_placeholder
174
176
  end
175
177
  end
178
+ class Context < Field
179
+ def is_root
180
+ true
181
+ end
182
+ end
176
183
  class Constant < Struct.new(:value,:parent)
177
184
  def parent
178
185
  nil
@@ -191,6 +198,9 @@ module Mappum
191
198
  def func
192
199
  nil
193
200
  end
201
+ def name
202
+ nil
203
+ end
194
204
  def value
195
205
  nil
196
206
  end
@@ -0,0 +1,11 @@
1
+ module Mappum
2
+ #
3
+ # Objects of this class hold variables
4
+ # and helper methods for a mapping.
5
+ # New object is created for each mapping
6
+ #
7
+ class MapSpace
8
+ attr_accessor :context
9
+
10
+ end
11
+ end
@@ -1,6 +1,14 @@
1
1
  module Mappum
2
2
  class MappumException < RuntimeError
3
- attr_accessor :from_name, :to_name, :from, :to, :from_root, :to_root, :mappum_backtrace
3
+ attr_accessor :from_name, :to_name, :from, :to, :from_root, :to_root, :mappum_backtrace , :caused_by
4
+
5
+ def initialize(mess=nil)
6
+ super(mess)
7
+ if mess.kind_of? Exception
8
+ @caused_by = mess
9
+ set_backtrace(mess.backtrace)
10
+ end
11
+ end
4
12
  def wrap(map, from, to)
5
13
 
6
14
  if map != nil and map != @map #don't store same maps twice
@@ -8,9 +16,9 @@ module Mappum
8
16
  from_suffix, to_suffix = "",""
9
17
 
10
18
  add_to_mappum_backtrace(map)
11
- from_suffix = "[]" if map.from.is_array
19
+ from_suffix = "[]" if map.from.array?
12
20
  add_from_name(map.from.name, from_suffix)
13
- to_suffix = "[]" if map.to.is_array
21
+ to_suffix = "[]" if map.to.array?
14
22
  add_to_name(map.to.name, to_suffix)
15
23
  end
16
24
  @to = to if @to.nil?
@@ -29,10 +37,10 @@ module Mappum
29
37
  def add_to_mappum_backtrace(map)
30
38
  if @mappum_backtrace.nil?
31
39
  @mappum_backtrace = []
32
- @mappum_backtrace << map.from.src_ref
33
- @mappum_backtrace << map.to.src_ref
40
+ @mappum_backtrace << map.from.src_ref if map.from.respond_to?(:src_ref)
41
+ @mappum_backtrace << map.to.src_ref if map.to.respond_to?(:src_ref)
34
42
  end
35
- @mappum_backtrace << map.src_ref
43
+ @mappum_backtrace << map.src_ref if map.respond_to?(:src_ref)
36
44
  end
37
45
  end
38
46
  end
@@ -157,7 +157,7 @@ DOT
157
157
  pname, path, level = get_name_and_path(element.parent, level)
158
158
  end
159
159
  path = "#{path}v#{name}".gsub(":","vv") unless name.nil?
160
- name = "#{name}[]" if not name.nil? and element.is_array
160
+ name = "#{name}[]" if not name.nil? and element.array?
161
161
  return name, path, level
162
162
  end
163
163
  end
@@ -81,17 +81,24 @@ module Mappum
81
81
  @catalogue = params[:splat][0] || "ROOT"
82
82
  @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
83
83
 
84
- map_name = nil
85
- map_name = params["map"] unless params["map"].nil? or params["map"] == "auto_select"
86
- force_openstruct = false
87
- force_openstruct = params["ignore"] unless params["map"].nil?
84
+ map_name = nil
85
+ map_name = params["map"] unless params["map"].nil? or params["map"] == "auto_select"
86
+ from_qname_str = params["from_qname"] unless params["from_qname"].nil? or params["from_qname"] == "auto_select"
87
+ from_qname = nil
88
+ unless from_qname_str.nil? or from_qname_str==''
89
+ /^\{([^}]*)\}(.*)$/ =~ from_qname_str
90
+ from_qname = XSD::QName.new($1,$2)
91
+ end
92
+ force_openstruct = false
93
+ force_openstruct = params["ignore"] unless params["map"].nil?
94
+
95
+ rt = Mappum::XmlTransform.new(@catalogue, force_openstruct)
96
+
97
+ xml = params["doc"]
88
98
 
89
- rt = Mappum::XmlTransform.new(@catalogue, force_openstruct)
90
-
91
- xml = params["doc"]
92
- content = rt.transform(xml,map_name)
93
-
94
- [200, {"Content-Type" => "text/xml"}, [content]]
99
+ content = rt.transform(xml,map_name, from_qname)
100
+
101
+ [200, {"Content-Type" => "text/xml"}, [content]]
95
102
  end
96
103
  post "*/transform-ws" do
97
104
  @catalogue = params[:splat][0] || "ROOT"
@@ -173,31 +180,31 @@ module Mappum
173
180
  @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
174
181
 
175
182
  map_name = params["map"]
176
- map = Mappum.catalogue(@catalogue).get_bidi_map(map_name)
177
- map ||= Mappum.catalogue(@catalogue)[map_name]
178
- return [404, {"Content-Type" => "text/html"}, ["No map '#{map_name}'"]] if map.nil?
179
- graph = Mappum::MapServer::Graph.new(map)
180
- [200, {"Content-Type" => "image/png"}, graph.getPng]
183
+ map = Mappum.catalogue(@catalogue).get_bidi_map(map_name)
184
+ map ||= Mappum.catalogue(@catalogue)[map_name]
185
+ return [404, {"Content-Type" => "text/html"}, ["No map '#{map_name}'"]] if map.nil?
186
+ graph = Mappum::MapServer::Graph.new(map)
187
+ [200, {"Content-Type" => "image/png"}, graph.getPng]
181
188
 
182
189
  end
183
190
  get "*/doc" do
184
191
  @catalogue = params[:splat][0] || "ROOT"
185
192
  @catalogue = @catalogue[1..-1] if @catalogue[0..0] == "/"
186
193
 
187
- @map_name = params["map"]
188
- @map = Mappum.catalogue(@catalogue).get_bidi_map(@map_name)
189
- @map ||= Mappum.catalogue(@catalogue)[@map_name]
190
- return [404, {"Content-Type" => "text/html"}, ["No map " + @map_name]] if @map.nil?
191
- graph = Mappum::MapServer::Graph.new(@map)
192
- @edge_maps = graph.edge_maps.keys.sort.collect{|k| [k, graph.edge_maps[k], explain(graph.edge_maps[k])]}
193
- [200, {"Content-Type" => "text/html"}, [erb(:doc)]]
194
+ @map_name = params["map"]
195
+ @map = Mappum.catalogue(@catalogue).get_bidi_map(@map_name)
196
+ @map ||= Mappum.catalogue(@catalogue)[@map_name]
197
+ return [404, {"Content-Type" => "text/html"}, ["No map " + @map_name]] if @map.nil?
198
+ graph = Mappum::MapServer::Graph.new(@map)
199
+ @edge_maps = graph.edge_maps.keys.sort.collect{|k| [k, graph.edge_maps[k], explain(graph.edge_maps[k])]}
200
+ [200, {"Content-Type" => "text/html"}, [erb(:doc)]]
194
201
  end
195
202
  get "/" do
196
203
  @catalogue = params["catalogue"] || "ROOT"
197
204
  @catalogues = Mappum.catalogues
198
- @bidi_maps_name_source = Mappum.catalogue(@catalogue).list_bidi_map_names.collect{|mn| [mn, Mappum.catalogue(@catalogue).get_bidi_map(mn).source] }
199
- @maps_name_source = Mappum.catalogue(@catalogue).list_map_names.collect{|mn| [mn, Mappum.catalogue(@catalogue)[mn].source]}
200
- [200, {"Content-Type" => "text/html"}, [erb(:main)]]
205
+ @bidi_maps_name_source = Mappum.catalogue(@catalogue).list_bidi_map_names.collect{|mn| [mn, Mappum.catalogue(@catalogue).get_bidi_map(mn).source] }
206
+ @maps_name_source = Mappum.catalogue(@catalogue).list_map_names.collect{|mn| [mn, Mappum.catalogue(@catalogue)[mn].source]}
207
+ [200, {"Content-Type" => "text/html"}, [erb(:main)]]
201
208
  end
202
209
  error do
203
210
  @xml_convertor = Syntax::Convertors::HTML.for_syntax "xml"
@@ -18,6 +18,7 @@
18
18
  <%end%>
19
19
  </select>
20
20
  <input type="checkbox" name="ignore" value="false">Ignore types</input>
21
+ <input type="text" name="from_qname"></input>
21
22
  <br/>
22
23
  <TEXTAREA name="doc" rows="20" cols="80"></TEXTAREA><br/>
23
24
  <INPUT type="submit" value="Send"/><INPUT type="reset"/>
@@ -4,6 +4,8 @@ require 'mappum'
4
4
  require 'ostruct'
5
5
  require 'mappum/autoconv_catalogue'
6
6
  require 'mappum/mappum_exception'
7
+ require 'mappum/map_space'
8
+
7
9
 
8
10
  module Mappum
9
11
  #
@@ -24,8 +26,18 @@ module Mappum
24
26
  #
25
27
  # Method for transforming from object using map to "to" object.
26
28
  #
27
- def transform(from, map=nil, to=nil)
29
+ def transform(from, map=nil, to=nil, options={})
28
30
  begin
31
+
32
+ options ||= {}
33
+
34
+ map_space_added = false
35
+ if options["map_space"].nil?
36
+ map_space_added = true
37
+ options["map_space"] = Mappum::MapSpace.new
38
+ options["map_space"].context = get_context(options)
39
+ end
40
+
29
41
  raise RuntimeError.new("Map catalogue is empty!") if @map_catalogue.nil?
30
42
 
31
43
  map ||= @map_catalogue[from.class]
@@ -39,29 +51,31 @@ module Mappum
39
51
 
40
52
  all_nils = true
41
53
  map.maps.each do |sm|
42
- begin
54
+ begin
43
55
  from_value, to_value = nil, nil
44
56
 
45
- from_value = get(from, sm.from, map.from)
57
+ from_value = get(from, sm.from, map.from, options)
46
58
 
47
59
  # skip to next mapping on false :map_when function
48
60
  next unless sm.map_when.nil? or sm.map_when.call(from_value)
49
61
 
50
62
  unless sm.func.nil? or (not sm.func_on_nil? and from_value.nil?)
51
- from_value = sm.func.call(from_value)
63
+ from_value = options["map_space"].instance_exec(from_value,&sm.func)
52
64
  end
53
65
  unless sm.from.func.nil? or from_value.nil?
54
66
  mappum_block = sm.from.block
55
- if from_value.kind_of?(Array)
56
- # TODO Fix it for JavaArrays
57
- #or (Module.constants.include? "ArrayJavaProxy" and from_value.kind_of?(Module.const_get(:ArrayJavaProxy)))
58
- from_value = from_value.compact.instance_eval(sm.from.func)
67
+ if from_value.kind_of?(Array)
68
+ from_value = from_value.compact.instance_eval(sm.from.func)
59
69
  else
70
+ # TODO Fix it for Java to make campact as well
71
+ #non real arrays
72
+ if is_array?(from_value)
73
+ from_value = convert_from(from_value,sm.from)
74
+ end
60
75
  from_value = from_value.instance_eval(sm.from.func)
61
76
  end
62
77
  end
63
-
64
- submaps = sm.maps
78
+ submaps = sm.maps
65
79
  if sm.maps.empty?
66
80
  unless sm.submap_alias.nil? or sm.submap_alias.empty?
67
81
  submaps = @map_catalogue[sm.submap_alias].maps
@@ -81,63 +95,70 @@ module Mappum
81
95
  unless submaps.empty? or from_value.nil?
82
96
  #We should make some kind of test like this
83
97
  #raise "Not an array: #{sm.from.name} inspect:" + from_value.inspect if sm.from.is_array and not from_value.kind_of?(Array)
84
- if from_value.kind_of?(Array) or
85
- (Module.constants.include? "ArrayJavaProxy" and from_value.kind_of?(Module.const_get(:ArrayJavaProxy)))
98
+ if is_array?(from_value)
86
99
  sm_v = sm.clone
87
- if sm_v.from.is_array
100
+ if sm_v.from.array?
88
101
  sm_v.from = sm.from.clone
89
- sm_v.from.is_array = false
102
+ sm_v.from.enum_type = nil
90
103
  end
91
- if sm_v.to.is_array
104
+ if sm_v.to.array?
92
105
  sm_v.to = sm.to.clone
93
- sm_v.to.is_array = false
106
+ sm_v.to.enum_type = nil
94
107
  end
95
108
  if sm_v.maps.empty?
96
- sm_v.maps = submaps
97
- sm_v.maps.each{|m| m.from.parent = sm_v.from}
98
- #don't add parent we need separation
99
- to_value = from_value.collect{|v| transform(v, sm_v)}
100
- else
101
- to_value = from_value.collect{|v| transform(add_parent(v, from), sm_v)}
102
- end
109
+ sm_v.maps = submaps
110
+ sm_v.maps.each{|m| m.from.parent = sm_v.from}
111
+ #don't add parent we need separation
112
+ to_value = from_value.collect{|v| transform(v, sm_v, nil, pass_options(options))}
113
+ else
114
+ to_value = from_value.collect{|v| transform(add_parent(v, from), sm_v, nil, pass_options(options))}
115
+ end
103
116
  else
104
117
  to ||= map.to.clazz.new unless @force_open_struct or map.to.clazz.nil? or map.to.clazz.kind_of?(Symbol)
105
118
  to ||= @default_struct_class.new
106
119
  v_to = []
107
120
  #array values are assigned after return
108
- v_to << get(to, sm.to) unless sm.to.is_array and not sm.from.is_array
121
+ v_to << get(to, sm.to, nil, options) unless sm.to.array? and not sm.from.array?
109
122
  #nless one whants to update existing to array
110
123
  if sm.to_array_take == :first
111
- arr_v = get(to, sm.to)
124
+ arr_v = get(to, sm.to, nil, options)
112
125
  v_to << arr_v[0] if not arr_v.nil?
113
126
  end
114
127
  if sm.to_array_take == :all
115
- arr_v = get(to, sm.to)
128
+ arr_v = get(to, sm.to, nil, options)
116
129
  v_to += arr_v if not arr_v.nil?
117
130
  end
131
+ #array values are assigned after return
132
+ v_to = [nil] if sm.to.array? and not sm.from.array? and v_to.empty?
118
133
  v_to.each do |v_t|
119
- sm_v = sm
120
- if sm_v.maps.empty?
121
- sm_v = sm.clone
122
- sm_v.maps = submaps
123
- sm_v.maps.each{|m| m.from.parent = sm_v.from}
124
- #don't add parent we need separation
125
- to_value = transform(from_value, sm_v, v_t)
126
- else
127
- to_value = transform(add_parent(from_value, from), sm_v, v_t)
128
- end
129
- end
134
+ sm_v = sm
135
+ if sm_v.maps.empty?
136
+ sm_v = sm.clone
137
+ sm_v.maps = submaps
138
+ sm_v.maps.each{|m| m.from.parent = sm_v.from}
139
+ #don't add parent we need separation
140
+ to_value = transform(from_value, sm_v, v_t, pass_options(options))
141
+ else
142
+ to_value = transform(add_parent(from_value, from), sm_v, v_t, pass_options(options))
143
+ end
144
+ end
130
145
  end
131
146
 
132
147
  end
133
148
  unless sm.dict.nil?
134
149
  to_value = sm.dict[to_value]
135
150
  end
136
- if sm.to.is_array and not sm.from.is_array
137
- to_array = convert_from(get(to,sm.to),sm.from)
138
- to_array ||= []
139
- to_array << to_value unless sm.to_array_take == :first or sm.to_array_take == :all
140
-
151
+
152
+ if sm.to.array? and not sm.from.array?
153
+ to_array = convert_from(get(to,sm.to,nil,options),sm.from)
154
+ to_array ||= sm.to.enum_type.new
155
+ to_array << to_value unless sm.to.enum_type != Array or sm.to_array_take == :first or sm.to_array_take == :all
156
+ #FIXME change array and hash to something sane!
157
+ if sm.to.enum_type == Hash and sm.to.func[0..6] == "self.[]"
158
+ bad_func = "self.[]=#{sm.to.func[7..-2]},to_value)"
159
+ to_array.instance_eval(bad_func)
160
+ end
161
+
141
162
  if to_array.empty? and sm.strip_empty?
142
163
  to_array = nil
143
164
  end
@@ -147,9 +168,13 @@ module Mappum
147
168
  if sm.to.name.nil?
148
169
  to = convert_to(to_array, sm.to)
149
170
  else
150
- to ||= map.to.clazz.new unless @force_open_struct or map.to.clazz.nil? or map.to.clazz.kind_of?(Symbol)
151
- to ||= @default_struct_class.new
152
- to.send("#{sm.to.name}=", convert_to(to_array, sm.to)) unless to_array.nil?
171
+ if sm.to.parent.kind_of? Context
172
+ get_context(options).send("#{sm.to.name}=", convert_to(to_array, sm.to, get_context(options))) unless to_array.nil?
173
+ else
174
+ to ||= map.to.clazz.new unless @force_open_struct or map.to.clazz.nil? or map.to.clazz.kind_of?(Symbol)
175
+ to ||= @default_struct_class.new
176
+ to.send("#{sm.to.name}=", convert_to(to_array, sm.to, to)) unless to_array.nil?
177
+ end
153
178
  end
154
179
  else
155
180
 
@@ -162,9 +187,13 @@ module Mappum
162
187
  if sm.to.name.nil?
163
188
  to ||= to_value
164
189
  else
165
- to ||= map.to.clazz.new unless @force_open_struct or map.to.clazz.nil? or map.to.clazz.kind_of?(Symbol)
166
- to ||= @default_struct_class.new
167
- to.send("#{sm.to.name}=", convert_to(to_value, sm.to)) unless to_value.nil?
190
+ if sm.to.parent.kind_of? Context
191
+ get_context(options).send("#{sm.to.name}=", convert_to(to_value, sm.to, get_context(options))) unless to_value.nil?
192
+ else
193
+ to ||= map.to.clazz.new unless @force_open_struct or map.to.clazz.nil? or map.to.clazz.kind_of?(Symbol)
194
+ to ||= @default_struct_class.new
195
+ to.send("#{sm.to.name}=", convert_to(to_value, sm.to, to)) unless to_value.nil?
196
+ end
168
197
  end
169
198
  end
170
199
  rescue Exception => e
@@ -173,6 +202,13 @@ module Mappum
173
202
  raise e
174
203
  end
175
204
  end
205
+ if map_space_added
206
+ if options.respond_to? :delete
207
+ options.delete("map_space")
208
+ else
209
+ options["map_space"]=nil
210
+ end
211
+ end
176
212
  if all_nils and map.strip_empty?
177
213
  return nil
178
214
  end
@@ -185,39 +221,44 @@ module Mappum
185
221
  end
186
222
 
187
223
  protected
188
-
189
- def get(object, field, parent_field=nil)
190
- if field.kind_of?(String) or field.kind_of?(Symbol)
191
- field_name = field
192
- else
193
- unless field.respond_to?(:name)
194
- return field.value
195
- end
196
- if field.name.nil? or object.nil?
197
- return object
198
- end
199
- #for fields targeted at parents go up the tree
200
- if (not parent_field.nil?) and field.parent != parent_field
201
- if object.respond_to?(:_mpum_parent)
202
- return get(object._mpum_parent, field, parent_field.parent)
203
- else
204
- raise "We hit an element with no parent: #{object.inspect}"
205
- end
206
- end
207
- field_name = field.name
208
- end
209
- begin
210
- return object.send(field_name)
211
- rescue NoMethodError => e
212
- #for open structures field will be defined later
213
- if object.kind_of?(@default_struct_class)
214
- return nil
215
- else
216
- raise e
217
- end
218
- end
224
+ def is_array?(obj)
225
+ return (obj.kind_of?(Array) or obj.kind_of?(Set) or obj.kind_of?(Hash))
219
226
  end
220
- def convert_to(to, field_def)
227
+ def get(object, field, parent_field=nil,options={})
228
+ if field.kind_of?(String) or field.kind_of?(Symbol)
229
+ field_name = field
230
+ else
231
+ unless field.respond_to?(:name)
232
+ return field.value
233
+ end
234
+ if field.parent.kind_of?(Context)
235
+ object = get_context(options)
236
+ end
237
+ if field.name.nil? or object.nil?
238
+ return object
239
+ end
240
+ #for fields targeted at parents go up the tree
241
+ if (not parent_field.nil?) and (not parent_field.is_root) and field.parent != parent_field
242
+ if object.respond_to?(:_mpum_parent)
243
+ return get(object._mpum_parent, field, parent_field.parent, options)
244
+ else
245
+ raise "No parent for this object"
246
+ end
247
+ end
248
+ field_name = field.name
249
+ end
250
+ begin
251
+ return object.send(field_name)
252
+ rescue NoMethodError => e
253
+ #for open structures field will be defined later
254
+ if object.kind_of?(@default_struct_class)
255
+ return nil
256
+ else
257
+ raise e
258
+ end
259
+ end
260
+ end
261
+ def convert_to(to, field_def, parent)
221
262
  return to
222
263
  end
223
264
  def convert_from(from, field_def)
@@ -232,6 +273,17 @@ module Mappum
232
273
  value._mpum_parent = parent
233
274
  return value
234
275
  end
276
+ def pass_options(options)
277
+ return options
278
+ end
279
+ def get_context(options)
280
+ ctx = options[:context]
281
+ ctx ||= options["context"]
282
+ if ctx.nil?
283
+ ctx = @default_struct_class.new
284
+ end
285
+ return ctx
286
+ end
235
287
  end
236
288
  class OpenStruct < OpenStruct
237
289
  def type(*attr)