mappum 0.2.3 → 0.2.4

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.
@@ -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)