Class: Mappum::RubyTransform

Inherits:
Object
  • Object
show all
Defined in:
lib/mappum/ruby_transform.rb

Overview

Main class handling transformation of ruby to ruby objects. This class is a base for other transformations in Mappum.

Direct Known Subclasses

JavaTransform, RubyXmlTransform

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(map_catalogue = nil, default_struct_class = nil, force_open_struct = false) ⇒ RubyTransform

Returns a new instance of RubyTransform.



18
19
20
21
22
23
24
25
# File 'lib/mappum/ruby_transform.rb', line 18

def initialize(map_catalogue=nil, default_struct_class=nil, force_open_struct=false)
  @map_catalogue = map_catalogue if map_catalogue.kind_of?(Mappum::Map)
  @map_catalogue ||= Mappum.catalogue(map_catalogue)
  @autoconv_map_catalogue = Mappum.catalogue("MAPPUM_AUTOCONV")
  @default_struct_class = default_struct_class
  @force_open_struct = force_open_struct
  @default_struct_class ||= Mappum::OpenStruct;
end

Instance Attribute Details

#map_catalogueObject

Returns the value of attribute map_catalogue.



16
17
18
# File 'lib/mappum/ruby_transform.rb', line 16

def map_catalogue
  @map_catalogue
end

Instance Method Details

#transform(from, map = nil, to = nil, options = {}) ⇒ Object

Method for transforming from object using map to "to" object.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/mappum/ruby_transform.rb', line 29

