Class: RestKat::IosMapping

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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_schema) ⇒ IosMapping

Returns a new instance of IosMapping.



289
290
291
292
# File 'lib/rest_kat.rb', line 289

def initialize api_schema
    raise "#{api_schema} does not exist" unless File.exist?(api_schema)
    @schema_file = api_schema
end

Class Method Details

.obj_c_type_for_property(parent_node, property_name) ⇒ Object



358
359
360
361
# File 'lib/rest_kat.rb', line 358

def self.obj_c_type_for_property parent_node, property_name
  parent_type = parent_node[:name].gsub /MSRest/, ''
  "MSRest#{parent_type.camelize}#{property_name.camelize}"
end

Instance Method Details

#classesObject



303
304
305
# File 'lib/rest_kat.rb', line 303

def classes
  @classes ||= []
end

#create_sequence(node, cached) ⇒ Object



423
424
425
426
427
428
429
430
431
432
433
434
435
# File 'lib/rest_kat.rb', line 423

def create_sequence node, cached
    if node[:sequence].length != 1
      raise "Only support sequence of map with one map type"
    end
    item_class = to_objective_c_class node:node[:sequence].first, cached:cached
    if item_class.is_a? ObjCMapType
        ObjCSequenceOfMap.new(item_class)
    elsif item_class.is_a? ObjCPrimitiveType
        ObjCSequenceOfPrimitve.new(item_class)
    else
        raise Exception.new "#{item_class.class} cannot be handled here"
    end
end

#find_processed_class(node) ⇒ Object



363
364
365
# File 'lib/rest_kat.rb', line 363

def find_processed_class node
  classes.find{|c| c.objc_class == node[:name]}
end

#generate_objective_c_classesObject

Generate the required objective c class AST’s for th name resource in the correct order so they can be written to code in the correct order in the templates



327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/rest_kat.rb', line 327

def generate_objective_c_classes
  @classes = []
  resources_from_schema.collect do |resource_hash|
    Resource.new(resource_hash).tap do |resource|
      # Generate the query classes first
      resource.queries.each do |query|
        # Query objects do not get cached in core data
        to_objective_c_class node:query["type"], cached:false
      end
      # Generate the resource classes next
      klass = to_objective_c_class node:resource.hash[:type], cached:resource.cached?
      # Mark this class as being a REST resource
      klass.resource = resource
    end
  end
end

#h_templateObject



316
317
318
# File 'lib/rest_kat.rb', line 316

def h_template
  template "model.h.erb"
end

#m_templateObject



320
321
322
# File 'lib/rest_kat.rb', line 320

def m_template
  template "model.m.erb"
end

#resourcesObject



307
308
309
# File 'lib/rest_kat.rb', line 307

def resources
  @resources ||= []
end

#resources_from_schemaObject



294
295
296
# File 'lib/rest_kat.rb', line 294

def resources_from_schema
  schema[:resources]
end

#schemaObject



298
299
300
301
# File 'lib/rest_kat.rb', line 298

def schema
  require 'kwalify'
  @schema ||= HashWithIndifferentAccess.new Kwalify::Yaml.load_file(@schema_file)
end

#template(name) ⇒ Object



311
312
313
314
# File 'lib/rest_kat.rb', line 311

def template name
  require 'erb'
  ERB.new File.read(File.expand_path(File.join("..", name), __FILE__)), 0, '<>'
end

#to_h(name) ⇒ Object

Generate the objective C header for name resource



345
346
347
348
# File 'lib/rest_kat.rb', line 345

def to_h name
  @resources = generate_objective_c_classes
  h_template.result binding
end

#to_m(name) ⇒ Object

Generate the objective C implementation file for name resource



351
352
353
354
355
356
# File 'lib/rest_kat.rb', line 351

def to_m name
  @resources = generate_objective_c_classes
  #TODO below 'header' must change
  header = (File.basename name, ".*") + ".h"
  m_template.result binding
end

#to_objective_c_class(options) ⇒ Object

Perform a depth first traversal of the type tree. The resulting classes array will have the top level class last in the array. In the code generation phase this classes will be injected last into the code making sure the dependencies are define in the correct order.

Raises:

  • (Exception)


372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/rest_kat.rb', line 372

def to_objective_c_class options

  node = options[:node]
  cached = options[:cached]

  unless node
    raise Exception.new("node is nil")
  end

  case node[:type]
  when "map"

    unless klass = find_processed_class(node)
      klass = ObjCMapType.new(node[:name], node[:type], node)

      klass.properties = node[:mapping].collect do |property_name, property_node|
        if property_node[:type] == "map"
          property_node[:name] ||= IosMapping.obj_c_type_for_property(node, property_name)
        end
        ObjCProperty.new(to_objective_c_class(node:property_node, cached:cached), property_name)
      end

      self.classes << klass
    end

    # Inherit caching from parent as the whole object graph 
    # of cached objects needs to go into Core Data
    klass.cached = cached

  when "seq"
    klass = create_sequence(node, cached)
  when "str", "text"
    klass = ObjCPrimitiveType.new(node[:name] || "NSString", node[:type], node)
  when "int"
    klass = ObjCPrimitiveType.new(node[:name] || "NSNumber", node[:type], node)
  when "float"
    klass = ObjCPrimitiveType.new(node[:name] || "NSNumber", node[:type], node)
  when "bool"
    klass = ObjCPrimitiveType.new(node[:name] || "NSNumber", node[:type], node)
  when "any"
    klass = ObjCPrimitiveType.new(node[:name] || "NSObject", node[:type], node)
  else
    raise Exception.new("Unhandled type '#{node[:type]} for node with name #{node[:name]}")
  end

  raise Exception.new("klass cannot be nil") unless klass

  klass

end