Class: SDL::Receivers::TypeInstanceReceiver

Inherits:
Object
  • Object
show all
Defined in:
lib/sdl/receivers/type_instance_receiver.rb

Overview

Receiver for setting the properties of Type instances

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type_instance) ⇒ TypeInstanceReceiver

When initialized for a fact or type instance, the receiver creates singleton methods on itself for all properties.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 9

def initialize(type_instance)
  @instance = type_instance

  type_instance.class.properties(true).each do |property|
    if property.single?
      # There are different ways of setting a single valued property
      # -> Specifying a symbol: "Set the value of this property to the instance referred by the symbol"
      # -> Specifying at least a symbol: "Create a new instance of this type and set its properties to the values"
      define_singleton_method property.name do |*args, &block|
        if property.simple_type?
          type_instance.set_sdl_property property, args[0]

          if args[1]
            type_instance.get_sdl_value(property).annotations << args[1][:annotation]
          end
        else
          # Replace all symbols with their type instance
          args.map! {|item| item.is_a?(Symbol) ? refer_or_copy(find_instance!(item)) : item }

          begin
            if(args.count == 1 && args[0].class <= property.type)
              # The first argument refers to a predefined instance of the property type. Set it as value
              type_instance.set_sdl_property property, refer_or_copy(args[0])
            else
              # The arguments are values for a new instance
              property_type_instance = property.type.new

              property_type_instance.set_sdl_values(*args)

              SDL::Receivers::TypeInstanceReceiver.new(property_type_instance).instance_eval(&block) if block

              type_instance.set_sdl_property property, property_type_instance
            end
          rescue RuntimeError => e
            raise RuntimeError, "Cannot set property '#{property.name}' of Type #{@instance.class.name}: #{e}", e.backtrace
          rescue Exception => e
            raise RuntimeError, e
          end
        end
      end
    else
      # Multi-valued properties are added to by their singular name,
      # e.g. 'browsers' is set by invoking 'browser'
      define_singleton_method property.name.singularize do |*arguments, &block|
        existing_list = type_instance.send property.name

        arguments.map! {|item| item.is_a?(Symbol) ? refer_or_copy(find_instance!(item)) : item }

        if arguments[0].is_a?(property.type)
          # The first argument is the value
          new_item = refer_or_copy(arguments[0])

          arguments.each do |arg|
            if arg.is_a?(Hash) && arg[:annotation]
              new_item.annotations << arg[:annotation]
            end
          end
        else
          if property.simple_type?
            new_item = property.type.new
            new_item.raw_value = arguments[0]

            if arguments[1]
              type_instance.get_sdl_value(property).annotations << arguments[1][:annotation]
            end
          else
            new_item = property.type.new

            new_item.set_sdl_values(*arguments) unless arguments.empty?

            self.class.new(new_item).instance_exec(&block) if block
          end
        end

        new_item.parent = type_instance
        new_item.parent_index = existing_list.count

        existing_list << new_item
      end
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

Catches calls to methods named similarily to possible predefined type instances



98
99
100
101
102
103
104
105
106
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 98

def method_missing(name, *args)
  instance = find_instance(name.to_sym)

  if (instance)
    refer_or_copy(instance)
  else
    raise Exception.new("I do not know what to do with '#{name}'.")
  end
end

Instance Attribute Details

#instanceObject

Returns the value of attribute instance.



4
5
6
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 4

def instance
  @instance
end

Instance Method Details

#annotation(value) ⇒ Object



92
93
94
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 92

def annotation(value)
  @instance.annotations << value
end

#dynamic(&block) ⇒ Object



130
131
132
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 130

def dynamic(&block)
  instance_eval &block
end

#find_instance(symbol) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 108

def find_instance(symbol)
  instance_key_value_pair = SDL::Base::Type.instances_recursive.find do |key, value|
    key == symbol
  end

  if instance_key_value_pair
    instance_key_value_pair[1]
  else
    nil
  end
end

#find_instance!(symbol) ⇒ Object



120
121
122
123
124
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 120

def find_instance!(symbol)
  instance = find_instance(symbol)

  instance ? instance : raise("Cannot find predefined instance #{symbol.to_s}!")
end

#noObject



139
140
141
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 139

def no
  false
end

#refer_or_copy(instance) ⇒ Object



126
127
128
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 126

def refer_or_copy(instance)
  instance.dup
end

#yesObject

Shortcuts for using ‘yes’ and ‘no’ in SDLs



135
136
137
# File 'lib/sdl/receivers/type_instance_receiver.rb', line 135

def yes
  true
end