def transform(from, map=nil, to=nil, options={})
  begin

  options ||= {}
  
  map_space_added = false
  if options["map_space"].nil?
    map_space_added = true
    options["map_space"] = Mappum::MapSpace.new
    options["map_space"].context = get_context(options)
  end
  
  raise RuntimeError.new("Map catalogue is empty!") if @map_catalogue.nil?
  
  map ||= @map_catalogue[from.class]
  
  map = @map_catalogue[map] if map.kind_of?(Symbol) or map.kind_of?(String)
  
  raise MapMissingException.new(from) if map.nil?
  
  # skip mapping on false :map_when function
  return to unless map.map_when.nil? or map.map_when.call(from)

  all_nils = true
  map.maps.each do |sm|
   begin
    from_value, to_value = nil, nil
    
    from_value = get(from, sm.from, map.from, options) 

    # skip to next mapping on false :map_when function
    next unless sm.map_when.nil? or sm.map_when.call(from_value)

    unless sm.func.nil? or (not sm.func_on_nil? and from_value.nil?)
      from_value = options["map_space"].instance_exec(from_value,&sm.func)
    end
    unless sm.from.func.nil? or from_value.nil?
      mappum_block = sm.from.block
        if from_value.kind_of?(Array)
            from_value = from_value.compact.instance_eval(sm.from.func)
        else
          # TODO Fix it for Java to make campact as well
          #non real arrays
          if is_array?(from_value)
            from_value = convert_from(from_value,sm.from)
          end
          from_value = from_value.instance_eval(sm.from.func)
        end
    end
    submaps = sm.maps
    if sm.maps.empty?
      unless sm.submap_alias.nil? or sm.submap_alias.empty?
        submaps = @map_catalogue[sm.submap_alias].maps
      end
      if sm.to.respond_to?(:clazz) and sm.from.respond_to?(:clazz) and sm.from.clazz != sm.to.clazz
        sub = @map_catalogue[sm.from.clazz,sm.to.clazz]
        sub ||= @autoconv_map_catalogue[sm.from.clazz,sm.to.clazz]
        unless  sub.nil? 
         submaps = sub.maps
        else
         to_value = from_value
        end
      else
        to_value = from_value
      end
    end
    unless submaps.empty? or from_value.nil?
      #We should make some kind of test like this
      #raise "Not an array: #{sm.from.name} inspect:" + from_value.inspect if sm.from.is_array and not from_value.kind_of?(Array)
      if is_array?(from_value)
        sm_v = sm.clone
        if sm_v.from.array?
          sm_v.from = sm.from.clone
          sm_v.from.enum_type = nil
        end
        if sm_v.to.array?
          sm_v.to = sm.to.clone
          sm_v.to.enum_type = nil
        end
        if sm_v.maps.empty?
          sm_v.maps = submaps 
          sm_v.maps.each{|m| m.from.parent = sm_v.from}
          #don't add parent we need separation
          to_value = from_value.collect{|v| transform(v, sm_v, nil, pass_options(options))}
        else
          to_value = from_value.collect{|v| transform(add_parent(v, from), sm_v, nil, pass_options(options))}
        end
      else
        to ||= map.to.clazz.new unless @force_open_struct or map.to.clazz.nil? or map.to.clazz.kind_of?(Symbol)
        to ||= @default_struct_class.new
        v_to = []
        #array values are assigned after return
        v_to << get(to, sm.to, nil, options) unless sm.to.array? and not sm.from.array?
        #nless one whants to update existing to array
        if sm.to_array_take == :first
          arr_v = get(to, sm.to, nil, options)
          v_to << arr_v[0]  if not arr_v.nil?
        end
        if sm.to_array_take == :all
          arr_v = get(to, sm.to, nil, options)
          v_to += arr_v  if not arr_v.nil?
        end
        #array values are assigned after return
        v_to = [nil] if sm.to.array? and not sm.from.array? and v_to.empty?
        v_to.each do |v_t|
    sm_v = sm
    if sm_v.maps.empty?
      sm_v = sm.clone
      sm_v.maps = submaps
      sm_v.maps.each{|m| m.from.parent = sm_v.from}
      #don't add parent we need separation
      to_value = transform(from_value, sm_v, v_t, pass_options(options))
    else
      to_value = transform(add_parent(from_value, from), sm_v, v_t, pass_options(options))
    end
    end
      end

    end
    unless sm.dict.nil?
      to_value = sm.dict[to_value]
    end

    if sm.to.array? and not sm.from.array?
      to_array = convert_from(get(to,sm.to,nil,options),sm.from)
      to_array ||= sm.to.enum_type.new
      to_array << to_value unless sm.to.enum_type != Array or sm.to_array_take == :first or sm.to_array_take == :all
      #FIXME change array and hash to something sane! 
      if sm.to.enum_type == Hash and sm.to.func[0..6] == "self.[]"
        bad_func = "self.[]=#{sm.to.func[7..-2]},to_value)"
        to_array.instance_eval(bad_func)
      end

      if to_array.empty? and sm.strip_empty?
        to_array = nil
      end
      
      all_nils = false unless to_array.nil?

      if sm.to.name.nil?
        to = convert_to(to_array, sm.to)
      else
        if sm.to.parent.kind_of? Context
          get_context(options).send("#{sm.to.name}=", convert_to(to_array, sm.to, get_context(options))) unless to_array.nil?
        else 
          to ||= map.to.clazz.new unless @force_open_struct or map.to.clazz.nil? or map.to.clazz.kind_of?(Symbol)
          to ||= @default_struct_class.new
          to.send("#{sm.to.name}=", convert_to(to_array, sm.to, to)) unless to_array.nil?
        end
      end
    else

      if to_value.respond_to?(:empty?) and to_value.empty? and sm.strip_empty?
        to_value = nil
      end
      
      all_nils = false unless to_value.nil?

      if sm.to.name.nil?
        to ||= to_value
      else
        if sm.to.parent.kind_of? Context
          get_context(options).send("#{sm.to.name}=", convert_to(to_value, sm.to, get_context(options))) unless to_value.nil?
        else 
         to ||= map.to.clazz.new unless @force_open_struct or map.to.clazz.nil? or map.to.clazz.kind_of?(Symbol)
         to ||= @default_struct_class.new 
         to.send("#{sm.to.name}=", convert_to(to_value, sm.to, to)) unless to_value.nil?
        end
      end
    end
   rescue Exception => e
    e = MappumException.new(e) unless e.kind_of?(MappumException)
    e.wrap(sm, from_value, to_value)
    raise e
   end 
  end
  if map_space_added
    if options.respond_to? :delete
      options.delete("map_space") 
    else
      options["map_space"]=nil
    end
  end
  if all_nils and map.strip_empty?
    return nil
  end
    return to
  rescue Exception => e
    e = MappumException.new(e) unless e.kind_of?(MappumException)
    e.wrap(map, from, to)
    raise e
  end
end